
Outil multi-plateforme de recherche de méthodes APK/DEX avec traçage de chaînes d'appels, désobfuscation ProGuard et détection d'API cachées.
Site web : junelegency.github.io/dexfinder
Recherche de références de méthodes et de champs dans les APK/DEX multiplateforme, avec traçage des chaînes d’appels, désobfuscation ProGuard/R8 et détection des API cachées Android.
Inspiré de l’outil veridex d’Android, réimplémenté en Go avec des fonctionnalités améliorées : détection plus rapide des réflexions, traçage des chaînes d’appels (veridex n’affiche qu’un seul niveau) et formats de sortie flexibles.
--fail-on blocked se termine avec un code non nul lorsque des API restreintes sont trouvées.dexfinder.yaml pour les valeurs par défaut du projet, les options CLI prévalentHomebrew (macOS / Linux) :```bash brew install junelegency/tap/dexfinder
**Script** (détecte automatiquement OS/arch):```bash
curl -sSL https://raw.githubusercontent.com/JuneLeGency/dexfinder/main/install.sh | bash
Installation Go :```bash go install github.com/JuneLeGency/dexfinder/cmd/dexfinder@latest
**Binary**: télécharger depuis [Releases](https://github.com/JuneLeGency/dexfinder/releases).
## Démarrage rapide```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
Le flag --query accepte plusieurs formats d'entrée. dexfinder détecte et convertit automatiquement entre eux.
| Format | Exemple | Comportement |
|---|---|---|
| Nom simple | getDeviceId | Correspondance floue par sous-chaîne sur toutes les API |
| Classe Java | android.telephony.TelephonyManager | Toutes les méthodes/champs de cette classe |
| Classe Java#méthode | android.telephony.TelephonyManager#getDeviceId | Toutes les surcharges de cette méthode |
| Signature Java complète | ...TelephonyManager#getDeviceId() | Exact + repli de surcharge |
| Signature DEX/JNI | Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String; | Correspondance exacte uniquement |
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"
## Contrôle de la sortie
Trois axes indépendants, librement 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| Valeur | Description |
|---|---|
text | Sortie texte brut avec balises colorées (par défaut) |
json | JSON — résultats d'analyse ou trace avec disposition arborescente/liste |
model | JSON structuré avec types complets MethodInfo/FieldInfo (pour IDE/CI) |
html | Rapport HTML autonome avec arbres repliables et recherche |
sarif | Format d'analyse statique SARIF 2.1.0 (GitHub / VS Code) |
--layout (utilisé avec --trace)| Valeur | Description |
|---|---|
tree | Arbre fusionné — chemins d'appel partagés réduits à un seul arbre (par défaut) |
list | Liste plate — chaque chaîne d'appel unique affichée comme pile indépendante |
--style| Valeur | Exemple | Cas d'utilisation |
|---|---|---|
java | com.example.Foo.method(Foo.java) | Lisible par l'humain (par défaut) |
dex | Foo.method(Ljava/lang/String;)V | Analyse précise des signatures |
--scope (portée de recherche)Contrôle le type de références que la requête vérifie. Ceci est crucial pour comprendre les résultats.
| Valeur | Ce qu'il recherche | Question à laquelle il répond | Balise de sortie |
|---|---|---|---|
all | APIs cibles + champs + chaînes de code | « Qui appelle cette API ? » (par défaut) | [METHOD] [FIELD] [STRING] |
callee | Uniquement les signatures d'API cibles dans les instructions invoke-* / get/put | « Qui appelle cette méthode/champ spécifique ? » | [METHOD] [FIELD] |
caller | Uniquement la signature de la méthode appelante | « Que cette méthode appelle-t-elle en interne ? » | [CALLER→] |
string | Constantes chaîne dans les instructions const-string | « Où cette chaîne est-elle utilisée dans le code ? » | [STRING] |
string-table | Chaînes de code + table de chaînes DEX complète | « Cette chaîne existe-t-elle quelque part dans le DEX ? » (inclut annotations, code mort) | [STRING] [STRING_TABLE] |
everything | Tout ce qui précède combiné | Vue d'ensemble | toutes les balises |
Comprendre la distinction entre callee et 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` (par défaut) = `callee` + `string`. La direction `caller` est délibérément exclue du comportement par défaut car elle répond à une question fondamentalement différente. Utilisez `--scope=caller` ou `--scope=everything` explicitement lorsque vous en avez besoin.