Voltar ao laboratório
Tutorial Android 10 min

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 apps
  • android: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

  1. New Project → Import File → selecione libnativa.so
  2. Ghidra detecta automaticamente ARM/ARM64
  3. Aceite o auto-analysis (demora ~30s para libs grandes)
  4. Na Symbol Tree, vá em Functions para 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 |


Referências

Análise Estática de APKs com JADX e Ghidra — APCosta Lab — APCosta