Flutter
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 to Google’s cross-platform UI toolkit, który pozwala deweloperom pisać jedną bazę kodu w Dart, którą Engine (rodzimy C/C++) zamienia na specyficzny dla platformy kod maszynowy dla Androida i iOS. Engine zawiera Dart VM, BoringSSL, Skia itd. i jest dystrybuowany jako biblioteka współdzielona libflutter.so (Android) lub Flutter.framework (iOS). Cała rzeczywista komunikacja sieciowa (DNS, sockets, TLS) odbywa się wewnątrz tej biblioteki, nie w zwykłych warstwach Java/Kotlin Swift/Obj-C. Ta izolowana architektura tłumaczy, dlaczego standardowe hooki Frida na poziomie Java zawodzą w aplikacjach Flutter.
Intercepting HTTPS traffic in Flutter
This is a summary of this blog post.
Why HTTPS interception is tricky in Flutter
- SSL/TLS verification lives two layers down in BoringSSL, so Java SSL‐pinning bypasses don’t touch it.
- BoringSSL uses its own CA store inside libflutter.so; importing your Burp/ZAP CA into Android’s system store changes nothing.
- Symbols in libflutter.so are stripped & mangled, hiding the certificate-verification function from dynamic tools.
Fingerprint the exact Flutter stack
Znajomość wersji pozwala na przebudowanie lub dopasowanie wzorców odpowiednich binarek.
| Step | Command / File | Outcome |
|---|---|---|
| Get snapshot hash | python3 get_snapshot_hash.py libapp.so | 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.
Target: ssl_crypto_x509_session_verify_cert_chain()
- Located in
ssl_x509.ccinside BoringSSL. - Returns
bool– a singletrueis enough to bypass the whole certificate chain check. - Same function exists on every CPU arch; only the opcodes differ.
Option A – Binary patching with reFlutter
- Clone the exact Engine & Dart sources for the app’s Flutter version.
- Regex-patch two hotspots:
- In
ssl_x509.cc, forcereturn 1; - (Optional) In
socket_android.cc, hard-code a proxy ("10.0.2.2:8080").
- Re-compile libflutter.so, drop it back into the APK/IPA, sign, install.
- Pre-patched builds for common versions are shipped in the reFlutter GitHub releases to save hours of build time.
### Option B – Live hooking with Frida (the “hard-core” path) Because the symbol is stripped, you pattern-scan the loaded module for its first bytes, then change the return value on the fly.
// 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"); }
});
Proszę wklej zawartość pliku src/mobile-pentesting/android-app-pentesting/flutter.md (lub potwierdź, że mam przetłumaczyć cały plik), abym mógł go przetłumaczyć na polski zachowując oryginalne znaczniki markdown/html.
frida -U -f com.example.app -l bypass.js
Wskazówki dotyczące portowania
- Dla arm64-v8a lub armv7, pobierz pierwsze ~32 bajty funkcji z Ghidra, skonwertuj je na oddzielony spacjami ciąg heksadecymalny i podmień
sig. - Trzymaj po jednym wzorcu na wydanie Flutter, przechowuj je w ściągawce do szybkiego wykorzystania.
Wymuszanie ruchu przez proxy
Flutter sam ignoruje ustawienia proxy urządzenia. Najprostsze opcje:
- Android Studio emulator: Settings ▶ Proxy → manual.
- Urządzenie fizyczne: evil Wi-Fi AP + DNS spoofing, lub moduł Magisk edytujący
/etc/hosts.
Szybki workflow obejścia TLS dla Flutter (Frida Codeshare + system CA)
Gdy potrzebujesz tylko obserwować pinowane API Fluttera, połączenie zrootowanego/zapisywalnego AVD, systemowo zaufanego CA proxy i gotowego skryptu Frida często bywa szybsze niż reverse-engineering libflutter.so:
-
Zainstaluj swój proxy CA w system store. Postępuj zgodnie z Install Burp Certificate, aby zahashować/zmienić nazwę certyfikatu DER Burp i wypchnąć go do
/system/etc/security/cacerts/(wymagany zapisywalny/system). -
Skopiuj pasujący binarny
frida-serveri uruchom go jako root, tak aby mógł dołączyć do procesu Flutter:
adb push frida-server-17.0.5-android-x86_64 /data/local/tmp/frida-server
adb shell "su -c 'chmod 755 /data/local/tmp/frida-server && /data/local/tmp/frida-server &'"
- Zainstaluj narzędzia po stronie hosta i wyenumeruj pakiet docelowy.
pip3 install frida-tools --break-system-packages
adb shell pm list packages -f | grep target
- Uruchom aplikację Flutter z Codeshare hook, który unieszkodliwia BoringSSL pin checks.
frida -U -f com.example.target --codeshare TheDauntless/disable-flutter-tls-v1 --no-pause
Skrypt Codeshare nadpisuje weryfikator TLS Fluttera, dzięki czemu każdy certyfikat (w tym dynamicznie generowane przez Burp) jest akceptowany, omijając public-key pin comparisons.
-
Przekieruj ruch przez swój serwer proxy. Skonfiguruj GUI proxy Wi‑Fi emulatora lub wymuś je za pomocą
adb shell settings put global http_proxy 10.0.2.2:8080; jeśli bezpośrednie routowanie zawiedzie, użyjadb reverse tcp:8080 tcp:8080albo host-only VPN. -
Jeśli aplikacja ignoruje ustawienia proxy systemu, przekieruj gniazda za pomocą Frida shim. Narzędzia takie jak frida4burp hookują tworzenie gniazd
dart:io/BoringSSL, aby wymusić wychodzące sesje TCP do twojego proxy, nawet przy hardcodowanymHttpClient.findProxyFromEnvironmentlub obejściach Wi‑Fi. Ustaw host/port proxy w skrypcie i uruchom go razem z TLS bypass:
frida -U -f com.example.target --no-pause \
--codeshare TheDauntless/disable-flutter-tls-v1 \
-l frida4burp.js
Działa na iOS przez Frida gadget lub USB frida-server; łączenie socket redirect z TLS bypass przywraca zarówno routing, jak i akceptację certyfikatów dla Burp/mitmproxy.
Gdy CA jest zaufany na warstwie OS i Frida unieszkodliwia Flutter’s pinning logic (oraz socket redirection, jeśli potrzeba), Burp/mitmproxy odzyskuje pełną widoczność do API fuzzingu (BOLA, token tampering itp.) bez repackowania APK.
Hook oparty na offsetcie weryfikacji BoringSSL (bez signature scan)
Kiedy skrypty oparte na wzorcach zawodzą między architekturami (np. x86_64 vs ARM), podczep się bezpośrednio do chain verifier BoringSSL przez adres absolutny w libflutter.so. Przebieg:
- Wyodrębnij bibliotekę o odpowiednim ABI z APK:
unzip -j app.apk "lib/*/libflutter.so" -d libs/i wybierz tę pasującą do urządzenia (np.lib/x86_64/libflutter.so). - Analizuj w Ghidra/IDA i zlokalizuj verifier:
- Źródło: BoringSSL ssl_x509.cc function
ssl_crypto_x509_session_verify_cert_chain(3 args, returns bool). - W stripped builds użyj Search → For Strings →
ssl_client→ XREFs, następnie otwórz każdy odwołanyFUN_...i wybierz ten z 3 argumentami wyglądającymi na wskaźniki oraz zwracający boolean. - Oblicz runtime offset: weź adres funkcji pokazywany przez Ghidra i odejmij image base (np. Ghidra często pokazuje
0x00100000dla PIE Android ELF-ów). Przykład:0x02184644 - 0x00100000 = 0x02084644. - Podczep się w czasie wykonywania używając base + offset i wymuś sukces:
// frida -U -f com.target.app -l bypass.js --no-pause
const base = Module.findBaseAddress('libflutter.so');
// Example offset from analysis. Recompute per build/arch.
const off = ptr('0x02084644');
const addr = base.add(off);
// ssl_crypto_x509_session_verify_cert_chain: 3 args, bool return
Interceptor.replace(addr, new NativeCallback(function (a, b, c) {
return 1; // true
}, 'int', ['pointer', 'pointer', 'pointer']));
console.log('[+] Hooked BoringSSL verify_cert_chain at', addr);
Uwagi
- Signature scans mogą się powieść na ARM, ale nie wykryć na x86_64, ponieważ układ opcode się zmienia; ta offset method jest architecture-agnostic, o ile przeliczy się RVA.
- Ten bypass powoduje, że BoringSSL akceptuje dowolny chain, umożliwiając HTTPS MITM niezależnie od pins/CA trust wewnątrz Flutter.
- Jeśli wymusisz routowanie ruchu podczas debuggingu, aby potwierdzić TLS blocking, np.:
iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination <Burp_IP>:<Burp_Port>
…wciąż będziesz potrzebować powyższego hooka, ponieważ weryfikacja odbywa się wewnątrz libflutter.so, a nie w systemowym magazynie zaufania Androida.
References
- https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/
- Flutter SSL Bypass: How to Intercept HTTPS Traffic When all other Frida Scripts Fail (vercel)
- Flutter SSL Bypass: How to Intercept HTTPS Traffic When all other Frida Scripts Fail (medium)
- PoC Frida hook for Flutter SSL bypass
- BoringSSL ssl_x509.cc (ssl_crypto_x509_session_verify_cert_chain)
- SSL Pinning Bypass – Android
- Practical Mobile Traffic Interception
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.


