mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/mobile-pentesting/android-app-pentesting/flutter.md'] t
This commit is contained in:
parent
8b0556771e
commit
df423d47d4
75
src/mobile-pentesting/android-app-pentesting/flutter.md
Normal file
75
src/mobile-pentesting/android-app-pentesting/flutter.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Flutter
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
# 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](https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/).
|
||||
|
||||
### 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<br>• `dart_boringssl_rev` → BoringSSL `87f316d7…`
|
||||
|
||||
Trova [get_snapshot_hash.py qui](https://github.com/Impact-I/reFlutter/blob/main/scripts/get_snapshot_hash.py).
|
||||
|
||||
### 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"`).
|
||||
3. **Ricompila** libflutter.so, reinseriscilo nell'APK/IPA, firma, installa.
|
||||
4. **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
|
||||
- [https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/](https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/)
|
Loading…
x
Reference in New Issue
Block a user