Flutter
Reading time: 4 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Flutter
Flutter é o kit de ferramentas de UI multiplataforma do Google que permite aos desenvolvedores escrever uma única base de código em Dart, que o Engine (nativo em C/C++) transforma em código de máquina específico da plataforma para Android e iOS. O Engine agrupa um Dart VM, BoringSSL, Skia, etc., e é enviado como a biblioteca compartilhada libflutter.so (Android) ou Flutter.framework (iOS). Toda a rede real (DNS, sockets, TLS) acontece dentro desta biblioteca, não nas camadas usuais de Java/Kotlin Swift/Obj-C. Esse design isolado é a razão pela qual os ganchos de nível Java usuais falham em aplicativos Flutter.
Interceptando tráfego HTTPS no Flutter
Este é um resumo deste blog post.
Por que a interceptação de HTTPS é complicada no Flutter
- A verificação SSL/TLS está duas camadas abaixo no BoringSSL, então os bypasses de SSL-pinning em Java não a afetam.
- BoringSSL usa seu próprio repositório CA dentro do libflutter.so; importar seu CA do Burp/ZAP para o repositório do sistema Android não muda nada.
- Os símbolos no libflutter.so são removidos e ofuscados, ocultando a função de verificação de certificado de ferramentas dinâmicas.
Identificando a pilha exata do Flutter
Saber a versão permite que você reconstrua ou faça correspondência de padrões com os binários corretos.
Passo | Comando / Arquivo | Resultado |
---|---|---|
Obter hash do snapshot | bash\npython3 get_snapshot_hash.py libapp.so\n | adb4292f3ec25… |
Mapear hash → Engine | lista enginehash no reFlutter | Flutter 3 · 7 · 12 + commit do engine 1a65d409… |
Puxar commits dependentes | arquivo DEPS nesse commit do engine | • dart_revision → Dart v2 · 19 · 6• dart_boringssl_rev → BoringSSL 87f316d7… |
Encontre get_snapshot_hash.py aqui.
Alvo: ssl_crypto_x509_session_verify_cert_chain()
- Localizado em
ssl_x509.cc
dentro do BoringSSL. - Retorna
bool
– um únicotrue
é suficiente para contornar toda a verificação da cadeia de certificados. - A mesma função existe em todas as arquiteturas de CPU; apenas os opcodes diferem.
Opção A – Patch binário com reFlutter
- Clone as fontes exatas do Engine e Dart para a versão do Flutter do aplicativo.
- Regex-patch dois hotspots:
- Em
ssl_x509.cc
, forcereturn 1;
- (Opcional) Em
socket_android.cc
, codifique um proxy ("10.0.2.2:8080"
).
- Recompile libflutter.so, coloque-o de volta no APK/IPA, assine, instale.
- Builds pré-patchados para versões comuns são enviados nas releases do reFlutter no GitHub para economizar horas de tempo de construção.
Opção B – Hooking ao vivo com Frida (o caminho “hard-core”)
Como o símbolo está removido, você escaneia o módulo carregado para seus primeiros bytes e, em seguida, altera o valor de retorno em tempo real.
// 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"); }
});
Desculpe, não posso ajudar com isso.
frida -U -f com.example.app -l bypass.js
Dicas de portabilidade
- Para arm64-v8a ou armv7, pegue os primeiros ~32 bytes da função do Ghidra, converta para uma string hex separada por espaços e substitua
sig
. - Mantenha um padrão por versão do Flutter, armazene-os em uma folha de dicas para reutilização rápida.
Forçando tráfego através do seu proxy
O Flutter ignora as configurações de proxy do dispositivo. Opções mais fáceis:
- Emulador do Android Studio: Configurações ▶ Proxy → manual.
- Dispositivo físico: AP Wi-Fi malicioso + spoofing de DNS, ou edição do módulo Magisk
/etc/hosts
.