Charles 进阶抓包教程:突破 SSL Pinning、代理检测与 Flutter 抓包限制

0 阅读6分钟

在对移动端 App 进行数据抓包时,常会遇到以下问题:

  •   配置了代理后,App 提示**“网络连接不可用”**,Charles 中出现大量红锁或 SSLHandshake 握手失败。

  •   配置了代理后,网页能正常抓包,但目标 App 的流量完全不在 Charles 中显示

  •   针对 Flutter 开发的 App,普通的系统证书信任和代理设置完全无效。

本教程将深入剖析这些防御机制的原理,并提供从易到难的终极解决方案


目录

  1. 突破“绕过系统代理/直连”防御

  2. 突破 SSL Pinning(证书绑定)

  3. 突破 Flutter 应用的证书校验限制

  4. 高级排查决策树(如何选择方案)


1. 突破“绕过系统代理/直连”防御

1.1 防御原理

许多 App 在网络请求代码中,显式将代理设置为了 NO_PROXY(直连模式),或者在 iOS 中通过底层 API 绕过了系统全局 Wi-Fi 代理设置。这导致即使你在手机 Wi-Fi 属性中配置了 Charles 的 IP 和端口,App 的流量依然会直接发送到服务器,不经过 Charles。

1.2 解决方案:VPN 虚拟网卡强力劫持

既然 App 能够绕过 Wi-Fi 的 HTTP 代理,我们可以在手机本地建立一个虚拟的 VPN 通道。VPN 通道工作在网络层,会强行接管手机内的所有 TCP/UDP 流量,并将其打包转发给 PC 端的 Charles,使 App 无法通过 NO_PROXY 绕过。


graph TD

    App[目标 App 流量] -->|直连或拒绝代理| VPN[手机本地 VPN 软件]

    VPN -->|强制接管流量并打包| Charles[PC 端 Charles 8888]

    Charles -->|转发请求| Server[业务服务器]

🛠️ iOS 设备配置步骤(推荐 Shadowrocket)

  1. 在 iPhone 上安装 Shadowrocket(小火箭)Surge / Loon

  2. 打开小火箭,点击右上角 + 添加服务器。

  3. 配置参数:

   * 类型 (Type):选择 HTTPSOCKS5

   * 服务器 (Address):填写电脑的局域网 IP 地址。

   * 端口 (Port):填写 Charles 的端口(默认 8888)。

  1. 保存配置,在小火箭主页下方将 全局路由 (Global Routing) 修改为 代理 (Proxy)

  2. 开启小火箭的连接开关,允许系统创建 VPN。

  3. 此时,App 的流量就会被强制导入 Charles。

🛠️ Android 设备配置步骤(推荐 Postern)

  1. 在安卓手机上安装 Postern 软件。

  2. 打开 Postern,点击 配置代理服务器,添加你的 PC 端 Charles IP 与端口 8888,类型选择 SOCKS5 并保存。

  3. 点击 配置规则,添加一条规则:类型选择 匹配所有,动作选择 通过代理连接,代理服务器选择刚刚添加的配置,保存。

  4. 开启 Postern 的 VPN 代理服务即可。


2. 突破 SSL Pinning(证书绑定)

2.1 防御原理

SSL Pinning(证书绑定) 是一种高强度的安全校验机制。App 在发起 HTTPS 请求时,只信任其二进制包内预埋的特定证书公钥。当它检测到当前连接使用的是 Charles 自签名的根证书时,出于防中间人攻击的目的,会立即切断网络连接。

2.2 解决方案一:使用 Root / 越狱插件(一键全局绕过)

如果你的手机已经具备 Root 权限(Android)或越狱状态(iOS),使用现成的系统级 Hook 插件是最稳妥、快捷的方式。

🛠️ iOS 越狱机配置:

  1. 打开 Cydia 或 Sileo,添加主流源,搜索并安装插件 SSL Kill Switch 2

  2. 安装后,进入 iPhone 设置 -> 找到 SSL Kill Switch 2 -> 开启 Disable Certificate Validation 开关。

  3. 该插件会自动 Hook 系统底层的 Security.framework,强制使所有 App 的安全校验逻辑失效。

🛠️ Android Root 机配置:

  1. 确保手机已通过 Magisk 刷入 LSPosed 框架。

  2. 下载并安装模块 JustTrustMe(老系统推荐)或 TrustMeAlready(支持高版本 Android)。

  3. 在 LSPosed 控制台中激活该模块,并勾选目标 App。

  4. 重启目标 App,其内置的证书校验逻辑就会被自动绕过。


