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

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

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

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

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

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


目录

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

  2. [突破 SSL Pinning(证书绑定)](#突破 SSL Pinning(证书绑定) "#2-%E7%AA%81%E7%A0%B4-ssl-pinning%E8%AF%81%E4%B9%A6%E7%BB%91%E5%AE%9A")

  3. [突破 Flutter 应用的证书校验限制](#突破 Flutter 应用的证书校验限制 "#3-%E7%AA%81%E7%A0%B4-flutter-%E5%BA%94%E7%94%A8%E7%9A%84%E8%AF%81%E4%B9%A6%E6%A0%A1%E9%AA%8C%E9%99%90%E5%88%B6")

  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 在内存中临时将验证函数"修改"掉。

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

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

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

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

bash 复制代码
# 对于 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
javascript 复制代码
// 通用 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% 移动端应用的抓包限制。

相关推荐
thesky1234562 小时前
智能体面试准备(九):工作流编排——DAG 与状态机两种范式的取舍与手写实现
面试·agent·状态机·工作流·智能体
Revolution612 小时前
reactive 对象重新赋值后,表单为什么没有恢复默认值
前端·vue.js·面试
HeiSenBerg2 小时前
Android Handler 机制完全解析:从源码到内存泄漏,一篇就够了
面试
only-qi4 小时前
大模型Agent面试攻略:落地工程痛点、评估体系与Agentic RAG核心精讲
人工智能·算法·面试·职场和发展·langchain·rag
ShineWinsu4 小时前
对于Linux:传输层协议UDP原理的解析
linux·c++·面试·udp·协议·传输层·计算机系统
GitLqr5 小时前
StatefulWidget 里的隐形炸弹:为什么不要在 State 类中使用 context.mounted
flutter·面试·dart
梦想的颜色6 小时前
2026 AI Agent 工程师完整技术图谱|从面试题「什么是本体 Ontology」切入,附精选面试题库
面试·知识图谱·langgraph·aiagent·大模型面试·本体·2026 面试真题
不简说7 小时前
JS 代码技巧 vol.10 — 20 个 V8 引擎原理,解释"为什么这样写快"
前端·javascript·面试
A富得流油的咸鸭蛋8 小时前
安卓鸿蒙面试
android·面试·harmonyos