Flutter
Reading time: 4 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Flutter
Flutter è il toolkit UI cross-platform di Google che consente agli sviluppatori di scrivere un'unica base di codice Dart che l'Engine (C/C++ nativo) trasforma in codice macchina specifico per Android e iOS.
L'Engine include un Dart VM, BoringSSL, Skia, ecc., e viene fornito come libreria condivisa libflutter.so (Android) o Flutter.framework (iOS). Tutte le operazioni di rete effettive (DNS, socket, TLS) avvengono all'interno di questa libreria, non nei soliti livelli Java/Kotlin Swift/Obj-C. Questo design isolato è il motivo per cui i soliti hook di Frida a livello Java non funzionano sulle app Flutter.
Intercettare il traffico HTTPS in Flutter
Questo è un riepilogo di questo blog post.
Perché l'intercettazione HTTPS è complicata in Flutter
- La verifica SSL/TLS si trova due livelli più in basso in BoringSSL, quindi i bypass di SSL‐pinning Java non la toccano.
- BoringSSL utilizza il proprio store CA all'interno di libflutter.so; importare il tuo CA di Burp/ZAP nello store di sistema di Android non cambia nulla.
- I simboli in libflutter.so sono strippati e offuscati, nascondendo la funzione di verifica del certificato dagli strumenti dinamici.
Identificare esattamente lo stack Flutter
Conoscere la versione ti consente di ricostruire o abbinare i binari giusti.
Passo | Comando / File | Risultato |
---|---|---|
Ottieni hash snapshot | bash\npython3 get_snapshot_hash.py libapp.so\n | adb4292f3ec25… |
Mappa hash → Engine | enginehash list in reFlutter | Flutter 3 · 7 · 12 + commit engine 1a65d409… |
Recupera commit dipendenti | File DEPS in quel commit engine | • dart_revision → Dart v2 · 19 · 6• dart_boringssl_rev → BoringSSL 87f316d7… |
Trova get_snapshot_hash.py qui.
Target: ssl_crypto_x509_session_verify_cert_chain()
- Situato in
ssl_x509.cc
all'interno di BoringSSL. - Restituisce
bool
– un singolotrue
è sufficiente per bypassare l'intero controllo della catena di certificati. - La stessa funzione esiste su ogni architettura CPU; solo gli opcode differiscono.
Opzione A – Patch binaria con reFlutter
- Clona esattamente le sorgenti di Engine e Dart per la versione Flutter dell'app.
- Regex-patch due hotspot:
- In
ssl_x509.cc
, forzarereturn 1;
- (Opzionale) In
socket_android.cc
, hard-code un proxy ("10.0.2.2:8080"
).
- Ricompila libflutter.so, reinseriscilo nell'APK/IPA, firma, installa.
- Build pre-patchate per versioni comuni sono disponibili nelle release di reFlutter su GitHub per risparmiare ore di tempo di build.
Opzione B – Hooking live con Frida (il percorso “hard-core”)
Poiché il simbolo è strippato, esegui una scansione del modulo caricato per i suoi primi byte, quindi cambia il valore di ritorno al volo.
// 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"); }
});
Esegui:
frida -U -f com.example.app -l bypass.js
Consigli per il porting
- Per arm64-v8a o armv7, prendi i primi ~32 byte della funzione da Ghidra, converti in una stringa esadecimale separata da spazi e sostituisci
sig
. - Mantieni un modello per ogni rilascio di Flutter, conservali in un cheat-sheet per un rapido riutilizzo.
Forzare il traffico attraverso il tuo proxy
Flutter stesso ignora le impostazioni del proxy del dispositivo. Opzioni più semplici:
- Emulatore Android Studio: Impostazioni ▶ Proxy → manuale.
- Dispositivo fisico: AP Wi-Fi malevolo + spoofing DNS, o modifica del modulo Magisk
/etc/hosts
.