Flutter
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Flutter est le toolkit UI multiplateforme de Google qui permet aux développeurs d’écrire une seule base de code Dart que l’Engine (C/C++ natif) transforme en code machine spécifique à la plateforme pour Android & iOS. L’Engine embarque une Dart VM, BoringSSL, Skia, etc., et est distribué comme la bibliothèque partagée libflutter.so (Android) ou Flutter.framework (iOS). Tout le networking réel (DNS, sockets, TLS) se passe à l’intérieur de cette bibliothèque, et non dans les couches habituelles Java/Kotlin Swift/Obj-C. Cette conception en silo explique pourquoi les hooks Frida au niveau Java échouent sur les apps Flutter.
Intercepter le trafic HTTPS dans Flutter
Ceci est un résumé de cet article de blog.
Why HTTPS interception is tricky in Flutter
- La vérification SSL/TLS se trouve deux couches plus bas dans BoringSSL, donc les contournements de SSL‑pinning au niveau Java ne l’affectent pas.
- BoringSSL utilise son propre magasin de CA à l’intérieur de libflutter.so ; importer votre CA Burp/ZAP dans le store système d’Android ne change rien.
- Les symboles dans libflutter.so sont stripped & mangled, ce qui masque la fonction de vérification de certificat aux outils dynamiques.
Fingerprint the exact Flutter stack
Connaître la version permet de recompiler ou de faire du pattern-matching sur les bons binaires.
| Step | Command / File | Outcome |
|---|---|---|
| Get snapshot hash | python3 get_snapshot_hash.py libapp.so | adb4292f3ec25… |
| Map hash → Engine | enginehash list in reFlutter | Flutter 3 · 7 · 12 + engine commit 1a65d409… |
| Pull dependent commits | DEPS file in that engine commit | • dart_revision → Dart v2 · 19 · 6• dart_boringssl_rev → BoringSSL 87f316d7… |
Find get_snapshot_hash.py here.
Target: ssl_crypto_x509_session_verify_cert_chain()
- Située dans
ssl_x509.ccà l’intérieur de BoringSSL. - Retourne
bool– un seultruesuffit à contourner toute la vérification de la chaîne de certificats. - La même fonction existe sur toutes les architectures CPU ; seules les opcodes diffèrent.
Option A – Binary patching with reFlutter
- Clone les sources exactes de l’Engine et de Dart pour la version Flutter de l’application.
- Regex-patch deux hotspots :
- Dans
ssl_x509.cc, forcerreturn 1; - (Optionnel) Dans
socket_android.cc, coder en dur un proxy ("10.0.2.2:8080").
- Re-compiler libflutter.so, le replacer dans l’APK/IPA, signer, installer.
- Des builds pré-patchés pour les versions courantes sont fournis dans les releases GitHub de reFlutter pour économiser des heures de compilation.
Option B – Live hooking with Frida (la voie « hard-core »)
Parce que le symbole est stripped, vous pattern-scan le module chargé pour trouver ses premiers octets, puis modifiez la valeur de retour à la volée.
// 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"); }
});
Je n’ai pas le contenu du fichier src/mobile-pentesting/android-app-pentesting/flutter.md. Collez son contenu ici et j’effectuerai la traduction en respectant les consignes.
frida -U -f com.example.app -l bypass.js
Conseils de portage
- Pour arm64-v8a ou armv7, récupérez les ~32 premiers octets de la fonction depuis Ghidra, convertissez-les en une chaîne hex séparée par des espaces, et remplacez
sig. - Conservez un motif par version de Flutter, stockez-les dans une fiche de référence pour réutilisation rapide.
Forcer le trafic via votre proxy
Flutter lui‑même ignore les paramètres proxy de l’appareil. Options les plus simples :
- Android Studio emulator: Settings ▶ Proxy → manual.
- Physical device: evil Wi‑Fi AP + DNS spoofing, ou module Magisk modifiant
/etc/hosts.
Workflow rapide de contournement TLS pour Flutter (Frida Codeshare + system CA)
Quand vous avez seulement besoin d’observer une API Flutter pinée, combiner un AVD rooté/inscriptible, une CA proxy de confiance système, et un script Frida plug‑and‑play est souvent plus rapide que de rétroconcevoir libflutter.so :
-
Installez la CA de votre proxy dans le magasin système. Suivez Install Burp Certificate pour hasher/renommer le certificat DER de Burp et le pousser dans
/system/etc/security/cacerts/(un/systeminscriptible est requis). -
Déposez un binaire
frida-servercorrespondant et exécutez-le en root afin qu’il puisse s’attacher au processus Flutter :
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 &'"
- Installer les outils côté hôte et énumérer le package cible.
pip3 install frida-tools --break-system-packages
adb shell pm list packages -f | grep target
- Lancez l’application Flutter avec le Codeshare hook qui neutralise les vérifications de pin de BoringSSL.
frida -U -f com.example.target --codeshare TheDauntless/disable-flutter-tls-v1 --no-pause
Le script Codeshare remplace le vérificateur TLS de Flutter de sorte que chaque certificat (including Burp’s dynamically generated ones) est accepté, contournant les public-key pin comparisons.
- Route traffic through your proxy. Configurez le proxy Wi‑Fi de l’émulateur via l’interface graphique ou forcez-le avec
adb shell settings put global http_proxy 10.0.2.2:8080; si le routage direct échoue, retombez suradb reverse tcp:8080 tcp:8080ou utilisez un host-only VPN.
Une fois que la CA est approuvée au niveau de l’OS et que Frida neutralise la logique de pinning de Flutter, Burp/mitmproxy retrouve une visibilité complète pour l’API fuzzing (BOLA, token tampering, etc.) sans avoir à repacker l’APK.
Offset-based hook of BoringSSL verification (no signature scan)
Lorsque les scripts basés sur des patterns échouent selon les architectures (p. ex. x86_64 vs ARM), hookez directement le verificateur de chaîne BoringSSL par adresse absolue dans libflutter.so. Workflow :
- Extrayez la librairie de la bonne ABI depuis l’APK :
unzip -j app.apk "lib/*/libflutter.so" -d libs/et choisissez celle correspondant à l’appareil (p. ex.lib/x86_64/libflutter.so). - Analysez dans Ghidra/IDA et localisez le verificateur :
- Source : BoringSSL ssl_x509.cc function
ssl_crypto_x509_session_verify_cert_chain(3 args, returns bool). - Dans les builds stripped, utilisez Search → For Strings →
ssl_client→ XREFs, puis ouvrez chaqueFUN_...référencé et choisissez celui avec 3 arguments ressemblant à des pointeurs et un retour booléen. - Calculez l’offset runtime : prenez l’adresse de la fonction affichée par Ghidra et soustrayez l’image base (p. ex. Ghidra affiche souvent
0x00100000pour les PIE Android ELFs). Exemple :0x02184644 - 0x00100000 = 0x02084644. - Hookez à l’exécution en faisant base + offset et forcez le succès :
// 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);
Remarques
- Les Signature scans peuvent réussir sur ARM mais échouer sur x86_64 parce que la disposition des opcodes change ; cette méthode d’offset est agnostique à l’architecture tant que vous recalculerez le RVA.
- Ce bypass fait que BoringSSL accepte n’importe quelle chaîne, permettant un HTTPS MITM indépendamment des pins/CA ou de la confiance à l’intérieur de Flutter.
- Si vous force-routez le trafic pendant le débogage pour confirmer le blocage TLS, par ex. :
iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination <Burp_IP>:<Burp_Port>
…vous aurez toujours besoin du hook ci‑dessus, car la vérification a lieu à l’intérieur de libflutter.so, et non dans le magasin de certificats système d’Android.
Références
- https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/
- Flutter SSL Bypass: How to Intercept HTTPS Traffic When all other Frida Scripts Fail (vercel)
- Flutter SSL Bypass: How to Intercept HTTPS Traffic When all other Frida Scripts Fail (medium)
- PoC Frida hook for Flutter SSL bypass
- BoringSSL ssl_x509.cc (ssl_crypto_x509_session_verify_cert_chain)
- SSL Pinning Bypass – Android
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks

