Análise Estática de APKs com JADX e Ghidra
26 de maio de 2026
Por que análise estática
Antes de instrumentar um app com Frida, a análise estática permite mapear:
- Implementações de segurança (SSL Pinning, root detection, criptografia)
- Secrets hardcoded (API keys, tokens, endpoints internos)
- Lógica de autenticação e autorização
- Bibliotecas nativas que requerem análise com Ghidra
A combinação JADX (código Java/Kotlin) + Ghidra (código nativo C/C++) cobre praticamente 100% da superfície de um APK.
JADX — Decompilando código Java e Kotlin
Instalação
# Via package manager (Linux)
sudo apt install jadx
# Ou baixe o release em: https://github.com/skylot/jadx/releases
# jadx-gui (interface gráfica) ou jadx (CLI)
Abrindo o APK
# CLI: exporta para diretório
jadx app.apk -d saida_jadx/
# GUI (recomendado para exploração)
jadx-gui app.apk
Estrutura do output
saida_jadx/
├── sources/
│ └── com/exemplo/app/
│ ├── MainActivity.java # Activities
│ ├── network/ApiClient.java # Cliente HTTP
│ └── security/PinManager.java
└── resources/
├── AndroidManifest.xml
└── res/values/strings.xml # Strings do app
O que procurar no código decompilado
1. Secrets hardcoded
# Busca por tokens, keys e senhas no código
grep -r "api_key\|apiKey\|secret\|password\|token\|Bearer" saida_jadx/sources/ -i
# Busca em strings.xml e outros resources
grep -r "key\|secret\|endpoint" saida_jadx/resources/ -i
Exemplo de achado comum:
// Encontrado em ApiClient.java
private static final String API_KEY = "sk-live-xxxxxxxxxxx";
private static final String BASE_URL = "https://api-interna.empresa.com";
2. Implementação de SSL Pinning
grep -r "CertificatePinner\|checkServerTrusted\|TrustManager\|X509" \
saida_jadx/sources/ -l
Exemplo para identificar quais hosts têm pinning ativo:
// PinManager.java
new CertificatePinner.Builder()
.add("api.empresa.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
3. Detecção de root e Frida
grep -r "su\|superuser\|RootBeer\|frida\|/proc/maps\|magisk" \
saida_jadx/sources/ -i -l
4. Criptografia
grep -r "AES\|DES\|RSA\|Cipher\|SecretKey\|KeyStore" \
saida_jadx/sources/ -i
Atenção a chaves fixas no código:
// Vulnerável: chave AES hardcoded
byte[] chave = "1234567890abcdef".getBytes();
SecretKeySpec keySpec = new SecretKeySpec(chave, "AES");
AndroidManifest.xml — Permissões e componentes expostos
cat saida_jadx/resources/AndroidManifest.xml
O que verificar:
android:exported="true"em Activities, Services e BroadcastReceivers — podem ser chamados por outros appsandroid:debuggable="true"— permite debug em produção (vulnerabilidade grave)- Permissões excessivas (READ_CONTACTS, CAMERA, etc. sem justificativa)
<!-- Componente exportado sem permissão — vulnerável a intent injection -->
<activity android:name=".DeepLinkActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<data android:scheme="app" android:host="open"/>
</intent-filter>
</activity>
Ghidra — Analisando bibliotecas nativas (.so)
Apps com código nativo compilam para .so (shared objects ARM/ARM64). O JADX não decompila C/C++ — é aqui que o Ghidra entra.
Instalação
# Baixe em: https://ghidra-sre.org/
# Requer Java 17+
unzip ghidra_*.zip
./ghidra_*/ghidraRun
Extraindo as libs do APK
# APK é um ZIP — extrai diretamente
unzip app.apk "lib/*" -d libs_extraidas/
# Estrutura:
# libs_extraidas/lib/
# ├── arm64-v8a/libnativa.so
# └── armeabi-v7a/libnativa.so
Fluxo de análise no Ghidra
- New Project → Import File → selecione
libnativa.so - Ghidra detecta automaticamente ARM/ARM64
- Aceite o auto-analysis (demora ~30s para libs grandes)
- Na Symbol Tree, vá em
Functionspara ver funções exportadas
Identificando funções JNI
Funções chamadas pelo Java seguem o padrão Java_pacote_Classe_metodo:
Java_com_exemplo_app_SecurityManager_validateToken
Java_com_exemplo_app_CryptoUtils_decrypt
Lendo o código decompilado (Decompiler view)
Exemplo de chave AES hardcoded em código nativo:
// Decompilado pelo Ghidra
void Java_com_exemplo_CryptoUtils_decrypt(JNIEnv *env, jobject obj) {
char key[16] = {0x41, 0x42, 0x43, 0x44, ...}; // "ABCD..."
AES_set_decrypt_key(key, 128, &aes_key);
// ...
}
Buscando strings suspeitas
No Ghidra: Search → For Strings — lista todas as strings presentes na lib:
- URLs de endpoints
- Chaves e tokens
- Mensagens de erro internas
Fluxo completo de análise estática
1. Extrair APK
└── unzip app.apk / adb pull
2. JADX — Análise de código Java/Kotlin
├── Secrets e keys hardcoded
├── Implementação de SSL Pinning (hosts e hashes)
├── Root/Frida detection (métodos e libs usadas)
└── Componentes exportados no Manifest
3. Ghidra — Análise de libs nativas (.so)
├── Funções JNI exportadas
├── Chaves criptográficas em memória
└── Lógica de validação em C/C++
4. Documentar achados para relatório
└── Mapeamento: superfície de ataque → bypass via Frida
Ferramentas complementares
| Ferramenta | Uso |
|-----------|-----|
| apkanalyzer | CLI do Android SDK para inspeção rápida |
| MobSF | Análise estática + dinâmica automatizada |
| objection | Wrapper Frida com comandos prontos para pentest |
| apksigner | Verifica assinatura e integridade do APK |