Flutter

Reading time: 5 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

Flutter

Flutter是谷歌的跨平台UI工具包,允许开发者编写单一的Dart代码库,引擎(本地C/C++)将其转换为Android和iOS的特定平台机器代码。引擎捆绑了Dart VMBoringSSL、Skia等,并作为共享库libflutter.so(Android)或Flutter.framework(iOS)发布。所有实际的网络操作(DNS、套接字、TLS)都发生在这个库内部而不是在通常的Java/Kotlin Swift/Obj-C层。这种孤立的设计是通常的Java级Frida钩子在Flutter应用中失败的原因。

在Flutter中拦截HTTPS流量

这是这篇博客文章的摘要。

为什么在Flutter中拦截HTTPS很棘手

  • SSL/TLS验证位于BoringSSL的两层下方,因此Java SSL固定绕过不会触及它。
  • BoringSSL在libflutter.so内部使用其自己的 CA存储;将你的Burp/ZAP CA导入Android的系统存储不会改变任何东西。
  • libflutter.so中的符号是剥离和混淆的,隐藏了证书验证功能,使动态工具无法使用。

确定确切的Flutter栈

知道版本可以让你重建或模式匹配正确的二进制文件。

步骤命令 / 文件结果
获取快照哈希bash\npython3 get_snapshot_hash.py libapp.so\nadb4292f3ec25…
映射哈希 → 引擎enginehash列表在reFlutter中Flutter 3 · 7 · 12 + 引擎提交 1a65d409…
拉取依赖提交在该引擎提交中的DEPS文件dart_revision → Dart v2 · 19 · 6
dart_boringssl_rev → BoringSSL 87f316d7…

在这里找到get_snapshot_hash.py

目标: ssl_crypto_x509_session_verify_cert_chain()

  • 位于BoringSSL内部的**ssl_x509.cc**。
  • 返回bool – 一个true就足以绕过整个证书链检查。
  • 每个CPU架构都有相同的函数;只有操作码不同。

选项A – 使用reFlutter进行二进制补丁

  1. 克隆应用的Flutter版本的确切引擎和Dart源代码。
  2. 正则补丁两个热点:
  • ssl_x509.cc中,强制return 1;
  • (可选)在socket_android.cc中,硬编码一个代理("10.0.2.2:8080")。
  1. 重新编译libflutter.so,将其放回APK/IPA中,签名,安装。
  2. 预补丁构建的常见版本在reFlutter GitHub发布中提供,以节省数小时的构建时间。

选项B – 使用Frida进行实时钩取(“硬核”路径)

由于符号被剥离,你需要对加载的模块进行模式扫描以获取其前几个字节,然后动态更改返回值。

javascript
// attach & locate libflutter.so
var flutter = Process.getModuleByName("libflutter.so");

// x86-64 pattern of the first 16 bytes of ssl_crypto_x509_session_verify_cert_chain
var sig = "55 41 57 41 56 41 55 41 54 53 48 83 EC 38 C6 02";

Memory.scan(flutter.base, flutter.size, sig, {
onMatch: function (addr) {
console.log("[+] found verifier at " + addr);
Interceptor.attach(addr, {
onLeave: function (retval) { retval.replace(0x1); }  // always 'true'
});
},
onComplete: function () { console.log("scan done"); }
});

请运行它:

bash
frida -U -f com.example.app -l bypass.js

移植提示

  • 对于 arm64-v8aarmv7,从 Ghidra 中获取函数的前 ~32 字节,转换为以空格分隔的十六进制字符串,并替换 sig
  • 每个 Flutter 版本保持 一个模式,将它们存储在备忘单中以便快速重用。

通过代理强制流量

Flutter 本身 忽略设备代理设置。最简单的选项:

  • Android Studio 模拟器: 设置 ▶ 代理 → 手动。
  • 物理设备: 恶意 Wi-Fi AP + DNS 欺骗,或 Magisk 模块编辑 /etc/hosts

参考