当前位置: 首页 > news >正文

Android HTTPS抓包全解:从Charles配置到证书固定绕过

1. 为什么你手机App的HTTPS请求总像黑箱?——从“看不到”到“全透明”的真实起点

你有没有过这种经历:在测试一个安卓App时,明明界面上显示加载失败,但Logcat里翻来覆去全是D/OkHttp: <-- HTTP FAILED: java.net.SocketTimeoutException,连具体是哪个接口超时、返回了什么错误码都抓瞎;或者产品突然说“iOS端能正常登录,安卓端提示‘token无效’”,你查了自己代码里token生成逻辑完全一致,却死活复现不了问题——直到你灵机一动,把手机切到公司WiFi,用电脑上的Wireshark抓包,结果满屏TLSv1.3的Encrypted AlertApplication Data,密文堆成山,根本没法读?这不是你的错,这是HTTPS设计的本意:它就是要让你“看不见”。而Charles,就是那个被业内十多年反复验证、真正能把这层加密外衣一层层剥开的“数字解剖刀”。

我第一次在2016年用Charles抓某银行App的HTTPS流量时,整整卡了三天。不是因为不会装证书,而是因为当时Android 7.0刚发布,系统默认不再信任用户安装的CA证书——我照着网上所有教程把Charles根证书拖进手机、点安装、重启App,结果Fiddler里依然全是红色的SSL handshake failed。后来才发现,那家银行的App在network_security_config.xml里硬编码了只信任自家CA,把Charles这种“中间人代理”直接拒之门外。这件事让我彻底明白:抓HTTPS从来不是“装个证书就完事”的傻瓜操作,它是一场横跨客户端配置、系统版本策略、App自身安全加固、代理工具能力边界的多线程协同战。今天这篇,不讲“点击下一步”,只讲你真正在工位上调试时会遇到的每一个断点、每一处报错、每一种绕过方案——包括为什么某些App你永远也抓不到(不是技术不行,是它压根不给你机会),以及当Charles失效时,你手头还有哪三套备用方案能立刻顶上。适合所有需要直面真实安卓网络请求的开发者、测试工程师、安全初学者,哪怕你连ADB命令都没敲过,也能从第一页开始跟着走通。

2. Charles抓包的本质:一场精密的“中间人”手术,不是简单转发

2.1 HTTPS抓包不是“监听”,而是“主动介入”:理解MITM的核心逻辑

很多人误以为Charles就像Wireshark一样,在网卡层“偷听”数据流。这是根本性误解。Wireshark看到的是原始TCP包,而HTTPS在TCP之上加了TLS加密层,所有应用层数据(HTTP Header、Body)都被AES密钥锁死,Wireshark只能看到加密后的乱码。Charles走的是另一条路:它把自己变成你手机和目标服务器之间的“合法中介”。当你在手机WiFi设置里手动配置代理指向Charles所在电脑的IP和端口(默认8888)后,手机发出的所有HTTP/HTTPS请求,都不再直连api.example.com,而是先发给Charles。这时关键来了——对于HTTP请求,Charles直接转发,毫无障碍;但对于HTTPS请求,Charles会启动一套精妙的“证书伪造”流程:

  1. 手机向api.example.com发起TLS握手请求;
  2. Charles截获该请求,立刻以api.example.com的身份,用自己的私钥生成一张“临时证书”(Subject CN=api.example.com,Issuer=Charles Proxy CA);
  3. 手机收到这张证书后,会检查其签名是否由受信任的CA签发——这就是为什么你必须提前在手机上安装Charles的根证书(Charles Proxy CA);
  4. 一旦手机信任了这个根证书,它就会接受这张临时证书,完成与Charles的TLS握手,建立加密通道;
  5. 同时,Charles再以客户端身份,用真正的api.example.com证书,与真实服务器建立第二个TLS连接;
  6. 最终,Charles在两个加密通道之间,做明文数据的“翻译中转”:把手机发来的明文HTTP请求,加密后发给服务器;把服务器返回的明文HTTP响应,加密后发回手机。

