Flutter

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Flutter je Google’s cross-platform UI toolkit koji omogućava developerima da napišu jedinstvenu Dart code-base koju Engine (native C/C++) pretvara u platformno-specifičan mašinski kod za Android & iOS. Engine obuhvata Dart VM, BoringSSL, Skia, itd., i isporučuje se kao deljena biblioteka libflutter.so (Android) ili Flutter.framework (iOS). Sav stvarni networking (DNS, sockets, TLS) se odvija inside this library, not u uobičajenim Java/Kotlin Swift/Obj‑C slojevima. Ta siloizovana arhitektura je razlog zašto uobičajeni Java-level Frida hook‑ovi ne rade na Flutter aplikacijama.

Intercepting HTTPS traffic in Flutter

Ovo je sažetak ovog 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

Poznavanje verzije omogućava da ponovo izgradite ili pattern-matchujete prave binarije.

StepCommand / FileOutcome
Dobijte snapshot hashpython3 get_snapshot_hash.py libapp.soadb4292f3ec25…
Mapiraj hash → Engineenginehash list in reFlutterFlutter 3 · 7 · 12 + engine commit 1a65d409…
Povucite zavisne commit-oveDEPS file in that engine commitdart_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.cc inside BoringSSL.
  • Returns bool – a single true is 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

  1. Clone the exact Engine & Dart sources for the app’s Flutter version.
  2. Regex-patch two hotspots:
  • In ssl_x509.cc, force return 1;
  • (Optional) In socket_android.cc, hard-code a proxy ("10.0.2.2:8080").
  1. Re-compile libflutter.so, drop it back into the APK/IPA, sign, install.
  2. 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) Pošto je simbol stripped, pattern-skanirate učitani modul po njegovim prvim bajtovima, a zatim menjate return vrednost u letu.

// 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"); }
});

Molim vas nalepite sadržaj fajla src/mobile-pentesting/android-app-pentesting/flutter.md koji želite da prevedem.

frida -U -f com.example.app -l bypass.js

Saveti za portovanje

  • Za arm64-v8a ili armv7, uzmite prvih ~32 bajta funkcije iz Ghidra, konvertujte u hex string razdvojen razmacima i zamenite sig.
  • Keep one pattern per Flutter release, čuvajte ih u cheat-sheetu za brzo ponovno korišćenje.

Forsiranje saobraćaja kroz vaš proxy

Flutter sam ignoriše podešavanja proxy-a na uređaju. Najlakše opcije:

  • Android Studio emulator: Settings ▶ Proxy → manual.
  • Physical device: evil Wi‑Fi AP + DNS spoofing, ili Magisk modul koji menja /etc/hosts.

Brzi workflow za zaobilaženje Flutter TLS-a (Frida Codeshare + system CA)

Ako sve što treba jeste da posmatrate pinned Flutter API, kombinovanje rootovanog AVD-a sa zapisivim /system-om, sistemski poverenog proxy CA i drop-in Frida skripte često je brže od reverse-engineering-a libflutter.so:

  1. Install your proxy CA in the system store. Pratite Install Burp Certificate da izračunate heš i preimenujete Burp-ov DER sertifikat i kopirate ga u /system/etc/security/cacerts/ (/system mora biti zapisiv).

  2. Drop a matching frida-server binary 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 &'"
  1. Instalirajte host-side tooling i izlistajte ciljni paket.
pip3 install frida-tools --break-system-packages
adb shell pm list packages -f | grep target
  1. Pokreni Flutter aplikaciju sa Codeshare hook-om koji onesposobljava BoringSSL pin checks.
frida -U -f com.example.target --codeshare TheDauntless/disable-flutter-tls-v1 --no-pause

The Codeshare script overrides the Flutter TLS verifier so every certificate (including Burp’s dynamically generated ones) is accepted, side-stepping public-key pin comparisons.

  1. Usmeri saobraćaj kroz svoj proxy. Konfigurišite emulator Wi-Fi proxy GUI ili ga nametnite preko adb shell settings put global http_proxy 10.0.2.2:8080; ako direktno rutiranje ne uspe, koristite adb reverse tcp:8080 tcp:8080 ili host-only VPN.

Kada je CA poverljiv na nivou OS-a i Frida ugasi Flutter-ovu pinning logiku, Burp/mitmproxy ponovo dobija potpunu vidljivost za API fuzzing (BOLA, token tampering, itd.) bez potrebe za repackovanjem APK-a.

Offset-based hook of BoringSSL verification (no signature scan)

Kada pattern-based skripte zakažu između arhitektura (npr. x86_64 vs ARM), direktno zakačite BoringSSL chain verifier po apsolutnoj adresi unutar libflutter.so. Radni tok:

  • Izvucite biblioteku odgovarajućeg ABI iz APK-a: unzip -j app.apk "lib/*/libflutter.so" -d libs/ i izaberite onu koja odgovara uređaju (npr. lib/x86_64/libflutter.so).
  • Analizirajte u Ghidra/IDA i pronađite verifier:
  • Izvor: BoringSSL ssl_x509.cc funkcija ssl_crypto_x509_session_verify_cert_chain (3 args, vraća bool).
  • U stripped build-ovima, koristite Search → For Strings → ssl_client → XREFs, zatim otvorite svaki referencirani FUN_... i izaberite onaj sa 3 argumenata koji liče na pokazivače i bool povratkom.
  • Izračunajte runtime offset: uzmite adresu funkcije koju prikazuje Ghidra i oduzmite image base (npr. Ghidra često prikazuje 0x00100000 za PIE Android ELF-ove). Primer: 0x02184644 - 0x00100000 = 0x02084644.
  • Zakačite u runtime-u na base + offset i forsirajte uspeh:
// 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);

Napomene

  • Signature scans mogu uspeti na ARM, ali izostati na x86_64 zato što se raspored opcode-a menja; ova offset metoda je nezavisna od arhitekture sve dok ponovo izračunate RVA.
  • Ovaj bypass tera BoringSSL da prihvati bilo koji chain, omogućavajući HTTPS MITM bez obzira na pins/CA trust unutar Flutter.
  • Ako prisilno usmerite saobraćaj tokom debugovanja da biste potvrdili blokiranje TLS-a, na primer:
iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination <Burp_IP>:<Burp_Port>

…i dalje će vam trebati hook gore, jer se verifikacija obavlja unutar libflutter.so, a ne u Android’s system trust store.

Reference

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks