Android 12 HTTPS抓包实战:绕过系统证书限制,用Charles解密流量

📅 2026/7/17 1:46:22
Android 12 HTTPS抓包实战:绕过系统证书限制,用Charles解密流量
1. 项目概述为什么在Android 12上抓HTTPS包变得如此棘手如果你是一名移动端开发、测试或者安全研究员那么通过抓包工具比如Charles来调试网络请求、分析API接口或者排查线上问题绝对是日常工作中的高频操作。在Android 11及之前的版本里这套流程已经相当成熟在手机上安装并信任Charles的根证书配置好代理基本上就能看到明文的HTTPS流量了。但自从Android 12API级别31开始很多开发者发现这套沿用多年的“标准操作”突然失灵了——即使你已经在手机的“用户证书”里安装了Charles证书App依然提示网络错误或者你只能看到一堆Tunnel to ...:443的加密隧道具体请求内容一概不见。这背后的核心原因是Android系统在安全策略上的一次重大升级。从Android 7.0开始Google就引入了“网络安全配置”机制鼓励App只信任系统预置的证书。到了Android 9.0默认行为变成了App不再信任用户安装的证书。而Android 12则彻底收紧了这一策略对于targetSdkVersion大于等于31的App系统会默认忽略用户安装的证书只信任系统证书存储区里的根证书。这意味着像Charles、Fiddler这类抓包工具提供的、需要用户手动安装的证书对于大多数新App来说已经失效了。所以“搞定Android 12模拟器抓HTTPS包”这个标题直指的就是这个让无数开发者头疼的“证书信任”壁垒。我们的目标不是去破解或攻击某个App而是在一个受控的开发和测试环境模拟器中重建我们作为开发者应有的网络流量可见性。本文将围绕“使用Charles”这个经典工具手把手带你走通从环境准备、证书安装、系统信任到最终成功抓包的完整流程并深入解析每一步背后的原理和可能遇到的坑。2. 环境准备与核心工具选型工欲善其事必先利其器。在开始具体操作前我们需要搭建一个稳定、可控的实验环境并理解每个工具的作用。2.1 模拟器的选择与考量首先我们强烈建议使用Android Studio自带的虚拟设备AVD而不是第三方模拟器如雷电、MuMu。原因有三点原生兼容性最佳AVD是Google官方维护的与Android SDK工具链如adb的集成度最高在涉及系统分区修改、证书推送等底层操作时出现奇怪问题的概率最低。系统镜像纯净我们可以选择最接近原生Android的系统镜像避免第三方模拟器预装软件或定制系统带来的干扰。快照Snapshot功能在进行系统级修改前创建一个快照。如果操作失误导致系统异常可以瞬间回滚到干净状态极大提升容错率。创建AVD的关键参数建议系统镜像选择带有“Google Play”或“Google APIs”标签的镜像。这确保了系统包含完整的Google服务框架更接近真实设备环境。对于测试可以选择Android 12API 31或更高版本。硬件配置RAM建议至少4GB存储空间不少于4GB。处理器选择x86_64以获得最佳性能。启动选项首次启动后务必进入系统设置完成初始向导如连接Wi-Fi、登录Google账户等确保系统处于完全就绪状态。然后立即创建一个系统快照命名为“Clean State”。2.2 抓包工具为什么是Charles市面上抓包工具很多Burp Suite、Fiddler、mitmproxy各有所长。这里选择Charles主要基于其在移动开发领域的普适性和易用性直观的GUI界面对于查看、筛选、重放请求非常友好适合调试和演示。强大的SSL代理功能其“SSL Proxying Settings”可以轻松配置需要解密的域名。成熟的移动端支持关于证书安装、代理设置的文档和社区资源非常丰富。你需要从Charles官网下载并安装适用于你操作系统Windows/macOS的版本。Charles是付费软件但有30天的免费试用期功能完整足够完成本次学习。2.3 辅助工具adb与opensslAndroid Debug Bridge这是与模拟器或真机通信的瑞士军刀。确保你的Android SDK Platform-Tools已安装并且adb命令可以在终端中直接调用。我们将用它来执行文件推送、Shell命令和重启操作。OpenSSL一个强大的密码学工具包。在macOS和Linux上通常已预装Windows用户可以通过Git Bash、WSL或单独安装OpenSSL for Windows来获得。我们将用它来转换Charles证书的格式这是将证书安装到系统区的关键一步。环境就绪后我们整体的解决思路可以概括为绕过App对用户证书的不信任将Charles的根证书直接安装到Android系统信任的证书存储区中。这需要对模拟器的系统分区进行临时修改。3. 核心原理Android的证书信任体系与我们的突破点要理解我们怎么做必须先明白Android是怎么管理证书的。3.1 证书存储区的“双轨制”Android系统将证书分为两个主要的存储区用户证书存储区路径通常对应/data/misc/user/0/cacerts加密后。用户通过浏览器下载安装的证书、或者通过系统设置“从存储设备安装”的证书都会放在这里。在Android 8.0之前所有App默认都信任这里的证书。系统证书存储区路径是/system/etc/security/cacerts/。这里存放着操作系统和手机制造商预置的全球公认的根证书如DigiCert, GlobalSign等。系统级别的信任根源于此。Android 12的安全策略简单说就是targetSdkVersion 31的App其默认的网络安全配置Network Security Config只信任系统证书存储区而不再自动信任用户证书存储区。3.2 我们的策略向系统区“注入”证书既然App只信系统区的证书那最直接的思路就是把Charles的根证书放到系统区去。但是/system分区在正常运行的Android系统中是只读的这是为了保证系统完整性。因此我们的操作流程本质上是获取Charles的根证书文件。将其转换为Android系统区要求的特定格式PEM格式并以证书哈希值重命名。让模拟器的/system分区临时可写通过重新挂载为读写模式。将转换后的证书文件推送到/system/etc/security/cacerts/目录。恢复/system分区的只读属性并重启模拟器使证书生效。这个过程相当于给系统打了一个“临时补丁”。在模拟器环境中这是完全可行且安全的因为我们可以随时通过快照还原。绝对不要在非你拥有的生产设备或他人设备上进行此操作。4. 完整实操流程一步步将Charles证书装进系统下面我们进入具体的操作环节。请严格按照步骤进行并注意观察每一步的输出。4.1 第一步启动环境并配置Charles代理启动Charles打开Charles首次运行会请求授予网络代理权限请允许。它会默认监听8888端口。获取本机IP地址在Charles的菜单栏点击Help - Local IP Address可以查看到你电脑在当前局域网内的IP地址例如192.168.1.100。记下这个地址。启动模拟器通过Android Studio的AVD Manager启动你之前创建好的Android 12模拟器。确保模拟器网络畅通可以打开浏览器访问网页测试。配置模拟器代理进入模拟器的设置 - 网络和互联网 - 互联网。长按你已连接的Wi-Fi网络通常是AndroidWifi选择“修改网络”。展开“高级选项”将代理设置为手动。代理服务器主机名填写你刚才记下的电脑IP如192.168.1.100。代理服务器端口填写8888。保存设置。此时模拟器的所有HTTP流量应该已经经过Charles。你可以在Charles里看到大量的HTTP请求。但HTTPS请求仍然是加密的。4.2 第二步导出并准备Charles根证书导出证书在Charles中点击Help - SSL Proxying - Save Charles Root Certificate...。选择保存为PEM格式文件命名为charles_root.pem保存到一个你熟悉的目录比如桌面。转换证书格式与重命名这是最关键的一步。Android系统区的证书要求是PEM格式且文件名必须是证书主题名的哈希值以.0结尾。我们使用OpenSSL命令来完成打开终端或命令提示符/PowerShell进入到保存charles_root.pem的目录。执行以下命令openssl x509 -inform PEM -subject_hash_old -in charles_root.pem | head -1这个命令会输出一个8位的十六进制字符串例如a0b1c2d3。这就是你的Charles证书的哈希值。接下来将证书复制一份并以这个哈希值命名cp charles_root.pem a0b1c2d3.0请将a0b1c2d3替换为你实际得到的哈希值验证文件你可以用文本编辑器打开a0b1c2d3.0文件内容应该以-----BEGIN CERTIFICATE-----开头以-----END CERTIFICATE-----结尾并且第一行就是哈希值。这是系统区证书的标准格式。注意subject_hash_old参数是为了兼容OpenSSL 1.0.x的哈希算法。如果你使用较新的OpenSSL 3.x并且上述命令不生效或哈希值不对可以尝试使用openssl x509 -inform PEM -subject_hash -in charles_root.pem。但根据经验在Android环境下使用-subject_hash_old的成功率更高。4.3 第三步将证书推送到模拟器系统分区现在我们需要把a0b1c2d3.0这个文件放到模拟器的系统证书目录。由于系统分区只读我们需要先获取root权限并重新挂载。检查adb连接在终端输入adb devices确保你的模拟器出现在设备列表中状态为device。获取root权限大多数Android模拟器的系统镜像是自带root权限的。我们需要以root身份执行后续操作adb root执行后应显示restarting adbd as root。重新挂载系统分区为可读写adb remount这个命令尝试以读写方式重新挂载/system分区。成功后通常没有输出或提示remount succeeded。如果adb remount失败可以尝试更明确的命令adb shell mount -o rw,remount /system或者adb shell mount -o rw,remount /推送证书文件adb push a0b1c2d3.0 /system/etc/security/cacerts/修改文件权限系统证书需要正确的权限才能被识别。adb shell chmod 644 /system/etc/security/cacerts/a0b1c2d3.0644的权限表示所有者可读写组用户和其他用户只读。恢复系统分区只读并重启可选但推荐adb shell mount -o ro,remount /system adb reboot等待模拟器重启完成。4.4 第四步在Charles中配置SSL代理模拟器重启后Charles证书理论上已被系统信任。但我们还需要告诉Charles对哪些域名的HTTPS流量进行解密。在Charles中启用SSL代理点击Proxy - SSL Proxying Settings...。添加SSL代理位置在SSL Proxying标签页点击Add。Host可以填写*表示拦截所有主机。但出于性能和安全考虑建议只添加你需要调试的域名例如*.yourdomain.com。Port填写443。信任Charles根证书在电脑上为了让Charles能正常解密你的操作系统也需要信任Charles证书。点击Help - SSL Proxying - Install Charles Root Certificate将其安装到你的系统钥匙串或证书存储中并设置为“始终信任”。4.5 第五步验证抓包成功在模拟器中打开一个浏览器访问https://www.google.com或任何其他HTTPS网站。回到Charles你应该能在左侧的Structure视图中看到清晰的www.google.com主机名展开后能看到具体的GET或POST请求并且Contents标签页里可以查看请求和响应的明文内容如Headers, JSON数据等而不是之前的Tunnel to。打开你正在开发的targetSdkVersion 31的App触发网络请求。此时这些HTTPS请求也应该能够被Charles成功解密和捕获。至此你已经成功绕过了Android 12的系统证书限制在模拟器上建立了完整的HTTPS抓包环境。5. 疑难杂症与深度排查指南实际操作中很少能一帆风顺。下面我汇总了可能遇到的各种问题及其解决方案。5.1 证书已安装但抓包仍失败Tunnel to...这是最常见的问题。请按以下清单逐一排查问题现象可能原因解决方案仍然看到大量Tunnel to ...:4431. Charles未配置SSL代理域名。2. 系统证书未生效。1. 检查Charles的SSL Proxying Settings确保添加了目标域名或*:443。2. 在模拟器设置 - 安全 - 加密与凭据 - 信任的凭据 - 系统中滚动查找是否有一个以你命名的哈希值如Charles Proxy CA...的证书。如果没有说明证书推送失败。特定App如Chrome、银行类App仍无法抓包1. App使用了证书锁定。2. App的网络安全配置显式禁止用户证书。1. 证书锁定是更高级的安全措施无法通过此方法绕过。需要反编译并修改App仅限测试环境。2. 对于自己开发的App可以修改其network_security_config.xml文件添加trust-anchors包含用户证书。请求失败出现SSL handshake failed等错误1. 系统时间不正确。2. 证书格式或哈希值错误。1. 检查模拟器和电脑的系统时间、时区是否一致且准确。2. 重新执行证书转换和推送步骤确认哈希值计算和文件权限无误。可以adb shell进入/system/etc/security/cacerts/目录用ls -l查看证书权限是否为-rw-r--r--。5.2 adb remount 失败怎么办如果adb remount命令失败提示remount failed或Read-only file system可以尝试以下方法启动模拟器时加入-writable-system参数关闭当前模拟器通过命令行启动emulator -avd 你的AVD名称 -writable-system其中你的AVD名称是你在AVD Manager中看到的名称。启动后再执行adb root和adb remount。使用更底层的mount命令如前文所述尝试adb shell mount -o rw,remount /system。检查是否使用了Google Play系统镜像部分Google Play镜像可能对系统分区保护更严格。可以尝试使用不带Google Play的“Google APIs”镜像或“Android Open Source Project”镜像重新创建AVD。5.3 证书哈希值冲突或无效极少数情况下计算出的哈希值可能与系统已有证书冲突或者证书本身不被Android识别。冲突如果推送证书时提示文件已存在可以在哈希值后加.1例如a0b1c2d3.1。系统会读取所有.0,.1,.2...的文件。无效确保你导出的是Charles的根证书而不是某个会话的临时证书。用openssl x509 -in a0b1c2d3.0 -text -noout命令查看证书详情确认颁发者是Charles Proxy CA。5.4 关于Android 13及更高版本的注意事项从Android 13开始系统对/system分区的保护可能进一步加强。上述方法在部分Android 13/14的模拟器镜像上可能仍然有效但如果遇到问题可以考虑以下备选方案使用Magisk模块如果模拟器或真机已安装Magisk可以寻找“Move Certificates”或“MagiskTrustUserCerts”这类模块它们能自动将用户证书提升为系统证书。修改App的调试构建变体对于自己开发的App最规范的做法是在build.gradle中为debug构建类型配置不同的网络安全配置使其信任用户证书。这不会影响发布版本的安全性。android { buildTypes { debug { buildConfigField boolean, ALLOW_USER_CERTS, true // 或者在src/debug/res/xml/下放置一个允许用户证书的network_security_config.xml } release { // ... } } }6. 进阶技巧与最佳实践成功抓包只是第一步如何高效地利用这个环境更重要。6.1 Charles的过滤与聚焦技巧当所有流量都经过Charles时信息会非常嘈杂。善用过滤功能Focus主机在左侧Structure视图右键点击你关心的域名如api.example.com选择Focus。这样其他主机的流量会被折叠到一个“Other Hosts”节点中界面瞬间清爽。Sequence视图切换到Sequence标签页这里按时间顺序排列所有请求更适合观察交互流程。断点与修改在请求或响应上右键选择Breakpoints可以中断特定请求在发送前修改请求参数或在返回前修改响应数据这对调试异常逻辑非常有用。6.2 模拟慢速网络与异常状态Charles的Proxy - Throttle Settings功能可以模拟不同的网络环境2G/3G/4G甚至自定义带宽和延迟。这对于测试App在网络不佳情况下的表现和容错能力至关重要。你还可以用Tools - Black List或White List来模拟特定API接口的阻塞或超时。6.3 长期维护与快照策略由于我们修改了系统分区这个修改在模拟器生命周期内是持久的。但如果你删除了这个AVD或者创建了新的就需要重做一遍。因此强烈建议在完成证书安装并验证成功后立即在AVD Manager中为这个模拟器再创建一个新的快照例如命名为“With Charles System Cert”。以后每次需要抓包调试时就从“With Charles System Cert”这个快照启动省去重复配置的麻烦。6.4 安全提醒与边界最后必须再次强调安全边界此方法仅用于合法授权的开发、测试和安全研究。严禁用于窥探他人隐私、干扰他人服务或进行任何非法活动。仅在你自己完全控制的模拟器或测试设备上进行。不要在个人日常使用的手机或公司未授权的设备上操作。意识到抓包环境的风险在这个环境下你的所有网络流量包括可能输入的密码对Charles都是明文可见。调试结束后记得关闭模拟器的代理设置或者关闭Charles。对于特别敏感的操作最好在纯净的网络环境中进行。整个流程走下来你会发现核心难点并不在于操作步骤的复杂而在于对Android系统安全机制变化的理解和适应。Android 12收紧证书信任策略本质上是移动生态安全进步的体现。而我们作为开发者掌握在测试环境下“合法开锁”的能力是为了构建更健壮、更安全的应用程序。这套方法是你工具箱里的一把利器请务必在正确的场景下使用它。