
1. 项目缘起当模拟器遇上抓包证书信任的“最后一公里”最近在折腾一个安卓应用的数据交互分析环境是Mumu模拟器工具是Charles。这本来是一个移动端开发或者安全测试里挺常规的组合但就在我以为一切就绪准备开始抓取HTTPS流量时那个经典的“证书不受信任”的提示框又弹了出来。相信用过Charles配合真机或模拟器抓HTTPS包的朋友对这个场景都不会陌生。本质上这就是一个中间人攻击MitM场景下的证书信任问题Charles作为代理需要向客户端这里是Mumu模拟器里的安卓系统出示一张它认可的证书才能解密HTTPS流量。这个过程听起来简单但在安卓7.0API 24之后系统对证书信任的要求变得更加严格。用户安装的证书即我们通过Charles导出的那张默认不再被系统级应用和部分应用信任它们只信任系统预置的证书。这就导致了一个尴尬的局面你在模拟器浏览器里访问chls.pro/ssl下载安装了Charles证书可能Chrome能正常抓包了但你的目标App却依然一片空白提示网络错误或证书无效。这个问题在各类安卓模拟器上包括Mumu、雷电、夜神等都普遍存在。网上的教程很多但往往只解决了“安装证书”这一步对于后续的“系统级信任”这个更关键的环节要么语焉不详要么给出的方法已经过时。特别是对于Mumu模拟器它的文件系统路径、ADB连接方式还有一些自己的特点照搬其他模拟器的命令很可能行不通。这次我就把从导出证书、推送到模拟器、安装为用户证书再到最终挂载为系统证书的完整链路结合我实际踩过的坑整理成这份“保姆级”指南。目标很明确不只是让你把证书装上去而是要让它真正生效捕获到所有应用的HTTPS流量。2. 核心原理为什么用户证书不顶用了系统证书的权限之谜要解决问题得先理解问题的根源。我们首先得搞清楚安卓系统里的证书分为哪几种以及Charles的中间人抓包究竟是如何工作的。2.1 证书的两种身份用户与系统在安卓的安全体系中证书权威CA证书被分为两大类用户证书由用户手动安装通常通过下载.crt或.pem文件在系统设置中导入。在安卓7.0之前所有应用默认都会信任用户安装的证书。它的存储路径通常在/data/misc/user/0/cacerts-added/不同系统版本路径略有差异。这类证书权限较低。系统证书在设备出厂时预置在系统分区/system/etc/security/cacerts/下的证书。这些证书拥有最高的信任级别系统所有组件和应用除非应用自己做了额外的证书锁定都会无条件信任它们。要添加证书到这里需要root权限或对系统分区有写权限。Charles以及Burp Suite、mitmproxy等在抓HTTPS包时会动态生成一张针对目标站点的证书。这张证书的签发者Issuer是Charles自己的根证书。因此客户端安卓系统必须信任Charles的根证书才会认可由它签发的所有站点证书。我们安装的正是Charles的这根“根证书”。2.2 安卓7.0的分水岭网络安全配置的改变安卓7.0引入了一项重要的安全变更应用默认不再信任用户安装的CA证书。这是通过应用的“网络安全配置”实现的。如果应用的目标API级别targetSdkVersion为24或更高且没有显式配置信任用户证书那么它就会忽略你装好的Charles用户证书导致抓包失败。解决方案通常有三种修改应用降低其targetSdkVersion或在其网络安全配置文件中添加信任用户证书的指令。这对于我们自己开发调试的应用可行但对于分析第三方应用则不现实。将Charles证书安装为系统证书这是最通用、一劳永逸的方法。一旦证书被放入/system/etc/security/cacerts/所有应用都会将其视为可信根证书无论其目标API级别是多少。使用已Root的模拟器或真机Root后可以直接修改系统分区为我们安装系统证书铺平道路。对于Mumu模拟器我们选择第二条路。幸运的是大多数安卓模拟器包括Mumu在启动时都提供了可写的系统分区或者我们可以通过ADB以root身份进行操作这比折腾一台真机要方便得多。2.3 证书格式的玄机PEM、DER与哈希命名系统证书目录cacerts下的文件不是简单的.crt或.pem文件。它们有特定的要求格式必须是DER编码的X.509证书文件通常以.crt或.der为扩展名。我们从Charles直接导出的.pem文件Base64编码的文本文件需要经过转换。文件名不能随意命名。文件名必须是证书主题Subject的哈希值旧版是MD5哈希新版是SHA-256哈希并以.0作为扩展名。例如9a5ba575.0。系统在启动时会读取这个目录根据文件名哈希来快速索引证书。所以我们的核心操作流程就清晰了获取Charles根证书 - 转换为DER格式 - 计算其哈希值并重命名 - 通过ADB推送到Mumu模拟器的系统证书目录。3. 环境准备与工具确认连接Mumu模拟器的ADB工欲善其事必先利其器。在开始操作前我们需要确保环境畅通。整个过程的核心工具是ADBAndroid Debug Bridge。3.1 确保Mumu模拟器已开启并连接ADB启动Mumu模拟器确保你的Mumu模拟器已经正常启动并进入桌面。建议使用性能相对稳定的版本避免使用过于陈旧的版本。查找Mumu的ADB端口Mumu模拟器有自己的ADB服务通常运行在127.0.0.1:7555这个端口上。这与Android Studio的默认ADB5037端口是独立的。你需要确认这个端口。可以在Mumu安装目录下例如D:\Program Files\Netease\MuMuPlayer-12.0\emulator\nemu\vmonitor\bin找到相关配置但最直接的方法是使用命令查看。连接ADB打开你的命令行终端CMD或PowerShell。首先连接到Mumu的ADB服务adb connect 127.0.0.1:7555如果看到connected to 127.0.0.1:7555的提示说明连接成功。然后获取shell环境并切换到root用户权限。这是后续操作的关键adb shell su执行su后模拟器屏幕上可能会弹出超级权限请求点击“允许”。在命令行中提示符通常会从$变为#这表示你已经拥有root权限。注意如果你电脑上安装了多个ADB版本例如Android Studio自带的和Mumu自带的可能会发生冲突出现类似adb server version (41) doesn‘t match this client (36)的错误。此时你需要统一ADB版本。一个简单的方法是将Mumu安装目录下的adb.exe通常在emulator\nemu\vmonitor\bin子目录下路径添加到系统环境变量PATH的最前面或者直接使用绝对路径来运行这个adb.exe。3.2 获取Charles根证书确保你的Charles正在运行。在Charles菜单栏点击Help - SSL Proxying - Save Charles Root Certificate...。将证书保存为一个文件例如charles-ssl-proxying-certificate.pem。记住这个文件的保存路径。至此我们的前置条件已经满足模拟器已root连接证书文件也已就位。接下来进入核心的转换和推送环节。4. 证书转换与系统部署从PEM到系统Cacerts这是整个流程中最需要细致操作的一步。我们将使用openssl这个强大的密码学工具来完成格式转换和哈希计算。4.1 安装或准备OpenSSL如果你的系统没有openssl命令需要先安装它。Windows从OpenSSL官网下载适合你系统的安装包例如Win64 OpenSSL v1.1.1w。安装时选择“将OpenSSL DLL复制到系统目录”或手动将其安装目录下的bin文件夹路径添加到系统PATH环境变量中。macOS通常自带OpenSSL但可能是LibreSSL。可以通过Homebrew安装brew install openssl。Linux使用包管理器安装如sudo apt install openssl。安装后在命令行输入openssl version验证是否可用。4.2 证书格式转换与哈希计算假设你的Charles根证书保存在C:\Users\YourName\Desktop\charles.pem。打开命令行切换到证书所在的目录。cd C:\Users\YourName\Desktop将PEM格式证书转换为DER格式openssl x509 -in charles.pem -outform DER -out charles.der这条命令解读x509是处理X.509证书的标准-in指定输入文件-outform DER指定输出格式为DER-out指定输出文件名。现在你得到了一个charles.der文件。计算DER证书的哈希值旧方法适用于大多数情况 安卓系统证书目录传统上使用MD5哈希值作为文件名虽然算法是MD5但这里只是取哈希值作为一个唯一标识名。openssl x509 -inform DER -in charles.der -subject_hash_old -noout执行后命令行会直接输出一个8位的十六进制字符串例如2f4a5b6c。这就是你的证书文件名不含.0扩展名。注意有些更新的系统可能需要SHA-256哈希。你可以用openssl x509 -inform DER -in charles.der -subject_hash -noout来计算SHA-256哈希输出是9位。但经过实测绝大多数安卓系统包括模拟器的cacerts目录仍兼容_oldMD5哈希命名的文件。为了兼容性建议使用_old哈希。如果后续不生效可以尝试用SHA-256哈希重命名文件再推送一次。重命名证书文件 将上一步得到的哈希值作为文件名。例如哈希值是2f4a5b6c则执行copy charles.der 2f4a5b6c.0Windows用copyLinux/macOS用cp。现在你得到了一个名为2f4a5b6c.0的系统证书文件。4.3 推送证书到Mumu模拟器系统目录现在回到之前已经建立了adb shell并拥有root权限的命令行窗口。首先将本地证书文件推送到模拟器的临时目录比如/data/local/tmp/。你需要另开一个命令行窗口不要关闭之前的adb shell窗口执行adb push C:\Users\YourName\Desktop\2f4a5b6c.0 /data/local/tmp/请将路径替换为你实际的文件路径。回到adb shell的root窗口执行以下命令# 1. 将系统分区重新挂载为可读写。这是关键一步 mount -o rw,remount /system # 如果上述命令报错可以尝试 mount -o rw,remount /system /system # 或者查看 /proc/mounts 找到/system的具体挂载点 # 2. 复制证书文件到系统证书目录 cp /data/local/tmp/2f4a5b6c.0 /system/etc/security/cacerts/ # 3. 修改证书文件的权限。系统证书需要特定的权限才能被读取。 chmod 644 /system/etc/security/cacerts/2f4a5b6c.0 # 4. 将系统分区重新挂载为只读恢复原状可选但建议操作 mount -o ro,remount /system重要提示mount -o rw,remount /system这一步是成败的关键。有些模拟器或系统版本可能需要不同的参数。如果失败可以尝试mount -o remount,rw /system或者先执行adb disable-verity如果支持的话。Mumu模拟器通常可以直接remount成功。验证证书是否安装成功ls -l /system/etc/security/cacerts/ | grep 2f4a5b6c你应该能看到类似-rw-r--r-- 1 root root ... 2f4a5b6c.0的输出权限是644。4.4 重启模拟器并验证证书被放入系统目录后需要重启安卓系统才能生效。最简单的方法是重启整个模拟器。在adb shell中执行reboot或者直接关闭Mumu模拟器再重新启动。模拟器重启后重新连接ADB (adb connect 127.0.0.1:7555)。验证证书是否已被系统识别方法一命令行进入adb shell执行cat /system/etc/security/cacerts/2f4a5b6c.0 | openssl x509 -inform DER -text -noout | grep Subject。如果能正确输出证书主题信息包含“Charles Proxy”等字样说明证书文件本身是有效的且已存在。方法二设置中查看在Mumu模拟器内打开设置 - 安全性与位置信息 - 加密与凭据 - 信任的凭据 - 系统。在长长的系统证书列表中你应该能找到以“Charles Proxy”或你自定义名称签发的证书。注意这里是“系统”页签而不是“用户”页签。找到它就大功告成了。5. Charles配置与抓包实战验证系统证书部署成功后Charles侧的配置就相对简单了但仍有几个关键点需要注意。5.1 配置Charles的SSL代理设置在Charles中确保Proxy - SSL Proxying Settings...已经启用。在“SSL Proxying”标签页添加你需要抓取的域名。为了方便可以添加一个通配符如*:*表示监听所有主机的所有443端口。但在生产环境或安全测试中建议只添加目标域名以减少干扰。确保Proxy - Proxy Settings...中的HTTP代理端口默认8888是开启的。5.2 配置Mumu模拟器的网络代理要让模拟器的流量经过Charles需要设置代理。在Mumu模拟器内长按“WLAN”网络通常是“WiredSSID”或类似名称选择“修改网络”。展开“高级选项”。代理选择“手动”。代理服务器主机名填写你电脑的IP地址不是127.0.0.1因为对于模拟器来说宿主机的回环地址不可达。在命令行输入ipconfig查看通常是192.168.x.x这样的局域网IP。代理服务器端口填写Charles的监听端口默认是8888。保存设置。5.3 首次连接的证书授权完成代理设置后在模拟器里首次打开浏览器访问任意HTTPS网站Charles会弹出连接请求。点击“Allow”允许。这一步是授权Charles代理该模拟器的连接。5.4 实战抓包验证现在进行最终测试。在模拟器中打开一个你确定会使用HTTPS的网络应用比如Chrome浏览器访问https://www.baidu.com。回到Charles你应该能在左侧的Structure视图里看到抓取到的网络请求。对于HTTPS请求如果之前配置正确你应该能看到明文的数据如图片、JSON响应等而不是乱码或unknown。最关键的一步找一个目标API级别24的App进行测试。在安装系统证书前这类App的HTTPS请求在Charles里通常是看不到内容或者直接失败的。现在你应该能成功解密其流量了。如果一切顺利恭喜你你已经成功打通了Mumu模拟器Charles抓取HTTPS流量的全链路。这个配置是持久化的只要你不重置模拟器的系统分区以后每次启动模拟器都可以直接使用Charles进行抓包。6. 疑难杂症与深度排坑指南在实际操作中你可能会遇到一些意外情况。下面是我在多次实践中总结的常见问题及其解决方案。6.1 证书已安装但抓包仍失败Unknown/乱码症状请求能抓到但内容是unknown或乱码无法解密。排查检查Charles的SSL代理设置确认目标域名是否在“SSL Proxying Settings”的列表中。可以尝试添加*:*通配符测试。检查证书是否真的被系统应用信任在模拟器“设置 - 安全 - 信任的凭据 - 系统”里确认Charles证书存在。有时即使文件在cacerts目录系统也可能因缓存等原因未加载。可以尝试再次重启模拟器。检查应用是否使用了证书锁定一些金融类、高安全级别的App会使用证书锁定只信任特定的证书即使你安装了系统证书也无法解密。这属于应用层的主动防御通常无法绕过。检查是否使用了HTTP/2或HTTP/3Charles对某些新协议的支持可能需要额外配置。尝试在Charles的Proxy - SSL Proxying Settings中勾选“Enable HTTP/2 proxying”。6.2 ADB连接失败或权限不足症状adb connect失败或执行su后无法获取#提示符。排查确认Mumu ADB端口确保Mumu模拟器已启动并尝试telnet 127.0.0.1 7555看端口是否开放。关闭冲突的ADB关闭Android Studio或其他可能启动ADB服务的程序然后重启Mumu模拟器。使用Mumu自带的ADB进入Mumu安装目录下的emulator\nemu\vmonitor\bin在此处打开命令行运行adb_server.exe connect 127.0.0.1:7555。检查模拟器Root设置某些Mumu版本需要在模拟器设置中手动开启“Root权限”。在Mumu侧边栏工具中找到“设置”检查是否有相关选项。6.3 系统分区挂载为可读写失败症状执行mount -o rw,remount /system时提示“Device or resource busy”或“Permission denied”。排查先进入su确保命令行提示符是#。尝试其他挂载点执行cat /proc/mounts | grep system查看/system具体挂载在哪个设备节点上如/dev/block/sda6然后尝试mount -o rw,remount /dev/block/sda6 /system。使用adb remount命令在宿主机的命令行非adb shell内执行adb remount。这个命令可能会更方便。但注意adb remount通常要求设备已解锁并具有root权限且模拟器内核支持。使用Magisk模块进阶如果模拟器安装了Magisk可以使用“Magisk挂载系统”相关的模块或功能来修改系统分区这比直接remount更安全。6.4 证书安装后系统“信任的凭据”中不显示症状文件已放入cacerts权限也是644但设置里找不到。排查等待或重启系统加载证书可能需要时间或者需要冷重启完全关闭模拟器再启动而不是热重启。检查证书哈希算法尝试使用SHA-256哈希重命名文件计算-subject_hash而非-subject_hash_old生成如abcdefghi.0的文件替换原来的文件并重启。检查证书格式确保最终的文件是DER格式。可以用file命令检查在Linux/macOS的宿主机上file 2f4a5b6c.0输出应包含“DER encoded”字样。检查其他证书目录极少数定制系统可能使用不同的证书路径如/system/etc/security/cacerts_google等。可以搜索一下。6.5 抓包时出现“Client SSL handshake failed”错误症状Charles界面显示该错误连接未能建立。排查时间不同步Charles证书有有效期如果模拟器或宿主机的系统时间不正确偏差太大会导致SSL握手失败。请同步时间。证书不匹配确保模拟器里安装的Charles根证书与当前正在运行的Charles实例使用的是同一张。如果你重装过Charles它会生成新的根证书需要重新导出并安装到模拟器。清除应用数据有些App会缓存证书信息。尝试在模拟器设置中清除目标App的数据和缓存然后重试。这个过程虽然步骤不少但每一步都有其明确的目的。一旦你成功完成一次就会对整个安卓系统的证书信任机制有更深的理解。以后无论换用雷电模拟器、真机还是遇到其他类似工具如Burp Suite解决问题的思路都是相通的获取根证书 - 转换为系统格式 - 推送到系统证书目录。掌握了这个核心你就掌握了在安卓高版本系统上进行HTTPS中间人分析的关键钥匙。