自 Android 7 起,应用会忽略用户提供的证书

自 Android 7 起,应用会忽略用户提供的证书,除非它们被配置为使用这些证书。由于大多数应用不会明确选择使用用户证书,我们需要将 mitmproxy CA 证书放入系统证书存储中,以避免必须为每个想要监控的应用打补丁。

注意:应用可以决定忽略系统证书存储并维护自己的 CA 证书。在这种情况下,你必须对该应用打补丁。

1. 先决条件

  • 已安装 Android Studio / Android SDK(已在 Linux 64 位版本 4.1.3 上测试)
  • 已创建 Android 虚拟设备(AVD)。设置文档可在此处获取
  • AVD 生产构建(标有“Google Play”的构建)会阻止你使用 adb root。如果你需要安装 Google Play,则需要使用 Magisk 方法
  • AVD 的代理设置已配置为使用 mitmproxy。文档在此处
  • Android SDK 中的 emulator 和 adb 可执行文件已添加到 $PATH 变量中

    • emulator 在 Linux 系统上通常位于 /home/<your_user_name>/Android/Sdk/emulator/emulator
    • adb 在 Linux 系统上通常位于 /home/<your_user_name>/Android/Sdk/platform-tools/adb
    • 我将这些行添加到了我的 .bashrc 中:

      export PATH=$PATH:$HOME/Android/Sdk/platform-tools
      export PATH=$PATH:$HOME/Android/Sdk/emulator
  • Mitmproxy CA 证书已创建

    • 在 Linux 系统上通常位于 ~/.mitmproxy/mitmproxy-ca-cert.cer
    • 如果该文件夹为空或不存在,请运行 mitmproxy 以生成证书

2. 重命名证书

Android 中的 CA 证书按其哈希值命名存储,扩展名为 0(例如:c8450d0d.0)。有必要计算出你的 CA 证书的哈希值,并将其复制到一个以该哈希值作为文件名的文件中。否则 Android 将忽略该证书。默认情况下,mitmproxy CA 证书位于此文件中:~/.mitmproxy/mitmproxy-ca-cert.cer

说明

  1. 进入你的证书文件夹:

    cd ~/.mitmproxy/
  2. 生成哈希并复制证书:

    hashed_name=`openssl x509 -inform PEM -subject_hash_old -in mitmproxy-ca-cert.cer | head -1` && cp mitmproxy-ca-cert.cer $hashed_name.0

3. 将证书插入系统证书存储

现在我们必须将我们的 CA 证书放入 Android 文件系统中位于 /system/etc/security/cacerts/ 的系统证书存储内。默认情况下,/system 分区以只读方式挂载。以下步骤描述了如何获得对 /system 分区的写入权限,以及如何复制上一步中创建的证书。

使用 Magisk 时的说明

如果你想使用生产构建(标有“Google Play”;就是那些安装了 Google Play 的构建),你可以使用 Magisk 在你的 AVD 中获取 root 权限。Magisk 允许在你的 Android 设备或模拟器上获得 root 权限。

有关在 AVD 上安装 Magisk 的说明,请参见此处。

注意:说明中说要启动你的 AVD。此时不要向 mitmproxy 提供 -http-proxy 指令。

完成后,你的模拟器将允许 root。你可以通过运行终端模拟器并输入 su 来检查这一点。Magisk 应该会询问你是否要向该程序授予 root 权限。授予后,输入 whoami 将显示 root。

然而,在你安装 Magisk 后,你不能再使用 -writable-system 启动模拟器。这会导致启动循环。(使用 -show-kernel 启动你的 AVD 以查看错误。)但是你可以通过将 mitmproxy 证书放入 Magisk 模块并安装该模块来安装它。Magisk 将在启动期间负责将你的证书复制到 /system/etc/security/cacerts/。

从 mitmweb 下载 Magisk 模块

如果你运行 mitmweb,你可以直接下载 Magisk 模块,而不必手工制作它:

  1. 停止你的 AVD,然后使用以下命令再次启动它:

    -http-proxy 127.0.0.1:8080

    (或你运行 mitmweb 代理所使用的任何 IP 和端口组合)

  2. 然后,在 AVD 内,启动浏览器并导航到:

    http://mitm.it/cert/magisk
  3. 你将被提示下载 mitmproxy-magisk-module.zip,这就是你需要的 Magisk 模块。将该文件存储在某处(例如“Downloads”中)。
  4. 然后打开 Magisk,点击 Modules 并安装你的模块。
  5. 重启你的 AVD。

创建包含你的证书的 Magisk 模块

