ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

支付宝小程序SSL验证与代理抓包:Frida绕过证书锁定实战

支付宝小程序SSL验证与代理抓包:Frida绕过证书锁定实战 简介这份资源聚焦移动端安全测试中的支付宝小程序抓包场景面向具备一定逆向基础的安全研究人员、渗透测试工程师及移动开发学习者用于解决小程序通信流量难以通过常规代理工具捕获的问题。压缩包共3个文件包含Python脚本、JavaScript注入脚本与Markdown说明文档整体仅约2KB体量轻巧但指向明确便于快速理解与二次调试。资源围绕SSL验证绕过与代理抓包两条主线展开脚本部分承担证书校验拦截与流量转发逻辑说明文档则梳理了环境准备与使用思路读者可据此搭建本地抓包链路观察小程序请求结构并在此基础上延伸分析接口鉴权、数据加密等安全机制。目前已有2978人学习下载适合作为移动端抓包与逆向分析的入门实践参考。1. 支付宝小程序 SSL 验证与代理抓包为什么你的抓包工具一开就断网做过支付宝小程序调试的同行大概率遇到过这个场景Charles 或 Fiddler 代理配好了手机 Wi-Fi 也指向了电脑浏览器里 HTTPS 请求看得清清楚楚唯独支付宝小程序里的接口请求全部超时或者直接报网络异常。这不是代理工具的问题而是支付宝小程序容器在发起网络请求时对 SSL 证书做了额外校验——它不信任你那个自签名的根证书于是 TLS 握手直接失败。这个方向解决的就是这个问题让支付宝小程序的网络请求能正常走本地代理从而在开发调试阶段看到完整的请求和响应数据。适合两类人一是做支付宝小程序前端开发、需要排查接口问题的工程师二是做安全测试、需要分析小程序通信协议的技术人员。核心思路围绕三个关键词展开支付宝小程序的 SSL 验证机制、代理抓包的流量劫持原理、以及绕过校验的具体手段。下面从原理到操作一步步拆开讲。2. 支付宝小程序的网络请求链路与 SSL 校验层级2.1 小程序容器是怎么发请求的支付宝小程序的网络请求并不走系统原生的 HTTP 栈而是由小程序容器基于 WebView 或自研渲染引擎统一接管。当你在代码里调用my.request或my.httpRequest时请求实际经过以下链路JS 层 API 调用 → 容器 Bridge → Native 网络模块 → 系统 TLS 栈 → 目标服务器关键点在 Native 网络模块这一层。支付宝容器在 Android 端通常使用 OkHttp 或自研网络库iOS 端使用 NSURLSession。这些网络库默认会走系统的证书信任链校验但支付宝在此基础上做了额外处理内置了证书锁定Certificate Pinning机制也就是说它不只看系统信任的 CA 列表还会校验服务器证书是否匹配预设的指纹或公钥。这就是为什么你装了 Charles 的根证书到系统信任区浏览器能正常抓包但小程序依然拒绝连接——因为 Charles 的证书不在支付宝的 Pinning 白名单里。2.2 SSL Pinning 在小程序场景下的具体表现证书锁定在不同平台和不同版本的支付宝客户端上表现不一样常见的有以下几种校验层级表现影响范围系统 CA 校验未安装代理根证书时直接失败所有 HTTPS 请求应用级 CA 校验只信任内置 CA 列表忽略用户安装的证书Android 7.0 默认行为证书指纹 Pinning校验服务器证书的公钥哈希核心支付接口双向认证 (mTLS)客户端也需要提供证书部分高安全接口大部分调试场景下你遇到的是第二层和第三层的问题。Android 7.0 之后应用默认不再信任用户安装的 CA 证书除非应用在network_security_config.xml中显式声明信任用户证书。支付宝作为金融级应用显然不会开这个口子。2.3 代理抓包的基本原理回顾代理抓包的核心是中间人MITM代理工具在客户端和目标服务器之间充当中间人对客户端出示自己签发的证书对服务器则作为正常客户端发起连接。要成功完成这个过程客户端必须信任代理工具的根证书。# 以 Charles 为例典型代理配置 # 1. 电脑端 Charles 监听端口 8888 # 2. 手机 Wi-Fi 设置代理为电脑 IP:8888 # 3. 手机浏览器访问 chls.pro/ssl 下载根证书 # 4. 将证书安装到系统信任区Android 需要 root 或 Magisk 模块上面这套流程对普通 App 和浏览器有效但对支付宝小程序不够。原因已经在 2.1 和 2.2 中说明容器层有额外的校验逻辑。接下来的章节会针对这个瓶颈给出具体的绕过方案。3. 绕过 SSL 校验的实操路径从 Frida Hook 到系统证书注入3.1 方案选型为什么选 Frida 而不是改包绕过 SSL Pinning 的常见思路有几种改包重签名、Xposed 模块、Frida 动态注入、以及系统级证书注入。改包重签名对支付宝这种有签名校验的应用基本不可行一动签名就闪退。Xposed 依赖特定框架环境兼容性越来越差。目前最稳定、最可控的方案是 Frida 动态 Hook配合系统证书注入作为辅助。Frida 的优势在于不需要修改 APK不需要重启设备可以精确 Hook 到具体的校验函数而且脚本可以热加载。对于支付宝小程序这种场景我们主要 Hook 两个目标一是 OkHttp 的 CertificatePinner 校验逻辑二是 TrustManager 的证书链验证方法。3.2 环境准备与 Frida 部署先确认设备环境。以下操作以 Android 真机为例模拟器可能缺少某些系统组件。# 检查设备连接 adb devices # 推送 frida-server 到设备需要 root adb push frida-server-16.x.x-android-arm64 /data/local/tmp/frida-server adb shell chmod 755 /data/local/tmp/frida-server adb shell /data/local/tmp/frida-server # 电脑端安装 frida 工具 pip install frida-tools # 验证连接 frida-ps -U参数说明frida-server的版本必须和电脑端fridaPython 包的版本一致否则会报协议不匹配。-U表示连接 USB 设备。如果frida-ps -U能列出进程列表说明环境就绪。注意frida-server 需要 root 权限运行。没有 root 的设备可以考虑使用 Magisk 模块方式注入或者使用免 root 方案如 objection 的 patch 模式但稳定性和覆盖面会打折扣。3.3 编写 SSL Pinning 绕过脚本下面是一个针对 Android 平台通用 SSL Pinning 绕过的 Frida 脚本覆盖了 OkHttp、TrustManager 和 SSLContext 三个层面// ssl_bypass.js - 通用 Android SSL Pinning 绕过 Java.perform(function () { // 1. 绕过 OkHttp 的 CertificatePinner try { var CertificatePinner Java.use(okhttp3.CertificatePinner); CertificatePinner.check.overload(java.lang.String, java.util.List).implementation function (host, peerCertificates) { console.log([] OkHttp CertificatePinner bypassed for: host); return; }; } catch (e) { console.log([-] OkHttp CertificatePinner not found: e); } // 2. 绕过 TrustManager 的证书链校验 try { var X509TrustManager Java.use(javax.net.ssl.X509TrustManager); var TrustManager Java.registerClass({ name: com.custom.TrustManager, implements: [X509TrustManager], methods: { checkClientTrusted: function (chain, authType) {}, checkServerTrusted: function (chain, authType) {}, getAcceptedIssuers: function () { return []; } } }); var SSLContext Java.use(javax.net.ssl.SSLContext); SSLContext.init.overload([Ljavax.net.ssl.KeyManager;, [Ljavax.net.ssl.TrustManager;, java.security.SecureRandom).implementation function (km, tm, sr) { console.log([] SSLContext.init hooked, replacing TrustManager); this.init(km, [TrustManager.$new()], sr); }; } catch (e) { console.log([-] TrustManager hook failed: e); } // 3. 绕过 HostnameVerifier try { var HostnameVerifier Java.use(javax.net.ssl.HostnameVerifier); var OkHostnameVerifier Java.use(okhttp3.internal.tls.OkHostnameVerifier); OkHostnameVerifier.verify.overload(java.lang.String, javax.net.ssl.SSLSession).implementation function (host, session) { console.log([] HostnameVerifier bypassed for: host); return true; }; } catch (e) { console.log([-] HostnameVerifier hook failed: e); } });逻辑说明脚本分三段分别针对 OkHttp 的证书锁定、JSSE 层的 TrustManager 校验、以及主机名验证。第一段直接让CertificatePinner.check返回空等于跳过了指纹比对。第二段用自定义的 TrustManager 替换系统默认实现所有证书都信任。第三段让主机名验证永远返回 true。参数说明overload方法用于指定具体重载版本因为同名方法可能有多个签名。Java.registerClass用于动态注册一个实现了指定接口的 Java 类。如果你的目标应用使用的是自研网络库而非 OkHttp第一段可能不生效但第二段和第三段通常仍然有效。3.4 启动注入并验证# 先启动支付宝再注入脚本 frida -U -f com.eg.android.AlipayGphone -l ssl_bypass.js --no-pause # 如果只想附加到已运行的进程 frida -U com.eg.android.AlipayGphone -l ssl_bypass.js注入成功后控制台会打印[]开头的日志。此时在支付宝里打开目标小程序触发网络请求Charles 里应该能看到对应的 HTTPS 流量了。如果某些请求仍然抓不到说明该请求走了更底层的网络栈比如 native 层的 libcurl 或自研协议需要进一步 Hook native 层的SSL_CTX_set_verify或X509_verify_cert函数。这部分在最后一章展开。4. 抓包环境搭建中的避坑与常见问题排查4.1 证书装了但小程序依然断网现象Charles 根证书已安装到系统信任区浏览器抓包正常但支付宝小程序内所有请求超时。原因Android 7.0 的应用默认不信任用户安装的 CA。即使你把证书装到了系统区如果应用的目标 SDK 版本大于等于 24且没有在network_security_config.xml中声明信任用户证书系统就不会把用户 CA 纳入信任链。解决两个方向。一是用 Frida 脚本 Hook 掉 TrustManager见 3.3 节这是最直接的方式。二是将证书安装到系统 CA 存储区需要 root具体做法是把证书文件复制到/system/etc/security/cacerts/并设置正确权限然后重启设备。注意 Android 10 之后系统分区只读需要用 Magisk 模块挂载。4.2 Frida 注入后支付宝闪退现象frida -U -f启动支付宝后应用在启动画面卡住然后闪退。原因支付宝有反调试和反注入检测。Frida 的默认进程名和端口特征容易被识别。另外某些版本的 frida-server 会在目标进程内存中留下明显特征。解决首先尝试重命名 frida-server 为不敏感的名称比如fs-daemon。其次修改默认端口frida-server -l 0.0.0.0:12345然后电脑端用frida -H 设备IP:12345连接。如果仍然闪退可以尝试使用 hluda-serverFrida 的修改版去除了部分特征或者用 objection 的 patch 模式重新打包 frida-gadget。4.3 部分接口能抓包部分接口抓不到现象小程序里的普通 API 请求能在 Charles 里看到但支付相关的接口看不到。原因核心支付接口通常走独立的网络通道可能使用了自研协议、私有加密、或者 native 层实现。这些通道不经过 Java 层的 OkHttp所以 Frida 的 Java Hook 覆盖不到。解决需要扩展到 native 层 Hook。用 Frida 的Interceptor.attach挂载libssl.so或libcrypto.so中的SSL_CTX_set_verify和X509_verify_cert。另外可以用frida-trace先摸清目标进程加载了哪些网络相关的 so 库frida-trace -U -i SSL_* com.eg.android.AlipayGphone frida-trace -U -i X509_* com.eg.android.AlipayGphone这能帮你快速定位 native 层的校验入口。4.4 Charles 看不到 WebSocket 流量现象小程序的 HTTP 请求抓到了但 WebSocket 连接没有出现在 Charles 里。原因Charles 对 WebSocket 的支持需要额外配置而且部分小程序使用自定义的 TCP 长连接而非标准 WebSocket。解决确认 Charles 版本支持 WebSocket4.x 以上。在 Proxy Settings 中勾选 “Enable WebSocket proxying”。如果是自定义 TCP 协议Charles 无能为力需要换用 tcpdump Wireshark 在更底层抓包但这样就拿不到解密后的明文了。4.5 代理开启后手机其他应用断网现象配好代理后支付宝能抓包了但微信、浏览器等其他应用全部无法联网。原因代理工具只对特定域名或特定应用做了证书签发其他应用的请求经过代理时证书校验失败。解决在 Charles 的 SSL Proxying Settings 中把*:*加入代理规则让所有域名都走 SSL 解密。如果不想全局解密可以只添加支付宝相关的域名比如*.alipay.com、*.alipayobjects.com、*.myxiaojia.com等。另外检查手机端是否安装了代理工具的根证书没装的话所有 HTTPS 都会失败。5. Native 层 Hook 与抓包稳定性的进阶技巧Java 层的 Hook 能解决大部分场景但支付宝的核心链路迟早会走到 native 层。我自己的习惯是先用 Java 层脚本跑一遍把能抓到的先抓到然后针对抓不到的那部分接口用frida-trace定位具体的 so 库和函数再写针对性的 native Hook。一个实用的 native 层绕过脚本框架// native_ssl_bypass.js - 针对 native 层 SSL 校验的 Hook var SSL_CTX_set_verify Module.findExportByName(libssl.so, SSL_CTX_set_verify); if (SSL_CTX_set_verify) { Interceptor.attach(SSL_CTX_set_verify, { onEnter: function (args) { // 第二个参数是 verify_mode设为 SSL_VERIFY_NONE (0) args[1] ptr(0); console.log([] SSL_CTX_set_verify called, set to VERIFY_NONE); } }); } var X509_verify_cert Module.findExportByName(libcrypto.so, X509_verify_cert); if (X509_verify_cert) { Interceptor.replace(X509_verify_cert, new NativeCallback(function (ctx) { console.log([] X509_verify_cert bypassed); return 1; // 返回 1 表示验证成功 }, int, [pointer])); }这段脚本直接修改了 native 层的证书校验行为。SSL_CTX_set_verify的第二个参数控制校验模式设为 0 即SSL_VERIFY_NONE完全跳过校验。X509_verify_cert被替换为永远返回 1表示证书链验证通过。参数说明Module.findExportByName用于查找导出函数地址第一个参数是库名第二个是函数名。不同 Android 版本上库名可能略有差异比如libssl.so在某些系统上是libssl1.so。可以用Module.enumerateExports先列出所有导出符号确认。验证方法注入后观察控制台日志同时在 Charles 里检查之前抓不到的接口是否出现了。如果 native Hook 生效但依然抓不到可能是应用使用了 BoringSSL 静态编译进主 so这时需要用 IDA 或 Ghidra 做静态分析找到函数偏移后用Module.base.add(offset)的方式 Hook。一个我踩过的坑某些版本的支付宝会把 SSL 校验逻辑放在一个叫libmarmot.so或类似名称的自研库里导出符号被 strip 掉了。这种情况下findExportByName找不到目标需要用frida-trace -U -i SSL*先看运行时有没有调用如果没有说明符号被隐藏了只能走静态分析路线。最后说一个习惯每次调试完把有效的 Frida 脚本按支付宝版本号归档。支付宝更新频率很高这个版本的绕过脚本下个版本可能就失效了。我一般会在脚本头部注释里写清楚适用的客户端版本号和测试日期下次遇到问题先翻归档能省不少时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表