Translated ['src/mobile-pentesting/android-app-pentesting/flutter.md'] t

This commit is contained in:
Translator 2025-05-20 05:38:20 +00:00
parent cf1033bbce
commit 51865b6f49

View File

@ -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<br>`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/)