如果你不运行 mitmweb,你需要自己创建一个 Magisk 模块。有关 Magisk 模块的深入信息,请参见此处,但基本上可以归结为:

  1. 创建以下目录:

    mitmproxycert                    (这将是你的模块根目录)
    mitmproxycert/com/google/android
    mitmproxycert/system/etc/security/cacerts
  2. 将你在第 2 步中重命名后的证书放入 mitmproxycert/system/etc/security/cacerts,并对其执行:

    chmod 664
  3. 将 https://github.com/topjohnwu/Magisk/blob/master/scripts/module_installer.sh 的内容保存为本地文件 update-binary,并放入 mitmproxycert/com/google/android。
  4. 创建一个名为 updater-script 的文件,其中仅包含字符串:

    #MAGISK

    并将其放入 mitmproxycert/com/google/android。

  5. 创建一个名为 module.prop 的文件,并将其放入 mitmproxycert。该文件应包含类似以下内容:

    id=mitmproxycert
    name=MITM proxy certificate
    version=1
    versionCode=1
    author=mitmproxycert
    description=My shiny MITM proxy certificate to reveal all secrets and obtain world domination!
  6. 使用类似以下命令将模块打包:

    cd ./mitmproxycert ; zip -r ./../mitmproxycert.zip ./

    然后使用以下命令将其推送到你正在运行的 AVD:

    adb push ./../mitmproxycert.zip /storage/emulated/0/Download/.
  7. 然后转到你的 AVD,打开 Magisk,点击 Modules 并安装你的模块(你会在 Downloads 文件夹中找到它)。
  8. 重启你的 AVD。

API 级别 > 28 且使用 -writable-system 的说明

默认情况下,/system 分区以只读方式挂载。以下步骤描述了如何获得对 /system 分区的写入权限,以及如何复制第 2 章中创建的证书。

从 API 级别 29(Android 10)开始,似乎无法将“/”分区挂载为读写。Google 使用 OverlayFS 为此问题提供了解决方法。不幸的是,在撰写本文时(2021 年 4 月 11 日),此解决方法中的说明会导致你的模拟器陷入启动循环。Stackoverflow 上某个聪明人找到了一种仍然可以让 /system 目录可写的方法。

请记住:如果你想使用你的证书,你必须始终使用 -writable-system 选项启动模拟器。否则 Android 将加载一个“干净”的系统镜像。

已在运行 API 级别 29 和 30 的模拟器上测试。

说明

  1. 列出你的 AVD:

    emulator -list-avds

    (如果这返回空列表,请在 Android Studio AVD Manager 中创建一个新的 AVD)

  2. 启动所需的 AVD:

    emulator -avd <avd_name_here> -writable-system

    (添加 -show-kernel 标志以查看内核日志)

  3. 以 root 身份重启 adb:

    adb root
  4. 禁用安全启动验证:

    adb shell avbctl disable-verification
  5. 重启设备:

    adb reboot
  6. 以 root 身份重启 adb:

    adb root
  7. 执行分区重新挂载为读写:

    adb remount

    (如果 adb 告诉你需要重启,请再次重启 adb reboot 并再次运行 adb remount。)

  8. 推送你在第 2 步中重命名后的证书:

    adb push <path_to_certificate> /system/etc/security/cacerts
  9. 设置证书权限:

    adb shell chmod 644 /system/etc/security/cacerts/<name_of_pushed_certificate>
  10. 重启设备:

    adb reboot

API 级别 <= 28 且使用 -writable-system 的说明

已在运行 API 级别 26、27 和 28 的模拟器上测试。

请记住:如果你想使用你的证书,你必须始终使用 -writable-system 选项启动模拟器。否则 Android 将加载一个“干净”的系统镜像。

说明

  1. 列出你的 AVD:

    emulator -list-avds

    (如果这返回空列表,请在 Android Studio AVD Manager 中创建一个新的 AVD)

  2. 启动所需的 AVD:

    emulator -avd <avd_name_here> -writable-system

    (添加 -show-kernel 标志以查看内核日志)

  3. 以 root 身份重启 adb:

    adb root
  4. 执行分区重新挂载为读写:

    adb remount

    (如果 adb 告诉你需要重启,请再次重启 adb reboot 并再次运行 adb remount。)

  5. 推送你在第 2 步中重命名后的证书:

    adb push <path_to_certificate> /system/etc/security/cacerts
  6. 设置证书权限:

    adb shell chmod 644 /system/etc/security/cacerts/<name_of_pushed_certificate>
  7. 重启设备:

    adb reboot

测试你的证书是否从系统证书存储中加载

在你的 AVD 中,转到:

设置 → 安全 → 高级 → 加密与凭据 → 受信任的凭据

在列表中找到你的证书(默认名称为 mitmproxy)。

标签: 开发, Proxy, 抓包

评论已关闭