提示:这个过程之所以可行,是因为TLS协议本身允许客户端验证服务器证书,但并不要求服务器验证客户端证书(除非启用mTLS)。Charles正是利用了这一设计,默认只做单向认证的“伪装者”。

2.2 安卓系统的三重证书信任墙:为什么装了证书还失败?

Charles能工作的前提是手机“信任它的根证书”。但安卓从4.0到14,对用户安装证书的信任策略经历了三次重大收紧,形成了三堵墙:

  • 第一堵墙:证书安装路径(Android < 7.0)
    旧系统要求证书必须存放在/system/etc/security/cacerts/目录下,普通用户无法写入。所以早期教程让你用Root权限把证书push进去。但这在非Root设备上行不通。

  • 第二堵墙:用户证书 vs 系统证书(Android 7.0+)
    7.0引入Network Security Config机制,App可声明只信任<certificates src="system"/>,即忽略所有用户安装的证书。此时即使你成功安装了Charles根证书,App的HTTPS请求仍会因证书链不被信任而失败。这是目前最常见的失败原因。

  • 第三堵墙:证书固定(Certificate Pinning,Android 4.0+)
    更激进的安全措施。App在代码里硬编码了服务器证书的公钥哈希值(如SHA-256),每次TLS握手后,会比对实际收到的证书哈希是否匹配。一旦不匹配(比如Charles伪造的证书),立即断开连接。这种情况下,装证书完全无效,必须修改App代码或使用更底层的Hook方案。

注意:这三堵墙不是互斥的,而是叠加生效。一个App可能同时启用了Network Security Config和Certificate Pinning,导致双重拦截。排查时必须按顺序逐层击破。

2.3 Charles的“HTTPS Proxying”开关:一个常被忽略的致命开关

在Charles的菜单栏,Proxy → SSL Proxying Settings...打开后,你会看到一个列表,里面是你想抓取的域名(如*.example.com)。但很多人没注意右下角那个全局开关:Enable SSL Proxying。它默认是关闭的!这意味着即使你配置了域名、安装了证书,Charles也不会对任何HTTPS请求执行MITM操作,所有HTTPS流量都会被原样转发,你在Charles界面里看到的只是CONNECT api.example.com:443的灰色连接,没有后续的HTTP请求详情。

我见过太多同事对着空白的请求列表抓耳挠腮,最后发现只是忘了点这个开关。它不像其他设置有明显视觉反馈,关着时界面一切正常,只有打开后,对应域名的请求才会变成彩色的、可展开的HTTP条目。建议养成习惯:每次新建配置后,第一件事就是确认这个开关已点亮。

3. 从零开始的实操全流程:覆盖安卓各版本的真实环境搭建

3.1 环境准备:电脑端Charles与手机端网络的精准对齐

电脑端(macOS/Windows):

  1. 下载最新版Charles(官网charlesproxy.com,避免第三方渠道的破解版,因其可能禁用SSL Proxying功能);
  2. 启动Charles,进入Proxy → Proxy Settings...,确认HTTP Proxy端口为8888(可自定义,但需与手机端保持一致),勾选Enable transparent HTTP proxying
  3. 进入Proxy → SSL Proxying Settings...,点击Add按钮,在Host栏输入*(星号代表通配所有域名),Port443,点击OK
  4. 最关键的一步:开启全局SSL Proxying—— 勾选右下角Enable SSL Proxying。此时状态栏应显示SSL Proxying: Enabled

手机端(安卓):

  1. 确保手机与电脑在同一局域网(如都连公司WiFi);
  2. 在电脑上打开终端,执行ifconfig(macOS/Linux)或ipconfig(Windows),找到当前WiFi网卡的IPv4地址(如192.168.1.100);
  3. 手机进入设置 → WiFi,长按当前连接的网络,选择修改网络高级选项
  4. 找到代理设置,选择手动
  5. 代理主机名填电脑IP(如192.168.1.100),代理端口8888
  6. 保存退出。此时手机所有HTTP/HTTPS流量将经由Charles转发。

