Frida/Objection 实战:Hook 3类SSL Pinning方法(JustTrustMe替代方案)
Frida/Objection 实战:手动Hook 3类SSL Pinning实现
在移动安全测试中,SSL Pinning(证书绑定)是最常见的防抓包手段之一。与直接使用JustTrustMe等现成工具不同,本文将深入OkHttp、X509TrustManager和CertificatePinner三种主流实现方式,通过Frida/Objection编写精准Hook脚本,提供更灵活的绕过方案。
1. SSL Pinning技术原理与分类
SSL Pinning的核心思想是将服务器证书或公钥预先内置在客户端,建立连接时对比校验。根据实现方式可分为三类:
- 网络框架层校验:以OkHttp为代表的框架内置校验逻辑
- 证书管理器校验:通过X509TrustManager自定义验证逻辑
- 证书固定校验:使用CertificatePinner进行公钥指纹匹配
// 典型SSL Pinning实现示例 OkHttpClient client = new OkHttpClient.Builder() .certificatePinner(new CertificatePinner.Builder() .add("example.com", "sha256/AAAAAAAA...") .build()) .sslSocketFactory(sslSocketFactory, trustManager) .build();三种方式的对比如下:
| 类型 | 实现位置 | 校验粒度 | 典型特征 |
|---|---|---|---|
| OkHttp校验 | 网络框架层 | 域名级别 | 使用OkHttpClient.Builder |
| X509TrustManager | 证书验证层 | 证书链 | 实现checkServerTrusted方法 |
| CertificatePinner | 公钥指纹层 | 公钥哈希 | 配置sha256/前缀的指纹 |
2. OkHttp校验的Hook方案
OkHttp的校验通常通过SSLSocketFactory和TrustManager实现。通过Frida Hook关键类方法:
// Hook OkHttpClient.Builder的sslSocketFactory方法 Java.perform(function() { var OkHttpClient_Builder = Java.use('okhttp3.OkHttpClient$Builder'); OkHttpClient_Builder.sslSocketFactory.overload( 'javax.net.ssl.SSLSocketFactory', 'javax.net.ssl.X509TrustManager' ).implementation = function(factory, manager) { console.log("[+] Bypassing OkHttp SSL verification"); // 替换为空的TrustManager var TrustManager = Java.registerClass({ name: 'com.example.BypassTrustManager', implements: [Java.use('javax.net.ssl.X509TrustManager')], methods: { checkClientTrusted: function(chain, authType) {}, checkServerTrusted: function(chain, authType) {}, getAcceptedIssuers: function() { return []; } } }); return this.sslSocketFactory(factory, TrustManager.$new()); }; });关键Hook点:
okhttp3.OkHttpClient.Builder的sslSocketFactory方法- 替换原TrustManager为空实现
- 保持原始SSLSocketFactory不变
3. X509TrustManager的Hook方案
自定义TrustManager是Android中最常见的校验方式,核心方法是checkServerTrusted:
Java.perform(function() { var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); // Hook系统TrustManager X509TrustManager.checkServerTrusted.implementation = function(chain, authType) { console.log("[+] Bypassing X509TrustManager verification"); return; // 直接跳过验证 }; // Hook自定义TrustManager Java.enumerateClassLoaders({ onMatch: function(loader) { try { var customManager = loader.loadClass('com.example.CustomTrustManager'); Java.use(customManager.getName()).checkServerTrusted.implementation = function() { console.log("[+] Bypassing custom TrustManager"); }; } catch(e) {} }, onComplete: function() {} }); });应对策略:
- 全局Hook系统X509TrustManager
- 动态扫描自定义TrustManager实现
- 使用Objection的
android sslpinning disable命令
4. CertificatePinner的Hook方案
CertificatePinner通过比对公钥指纹实现校验,需Hook其校验逻辑:
Java.perform(function() { var CertificatePinner = Java.use('okhttp3.CertificatePinner'); CertificatePinner.check.overload( 'java.lang.String', 'java.util.List' ).implementation = function(hostname, pins) { console.log(`[+] Bypassing CertificatePinner for ${hostname}`); return; // 跳过指纹校验 }; // 针对新版OkHttp的Hook CertificatePinner.check$okhttp.overload( 'java.lang.String', '[Ljava.security.cert.Certificate;' ).implementation = function() { console.log("[+] Bypassing OkHttp3.14+ CertificatePinner"); }; });注意事项:
- OkHttp 3.x与4.x的API差异
- 多域名配置情况下的处理
- 备用指纹(fallback pins)的绕过
5. 综合防护的应对策略
当应用同时采用多种防护手段时,需要组合Hook方案:
层级化Hook顺序:
- 先处理CertificatePinner
- 再处理自定义TrustManager
- 最后处理网络框架层校验
Objection自动化脚本:
objection -g com.example.app explore -s "android sslpinning disable"- 典型防护组合的Hook方案:
| 防护组合 | 需Hook的类/方法 | 工具推荐 |
|---|---|---|
| OkHttp + CertificatePin | OkHttpClient.Builder, CertificatePinner | Frida + Objection |
| ApacheHttp + TrustManager | SSLSocketFactoryImpl, X509TrustManager | Frida独立脚本 |
| 双向认证 | KeyManagerFactory, ClientAuthType | 需导出客户端证书 |
6. 实战案例与排错指南
案例1:某金融App的复合校验
// Hook链式调用 Java.perform(function() { // 第一层:CertificatePinner var CertPinner = Java.use('okhttp3.CertificatePinner'); CertPinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {}; // 第二层:自定义TrustManager Java.enumerateLoadedClasses({ onMatch: function(className) { if (className.includes("SecurityManager")) { var clazz = Java.use(className); if (clazz.checkServerTrusted) { clazz.checkServerTrusted.implementation = function() {}; } } }, onComplete: function() {} }); // 第三层:WebView校验 var WebViewClient = Java.use('android.webkit.WebViewClient'); WebViewClient.onReceivedSslError.implementation = function(view, handler, error) { handler.proceed(); // 忽略SSL错误 }; });常见问题排查:
Hook不生效:
- 检查类名是否混淆(使用jadx分析)
- 确认Hook时机(尽早注入)
- 验证Frida版本兼容性
应用崩溃:
- 避免修改方法返回值类型
- 保持原始参数传递
- 使用try-catch包裹关键操作
检测Frida:
- 使用非常规端口(-l 参数)
- 替换Frida-server文件名
- 采用静态编译的注入工具
建议的测试流程:
- 使用Burp/Charles确认基础代理拦截
- 逐步启用各级Hook脚本
- 通过日志观察校验绕过情况
- 最后处理证书加密和签名校验
对于最新Android版本的适配要点:
- Android 10+的证书存储位置变化
- 非Root环境下使用frida-gadget注入
- 应对证书透明化(CT)校验
- 处理强化后的JNI保护机制
通过理解各层校验原理并编写针对性Hook脚本,可以构建比通用工具更精准的解决方案。实际测试中建议先静态分析确定防护方案,再动态验证Hook效果,最后形成自动化测试脚本。
