
Buscador de métodos APK/DEX multiplataforma con trazado de cadenas de llamadas, desofuscación de ProGuard y detección de API ocultas.
Sitio web: junelegency.github.io/dexfinder
Buscador de referencias a métodos y campos de APK/DEX multiplataforma con trazado de cadenas de llamadas, desofuscación ProGuard/R8 y detección de API ocultas de Android.
Inspirado en la herramienta veridex de Android, reimplementado en Go con capacidades mejoradas: detección de reflexión más rápida, trazado de cadenas de llamadas (veridex solo muestra un nivel) y formatos de salida flexibles.
--fail-on blocked termina con un código de salida distinto de cero cuando se encuentran API restringidas.dexfinder.yaml para los valores predeterminados del proyecto; las opciones de CLI lo sobrescribenHomebrew (macOS / Linux):```bash brew install junelegency/tap/dexfinder
**Script** (detecta automáticamente SO/arquitectura):```bash
curl -sSL https://raw.githubusercontent.com/JuneLeGency/dexfinder/main/install.sh | bash
Instalación con Go:```bash go install github.com/JuneLeGency/dexfinder/cmd/dexfinder@latest
**Binario**: descargar desde [Releases](https://github.com/JuneLeGency/dexfinder/releases).
## Inicio 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
El indicador --query acepta múltiples estilos de entrada. dexfinder los detecta automáticamente y convierte entre ellos.
| Formato | Ejemplo | Comportamiento |
|---|---|---|
| Nombre simple | getDeviceId | Coincidencia difusa de subcadena en todas las APIs |
| Clase Java | android.telephony.TelephonyManager | Todos los métodos/campos de esa clase |
| Clase Java#método | android.telephony.TelephonyManager#getDeviceId | Todas las sobrecargas de ese método |
| Firma completa de Java | ...TelephonyManager#getDeviceId() | Coincidencia exacta + respaldo de sobrecarga |
| Firma DEX/JNI | Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String; | Solo coincidencia exacta |
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"
## Control de Salida
Tres ejes independientes, libremente combinables:```
--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| Value | Description |
|---|---|
text | Salida de texto plano con etiquetas de colores (predeterminado) |
json | JSON: resultados del escaneo o trace con diseño de árbol/lista |
model | JSON estructurado con tipos completos MethodInfo/FieldInfo (para IDE/CI) |
html | Informe HTML autónomo con árboles plegables y búsqueda |
sarif | Formato de análisis estático SARIF 2.1.0 (GitHub / VS Code) |
--layout (usado con --trace)| Value | Description |
|---|---|
tree | Árbol combinado: las rutas de llamada compartidas se colapsan en un único árbol (predeterminado) |
list | Lista plana: cada cadena de llamadas única se muestra como una pila independiente |
--style| Value | Example | Use case |
|---|---|---|
java | com.example.Foo.method(Foo.java) | Legible para humanos (predeterminado) |
dex | Foo.method(Ljava/lang/String;)V | Análisis preciso de firmas |
--scope (alcance de búsqueda)Controla qué tipo de referencias coincide con la consulta. Esto es fundamental para entender los resultados.
| Value | Qué busca | Pregunta que responde | Etiqueta de salida |
|---|---|---|---|
all | APIs callee + campos + strings de código | "¿Quién llama a esta API?" (predeterminado) | [METHOD] [FIELD] [STRING] |
callee | Solo las firmas de API objetivo en instrucciones invoke-* / get/put | "¿Quién llama a este método/campo específico?" | [METHOD] [FIELD] |
caller | Solo la firma del método que llama | "¿Qué llama este método internamente?" | [CALLER→] |
string | Constantes de cadena en instrucciones const-string | "¿Dónde se usa esta cadena en el código?" | [STRING] |
string-table | Strings de código + tabla completa de strings de DEX | "¿Existe esta cadena en algún lugar del DEX?" (incluye anotaciones, código muerto) | [STRING] [STRING_TABLE] |
everything | Todo lo anterior combinado | Panorama completo | todas las etiquetas |
Entendiendo 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` (predeterminado) = `callee` + `string`. La dirección `caller` se excluye intencionalmente del valor predeterminado porque responde a una pregunta fundamentalmente distinta. Usa `--scope=caller` o `--scope=everything` explícitamente cuando lo necesites.
**Entender las etiquetas de salida:**