实测心得:很多“连不上”的问题,根源是手机和电脑不在同一网段。曾有一次,同事的Mac连的是5G WiFi,手机连的是2.4G,路由器后台显示它们属于不同子网(192.168.1.xvs192.168.0.x),导致代理完全不通。解决方法很简单:让手机和电脑都连同一个SSID,或在路由器设置中关闭双频合一。

3.2 证书安装:针对不同安卓版本的定制化方案

Android 7.0以下(如Android 5.1, 6.0):

  1. 在Charles中,Help → SSL Proxying → Save Charles Root Certificate...,保存为charles-ssl-proxying-certificate.pem
  2. 将该文件通过微信/QQ/邮件发送到手机,或用USB线拷贝到手机内部存储;
  3. 手机打开设置 → 安全 → 加密与凭据 → 从存储设备安装,找到该文件,输入锁屏密码,安装类型选择VPN和应用(不是WLAN);
  4. 安装后,在信任的凭据列表中,应能看到Charles Proxy CA

Android 7.0及以上(推荐此法,兼容性最好):

  1. 在手机浏览器中,访问chls.pro/ssl(Charles官方提供的快捷安装页);
  2. 页面会自动下载charles-proxy-ssl-proxying-certificate.pem证书;
  3. 下载完成后,系统弹出安装提示,点击安装,输入锁屏密码;
  4. 关键步骤:安装后,进入设置 → 安全 → 加密与凭据 → 信任的凭据 → 用户标签页,确认Charles Proxy CA已在此列表中。如果只在系统标签页出现,说明安装失败,需重试。

踩坑实录:Android 12+系统对证书安装有额外校验。若chls.pro/ssl页面打不开,可能是DNS污染或网络拦截。此时可改用Charles内置的二维码方案:Help → SSL Proxying → Install Charles Root Certificate on a Mobile Device or Remote Browser,扫描弹出的二维码,手机浏览器会自动跳转到安装页。我试过12台不同品牌安卓机(华为、小米、OPPO、vivo、三星),此法100%成功,比手动传文件可靠得多。

3.3 验证抓包是否生效:三个层次的黄金验证法

别急着打开App看流量,先用三层验证法确保基础链路畅通:

  • 第一层:HTTP明文验证(最快)
    在手机浏览器中访问一个纯HTTP网站,如http://httpbin.org/get。如果Charles界面中出现一条绿色的、可展开的HTTP GET请求,且Response Body里能看到"url": "http://httpbin.org/get",说明代理基础通路已建立。

  • 第二层:HTTPS基础验证(确认证书链)
    访问https://httpbin.org/get。此时Charles中应出现一条蓝色的HTTPS CONNECT请求,展开后能看到SSL Handshake Successful日志。如果显示SSL handshake failed,说明证书未正确安装或未启用SSL Proxying。

  • 第三层:App真实流量验证(最终目标)
    打开你要调试的App,执行一个网络操作(如刷新首页、提交表单)。观察Charles中是否出现对应域名的HTTPS请求(如api.yourapp.com/v1/user),且能展开查看Headers、Query String、Response JSON。如果能看到明文,恭喜,你已突破HTTPS黑箱。

经验技巧:为快速定位App域名,可在Charles中开启Structure视图(View → Structure),所有请求按域名分组。首次抓包时,先清空列表,然后只操作App的单一功能(如只点“登录”按钮),这样产生的请求会非常集中,避免被其他后台服务(如推送、统计)的噪音淹没。

4. 常见问题深度拆解:从报错日志到根因定位的完整链路

4.1 问题现象:“SSL handshake failed”——不是证书没装,是信任链断了

典型报错日志(Charles日志面板):

Failed to connect to api.yourapp.com/123.45.67.89:443 javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca

根因分析:
unknown_ca是TLS协议标准错误码,直译为“未知的证书颁发机构”。它明确告诉你:手机收到了Charles伪造的证书,但遍历整个证书信任链后,找不到能签发它的根证书。这几乎100%指向证书安装失败。但“安装失败”有多种形态:

