Flutter
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Flutter ist Googles plattformübergreifendes UI-Toolkit, mit dem Entwickler eine einzige Dart-Codebasis schreiben können, die die Engine (native C/C++) in plattformspezifischen Maschinencode für Android & iOS übersetzt. Die Engine bündelt eine Dart VM, BoringSSL, Skia etc. und wird als Shared Library libflutter.so (Android) oder Flutter.framework (iOS) ausgeliefert. Alle eigentlichen Netzwerkfunktionen (DNS, sockets, TLS) laufen innerhalb dieser Library, nicht in den üblichen Java/Kotlin- oder Swift/Obj‑C‑Schichten. Dieses isolierte Design ist der Grund, warum die üblichen Java-Ebene Frida-Hooks bei Flutter-Apps fehlschlagen.
HTTPS-Verkehr in Flutter abfangen
Dies ist eine Zusammenfassung dieses blog post.
Warum das Abfangen von HTTPS in Flutter knifflig ist
- SSL/TLS-Verifikation liegt zwei Ebenen tiefer in BoringSSL, daher greifen Java-SSL‑Pinning-Bypässe nicht.
- BoringSSL verwendet seinen eigenen CA-Store innerhalb von libflutter.so; das Importieren deiner Burp/ZAP-CA in den Android-Systemstore ändert nichts.
- Symbole in libflutter.so sind stripped und mangled, wodurch die Zertifikatsprüfungsfunktion vor dynamischen Tools verborgen wird.
Fingerprint des genauen Flutter-Stacks
Wenn du die Version kennst, kannst du die richtigen Binärdateien neu bauen oder per Pattern abgleichen.
| 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 die exakten Engine- & Dart-Quellen für die Flutter-Version der App.
- Regex-patch zwei Hotspots:
- In
ssl_x509.ccerzwingereturn 1; - (Optional) In
socket_android.cceinen Proxy hart kodieren ("10.0.2.2:8080").
- Re-compile libflutter.so, ersetze sie im APK/IPA, signiere, installiere.
- Pre-patched builds für gängige Versionen werden in den reFlutter GitHub-Releases mitgeliefert, um Stunden an Build-Zeit zu sparen.
### Option B – Live hooking with Frida (the “hard-core” path) Weil das Symbol stripped ist, pattern-scannt man das geladene Modul nach seinen ersten Bytes und ändert dann zur Laufzeit den Rückgabewert.
// 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"); }
});
Ich habe die Anweisung verstanden. Bitte füge den Inhalt der Datei src/mobile-pentesting/android-app-pentesting/flutter.md hier ein (oder bestätige, dass ich Zugriff darauf habe), dann übersetze ich den relevanten englischen Text ins Deutsche unter Beibehaltung der Markdown-/HTML-Syntax.
frida -U -f com.example.app -l bypass.js
Portierungstipps
- For arm64-v8a or armv7, grab the first ~32 bytes of the function from Ghidra, convert to a space-separated hex string, and replace
sig. - Keep one pattern per Flutter release, store them in a Spickzettel for fast reuse.
Verkehr über deinen Proxy erzwingen
Flutter selbst ignoriert die Proxy-Einstellungen des Geräts. Einfachste Optionen:
- Android Studio emulator: Settings ▶ Proxy → manual.
- Physisches Gerät: evil Wi-Fi AP + DNS spoofing, oder Magisk-Modul (Bearbeitung von
/etc/hosts).
Schneller Flutter TLS-Bypass-Workflow (Frida Codeshare + system CA)
When you only need to observe a pinned Flutter API, combining a rooted/writable AVD, a system-trusted proxy CA, and a drop-in Frida script is often faster than reverse-engineering libflutter.so:
-
Install your proxy CA in the system store. Follow Install Burp Certificate to hash/rename Burp’s DER certificate and push it into
/system/etc/security/cacerts/(writable/systemrequired). -
Drop a matching
frida-serverbinary and run it as root so it can attach to the Flutter process:
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 &'"
- Installieren Sie die hostseitigen Tools und enumerieren Sie das target package.
pip3 install frida-tools --break-system-packages
adb shell pm list packages -f | grep target
- Spawn die Flutter-App mit dem Codeshare-Hook, der BoringSSL pin checks neutralisiert.
frida -U -f com.example.target --codeshare TheDauntless/disable-flutter-tls-v1 --no-pause
Das Codeshare-Skript überschreibt den Flutter TLS-Verifier, sodass jedes Zertifikat (einschließlich der dynamisch von Burp erzeugten) akzeptiert wird und Public-Key-Pin-Vergleiche umgangen werden.
-
Route traffic through your proxy. Konfiguriere die Proxy-GUI des Emulators für Wi‑Fi oder setze ihn über
adb shell settings put global http_proxy 10.0.2.2:8080durch; falls direkte Weiterleitung fehlschlägt, greife aufadb reverse tcp:8080 tcp:8080oder ein host-only VPN zurück. -
If the app ignores OS proxy settings, redirect sockets with a Frida shim. Tools wie frida4burp hook
dart:io/BoringSSL socket creation, um ausgehende TCP-Sessions auf deinen Proxy zu zwingen, selbst bei hartkodiertemHttpClient.findProxyFromEnvironmentoder Wi‑Fi-Umgehungen. Setze Host/Port des Proxys im Skript und starte es zusammen mit dem TLS-Bypass:
frida -U -f com.example.target --no-pause \
--codeshare TheDauntless/disable-flutter-tls-v1 \
-l frida4burp.js
Funktioniert auf iOS via a Frida gadget oder USB frida-server; die Verkettung des socket redirect mit dem TLS bypass stellt sowohl das Routing als auch die Zertifikatsakzeptanz für Burp/mitmproxy wieder her.
Sobald die CA auf OS-Ebene vertraut wird und Frida Flutters pinning-Logik außer Kraft setzt (plus socket redirection falls nötig), erhält Burp/mitmproxy wieder volle Sichtbarkeit für API fuzzing (BOLA, token tampering, etc.) ohne das APK neu zu packen.
Offset-basierter Hook of BoringSSL verification (no signature scan)
Wenn pattern-based scripts über Architekturen hinweg fehlschlagen (z. B. x86_64 vs ARM), hooke direkt den BoringSSL chain verifier per absoluter Adresse innerhalb von libflutter.so. Workflow:
- Extrahiere die richtige-ABI Bibliothek aus dem APK:
unzip -j app.apk "lib/*/libflutter.so" -d libs/und wähle diejenige, die zum Gerät passt (z. B.lib/x86_64/libflutter.so). - Analysiere in Ghidra/IDA und finde den verifier:
- Source: BoringSSL ssl_x509.cc function
ssl_crypto_x509_session_verify_cert_chain(3 args, returns bool). - In stripped builds, benutze Search → For Strings →
ssl_client→ XREFs, öffne dann jede referenzierteFUN_...und wähle diejenige mit 3 pointer-like args und einem boolean return. - Berechne das Runtime-Offset: nimm die von Ghidra angezeigte Funktionsadresse und subtrahiere die image base (z. B. zeigt Ghidra oft
0x00100000für PIE Android ELFs). Beispiel:0x02184644 - 0x00100000 = 0x02084644. - Hook zur Laufzeit bei base + offset und erzwinge Erfolg:
// 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);
Hinweise
- Signature scans können auf ARM erfolgreich sein, aber auf x86_64 fehlschlagen, weil sich das Opcode-Layout ändert; diese Offset-Methode ist architekturunabhängig, solange du die RVA neu berechnest.
- Dieser Bypass veranlasst BoringSSL, jede Chain zu akzeptieren, wodurch HTTPS MITM ermöglicht wird, unabhängig von pins/CA trust innerhalb von Flutter.
- Wenn du den Traffic während des Debuggings umleitest, um TLS-Blocking zu bestätigen, z. B.:
iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination <Burp_IP>:<Burp_Port>
…du wirst trotzdem den obenstehenden hook benötigen, da die Verifikation innerhalb von libflutter.so stattfindet, nicht in Android’s system trust store.
Referenzen
- 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
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.


