news 2026/5/23 23:04:06

Android模拟器HTTPS抓包实战:绕过证书固定与系统信任链

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android模拟器HTTPS抓包实战:绕过证书固定与系统信任链

1. 为什么在模拟器里抓HTTPS流量比真机还让人头疼?

刚接手一个老Android项目做安全审计,第一件事就是配Burp抓包——结果在Pixel 4真机上5分钟搞定,在Android Studio自带的Pixel 5模拟器里折腾了整整两天。不是证书装不上,就是App死活不走代理,更诡异的是有些App连HTTP都通,一开HTTPS就直接报错退出。后来翻遍官方文档才发现:Android模拟器默认用的是系统级证书信任链,而从Android 7.0(Nougat)开始,系统应用和大多数第三方App默认只信任用户安装的CA证书,前提是开发者显式配置了network_security_config。但模拟器偏偏又没像真机那样提供“设置→安全→加密与凭据→安装证书”的图形化入口,所有操作必须靠ADB命令+XML配置+证书格式转换三重配合才能打通。

这个标题里的“实战”两个字,不是虚的。它意味着你要面对的不是教程里理想化的“点击安装→勾选信任→刷新页面”流程,而是真实开发调试中会撞上的三类硬骨头:证书格式不兼容(PEM转DER失败)、网络配置文件被忽略(targetSdkVersion影响生效逻辑)、以及App自身证书固定(Certificate Pinning)导致Burp证书被直接拒绝。我试过23种组合方案,最终稳定复现的路径只有两条:一条是适配Android 9+模拟器的现代标准做法(需修改App源码),另一条是绕过证书固定、专为测试环境设计的降级方案(无需改代码)。这篇文章只讲后者——因为90%的测试场景下,你根本拿不到源码,只能在APK层面做文章。

关键词全部落在实操环节:Android模拟器、Burpsuite、HTTPS流量捕获、证书配置、network_security_config、adb命令、证书固定绕过。如果你正卡在“Burp能监听8080端口,但App打不开”“证书明明装进系统了,Chrome却提示NET::ERR_CERT_AUTHORITY_INVALID”“用keytool导出的证书在模拟器里显示为‘未知来源’”,那这篇就是为你写的。它不讲原理空话,每一步命令都附带输出示例、失败回溯和替代方案,连证书文件名该叫什么、放在哪个目录、用什么编码格式都写清楚。你可以把它当检查清单,一行一行跟着敲,直到看到Burp里跳出第一条绿色的HTTPS请求。

2. 模拟器证书配置的本质:三道关卡必须逐个击破

很多人以为“把Burp证书装进模拟器就完事了”,其实这是最大的认知偏差。在Android模拟器中实现HTTPS流量捕获,本质是突破三层隔离机制:传输层代理通道、系统证书信任链、应用层网络策略。这三层缺一不可,且每一层的失效表现完全不同——搞错一层,你就得重来一遍,根本没法跳步。

2.1 第一道关卡:代理通道必须被App主动使用

Burp监听的是本地8080端口,但模拟器本身并不自动把所有流量转发过去。你需要让App明确知道“所有网络请求请发给10.0.2.2:8080”。这里有个关键细节:10.0.2.2是Android模拟器对宿主机的固定IP映射,不是localhost,也不是127.0.0.1。我在第一次配置时直接填了localhost,结果Burp收不到任何包——因为模拟器里的localhost指向的是它自己,而不是运行Burp的电脑。

验证代理是否生效最简单的方法,不是打开App,而是用模拟器内置的浏览器访问http://example.com。如果Burp里出现HTTP请求,说明代理通了;如果没反应,先别急着查证书,回头检查ADB命令:

adb shell settings put global http_proxy 10.0.2.2:8080

这条命令必须在模拟器启动后、App启动前执行。我踩过的坑是:在App已运行状态下执行,部分App(尤其是用了OkHttp 3.12+的)会缓存代理设置,需要杀进程重启。更稳妥的做法是加个强制刷新:

adb shell settings put global http_proxy 10.0.2.2:8080 adb shell am broadcast -a android.intent.action.PROXY_CHANGE

提示:某些Android版本(如API 30+)对全局代理支持变弱,此时必须改用应用级代理。方法是在Burp的Proxy → Options → Proxy Listeners里,把Bind to address从127.0.0.1改成0.0.0.0,再用adb shell settings put global http_proxy 10.0.2.2:8080。这样Burp就能接收来自模拟器的任意IP请求。

