From 3756eca7a8f37494a637bfc04be39035756e289d Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 20 May 2025 05:38:07 +0000 Subject: [PATCH] Translated ['src/mobile-pentesting/android-app-pentesting/flutter.md'] t --- .../android-app-pentesting/flutter.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/mobile-pentesting/android-app-pentesting/flutter.md diff --git a/src/mobile-pentesting/android-app-pentesting/flutter.md b/src/mobile-pentesting/android-app-pentesting/flutter.md new file mode 100644 index 000000000..8e4b67c5d --- /dev/null +++ b/src/mobile-pentesting/android-app-pentesting/flutter.md @@ -0,0 +1,74 @@ +# Flutter + +{{#include ../../banners/hacktricks-training.md}} + +# Flutter +Flutter是**谷歌的跨平台UI工具包**,允许开发者编写单一的Dart代码库,**引擎**(本地C/C++)将其转换为Android和iOS的特定平台机器代码。引擎捆绑了**Dart VM**、**BoringSSL**、Skia等,并作为共享库**libflutter.so**(Android)或**Flutter.framework**(iOS)发布。所有实际的网络操作(DNS、套接字、TLS)都发生在**这个库内部**,*而不是*在通常的Java/Kotlin Swift/Obj-C层。这种孤立的设计是通常的Java级Frida钩子在Flutter应用中失败的原因。 + +## 在Flutter中拦截HTTPS流量 + +这是这篇[博客文章](https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/)的摘要。 + +### 为什么在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\n``` | `adb4292f3ec25…` +映射哈希 → 引擎 | **enginehash**列表在reFlutter中 | Flutter 3 · 7 · 12 + 引擎提交 `1a65d409…` +拉取依赖提交 | 在该引擎提交中的DEPS文件 | • `dart_revision` → Dart v2 · 19 · 6
• `dart_boringssl_rev` → BoringSSL `87f316d7…` + +在这里找到[get_snapshot_hash.py](https://github.com/Impact-I/reFlutter/blob/main/scripts/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"`)。 +3. **重新编译**libflutter.so,将其放回APK/IPA中,签名,安装。 +4. **预补丁构建**的常见版本在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-v8a** 或 **armv7**,从 Ghidra 中获取函数的前 ~32 字节,转换为以空格分隔的十六进制字符串,并替换 `sig`。 +* 每个 Flutter 版本保持 **一个模式**,将它们存储在备忘单中以便快速重用。 + +### 通过代理强制流量 +Flutter 本身 **忽略设备代理设置**。最简单的选项: +* **Android Studio 模拟器:** 设置 ▶ 代理 → 手动。 +* **物理设备:** 恶意 Wi-Fi AP + DNS 欺骗,或 Magisk 模块编辑 `/etc/hosts`。 + +## 参考 +- [https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/](https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/)