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-ov alat za izradu UI koji radi na više platformi (cross-platform UI toolkit) koji omogućava developerima da pišu jedinstvenu Dart code-base koju Engine (native C/C++) pretvara u platform-specific machine code za Android & iOS. Engine sadrži Dart VM, BoringSSL, Skia, itd., i isporučuje se kao shared library libflutter.so (Android) ili Flutter.framework (iOS). Sav stvarni networking (DNS, sockets, TLS) se dešava unutar ove biblioteke, ne u uobičajenim Java/Kotlin Swift/Obj-C slojevima. Ta siloizovana arhitektura je razlog zašto uobičajeni Java-level Frida hookovi ne rade na Flutter aplikacijama.

Presretanje HTTPS saobraćaja u Flutter-u

Ovo je sažetak ovog blog post.

Zašto je presretanje HTTPS-a komplikovano u Flutter-u

  • SSL/TLS verification živi dva sloja niže u BoringSSL, pa Java SSL‐pinning bypasses ne utiču na to.
  • BoringSSL koristi svoj own CA store unutar libflutter.so; uvoz vašeg Burp/ZAP CA u Android’s system store ne menja ništa.
  • Simboli u libflutter.so su stripped & mangled, skrivajući funkciju za verifikaciju sertifikata od dinamičkih alata.

Fingerprint the exact Flutter stack

Poznavanje verzije vam omogućava da ponovo izgradite ili pattern-match-ujete odgovarajuće binarne fajlove.

StepCommand / FileOutcome
Get snapshot hashpython3 get_snapshot_hash.py libapp.soadb4292f3ec25…
Map hash → Engineenginehash list in reFlutterFlutter 3 · 7 · 12 + engine commit 1a65d409…
Pull dependent commitsDEPS 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) 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"); }
});

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

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

Saveti za portovanje

  • 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 cheat-sheet for fast reuse.

Forsiranje saobraćaja kroz vaš proxy

Flutter itself ignores device proxy settings. Easiest options:

  • Android Studio emulator: Settings ▶ Proxy → manual.
  • Fizički uređaj: zlonamerni Wi‑Fi AP + DNS spoofing, ili Magisk modul koji menja /etc/hosts.

Brzi workflow za zaobilaženje TLS-a u Flutter-u (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:

  1. 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 /system required).

  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 alatke na host strani i izlistajte ciljni paket.
pip3 install frida-tools --break-system-packages
adb shell pm list packages -f | grep target
  1. Pokrenite Flutter aplikaciju sa Codeshare hook-om koji onemogućava BoringSSL pin checks.
frida -U -f com.example.target --codeshare TheDauntless/disable-flutter-tls-v1 --no-pause

The Codeshare skripta pregazi Flutter TLS verifier tako da je svaki sertifikat (uključujući Burp-ove dinamički generisane) prihvaćen, zaobilazeći public-key pin comparisons.

  1. Usmerite saobraćaj kroz svoj proxy. Konfigurišite emulator Wi‑Fi proxy GUI ili ga primenite komandom adb shell settings put global http_proxy 10.0.2.2:8080; ako direktno rutiranje ne uspe, pređite na adb reverse tcp:8080 tcp:8080 ili host-only VPN.

  2. Ako aplikacija ignoriše OS proxy podešavanja, preusmerite sokete pomoću Frida shim. Alati kao što je frida4burp hook-uju kreiranje soketa dart:io/BoringSSL da bi prisilili izlazne TCP sesije kroz vaš proxy, čak i kod hardkodovanog HttpClient.findProxyFromEnvironment ili Wi‑Fi zaobilaženja. Postavite proxy host/port u skripti i pokrenite je zajedno sa TLS bypass-om:

frida -U -f com.example.target --no-pause \
--codeshare TheDauntless/disable-flutter-tls-v1 \
-l frida4burp.js

Radi na iOS-u preko Frida gadget-a ili USB frida-server-a; lančanje socket redirect-a sa TLS bypass-om vraća i rutiranje i prihvatanje sertifikata za Burp/mitmproxy.

Kada je CA poveren na OS nivou i Frida poništi Flutter-ovu pinning logiku (plus socket redirection ako je potrebno), Burp/mitmproxy ponovo dobija potpunu vidljivost za API fuzzing (BOLA, token tampering, itd.) bez repack-ovanja APK-a.

Hook zasnovan na offsetu BoringSSL verification (no signature scan)

Kada skripte zasnovane na pattern-u ne uspevaju između arhitektura (npr. x86_64 vs ARM), direktno hook-ujte BoringSSL chain verifier koristeći apsolutnu adresu unutar libflutter.so. Radni tok:

  • Izdvojite biblioteku odgovarajućeg ABI-ja 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, returns bool).
  • U stripped build-ovima, koristite Search → For Strings → ssl_client → XREFs, zatim otvorite svaki referencirani FUN_... i odaberite onaj sa 3 argumenata slična pokazivačima i boolean povratnom vrednošću.
  • Izračunajte runtime offset: uzmite adresu funkcije koju pokazuje Ghidra i oduzmite image base (npr. Ghidra često prikazuje 0x00100000 za PIE Android ELF-ove). Primer: 0x02184644 - 0x00100000 = 0x02084644.
  • Hook-ujte u runtime-u koristeći 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

  • Skeniranja potpisa mogu uspeti na ARM, ali propasti na x86_64 zato što se raspored opcode-a menja; ova metoda sa offset-om je nezavisna od arhitekture sve dok ponovo izračunate RVA.
  • Ovaj bypass navodi BoringSSL da prihvati bilo koji lanac sertifikata, omogućavajući HTTPS MITM bez obzira na pins/CA trust u Flutter-u.
  • Ako prisilno preusmerite saobraćaj tokom debugovanja da potvrdite blokiranje TLS-a, npr.:
iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination <Burp_IP>:<Burp_Port>

…i dalje će vam trebati hook iznad, pošto se verifikacija vrši 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