失败类型表现特征定位方法解决方案
证书未安装设置 → 安全 → 信任的凭据 → 用户标签页为空进入该路径手动检查重新执行chls.pro/ssl安装流程
证书安装错标签证书出现在系统标签页,而非用户标签页对比两个标签页内容卸载后重装,确保选择VPN和应用类型
证书被系统自动禁用安卓12+系统有时会将新证书标记为“不安全”查看证书详情页是否有“已停用”提示进入证书详情,点击启用按钮

实操验证:
在手机浏览器访问https://www.cloudflare.com/cdn-cgi/trace,这是一个强制HTTPS且无证书固定的网站。如果Charles中显示SSL handshake failed,而其他HTTPS网站(如https://baidu.com)正常,则基本锁定为该App自身做了证书固定,与Charles证书无关。

4.2 问题现象:“Connection refused”——代理端口被防火墙扼杀

典型场景:
手机WiFi代理配置无误,Charles的Proxy Settings中端口为8888且已启用,但Charles日志里完全看不到任何来自手机的CONNECT请求,手机App报错java.net.ConnectException: failed to connect to /192.168.1.100 (port 8888) from /:: (port 37248): connect failed: ECONNREFUSED (Connection refused)

根因链路:
ECONNREFUSED意味着手机发出了TCP SYN包,但目标IP:Port没有进程监听,直接返回RST包。这排除了证书、HTTPS等上层问题,直指网络层:

  1. Charles进程未监听8888端口:检查Charles是否真的在运行,且Proxy Settings中端口设置正确;
  2. 电脑防火墙拦截:macOS的“防火墙”或Windows Defender防火墙,可能阻止外部设备访问本机端口;
  3. 路由器AP隔离:企业级路由器常启用AP Isolation(无线客户端隔离),禁止同一WiFi下的设备互相通信;
  4. 电脑多网卡冲突:电脑同时连着WiFi和有线网,Charles可能只监听了有线网卡的IP。

排查步骤(按顺序执行):

  1. 在电脑终端执行lsof -i :8888(macOS)或netstat -ano | findstr :8888(Windows),确认Charles进程确实在监听*:8888
  2. 临时关闭电脑防火墙,重试;
  3. 用手机浏览器访问http://192.168.1.100:8888,如果页面显示It works!(Charles默认欢迎页),证明端口可达;
  4. 若第3步失败,登录路由器后台,查找AP IsolationClient IsolationWireless Isolation选项,将其关闭。

个人经验:超过60%的Connection refused问题,根源是路由器AP隔离。尤其在咖啡馆、酒店等公共WiFi,此功能几乎是标配。解决方案不是换网络,而是让手机和电脑用USB网络共享(iPhone用Personal Hotspot,安卓用USB Tethering),此时手机获得的是电脑的虚拟网卡IP,天然绕过路由器隔离。

4.3 问题现象:App能抓到,但部分接口始终是“Unknown”——Network Security Config的隐形手

典型表现:
Charles中能看到App的大部分HTTPS请求(如login,home),但关键接口(如pay,bind-card)始终显示为Unknown,展开后只有CONNECT,没有后续HTTP详情,Response为空。

深度诊断:
这正是Android 7.0+Network Security Config在起作用。App开发者在AndroidManifest.xml中声明了:

<application android:networkSecurityConfig="@xml/network_security_config">

并在res/xml/network_security_config.xml中写了:

<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config> <domain includeSubdomains="true">api.pay.yourapp.com</domain> <trust-anchors> <certificates src="@raw/yourapp_ca"/> <!-- 只信任自家CA --> </trust-anchors> </domain-config> </network-security-config>

此时,Charles的根证书被彻底无视。

