文章目录
- [1. 前言](#1. 前言)
- [2. 代码修改](#2. 代码修改)
- [3. Hook](#3. Hook)
-
- [3.1 归一后的完整脚本](#3.1 归一后的完整脚本)
- [3.2 脚本作用详解](#3.2 脚本作用详解)
- [3.3 绕过效果和Burp抓包](#3.3 绕过效果和Burp抓包)
- [4. 本章总结](#4. 本章总结)
- [5. 下章预告](#5. 下章预告)
⚠️本博文所涉安全渗透测试技术、方法及案例,仅用于网络安全技术研究与合规性交流,旨在提升读者的安全防护意识与技术能力。任何个人或组织在使用相关内容前,必须获得目标网络 / 系统所有者的明确且书面授权,严禁用于未经授权的网络探测、漏洞利用、数据获取等非法行为。
1. 前言
在移动应用的网络通信安全中,证书校验(尤其是SSL Pinning技术)是保护应用免受中间人攻击的重要手段。然而,在应用调试、安全测试或逆向分析场景中,我们常常需要绕过这些校验以捕获和分析网络请求。
在前三个章节中,我们分别学习了三种主流的证书校验机制及对应的绕过方法:
- 重写
X509TrustManager类的方法:通过自定义信任管理器,直接控制证书校验逻辑 network_security_config.xml配置:利用Android系统级的网络安全配置,管理证书信任策略- OkHttp的
certificatePinner方法:通过OkHttp框架自带的证书绑定功能,强制校验指定证书
但实际场景中,很多应用会同时采用多种校验机制以提高安全性。因此,本章将整合上述三种场景的绕过逻辑,提供一个通用的Hook脚本,实现"一次Hook,多场景适配"的效果,帮助大家更高效地应对复杂的证书校验环境。
2. 代码修改
本章节使用的示例 APK 和 APK 源码如下:
链接: https://pan.baidu.com/s/176Iw6OocOYi28z5dXoYYqg
提取码: rwdw
为了模拟真实应用中可能存在的多种证书校验场景,我们对原始APK的源码进行了针对性修改,使其同时包含三种常见的证书校验机制,具体修改如下:
-
启用OkHttp证书绑定
在
OkHttpClient.Builder()构建客户端时,添加certificatePinner方法,手动指定目标域名需要绑定的证书哈希。这样应用在使用OkHttp发起请求时,会强制校验服务器返回的证书是否与绑定的哈希匹配。 -
恢复默认X509TrustManager校验
删除之前重写的
X509TrustManager子类实现,让应用使用系统默认的信任管理器。此时应用会严格校验服务器证书是否在系统信任的CA列表中,未信任的证书会被拒绝。 -
配置系统级证书校验
在
AndroidManifest.xml中引用network_security_config.xml配置文件,并在配置文件中开启系统默认证书校验(即不允许信任用户添加的证书)。这会从系统层面限制应用仅信任预设的CA证书,进一步增强校验强度。
通过以上修改,目标APK同时具备了"应用层信任管理器校验"、"系统级网络安全配置校验"和"框架级OkHttp证书绑定"三种防护,模拟了真实应用的复杂安全环境。
3. Hook
针对上一节中修改后APK的三种证书校验机制,我们设计了以下归一化Hook脚本,实现一站式绕过。
3.1 归一后的完整脚本
javascript
import Java from "frida-java-bridge";
Java.perform(function () {
console.log("[*] ======================================");
console.log("[*] 通用证书绑定绕过脚本启动 (支持多场景)");
console.log("[*] 支持: SSLContext校验 + OkHttp3 CertificatePinner");
console.log("[*] ======================================");
// ======================================
// 替换 SSLContext TrustManager 绕过证书校验
// ======================================
try {
// 创建无校验的自定义 TrustManager
const CustomTrustManager = Java.registerClass({
name: 'com.example.frida.CustomTrustManager',
implements: [Java.use("javax.net.ssl.X509TrustManager")],
methods: {
checkClientTrusted: function (chain, authType) {
// 空实现:不校验客户端证书
},
checkServerTrusted: function (chain, authType) {
// 空实现:不校验服务器证书(核心绕过逻辑)
},
getAcceptedIssuers: function () {
return []; // 返回空列表,不限制信任CA
}
}
});
const trustManagerInstance = CustomTrustManager.$new();
const SSLContext = Java.use("javax.net.ssl.SSLContext");
// Hook SSLContext 初始化方法,替换信任管理器
SSLContext.init.overload(
"[Ljavax.net.ssl.KeyManager;",
"[Ljavax.net.ssl.TrustManager;",
"java.security.SecureRandom"
).implementation = function (keyManagers, trustManagers, secureRandom) {
console.log("[+] [SSLContext] 拦截初始化,替换为无校验TrustManager");
// 强制使用自定义TrustManager,忽略原始配置
this.init(keyManagers, [trustManagerInstance], secureRandom);
};
console.log("[+] [SSLContext] 绕过逻辑加载成功");
} catch (e) {
console.log("[-] [SSLContext] 绕过逻辑加载失败: " + e.message);
}
// ======================================
// OkHttp3 CertificatePinner 专属绕过
// ======================================
try {
const CertPinner = Java.use("okhttp3.CertificatePinner");
// Hook check 方法(直接跳过校验)
if (CertPinner.check) {
CertPinner.check.overloads.forEach((overload) => {
overload.implementation = function (...args) {
const hostname = args[0] || "未知域名";
console.log(`[+] [OkHttp3] 绕过 CertificatePinner.check | 域名: ${hostname}`);
// 空实现:不执行原校验逻辑
};
});
}
// Hook findMatchingPins 方法(返回空列表)
if (CertPinner.findMatchingPins) {
CertPinner.findMatchingPins.overload("java.lang.String").implementation = function (hostname) {
console.log(`[+] [OkHttp3] 绕过 CertificatePinner.findMatchingPins | 域名: ${hostname}`);
// 返回空列表,让OkHttp认为无证书绑定
return Java.use("java.util.ArrayList").$new();
};
}
console.log("[+] [OkHttp3] 绕过逻辑加载成功");
} catch (e) {
console.log("[-] [OkHttp3] 绕过逻辑加载失败 (可能未使用OkHttp3): " + e.message);
}
console.log("[*] ======================================");
console.log("[*] 所有绕过逻辑加载完成,等待目标请求...");
console.log("[*] ======================================");
});
3.2 脚本作用详解
-
SSLContext校验绕过
- 核心逻辑:创建一个"无校验"的自定义
X509TrustManager(CustomTrustManager),其checkClientTrusted和checkServerTrusted方法均为空实现(不做任何校验)。 - Hook点:拦截
SSLContext.init方法,强制将应用原本使用的信任管理器替换为自定义的无校验版本。这样无论应用是通过默认信任管理器还是自定义实现进行校验,都会被替换为"不校验"逻辑,绕过应用层和系统级的证书校验。
- 核心逻辑:创建一个"无校验"的自定义
-
OkHttp3 CertificatePinner绕过
- 针对OkHttp框架的证书绑定机制,通过两个关键点Hook实现绕过:
- Hook
check方法:直接空实现,跳过证书绑定的核心校验步骤。 - Hook
findMatchingPins方法:返回空列表,让OkHttp认为当前域名没有绑定任何证书,从而不触发校验逻辑。
- Hook
- 这两个Hook点配合,可彻底绕过OkHttp的证书绑定限制。
- 针对OkHttp框架的证书绑定机制,通过两个关键点Hook实现绕过:
-
未保留
TrustManagerImpl绕过方式- 当前 Hook 脚本未保留《实战篇5》的方案一代码,因为
TrustManagerImpl本质是X509TrustManager接口的具体实现类,而本脚本通 HookSSLContext.init方法替换整个TrustManager数组,无论应用使用的是系统默认的TrustManagerImpl,还是自定义的TrustManager子类,都会被统一替换为无校验的自定义实现,已完全覆盖TrustManagerImpl的绕过场景。
- 当前 Hook 脚本未保留《实战篇5》的方案一代码,因为
3.3 绕过效果和Burp抓包
如《实战篇4》中,在本地启动Python HTTPS服务后,依次启动设备中的Frida服务,加载上述Hook脚本。操作APK发送请求后,可观察到以下效果:
- 应用能正常响应GET和POST请求,说明证书校验被成功绕过。


- 在《实战篇2》中配置了 BurpSuite 作为中间人代理后,可在BurpSuite中完整捕获到应用的所有网络请求和响应),证明Hook成功解除了证书校验限制,实现了中间人抓包。

4. 本章总结
本章通过整合前三个章节的知识点,实现了一个通用的证书校验绕过Hook脚本,主要包含以下核心内容:
-
场景覆盖 :脚本同时支持三种常见证书校验场景------基于
SSLContext的信任管理器校验、network_security_config.xml的系统级校验、OkHttp框架的CertificatePinner绑定,解决了单一脚本难以适配多场景的问题。 -
技术要点:
- 通过替换
SSLContext的信任管理器,从底层绕过证书链校验逻辑; - 通过Hook OkHttp的
check和findMatchingPins方法,针对性解除框架级证书绑定; - 采用模块化设计,各绕过逻辑独立封装,降低了维护成本。
- 通过替换
-
实战价值:绕过SSL Pinning(证书绑定)是Frida Hook技术在移动安全测试中的核心应用场景之一。通过Frida动态Hook,我们无需修改应用源码或重新打包,即可临时解除证书校验限制,快速实现中间人抓包,为分析应用通信协议、调试接口逻辑提供了便利。
-
扩展说明 :需要注意的是,本章提供的脚本仅覆盖了主流的证书校验机制,而现实场景中,很多应用为了提升安全性,可能会采用更复杂的定制化校验方案 ------ 例如:自定义实现非标准的证书校验逻辑(而非依赖
X509TrustManager)、基于第三方加密库(如 BoringSSL)的底层证书校验、对证书链完整性的额外校验(如校验证书颁发者、有效期之外的自定义规则)、甚至通过 Native 层(C/C++)实现证书校验逻辑以规避 Java 层 Hook。
因此,本脚本可作为通用绕过的基础框架,大家在实际使用时,可根据目标应用的具体校验机制进一步强化:比如增加对其他网络库(如 Volley、Alamofire 等)的 Hook 支持、扩展 Native 层证书校验的绕过逻辑、添加对定制化TrustManager的针对性 Hook、补充证书哈希校验的拦截逻辑等。通过不断积累不同应用的校验场景,逐步完善脚本的通用性和适配能力,应对更多复杂的实际需求。
5. 下章预告
本章我们完成了客户端对服务端的证书校验绕过,但在金融、政务、隐私保护等敏感类 APP中,证书绑定的防护逻辑更为严密 ------ 服务端会通过客户端证书绑定执行双向校验,仅允许持有合规客户端证书的设备建立连接,以此杜绝非法客户端接入、保障核心数据传输安全。
下一章,我们将精准聚焦这一高频应用场景。