Frida Hook SSL Pinning抓包全攻略
Frida Hook SSL Pinning 实现抓包完整方案SSL Pinning证书绑定是移动应用常用的安全机制它通过将服务器证书硬编码或校验逻辑内置于客户端来防止中间人攻击这直接导致常规抓包工具如Charles、Fiddler无法捕获HTTPS流量。使用Frida进行动态Hook可以绕过此校验机制是实现抓包的有效技术手段。1. 核心原理与Hook目标SSL Pinning的校验逻辑通常存在于两个层面Java/Android框架层和NativeC/C层。Frida可以同时对这两层进行Hook。校验层次常见Hook目标作用与说明Java层TrustManager、HostnameVerifier、OkHttp的证书校验方法拦截并修改Java层的证书验证逻辑使其直接返回“信任”或“验证通过”。这是最通用和常见的方法。Native层libssl.so、libcrypto.so或应用自定义的libxxx.so如libsscronet.so中的函数如SSL_CTX_set_custom_verify当应用在Native层实现更底层的证书校验时需要Hook相应的Native函数修改其返回值例如将校验失败改为成功。2. 通用Java层Hook方案以OkHttp为例大多数Android应用使用OkHttp或类似网络库Hook其验证器是最快的方法。步骤1定位关键类与方法使用逆向工具如Jadx-GUI分析目标APK搜索关键词如X509TrustManagerHostnameVerifierCertificatePinnercheckServerTrusted通常找到的验证方法会返回void或boolean我们的目标是让其不抛异常或返回true。步骤2编写Frida Hook脚本以下脚本演示了如何Hook常见的TrustManager和HostnameVerifier// ssl_pinning_bypass.js Java.perform(function () { console.log([*] 开始Hook SSL Pinning 相关方法...); // 1. Hook TrustManager 绕过证书链验证 var X509TrustManager Java.use(javax.net.ssl.X509TrustManager); var X509ExtendedTrustManager Java.use(javax.net.ssl.X509ExtendedTrustManager); var TrustManagerHook function() { return { // 客户端证书验证 - 直接置空不执行任何操作 checkClientTrusted: function(chain, authType) { console.log([] Bypassing checkClientTrusted); }, // 服务器证书验证 - 关键置空以信任所有服务器证书 checkServerTrusted: function(chain, authType) { console.log([] Bypassing checkServerTrusted for authType: authType); }, getAcceptedIssuers: function() { return []; } }; }; // 替换应用的TrustManager实现 Java.choose(com.example.SomeClass, { onMatch: function(instance) { // 找到并替换实例中的TrustManager }, onComplete: function() {} }); // 更直接的方法Hook所有实现的checkServerTrusted方法 var trustManagerClasses [X509TrustManager, X509ExtendedTrustManager]; trustManagerClasses.forEach(function(clazz) { if (clazz.checkServerTrusted) { clazz.checkServerTrusted.implementation function(chain, authType) { console.log([] Bypassed checkServerTrusted via Frida Hook); return; // 不抛异常即表示信任 }; } }); // 2. Hook HostnameVerifier 绕过主机名验证 var HostnameVerifier Java.use(javax.net.ssl.HostnameVerifier); HostnameVerifier.verify.implementation function(hostname, session) { console.log([] Bypassing HostnameVerifier for: hostname); return true; // 始终返回true验证通过 }; // 3. Hook OkHttp的CertificatePinner (如果使用) try { var CertificatePinner Java.use(okhttp3.CertificatePinner); CertificatePinner.check.overload(java.lang.String, java.util.List).implementation function(pin, certs) { console.log([] Bypassing OkHttp CertificatePinner check for: pin); return; // 不执行任何检查 }; } catch (e) { console.log([!] OkHttp CertificatePinner not found or hook failed: e); } console.log([*] SSL Pinning Java层Hook完成); });步骤3执行Hook脚本将上述脚本保存为bypass.js并通过以下命令注入到目标进程# 附加到已运行的应用 frida -U -f com.target.app -l bypass.js --no-pause # 或重新启动应用并注入 frida -U -f com.target.app -l bypass.js3. Native层Hook方案针对深度校验对于在Native层如libsscronet.so实现校验的应用需要Hook Native函数。步骤1定位Native校验函数使用IDA Pro等工具分析应用的Native库.so文件寻找与SSL验证相关的函数常见函数名包含verify、SSL_CTX、cert等关键词。步骤2编写Native Hook脚本以下示例展示如何Hook一个假设的native_ssl_verify函数以及如何监控特定SO库的加载以进行Hook// native_hook.js Java.perform(function () { console.log([*] 准备Hook Native层SSL函数...); // 方案A拦截so库加载并在其加载后立即Hook内部函数 var android_dlopen_ext Module.findExportByName(null, android_dlopen_ext); if (android_dlopen_ext) { Interceptor.attach(android_dlopen_ext, { onEnter: function(args) { var soName args[0].readCString(); // 当目标so如libsscronet.so加载时 if (soName soName.indexOf(libsscronet.so) ! -1) { console.log([] 目标SO加载: soName); this.targetSo true; } }, onLeave: function(retval) { if (this.targetSo) { // 延迟执行确保so完全加载 setTimeout(hookInTargetSo, 500); } } }); } function hookInTargetSo() { var libtarget Module.findBaseAddress(libsscronet.so); if (libtarget) { console.log([] libsscronet.so 基址: libtarget); // 假设通过逆向分析找到关键函数偏移为 0x123456 var verifyFuncAddr libtarget.add(0x123456); // Hook该函数强制其返回0表示校验成功 Interceptor.attach(verifyFuncAddr, { onEnter: function(args) { console.log([] Native SSL Verify 函数被调用); }, onLeave: function(retval) { console.log([] 强制Native验证函数返回 0); retval.replace(ptr(0)); // 替换返回值为0 } }); } } // 方案B直接Hook标准libssl.so中的函数 (如果应用使用系统库) var sslVerify Module.findExportByName(libssl.so, SSL_verify_cert_chain); if (sslVerify) { Interceptor.attach(sslVerify, { onLeave: function(retval) { console.log([] Bypassing SSL_verify_cert_chain, original ret: retval); retval.replace(ptr(1)); // 假设1表示成功 } }); } });4. 集成工具与自动化为了提高效率可以结合一些成熟的Frida脚本或工具Objection一个基于Frida的运行时移动探索工具它内置了SSL Pinning绕过命令可以一键尝试多种绕过方式。objection -g com.target.app explore # 在 objection 会话中执行 android sslpinning disabler0capture一个专用于Android应用抓包的工具集成了Frida脚本能自动处理SSL Pinning并导出流量。JustTrustMe 模块 (Xposed)虽然这不是Frida方案但思路类似。它是一个Xposed模块通过Hook Android的证书验证API来全局禁用SSL Pinning。在具备Xposed环境的设备上安装即可无需为每个应用单独编写脚本。5. 流程与验证环境准备确保手机已root或为模拟器并安装Frida-server两边版本一致可以避免很多问题如果使用objection也需要版本匹配。启动抓包代理配置好Charles或Burp Suite(证书制作流程稍复杂点)的代理设置。逆向分析使用Jadx、IDA等工具快速定位应用的网络库和可能的校验点。编写与注入脚本根据分析结果选择Java层或Native层脚本进行注入。触发网络请求操作应用使其产生网络流量。验证抓包在Charles/Burp中查看HTTPS请求是否已被成功解密和捕获。若成功将能看到明文的请求和响应数据。注意事项稳定性Hook Native函数可能导致应用崩溃需谨慎操作。对抗升级应用可能更新校验逻辑需要重新分析。法律风险此技术仅用于安全研究、测试自己拥有或已获授权的应用严禁用于非法用途。通过上述Frida Hook方案你可以有效地绕过大多数APP的SSL Pinning机制为安全分析、漏洞挖掘和协议研究铺平道路。参考来源如何解决APP抓包问题【网络安全】某金融app的加解密hookrpc绕过SSLPinning抓包chatGPT与逆向的相遇快速解决sslpinning抓包问题实用FRIDA进阶内存漫游、hook anywhere、抓包