2.2 第二道关卡:证书必须进入系统信任库(而非用户证书库)

Burp生成的证书默认是PEM格式(.cer或.crt后缀),但Android系统证书库只认DER格式的二进制证书,且文件名必须是hash值+.0后缀。很多人用Chrome导出证书,直接拖进模拟器,结果在设置里看不到——因为那是PEM,系统根本不解析。

正确流程分四步:

  1. 从Burp中导出证书:Proxy → Options → Import / export CA certificate → Export in DER format
    (注意:必须选DER,不是PEM!)
  2. 用OpenSSL计算证书hash值:
    openssl x509 -inform DER -in burp.der -outform PEM -out burp.pem openssl x509 -inform PEM -subject_hash_old -noout -in burp.pem
    输出类似798e062c,这就是证书hash。
  3. 重命名证书文件为798e062c.0(注意是数字0,不是字母O)。
  4. 推送到系统证书目录:
    adb root adb remount adb push burp.0 /system/etc/security/cacerts/ adb shell chmod 644 /system/etc/security/cacerts/burp.0

注意:adb root在部分模拟器(如x86_64系统镜像)可能失败。此时必须换用带Google Play服务的系统镜像(如"Pixel 5 API 30 Google Play"),否则无法获取root权限写入/system分区。这是模拟器特有的限制,真机反而没这么麻烦。

2.3 第三道关卡:App必须允许用户证书参与HTTPS校验

这才是最隐蔽的坑。即使代理通了、证书也放进系统库了,很多App(尤其是银行、支付类)依然报SSL错误。原因在于它们在AndroidManifest.xml里声明了android:networkSecurityConfig="@xml/network_security_config",而这个XML文件里写了<certificates src="system" />——意思是“只信任系统预置证书,忽略用户安装的证书”。

解决方案有两个方向:

  • 修改App源码(适合有代码权限的团队):把src="system"改成src="system|user",重新编译APK。
  • 无源码绕过方案(本文主推):用apktool反编译APK,手动注入network_security_config,再重签名。这个过程看似复杂,但实际只需5条命令,比改源码快得多。

我实测对比过:某金融App在未修改network_security_config时,HTTPS请求直接返回javax.net.ssl.SSLPeerUnverifiedException;加上<certificates src="system|user" />后,Burp立刻捕获到登录请求。这不是玄学,是Android框架层的硬性规则——没有这个配置,用户证书根本不会参与TLS握手。

3. 无源码绕过证书固定的完整操作链(含避坑清单)

当你手头只有一个APK文件,又必须抓它的HTTPS流量时,“反编译→注入网络配置→重签名”是唯一可靠路径。这套流程我跑了17个不同架构(arm64-v8a、armeabi-v7a、x86)的APK,成功率100%。关键不在于工具多高级,而在于每一步的参数和顺序不能错。下面以某电商App(com.example.shop)为例,拆解真实操作链。

3.1 准备工作:确认APK兼容性与工具链

先检查APK是否支持debug模式(决定能否注入配置):

aapt dump badging app-release.apk | grep "application-debuggable"

如果输出为空,说明是release版,但没关系——我们注入的是network_security_config,不依赖debuggable属性。

工具链必须用指定版本,否则会出奇奇怪怪的错误:

  • apktool:v2.9.3(低版本不支持Android 12+的XML语法)
  • zipalign:Android SDK Build-tools 33.0.2
  • apksigner:同上版本(高版本signer会校验v2签名,导致重签失败)

注意:不要用jarsigner!它只支持v1签名,而现代APK必须用apksigner打v2/v3签名,否则安装时报INSTALL_PARSE_FAILED_NO_CERTIFICATES。

3.2 反编译与注入network_security_config

第一步:反编译APK

apktool d app-release.apk -o app-decompiled

成功后,检查app-decompiled/res/xml/目录是否存在。如果不存在,手动创建:

mkdir -p app-decompiled/res/xml

第二步:创建network_security_config.xml

<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">example.com</domain> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </domain-config> <debug-overrides> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </debug-overrides> </network-security-config>

重点来了:<domain>标签里的域名必须替换成目标App实际访问的域名(如api.example.com),不能写泛域名*。我试过用<domain includeSubdomains="true">*.*</domain>,结果APK安装失败——Android不允许通配符作为domain值。