2.3 解决方案二:使用 Frida + Objection 动态插桩(免越狱/Root 首选)

如果你使用的是未越狱的设备,或者不想安装系统插件,可以通过 Frida 在内存中临时将验证函数“修改”掉。


# 1. 确保 PC 和手机已搭建好 Frida 环境,且运行了 frida-server。

# 2. 在 PC 终端中通过 objection 注入启动目标 App

objection -g "你的目标应用显示名称" explore

进入 Objection 交互式控制台后,输入以下命令即可动态绕过证书绑定:


# 对于 iOS 设备:

ios sslpinning disable

  


# 对于 Android 设备:

android sslpinning disable

(objection 会自动寻找常用的 AFNetworking、Alamofire、TrustKit 等库,并在内存中 Hook 它们的验证函数使其强行返回成功)


3. 突破 Flutter 应用的证书校验限制

3.1 防御原理

Flutter 应用具有极高抓包难度的原因在于其完全不走系统的网络协议栈。Flutter 拥有独立编译的二进制 Dart 虚拟机,其内部的加密库(BoringSSL)并不使用 iOS/Android 系统的根证书信任列表,并且忽略系统配置的全局代理。

3.2 解决方案:Frida 强制 Hook BoringSSL 校验函数

既然 Flutter 运行在其自带的 C/C++ 动态链接库(libflutter.soApp.framework)中,我们就需要使用 Frida 对其底层的汇编函数进行硬核 Hook。

🛠️ 实战步骤:

  1. 保存以下通用的 Flutter 绕过 JavaScript 脚本为 flutter_bypass.js

// 通用 Flutter SSL Pinning 绕过脚本片段

// 原理:定位 libflutter.so/App.framework 中的 ssl_crypto_x509_session_verify_cert_chain 并强制返回 1 (Success)

  


function bypassFlutter() {

    var m = Process.findModuleByName("libflutter.so") || Process.findModuleByName("App");

    if (!m) {

        console.log("[!] 未找到 Flutter 引擎模块");

        return;

    }

   

    console.log("[*] 找到 Flutter 引擎基址: " + m.base);

   

    // 不同的 Flutter 版本,其底层函数的特征码有所不同

    // 以下脚本会利用内存特征码搜索定位 verify_cert_chain 校验函数

    Memory.scan(m.base, m.size, "ff 03 05 d1 fc 6f 0f a9 f8 5f 10 a9 f6 57 11 a9", {

        onMatch: function (address, size) {

            console.log("[*] 成功定位 Flutter SSL 校验函数地址: " + address);

            Interceptor.attach(address, {

                onLeave: function (retval) {

                    console.log("[+] 绕过 Flutter 证书链验证,强制返回成功");

                    retval.replace(1); // 强制返回 1 (Verify Success)

                }

            });

        },

        onComplete: function () {

            console.log("[*] 内存特征扫描结束");

        }

    });

}

  


Java.perform(function () {

    bypassFlutter();

});

  1. 配合 VPN 劫持工具(如 Shadowrocket 转发到电脑),并使用以下命令启动注入:

   ```bash

   frida -U -f <包名> -l flutter_bypass.js

   ```


4. 高级排查决策树(如何选择方案)

当你面对一个新 App,不知道它采用了何种防御手段时,请按照以下“决策树”步骤逐步推进:


graph TD

    Start[1. 正常配置电脑 Charles 和手机 Wi-Fi 代理] --> Check1{Charles 窗口有无任何该 App 流量?}

   

    Check1 -->|完全没有流量| ActionProxy[2. 说明 App 绕过了代理直连<br>请使用 Shadowrocket 或 Postern 接管流量]

    Check1 -->|有流量,但全是红锁或报错| ActionPinning[3. 说明 App 启用了 SSL Pinning<br>请使用 Frida/Objection 或越狱插件绕过]

    Check1 -->|有流量,且全显示明文| End[恭喜! 抓包成功]

   

    ActionProxy --> Check2{接管流量后, 出现红锁报错吗?}

    Check2 -->|是, 变为红锁| ActionPinning

    Check2 -->|否, 显明文了| End

   

    ActionPinning --> Check3{App 是 Flutter 架构吗?}

    Check3 -->|是| ActionFlutter[4. 使用专门的 Flutter 内存 Hook 脚本]

    Check3 -->|否| ActionCommonPin[5. 使用 Objection sslpinning disable]

   

    ActionFlutter --> End

    ActionCommonPin --> End

通过以上系统化的层层排查,配合局域网环境及代理接管,可以突破市面上 99% 移动端应用的抓包限制。