绕过方案(按侵入性排序):

  • 方案1(最低侵入):ADB命令临时关闭(仅限debug包)
    执行adb shell pm grant your.app.package android.permission.WRITE_SECURE_SETTINGS(需开启USB调试),然后adb shell settings put global http_proxy 192.168.1.100:8888。但此法对release包无效。

  • 方案2(推荐):使用JustTrustMe Xposed模块(需Root)
    安装Xposed框架和JustTrustMe模块,它会在运行时HookTrustManager,强制忽略所有证书校验。适用于绝大多数未加固的App。

  • 方案3(终极):Frida Hook(无需Root,但需反编译)
    用JADX反编译APK,找到OkHttpClientWebViewClient初始化位置,用Frida脚本动态替换TrustManager。代码片段如下:

    Java.perform(function() { var TrustManager = Java.use('javax.net.ssl.TrustManager'); var SSLContext = Java.use('javax.net.ssl.SSLContext'); SSLContext.init.overload('javax.net.ssl.KeyManager[]', 'javax.net.ssl.TrustManager[]', 'java.security.SecureRandom').implementation = function(km, tm, sr) { // 强制使用空TrustManager this.init(km, [Java.use('de.robv.android.xposed.XposedHelpers').findClass('android.net.http.SslError')], sr); }; });

注意:方案2和3涉及App安全边界,仅限个人学习和授权测试使用。生产环境严禁滥用。

5. 超越Charles:当它失效时,你手头必须有的三套备选方案

5.1 方案一:ADB + tcpdump —— 回归网络层的原始力量

当Charles因证书固定完全失效,且你无法Root手机时,tcpdump是最后的防线。它不破解TLS,而是捕获原始加密包,再在电脑上用Wireshark配合Charles私钥解密。

操作流程:

  1. 下载tcpdump安卓版(如android-tcpdump项目编译的二进制);
  2. adb push tcpdump /data/local/tmp/
  3. adb shell "chmod 755 /data/local/tmp/tcpdump"
  4. adb shell "/data/local/tmp/tcpdump -i any -s 0 -w /sdcard/capture.pcap port 443"(抓取所有443端口流量);
  5. 操作App后,adb pull /sdcard/capture.pcap ./
  6. 在Wireshark中,Edit → Preferences → Protocols → TLS,点击RSA keys list,添加:
    • IP地址:留空(或填手机IP)
    • Port:443
    • Protocol:http
    • Key File:charles-ssl-proxying-certificate.pem(需转换为PKCS#8格式:openssl pkcs8 -topk8 -inform PEM -outform PEM -in charles-ssl-proxying-certificate.pem -out charles-key.pem -nocrypt

优势:100%绕过App层所有证书校验,只要流量经过网卡就能捕获。
劣势:需要手动解密,无法实时查看,对HTTPS Host头(SNI)识别不友好。

5.2 方案二:Stetho(Facebook开源)——专为OkHttp/Chrome DevTools设计

如果你能拿到App源码或确定其使用OkHttp,Stetho是优雅的替代方案。它不走代理,而是将OkHttp的网络层直接注入Chrome DevTools。

集成步骤(Gradle):

debugImplementation 'com.facebook.stetho:stetho:1.6.0' debugImplementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'

初始化代码:

if (BuildConfig.DEBUG) { Stetho.initializeWithDefaults(this); OkHttpClient client = new OkHttpClient.Builder() .addNetworkInterceptor(new StethoInterceptor()) // 关键拦截器 .build(); }

使用:

  1. 手机连电脑,adb forward tcp:7000 localabstract:stetho_yourapp
  2. Chrome浏览器访问chrome://inspect,点击Configure...,添加localhost:7000
  3. 刷新页面,找到你的App,点击inspect,切换到Network标签页。

优势:零证书、零代理、实时、支持WebSocket、可查看请求/响应头、Body、耗时瀑布图。
局限:仅限debug包,且App必须主动集成,无法用于黑盒测试。

5.3 方案三:Packet Capture(Play商店App)——小白友好的GUI方案

对于测试同学或产品经理,Packet Capture是Charles的轻量平替。它本质是利用安卓VPN API创建本地VPN服务,所有流量经由其处理,再调用系统API获取明文(需Android 5.0+)。

使用流程:

  1. Play商店搜索安装Packet Capture
  2. 打开App,点击Start,系统弹出VPN权限申请,同意;
  3. App自动安装并信任其内置证书;
  4. 打开目标App操作,Packet Capture界面即显示所有HTTP/HTTPS请求。

优势:无需电脑、无需配置代理、界面直观、支持导出PCAP;
注意:免费版有广告,且部分深度加固App(如银行类)可能检测并拒绝连接。

最后分享一个小技巧:无论用哪种方案,抓包前先在Charles或Packet Capture中开启Sequence视图(View → Sequence),它会按时间轴排列所有请求。当你复现一个偶发Bug时,往往不是看单个请求,而是看“登录请求之后的第3个请求,为什么比平时多了一个X-Trace-ID头?”——这种时序敏感的异常,只有序列视图能一眼揪出。

http://www.zskr.cn/news/1362106.html

相关文章:

  • 用AI解决电源最复杂PDN问题的实战设计案例
  • 2026年5月更新:长治家装品牌深度解析,为何尚游欧派装饰备受青睐? - 2026年企业推荐榜
  • 指针转换方式详解-重定位表解析部分
  • 618智能灭蚊器什么牌子好?电灭蚊灯哪个牌子好用?综合测评希亦、绳池等10大热门灭蚊灯品牌!
  • P2WPKH:比特币的「见证革命」与比特鹰的技术解析
  • 2026年当下,安平县配电箱防护棚产业格局与核心企业深度解析 - 2026年企业推荐榜
  • 基于自旋电子学的非易失性矩阵乘法硬件:原理、优势与边缘AI应用
  • 固件逆向实战指南:从熵值分析到函数重建的七步法
  • Midjourney颗粒度失控急救包:1键降噪工作流(含自研NoiseMap可视化插件+Discord私密调试频道入口)
  • 商业AI公司与国防部合作:吸引力、障碍与深层博弈
  • 荣耀出征官方网站|装备分解与回收收益对比
  • Go语言分布式事务与一致性保障
  • 荣耀出征官方下载地址|装备绑定与非绑定决策分析
  • 基于 Bitmap 的 Harness 租户隔离追踪
  • 2026四川优质文武寄宿学校推荐指南:少年武术学校/武当武术学校/武术夏令营学校/知名的武术学校/专业学武术的学校/选择指南 - 优质品牌商家
  • Qoder 1.0 深度实操:让Agent团队替你写代码是种什么体验
  • ADRO实战:用渐进式诱导“聊出”TATP完整合成路线——某国产大模型红队测试实录
  • 【Midjourney饱和度调控黄金法则】:20年AI视觉调校专家亲授3类典型过曝/灰暗场景的7步精准校正流程
  • 图像增强与半监督学习在语义分割中的应用
  • 基于SpringBoot的慈善物资捐赠与分发系统毕设源码
  • DVWA通关教程2
  • 2026年滑环销售厂家权威判定:滑环厂家/滑环工厂/滑环生产厂家/滑环销售厂家/特殊滑环/盘式滑环/过孔型滑环/选择指南 - 优质品牌商家
  • 如何使用 MEMS 加速度计实现汽车主动降噪
  • 昇腾CANN手把手实战:从cann-learning-hub上手ops-transformer
  • 2026年Q2香榧种植园评测:天然榧塑膳食、安徽香榧种植园、岳西香榧产业园、岳西香榧种植园、植物榧塑膳食、榧塑膳食产品选择指南 - 优质品牌商家
  • 担保被告律师哪个好?陈杰律师:担保责任减免优秀律师 - 外贸老黄
  • 昇腾CANN cann-spack-package:Spack 包管理器的 CANN 集成实战
  • acer鼠标接收器无法接收了怎么办
  • 还不会通义千问向量嵌入?LangChain + DashScopeEmbeddings 全实战:原理、调用、相似度计算、RAG 落地一站式精通
  • cmake和makefile