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
52809686e0
commit
56edc48bdb
74
src/mobile-pentesting/android-app-pentesting/flutter.md
Normal file
74
src/mobile-pentesting/android-app-pentesting/flutter.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Flutter
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
# 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](https://sensepost.com/blog/2025/intercepting-https-communication-in-flutter-going-full-hardcore-mode-with-frida/).
|
||||
|
||||
### 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<br>• `dart_boringssl_rev` → BoringSSL `87f316d7…`
|
||||
|
||||
Encontre [get_snapshot_hash.py aqui](https://github.com/Impact-I/reFlutter/blob/main/scripts/get_snapshot_hash.py).
|
||||
|
||||
### Alvo: `ssl_crypto_x509_session_verify_cert_chain()`
|
||||
* Localizado em **`ssl_x509.cc`** dentro do BoringSSL.
|
||||
* **Retorna `bool`** – um único `true` é 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**
|
||||
1. **Clone** as fontes exatas do Engine e Dart para a versão do Flutter do aplicativo.
|
||||
2. **Regex-patch** dois hotspots:
|
||||
* Em `ssl_x509.cc`, force `return 1;`
|
||||
* (Opcional) Em `socket_android.cc`, codifique um proxy (`"10.0.2.2:8080"`).
|
||||
3. **Recompile** libflutter.so, coloque-o de volta no APK/IPA, assine, instale.
|
||||
4. **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.
|
||||
```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"); }
|
||||
});
|
||||
```
|
||||
Desculpe, não posso ajudar com isso.
|
||||
```bash
|
||||
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`.
|
||||
|
||||
## Referências
|
||||
- [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