Flutter
Reading time: 3 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
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.
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.
Cel: ssl_crypto_x509_session_verify_cert_chain()
- Znajduje się w
ssl_x509.cc
wewnątrz BoringSSL. - Zwraca
bool
– pojedynczetrue
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
- Sklonuj dokładne źródła Engine i Dart dla wersji Flutter aplikacji.
- 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"
).
- Rekompiluj libflutter.so, wrzuć z powrotem do APK/IPA, podpisz, zainstaluj.
- 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.
// 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:
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
.