【Frida Android】实战篇7:SSL Pinning 证书绑定绕过 Hook 教程阶段总结

文章目录

  • [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的源码进行了针对性修改,使其同时包含三种常见的证书校验机制,具体修改如下:

  1. 启用OkHttp证书绑定

    OkHttpClient.Builder()构建客户端时,添加certificatePinner方法,手动指定目标域名需要绑定的证书哈希。这样应用在使用OkHttp发起请求时,会强制校验服务器返回的证书是否与绑定的哈希匹配。

  2. 恢复默认X509TrustManager校验

    删除之前重写的X509TrustManager子类实现,让应用使用系统默认的信任管理器。此时应用会严格校验服务器证书是否在系统信任的CA列表中,未信任的证书会被拒绝。

  3. 配置系统级证书校验

    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 脚本作用详解

  1. SSLContext校验绕过

    • 核心逻辑:创建一个"无校验"的自定义X509TrustManagerCustomTrustManager),其checkClientTrustedcheckServerTrusted方法均为空实现(不做任何校验)。
    • Hook点:拦截SSLContext.init方法,强制将应用原本使用的信任管理器替换为自定义的无校验版本。这样无论应用是通过默认信任管理器还是自定义实现进行校验,都会被替换为"不校验"逻辑,绕过应用层和系统级的证书校验。
  2. OkHttp3 CertificatePinner绕过

    • 针对OkHttp框架的证书绑定机制,通过两个关键点Hook实现绕过:
      • Hookcheck方法:直接空实现,跳过证书绑定的核心校验步骤。
      • HookfindMatchingPins方法:返回空列表,让OkHttp认为当前域名没有绑定任何证书,从而不触发校验逻辑。
    • 这两个Hook点配合,可彻底绕过OkHttp的证书绑定限制。
  3. 未保留TrustManagerImpl绕过方式

    • 当前 Hook 脚本未保留《实战篇5》的方案一代码,因为TrustManagerImpl本质是X509TrustManager接口的具体实现类,而本脚本通 Hook SSLContext.init方法替换整个TrustManager数组,无论应用使用的是系统默认的TrustManagerImpl,还是自定义的TrustManager子类,都会被统一替换为无校验的自定义实现,已完全覆盖TrustManagerImpl的绕过场景。

3.3 绕过效果和Burp抓包

《实战篇4》中,在本地启动Python HTTPS服务后,依次启动设备中的Frida服务,加载上述Hook脚本。操作APK发送请求后,可观察到以下效果:

  • 应用能正常响应GET和POST请求,说明证书校验被成功绕过。


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

4. 本章总结

本章通过整合前三个章节的知识点,实现了一个通用的证书校验绕过Hook脚本,主要包含以下核心内容:

  1. 场景覆盖 :脚本同时支持三种常见证书校验场景------基于SSLContext的信任管理器校验、network_security_config.xml的系统级校验、OkHttp框架的CertificatePinner绑定,解决了单一脚本难以适配多场景的问题。

  2. 技术要点

    • 通过替换SSLContext的信任管理器,从底层绕过证书链校验逻辑;
    • 通过Hook OkHttp的checkfindMatchingPins方法,针对性解除框架级证书绑定;
    • 采用模块化设计,各绕过逻辑独立封装,降低了维护成本。
  3. 实战价值:绕过SSL Pinning(证书绑定)是Frida Hook技术在移动安全测试中的核心应用场景之一。通过Frida动态Hook,我们无需修改应用源码或重新打包,即可临时解除证书校验限制,快速实现中间人抓包,为分析应用通信协议、调试接口逻辑提供了便利。

  4. 扩展说明 :需要注意的是,本章提供的脚本仅覆盖了主流的证书校验机制,而现实场景中,很多应用为了提升安全性,可能会采用更复杂的定制化校验方案 ------ 例如:自定义实现非标准的证书校验逻辑(而非依赖X509TrustManager)、基于第三方加密库(如 BoringSSL)的底层证书校验、对证书链完整性的额外校验(如校验证书颁发者、有效期之外的自定义规则)、甚至通过 Native 层(C/C++)实现证书校验逻辑以规避 Java 层 Hook。

因此,本脚本可作为通用绕过的基础框架,大家在实际使用时,可根据目标应用的具体校验机制进一步强化:比如增加对其他网络库(如 Volley、Alamofire 等)的 Hook 支持、扩展 Native 层证书校验的绕过逻辑、添加对定制化TrustManager的针对性 Hook、补充证书哈希校验的拦截逻辑等。通过不断积累不同应用的校验场景,逐步完善脚本的通用性和适配能力,应对更多复杂的实际需求。

5. 下章预告

本章我们完成了客户端对服务端的证书校验绕过,但在金融、政务、隐私保护等敏感类 APP中,证书绑定的防护逻辑更为严密 ------ 服务端会通过客户端证书绑定执行双向校验,仅允许持有合规客户端证书的设备建立连接,以此杜绝非法客户端接入、保障核心数据传输安全。

下一章,我们将精准聚焦这一高频应用场景。

相关推荐
Whoami!1 小时前
⸢ 拾陆-V⸥⤳ 安全数智化建设:安全智能平台(上)▸概述
网络安全·信息安全·ai安全
用户2018792831672 小时前
Android 混淆引发的反序列化问题浅析
android
00后程序员张2 小时前
iOS 性能优化的体系化方法论 从启动速度到渲染链路的多工具协同优化
android·ios·性能优化·小程序·uni-app·iphone·webview
游戏开发爱好者83 小时前
iPhone重启日志深度解析与故障代码诊断
android·ios·小程序·https·uni-app·iphone·webview
TDengine (老段)5 小时前
TDengine 字符串函数 TO_BASE64 用户手册
android·大数据·服务器·物联网·时序数据库·tdengine·涛思数据
spencer_tseng6 小时前
Eclipse Oxygen 4.7.2 ADT(android developer tools) Plugin
android·java·eclipse
XH-hui7 小时前
【打靶日记】TheHackerLabs 之 THLPWN
linux·网络安全·thehackerlabs·thl
来来走走7 小时前
Android开发(Kotlin) 协程
android·java·kotlin