From 51865b6f49cc1a1620a1d78d353692c276b20cb3 Mon Sep 17 00:00:00 2001 From: Translator Date: Tue, 20 May 2025 05:38:20 +0000 Subject: [PATCH] Translated ['src/mobile-pentesting/android-app-pentesting/flutter.md'] t --- .../android-app-pentesting/flutter.md | 75 +++++++++++++++++++ 1 file changed, 75 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..6b86ce25a --- /dev/null +++ b/src/mobile-pentesting/android-app-pentesting/flutter.md @@ -0,0 +1,75 @@ +# Flutter + +{{#include ../../banners/hacktricks-training.md}} + +# Flutter +Flutter to **cross-platformowy zestaw narzędzi UI Google**, który pozwala deweloperom pisać jedną bazę kodu w Dart, którą **Engine** (natywny C/C++) przekształca w specyficzny dla platformy kod maszynowy dla Androida i iOS. +Engine łączy **Dart VM**, **BoringSSL**, Skia itp. i jest dostarczany jako wspólna biblioteka **libflutter.so** (Android) lub **Flutter.framework** (iOS). Cała rzeczywista komunikacja sieciowa (DNS, gniazda, TLS) odbywa się **wewnątrz tej biblioteki**, *a nie* w zwykłych warstwach Java/Kotlin Swift/Obj-C. Taki izolowany projekt jest powodem, dla którego zwykłe haki na poziomie Java nie działają w aplikacjach Flutter. + +## Przechwytywanie ruchu HTTPS w Flutter + +To jest podsumowanie tego [blog postu](https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/). + +### Dlaczego przechwytywanie HTTPS jest trudne w Flutter +* **Weryfikacja SSL/TLS znajduje się dwa poziomy niżej** w BoringSSL, więc obejścia SSL-pinningu w Java go nie dotykają. +* **BoringSSL używa swojego *własnego* magazynu CA** wewnątrz libflutter.so; importowanie swojego CA Burp/ZAP do systemowego magazynu Androida nic nie zmienia. +* Symbole w libflutter.so są **usunięte i zniekształcone**, ukrywając funkcję weryfikacji certyfikatu przed dynamicznymi narzędziami. + +### Zidentyfikuj dokładny stos Flutter +Znajomość wersji pozwala na odbudowanie lub dopasowanie odpowiednich binariów. + +Step | Command / File | Outcome +----|----|---- +Get snapshot hash | ```bash\npython3 get_snapshot_hash.py libapp.so\n``` | `adb4292f3ec25…` +Map hash → Engine | **enginehash** list in reFlutter | Flutter 3 · 7 · 12 + engine commit `1a65d409…` +Pull dependent commits | DEPS file in that engine commit | • `dart_revision` → Dart v2 · 19 · 6
• `dart_boringssl_rev` → BoringSSL `87f316d7…` + +Find [get_snapshot_hash.py here](https://github.com/Impact-I/reFlutter/blob/main/scripts/get_snapshot_hash.py). + +### Cel: `ssl_crypto_x509_session_verify_cert_chain()` +* Znajduje się w **`ssl_x509.cc`** wewnątrz BoringSSL. +* **Zwraca `bool`** – pojedyncze `true` wystarczy, aby obejść całą kontrolę łańcucha certyfikatów. +* Ta sama funkcja istnieje na każdej architekturze CPU; różnią się tylko kody operacyjne. + +### Opcja A – Łatanie binarne z **reFlutter** +1. **Sklonuj** dokładne źródła Engine i Dart dla wersji Flutter aplikacji. +2. **Regex-patch** dwa gorące punkty: +* W `ssl_x509.cc`, wymuś `return 1;` +* (Opcjonalnie) W `socket_android.cc`, twardo zakoduj proxy (`"10.0.2.2:8080"`). +3. **Rekompiluj** libflutter.so, wrzuć z powrotem do APK/IPA, podpisz, zainstaluj. +4. **Wstępnie załatane wersje** dla popularnych wersji są dostarczane w wydaniach reFlutter na GitHubie, aby zaoszczędzić godziny czasu budowy. + +### Opcja B – Żywe hakowanie z **Frida** (ścieżka "hard-core") +Ponieważ symbol jest usunięty, skanujesz wzór załadowanego modułu w poszukiwaniu jego pierwszych bajtów, a następnie zmieniasz wartość zwracaną w locie. +```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"); } +}); +``` +Przeprowadź to: +```bash +frida -U -f com.example.app -l bypass.js +``` +*Porady dotyczące przenoszenia* +* Dla **arm64-v8a** lub **armv7**, pobierz pierwsze ~32 bajty funkcji z Ghidra, przekształć na ciąg szesnastkowy oddzielony spacjami i zastąp `sig`. +* Zachowaj **jeden wzór na każdą wersję Fluttera**, przechowuj je w ściągawce dla szybkiego ponownego użycia. + +### Wymuszanie ruchu przez swój proxy +Flutter sam w sobie **ignoruje ustawienia proxy urządzenia**. Najprostsze opcje: +* **Emulator Android Studio:** Ustawienia ▶ Proxy → ręczne. +* **Urządzenie fizyczne:** złośliwy punkt dostępu Wi-Fi + spoofing DNS, lub edytowanie modułu Magisk `/etc/hosts`. + +## Odniesienia +- [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/)