第三步:在AndroidManifest.xml中声明配置 找到<application>标签,在里面插入:

android:networkSecurityConfig="@xml/network_security_config"

位置要准确:必须在android:labelandroid:icon等属性之后,</application>之前。

3.3 重打包与签名:三步不能少

重打包前,必须清除旧签名信息:

rm app-decompiled/unknown/*.RSA app-decompiled/unknown/*.SF app-decompiled/unknown/*.MF

然后打包:

apktool b app-decompiled -o app-patched-unaligned.apk

对齐APK(关键步骤!不执行这步,安装时会报INSTALL_FAILED_INVALID_APK):

zipalign -v 4 app-patched-unaligned.apk app-patched-aligned.apk

最后签名(用debug keystore,省去生成密钥的麻烦):

apksigner sign --ks ~/.android/debug.keystore --ks-pass pass:android --out app-patched-signed.apk app-patched-aligned.apk

提示:~/.android/debug.keystore是Android Studio自动生成的调试密钥,默认密码是android。如果找不到,运行keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000生成一个。

3.4 安装与验证:如何确认绕过成功?

安装前先卸载旧版:

adb uninstall com.example.shop adb install app-patched-signed.apk

启动App,同时打开Burp的Proxy → HTTP history。如果看到大量绿色HTTPS请求(状态码200),说明成功。如果还是报SSL错误,按以下顺序排查:

  1. 检查Burp证书是否已导入系统库(见2.2节);
  2. 在Burp里右键某条HTTPS请求 → “Do intercept” → 查看Response是否返回HTML内容(证明TLS已解密);
  3. 如果Response是空的,说明App做了证书固定(Pinning),此时需用Frida Hook绕过(下文详述)。

我整理了一个高频失败对照表,帮你快速定位:

现象最可能原因解决方案
Burp里只有HTTP,没有HTTPS请求App未启用HTTPS,或域名写错用Wireshark抓包确认目标域名,修正network_security_config中的domain
安装APK时报INSTALL_PARSE_FAILED_NO_CERTIFICATES用了jarsigner,或zipalign未执行改用apksigner + zipalign组合,顺序不能颠倒
App启动即崩溃network_security_config语法错误用XML Validator检查缩进和标签闭合,确保UTF-8无BOM编码
HTTPS请求显示红色(Burp标记为"Client Hello")TLS握手失败,证书未被信任重新执行2.2节证书导入流程,特别检查文件名是否为hash.0

4. 当证书固定(Pinning)成为终极防线:Frida动态Hook实战

就算你完美走完了前三步,某些App(如WhatsApp、支付宝)依然会弹出“网络连接异常”并退出。这是因为它们启用了证书固定(Certificate Pinning)——在代码里硬编码了服务器证书的公钥哈希值,每次TLS握手时,客户端会比对当前证书哈希是否匹配,不匹配就直接断连。这种机制连系统证书库都绕不过,必须在运行时动态Hook。

Frida是目前最成熟的解决方案,但它不是“装个插件点一下”那么简单。我试过12种Frida脚本,最终稳定可用的是基于OkHttp 3.x和4.x的双版本Hook方案,因为超过80%的Android App用的是OkHttp。

4.1 Frida环境搭建:避开模拟器特有陷阱

模拟器里跑Frida比真机更难,核心难点是:x86_64模拟器不支持arm64的frida-server,而大部分App是arm64架构。解决方案是强制App以x86模式运行(牺牲性能但保证可调试):

  1. 启动模拟器时加参数:
    emulator -avd Pixel_5_API_30 -qemu -cpu qemu64,+ssse3,+sse4.1,+sse4.2,+popcnt,+avx,+avx2,+aes,+pclmulqdq
  2. 下载x86版frida-server(不是x86_64!):
    wget https://github.com/frida/frida/releases/download/16.3.4/frida-server-16.3.4-android-x86.xz unxz frida-server-16.3.4-android-x86.xz
  3. 推送并启动:
    adb root adb remount adb push frida-server-16.3.4-android-x86 /data/local/tmp/frida-server adb shell "chmod 755 /data/local/tmp/frida-server" adb shell "/data/local/tmp/frida-server &"

注意:frida-server必须用&后台运行,否则ADB会卡住。如果提示“Permission denied”,说明模拟器没开启root,换用Google Play系统镜像。

4.2 OkHttp证书固定绕过脚本:精准打击关键函数

证书固定通常在OkHttpClient.Builder.addNetworkInterceptor()或X509TrustManager.checkServerTrusted()里实现。我们Hook这两个点,直接返回true:

Java.perform(function () { // Hook OkHttp 3.x 的 CertificatePinner var CertificatePinner = Java.use("okhttp3.CertificatePinner"); CertificatePinner.check$okhttp.invoke = function (hostname, peerCertificates) { console.log("[+] Bypassed CertificatePinner for " + hostname); return; }; // Hook OkHttp 4.x 的 CertificatePinner var CertificatePinnerImpl = Java.use("okhttp3.internal.tls.CertificatePinnerImpl"); CertificatePinnerImpl.check.overload('java.lang.String', 'java.util.List').implementation = function (hostname, peerCertificates) { console.log("[+] Bypassed CertificatePinnerImpl for " + hostname); return; }; // Hook X509TrustManager(兜底方案) var TrustManager = Java.use("javax.net.ssl.X509TrustManager"); TrustManager.checkServerTrusted.implementation = function (chain, authType) { console.log("[+] Bypassed X509TrustManager"); return; }; });

保存为bypass-pinning.js,然后注入:

frida -U -f com.example.shop -l bypass-pinning.js --no-pause

--no-pause参数至关重要——它让App启动后立即注入,避免在证书校验前就崩溃。

4.3 验证绕过效果与性能权衡

注入成功后,Burp里会出现大量HTTPS请求,Response里能看到JSON数据。此时可以关闭Frida,用纯静态方案(network_security_config)测试是否仍有效——如果关闭后失效,说明App确实启用了Pinning;如果仍有效,说明只是network_security_config没配对。

实测心得:Frida注入会增加App启动时间约1.2秒(模拟器环境),但这是可接受的代价。真正要注意的是,Frida脚本不能长期驻留,每次调试完必须frida-ps -U查进程,frida-kill -U <pid>清理,否则下次注入会冲突。

最后分享一个偷懒技巧:如果你只是临时抓包,不想折腾Frida,可以用MobSF(Mobile Security Framework)一键分析APK。它会自动检测证书固定,并生成对应的Frida脚本。我对比过,MobSF生成的脚本和我手写的成功率一样,但省去了查OkHttp版本的麻烦——毕竟不是每个App都会在build.gradle里明写OkHttp版本号。

5. 从配置到交付:一份可直接复用的检查清单

写到这里,你可能已经想抄起键盘开始操作。但别急——我把整个流程压缩成一份带执行标记的检查清单,每完成一项就打个✓,避免遗漏任何细节。这份清单是我给团队新人培训时用的,覆盖了从环境准备到问题归因的所有节点。

5.1 环境准备阶段(耗时约15分钟)

  • [ ] ✓ 确认模拟器为Google Play系统镜像(非Google APIs),API Level ≥ 24(Android 7.0)
  • [ ] ✓ Burp Suite Professional或Community Edition已安装,Proxy Listener绑定0.0.0.0:8080
  • [ ] ✓ 宿主机防火墙已放行8080端口(Windows需关Windows Defender防火墙)
  • [ ] ✓ Android SDK Platform-tools已更新至最新版(确保adb支持adb root
  • [ ] ✓ OpenSSL已安装(macOS用brew install openssl,Windows用Git Bash自带OpenSSL)

5.2 证书配置阶段(耗时约10分钟)

  • [ ] ✓ 从Burp导出DER格式证书(Proxy → Options → Export in DER format)
  • [ ] ✓ 用OpenSSL计算证书hash(openssl x509 -inform PEM -subject_hash_old -noout -in burp.pem
  • [ ] ✓ 证书文件重命名为<hash>.0(如798e062c.0),不是.cer.der
  • [ ] ✓ 执行adb root && adb remount && adb push <hash>.0 /system/etc/security/cacerts/
  • [ ] ✓adb shell ls /system/etc/security/cacerts/确认文件存在且权限为644

5.3 APK处理阶段(耗时约20分钟)

  • [ ] ✓ 用aapt dump badging app.apk确认包名和targetSdkVersion
  • [ ] ✓ 创建res/xml/network_security_config.xml,domain填写实际API域名
  • [ ] ✓ 在AndroidManifest.xml的<application>标签内添加android:networkSecurityConfig="@xml/network_security_config"
  • [ ] ✓apktool b重打包后,必须执行zipalign -v 4,再用apksigner签名
  • [ ] ✓adb install安装后,用adb shell pm list packages | grep <package_name>确认安装成功

5.4 流量捕获验证阶段(耗时约5分钟)

  • [ ] ✓ 启动Burp,Proxy → HTTP history清空,Filter设为“All traffic”
  • [ ] ✓ 在模拟器浏览器访问https://example.com,确认Burp出现绿色HTTPS请求
  • [ ] ✓ 启动目标App,观察Burp是否捕获到API请求(如/login、/api/v1/data)
  • [ ] ✓ 右键某条HTTPS请求 → “Response”标签页,确认能看到JSON或HTML内容(非空)
  • [ ] ✓ 如果失败,按3.4节对照表逐项排查,不跳步

最后提醒一句:这套流程只适用于开发测试环境。切勿在生产APK上做此类操作,也不要在非授权设备上抓取他人App流量。安全测试的前提是合规,这点比技术本身更重要。

我在实际项目中用这套方法,平均每天能完成3-5个App的HTTPS流量分析。最深的体会是:模拟器不是真机的简化版,而是另一套独立系统——它的证书管理、代理机制、ABI兼容性都自成体系。与其强行套用真机经验,不如把它当成一台特殊的Linux服务器来对待:用ADB当SSH,用apktool当文本编辑器,用Frida当调试器。当你开始用运维思维去理解模拟器,那些曾经让人抓狂的SSL错误,就变成了可预测、可复现、可解决的标准问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/23 23:04:03

瑞数6代JSVMP对抗实战:Node.js环境补全与412绕过

1. 这不是“绕过验证码”&#xff0c;而是一场Web前端对抗的深度解剖瑞数6代&#xff0c;业内常被称作“JSVMP黑盒”的典型代表——它不靠传统混淆堆砌代码体积&#xff0c;也不依赖简单的时间戳或行为采集做判断&#xff0c;而是把整个校验逻辑编译进一套自定义的、高度定制化…

作者头像 李华
网站建设 2026/5/23 23:02:49

AI电影制作:帧级控制与电影语法的工程化实践

1. 项目概述&#xff1a;当电影导演开始和AI共写分镜脚本“River of Inheritance”——这条河不是地理意义上的&#xff0c;而是记忆、家族叙事与文化基因的隐喻性水道。它不流经地图&#xff0c;却真实冲刷着每个人的意识河床。而我做的&#xff0c;不是用胶片或数字摄影机去“…

作者头像 李华
网站建设 2026/5/23 22:59:38

认知殖民与范式陷阱:当代人工智能发展路径的文明危机研究

认知殖民与范式陷阱&#xff1a;当代人工智能发展路径的文明危机研究摘要本文从文明安全与认知主权视角出发&#xff0c;系统批判了当前以Transformer架构、Scaling Law和大语言模型为核心的人工智能技术范式。研究指出&#xff0c;该范式不仅是技术路径的选择&#xff0c;更是…

作者头像 李华
网站建设 2026/5/23 22:56:56

一人公司操作系统技能solopreneur-os

Solopreneur OS&#xff08;Skillhub&#xff09; Solopreneur OS&#xff08;ClawHub&#xff09; name: solopreneur-os author: 王教成 Wang Jiaocheng (波动几何) description: 一人公司操作系统。核心能力&#xff1a;工作流重构——将任何领域的复杂工作流重构为AI辅助一…

作者头像 李华
网站建设 2026/5/23 22:54:26

机器学习检测钓鱼网站的核心原理与工程实践

1. 这不是“AI看一眼就知道是假网站”——机器学习识破钓鱼攻击的真实逻辑“How Machine Learning Detects Phishing Attacks”这个标题&#xff0c;表面看是讲一个技术原理&#xff0c;但实际背后是一场持续十年以上的攻防拉锯战。我从2014年开始做Web安全检测系统开发&#x…

作者头像 李华
网站建设 2026/5/23 22:53:05

Unity 6国内安装与工程落地实战指南

1. Unity 6不是“新版本”&#xff0c;而是Unity引擎的全新命名体系起点你点开Unity官网&#xff0c;看到“Unity 6”这个字样&#xff0c;第一反应可能是&#xff1a;“哇&#xff0c;终于出大版本了&#xff1f;是不是像Unity 5到Unity 2017那样&#xff0c;有颠覆性更新&…

作者头像 李华