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

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.

PassoComando / FileRisultato
Ottieni hash snapshotbash\npython3 get_snapshot_hash.py libapp.so\nadb4292f3ec25…
Mappa hash → Engineenginehash list in reFlutterFlutter 3 · 7 · 12 + commit engine 1a65d409…
Recupera commit dipendentiFile DEPS in quel commit enginedart_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 singolo true è 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

  1. Clona esattamente le sorgenti di Engine e Dart per la versione Flutter dell'app.
  2. Regex-patch due hotspot:
  • In ssl_x509.cc, forzare return 1;
  • (Opzionale) In socket_android.cc, hard-code un proxy ("10.0.2.2:8080").
  1. Ricompila libflutter.so, reinseriscilo nell'APK/IPA, firma, installa.
  2. 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.

javascript
// 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:

bash
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.

Riferimenti