
Ferramenta multiplataforma para localização de métodos APK/DEX com rastreamento de cadeia de chamadas, desofuscação ProGuard e deteção de APIs ocultas
Localizador de referências de métodos e campos APK/DEX multiplataforma com rastreamento de cadeia de chamadas, desofuscação ProGuard/R8 e detecção de APIs ocultas do Android.
Inspirado pela ferramenta veridex do Android, reimplementada em Go com capacidades aprimoradas: detecção de reflexão mais rápida, rastreamento de cadeia de chamadas (o veridex mostra apenas um nível) e formatos de saída flexíveis.
--fail-on blocked sair com código diferente de zero quando APIs restritas são encontradas.dexfinder.yaml para padrões do projeto, flags de CLI sobrescrevemHomebrew (macOS / Linux):```bash brew install junelegency/tap/dexfinder
**Script** (detecta automaticamente SO/arquitetura):```bash
curl -sSL https://raw.githubusercontent.com/JuneLeGency/dexfinder/main/install.sh | bash
Instalação com Go:```bash go install github.com/JuneLeGency/dexfinder/cmd/dexfinder@latest
**Binário**: baixe dos [Lançamentos](https://github.com/JuneLeGency/dexfinder/releases).
## Início Rápido```bash
# Show APK overview
dexfinder --dex-file app.apk --stats
# Find all calls to getDeviceId (IMEI)
dexfinder --dex-file app.apk --query "getDeviceId"
# Trace call chains as merged tree
dexfinder --dex-file app.apk --query "getDeviceId" --trace
# Trace as flat call stacks (Java crash style)
dexfinder --dex-file app.apk --query "getDeviceId" --trace --layout list
# Exact JNI signature query
dexfinder --dex-file app.apk \
--query "Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;" \
--trace --depth 8
# Hidden API detection
dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv
A flag --query aceita múltiplos estilos de entrada. O dexfinder detecta e converte automaticamente entre eles.
| Formato | Exemplo | Comportamento |
|---|---|---|
| Nome simples | getDeviceId | Correspondência difusa por substring em todas as APIs |
| Classe Java | android.telephony.TelephonyManager | Todos os métodos/campos dessa classe |
| Classe Java#método | android.telephony.TelephonyManager#getDeviceId | Todas as sobrecargas desse método |
| Assinatura completa Java | ...TelephonyManager#getDeviceId() | Correspondência exata + fallback de sobrecarga |
| Assinatura DEX/JNI | Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String; | Correspondência exata apenas |
dexfinder --dex-file app.apk --query "requestLocationUpdates" dexfinder --dex-file app.apk --query "android.location.LocationManager#requestLocationUpdates" dexfinder --dex-file app.apk --query "Landroid/location/LocationManager;->requestLocationUpdates(Ljava/lang/String;JFLandroid/location/LocationListener;)V"
## Controle de Saída
Três eixos independentes, livremente combináveis:```
--format (text / json / model / html / sarif) what to output
--layout (tree / list) how to arrange traces
--style (java / dex) how to display names
--color (auto / always / never) terminal colors
--format| Valor | Descrição |
|---|---|
text | Saída de texto simples com tags coloridas (padrão) |
json | JSON — resultados de varredura ou rastreamento com layout em árvore/lista |
model | JSON estruturado com tipos completos MethodInfo/FieldInfo (para IDE/CI) |
html | Relatório HTML autossuficiente com árvores recolhíveis e pesquisa |
sarif | Formato de análise estática SARIF 2.1.0 (GitHub / VS Code) |
--layout (usado com --trace)| Valor | Descrição |
|---|---|
tree | Árvore mesclada — caminhos de chamada compartilhados colapsados em uma árvore (padrão) |
list | Lista plana — cada cadeia de chamada única mostrada como pilha independente |
--style| Valor | Exemplo | Caso de uso |
|---|---|---|
java | com.example.Foo.method(Foo.java) | Legível para humanos (padrão) |
dex | Foo.method(Ljava/lang/String;)V | Análise precisa de assinatura |
--scope (escopo de pesquisa)Controla que tipo de referências a consulta corresponde. Isto é crítico para compreender os resultados.
| Valor | O que pesquisa | Pergunta que responde | Tag de saída |
|---|---|---|---|
all | APIs de destino + campos + strings de código | "Quem chama esta API?" (padrão) | [METHOD] [FIELD] [STRING] |
callee | Apenas assinaturas de API de destino nas instruções invoke-* / get/put | "Quem chama este método/campo específico?" | [METHOD] [FIELD] |
caller | Apenas a assinatura do método chamador | "O que este método chama internamente?" | [CALLER→] |
string | Constantes de string em instruções const-string | "Onde esta string é usada no código?" | [STRING] |
string-table | Strings de código + tabela completa de strings DEX | "Esta string existe em algum lugar no DEX?" (inclui anotações, código morto) | [STRING] [STRING_TABLE] |
everything | Tudo acima combinado | Quadro completo | todas as tags |
Compreendendo callee vs caller:``` scope=callee: "Who calls finish()?" onCreate ──calls──→ finish() ← these callers are shown onResume ──calls──→ finish()
scope=caller: "What does finish() call internally?" finish() ──calls──→ Log.i() ← these callees are shown finish() ──calls──→ super.finish()
`--scope=all` (padrão) = `callee` + `string`. A direção `caller` é intencionalmente excluída do padrão porque responde a uma pergunta fundamentalmente diferente. Use `--scope=caller` ou `--scope=everything` explicitamente quando precisar.
**Entendendo as tags de saída:**