Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
dexfinder — Кроссплатформенный поисковик методов APK/DEX с трассировкой цепочек вызовов, деобфускацией ProGuard и обнаружением скрытых API | Kitploit
Инструменты/GitHubGitHub/junelegency/dexfinder
Безопасность AndroidСтатический анализАнализ уязвимостейАнализ КодаОбратная инженерияСбор информацииDevSecOpsМобильная безопасностьАнализ Бинарных Файлов
GitHubjunelegency/dexfinder

dexfinder

Кроссплатформенный поисковик методов APK/DEX с трассировкой цепочек вызовов, деобфускацией ProGuard и обнаружением скрытых API

92104 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Репозиторий

dexfinder

Английский | Китайский | Сайт dexfinder demo


Сайт: junelegency.github.io/dexfinder

Кроссплатформенное средство поиска ссылок на методы и поля APK/DEX с трассировкой цепочек вызовов, деобфускацией ProGuard/R8 и обнаружением скрытых API Android.

Вдохновлено инструментом veridex от Android, перереализовано на Go с расширенными возможностями: более быстрое обнаружение рефлексии, трассировка цепочек вызовов (veridex показывает только один уровень) и гибкие форматы вывода.

Возможности

  • Сканирование APK/DEX/JAR — парсинг байт-кода DEX, извлечение всех ссылок на методы, поля и строки
  • Многоформатные запросы — поиск по Java-имени, сигнатуре DEX/JNI или простому ключевому слову
  • Трассировка цепочек вызовов — отслеживание вызывающих на N уровней вглубь, объединённое дерево или плоский список, с обнаружением циклов
  • Деобфускация ProGuard/R8 — загрузка mapping.txt, отображение исходных имён вместе с обфусцированными
  • Обнаружение скрытых API — загрузка hiddenapi-flags.csv, обнаружение заблокированных/неподдерживаемых API
  • Обнаружение рефлексии — перекрёстное сопоставление классов × строк для поиска использования скрытых API через рефлексию
  • Гибкий вывод — text / json / model / html / sarif, раскладка tree / list, стиль имён java / dex — все ортогонально
  • Цветной вывод в терминале — автоматически определяемые ANSI-цвета для тегов, соединителей дерева и уровней API
  • Сравнение APK — сравнение двух версий APK/DEX, выявление добавленных, удалённых и изменённых ссылок на API
  • HTML-отчёты — самодостаточный интерактивный HTML со сворачиваемыми деревьями, поиском и тёмной темой
  • Вывод SARIF — SARIF 2.1.0 для сканирования кода GitHub, VS Code и CI-пайплайнов
  • Интеграция с CI — --fail-on blocked завершается с ненулевым кодом при обнаружении ограниченных API
  • Файл конфигурации — .dexfinder.yaml для настроек проекта, флаги CLI переопределяют
  • Ноль внешних зависимостей — чистый Go, самодостаточный парсер DEX
  • Кроссплатформенность — macOS (Intel / Apple Silicon), Linux (amd64 / arm64), Windows

Установка

Homebrew (macOS / Linux):```bash brew install junelegency/tap/dexfinder

root@kitploit:~
**Скрипт** (автоопределение ОС/архитектуры):```bash
curl -sSL https://raw.githubusercontent.com/JuneLeGency/dexfinder/main/install.sh | bash

Go install:```bash go install github.com/JuneLeGency/dexfinder/cmd/dexfinder@latest

root@kitploit:~
**Бинарный файл**: скачать из [Релизы](https://github.com/JuneLeGency/dexfinder/releases).

## Быстрый старт```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

Query Formats

Флаг --query принимает несколько стилей ввода. dexfinder автоматически определяет и преобразует между ними.

All equivalent — find requestLocationUpdates in LocationManager:

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"

root@kitploit:~
## Управление выводом

Три независимые оси, свободно комбинируемые:```
--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

--layout (используется с --trace)

ЗначениеОписание
treeОбъединенное дерево — общие пути вызовов свернуты в одно дерево (по умолчанию)
listПлоский список — каждая уникальная цепочка вызовов показана как независимый стек

--style

ЗначениеПримерСлучай использования
javacom.example.Foo.method(Foo.java)Человекочитаемый (по умолчанию)
dexFoo.method(Ljava/lang/String;)VТочный анализ сигнатур

--scope (область поиска)

Управляет типом ссылок, по которым выполняется поиск. Это критически важно для понимания результатов.

Понимание 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()

root@kitploit:~
`--scope=all` (по умолчанию) = `callee` + `string`. Направление `caller` намеренно исключено из значения по умолчанию, так как оно отвечает на принципиально другой вопрос. Используйте `--scope=caller` или `--scope=everything` явно, когда это необходимо.

**Понимание выходных тегов:**

| Тег | Значение |
|---|---|
| `[METHOD]` | **Вызываемый** метод соответствует вашему запросу (совпадение callee). Строки с отступом — это вызывающие методы. |
| `[FIELD]` | **Доступное** поле соответствует вашему запросу. Строки с отступом — это те, кто обращается к полю. |
| `[CALLER→]` | **Вызывающий** метод соответствует вашему запросу. Строка с отступом показывает, какой API он вызывает. |
| `[STRING]` | Строковая константа в коде соответствует вашему запросу. Строки с отступом — это места её использования. |
| `[STRING_TABLE]` | Строка существует в таблице строк DEX, но не имеет ссылки `const-string` в коде (может быть в аннотациях, оптимизирована R8 и т.д.) |

## Примеры

### 1. Сканирование статистики APK```bash
dexfinder --dex-file app.apk --stats
root@kitploit:~
Loaded 31 DEX file(s): 183913 classes, 1250566 method refs
Method references: 680610
Field references:  625572
String constants:  654353
Referenced types:  192586
Time: 3.9s

2. Найти все вызовы отслеживания местоположения```bash

dexfinder --dex-file app.apk --query "requestLocationUpdates"

root@kitploit:~

[METHOD] Landroid/location/LocationManager;->requestLocationUpdates(Ljava/lang/String;JFLandroid/location/LocationListener;)V (3 ref) Lcom/example/TestEntry;->init(Landroid/content/Context;)V (2 occurrences) Lcom/example/service/LocationService;->onStartCommand(Landroid/content/Intent;II)I

root@kitploit:~
### 3. Трассировка цепочек вызовов — древовидное представление```bash
dexfinder --dex-file app.apk \
  --query "Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;" \
  --trace --depth 5
root@kitploit:~
android.telephony.TelephonyManager.getDeviceId()
└── com.example.aopsdk.TelephonyManager.getDeviceId(TelephonyManager.java)
    ├── com.example.session.PhoneInfo.getImei(PhoneInfo.java)
    ├── com.example.logging.ClientIdHelper.initClientId(ClientIdHelper.java)
    │   └── com.example.logging.ContextInfo.<init>(ContextInfo.java)
    │       ├── com.example.logging.LogStrategyManager.getInstance(LogStrategyManager.java)
    │       └── com.example.logging.LogContextImpl.<init>(LogContextImpl.java)
    ├── com.example.msp.DeviceInfo.k(DeviceInfo.java)
    │   └── com.example.msp.DeviceInfo.<init>(DeviceInfo.java)
    │       └── com.example.msp.DeviceInfo.getInstance(DeviceInfo.java)
    │           ├── com.example.msp.TidHelper.getIMEI(TidHelper.java)
    │           ├── com.example.msp.TidHelper.getIMSI(TidHelper.java)
    │           └── com.example.msp.DeviceCollector.collectData(DeviceCollector.java)
    └── com.example.weex.WXEnvironment.getDevId(WXEnvironment.java)
        └── com.example.weex.WXEnvironment.<clinit>(WXEnvironment.java)

4. Трассировка цепочек вызовов — представление в виде списка (стиль краха Java)```bash

dexfinder --dex-file app.apk
--query "Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;"
--trace --depth 5 --layout list

root@kitploit:~

--- Call chain #1 for android.telephony.TelephonyManager.getDeviceId() --- at com.example.session.PhoneInfo.getImei(PhoneInfo.java) at com.example.aopsdk.TelephonyManager.getDeviceId(TelephonyManager.java) at android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java)

--- Call chain #2 for android.telephony.TelephonyManager.getDeviceId() --- at com.example.logging.LogStrategyManager.getInstance(LogStrategyManager.java) at com.example.logging.ContextInfo.(ContextInfo.java) at com.example.logging.ClientIdHelper.initClientId(ClientIdHelper.java) at com.example.aopsdk.TelephonyManager.getDeviceId(TelephonyManager.java) at android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java)

root@kitploit:~
### 5. Трассировка с использованием стиля подписи DEX```bash
dexfinder --dex-file app.apk --query "getDeviceId" --trace --depth 3 --style dex
root@kitploit:~
Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;
└── TelephonyManager.getDeviceId(Landroid/telephony/TelephonyManager;)Ljava/lang/String;
    ├── PhoneInfo.getImei(Landroid/content/Context;)Ljava/lang/String;
    ├── ClientIdHelper.initClientId(Landroid/content/Context;)Ljava/lang/String;
    └── DeviceInfo.k(Landroid/content/Context;)V

6. Вывод JSON — дерево```bash

dexfinder --dex-file app.apk --query "getDeviceId" --trace --depth 2 --format json

root@kitploit:~
```json
{
  "targets": [{
    "api": "android.telephony.TelephonyManager.getDeviceId()",
    "tree": {
      "method": "android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java)",
      "callers": [
        { "method": "com.example.aopsdk.TelephonyManager.getDeviceId(TelephonyManager.java)",
          "callers": [
            { "method": "com.example.session.PhoneInfo.getImei(PhoneInfo.java)" },
            { "method": "com.example.logging.ClientIdHelper.initClientId(ClientIdHelper.java)" }
          ]}
      ]
    }
  }]
}

7. JSON вывод — список```bash

dexfinder --dex-file app.apk --query "getDeviceId" --trace --depth 2 --format json --layout list

root@kitploit:~
```json
{
  "targets": [{
    "api": "android.telephony.TelephonyManager.getDeviceId()",
    "chains": [
      ["com.example.session.PhoneInfo.getImei(PhoneInfo.java)",
       "com.example.aopsdk.TelephonyManager.getDeviceId(TelephonyManager.java)",
       "android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java)"],
      ["com.example.logging.ClientIdHelper.initClientId(ClientIdHelper.java)",
       "com.example.aopsdk.TelephonyManager.getDeviceId(TelephonyManager.java)",
       "android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java)"]
    ]
  }]
}

8. Структурированный вывод модели (для CI/IDE)```bash

dexfinder --dex-file app.apk --query "getDeviceId" --trace --format model | jq '.call_chains[0]'

root@kitploit:~
```json
{
  "target": "Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;",
  "chain": [
    { "method": { "dex_signature": "...", "class": "...", "name": "getImei",
                   "param_types": ["Landroid/content/Context;"], "return_type": "Ljava/lang/String;",
                   "java_readable": "com.example.session.PhoneInfo.getImei(...)" }},
    { "method": { "dex_signature": "...", "java_readable": "...TelephonyManager.getDeviceId(...)" }},
    { "method": { "dex_signature": "...", "java_readable": "...TelephonyManager.getDeviceId(...)" }}
  ],
  "depth": 2
}

9. ProGuard/R8 маппинг — запрос и отображение

С помощью --mapping как входные, так и выходные данные поддерживают оригинальные (необфусцированные) имена.

Запрос по оригинальному имени → автоматически преобразуется в обфусцированное имя для поиска в DEX:```bash

Query with original simple class name (mapping converts "KotlinCases" → "LJ7;" internally)

dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt

Query with original Java full name

dexfinder --dex-file app.apk --query "com.example.app.utils.Helper" --mapping mapping.txt

Query with obfuscated name still works

dexfinder --dex-file app.apk --query "LJ7;" --mapping mapping.txt

root@kitploit:~
**Выводить деобфусцированные имена в трассировке:**```bash
# Tree trace with deobfuscated names
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace --depth 3
root@kitploit:~
com.example.kotlin.KotlinCases$$ExternalSyntheticLambda1.<init>(int)
└── com.example.TestEntry.runAllTests(TestEntry.java)
    └── com.example.MainActivity.onCreate(MainActivity.java)

Показать как обфусцированные, так и исходные имена:```bash dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --show-obf --trace

root@kitploit:~

com.example.kotlin.KotlinCases.fetchLocationAsync(KotlinCases.java) └── com.example.kotlin.KotlinCases$testCoroutines$3.invokeSuspend(KotlinCases.java) [obf: G7.e] └── com.example.kotlin.KotlinCases$testCoroutines$3.create(KotlinCases.java) [obf: G7.b]

root@kitploit:~
**Все комбинации с другими флагами:**```bash
# Original name + trace as flat list
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace --layout list

# Original name + DEX signature style
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace --style dex

# Original name + JSON tree + show-obf
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --show-obf --trace --format json

# Original name + reverse direction (what does this class call?)
dexfinder --dex-file app.apk --query "com.example.kotlin.KotlinCases" --mapping mapping.txt --scope caller

Матрица «Вход × Результат»:

10. Обнаружение скрытых API```bash

Download CSV (one-time)

curl -o hiddenapi-flags.csv
https://dl.google.com/developers/android/baklava/non-sdk/hiddenapi-flags.csv

Full scan — linking + reflection detection

dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv

root@kitploit:~

#1: Linking unsupported Lsun/misc/Unsafe;->allocateInstance(Ljava/lang/Class;)Ljava/lang/Object; use(s): Lcom/google/gson/internal/UnsafeAllocator;->create()Lcom/google/gson/internal/UnsafeAllocator;

#2: Reflection blocked Landroid/location/ILocationManager;->getCurrentLocation potential use(s): Lcom/example/monitor/LocationMonitor;->hookSystemLocationManager(Landroid/content/Context;)V

root@kitploit:~
### 11. Поиск строковых констант (content:// URIs, ключи API, и т.д.)```bash
# Find content:// URIs in code
dexfinder --dex-file app.apk --query "content://com.android.contacts" --scope string

# Include strings only in DEX table (optimized out by R8, annotations, etc.)
dexfinder --dex-file app.apk --query "content://com.android.contacts" --scope everything
root@kitploit:~
[STRING] "content://com.android.contacts/" (1 ref)
       Lcom/example/imageloader/BaseImageDownloader;->getStreamFromContent(Ljava/lang/String;)Ljava/io/InputStream;
[STRING_TABLE] "content://com.android.contacts" (in DEX string table, no code reference found)

12. Фильтрация по префиксу класса```bash

Only scan classes in your own package

dexfinder --dex-file app.apk --query "getDeviceId" --class-filter "Lcom/mycompany/"

Scan multiple packages

dexfinder --dex-file app.apk --query "getDeviceId" --class-filter "Lcom/mycompany/,Lcom/mylib/"

root@kitploit:~
### 13. Объединить всё```bash
# Deobfuscated JSON tree of location API usage, filtered to your code
dexfinder --dex-file app.apk \
  --query "android.location.LocationManager#requestLocationUpdates" \
  --trace --depth 8 \
  --format json --layout tree --style java \
  --mapping mapping.txt --show-obf \
  --class-filter "Lcom/mycompany/"

14. HTML-отчет```bash

dexfinder --dex-file app.apk --query "getDeviceId" --trace --format html --output report.html

root@kitploit:~
Открывается в любом браузере — сворачиваемые деревья вызовов, строка поиска, темная тема.

### 15. SARIF for GitHub Code Scanning```bash
dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv --format sarif > results.sarif
# Upload to GitHub:
# gh api repos/OWNER/REPO/code-scanning/sarifs -f "[email protected]"

16. APK diff```bash

Compare two APK versions

dexfinder --dex-file new.apk --diff old.apk --query "getDeviceId"

root@kitploit:~
  • 1 added method(s)
    • Lcom/new/Feature;->trackDevice()V
  • 1 removed method(s)
    • Lcom/old/Legacy;->getIMEI()V

Summary: +1 added, -1 removed, ~0 changed

root@kitploit:~
### 17. CI-шлюз с --fail-on```bash
# Fail CI if any blocked hidden APIs are used
dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv --fail-on blocked
# Exit code: 0 = clean, 2 = violations found

Производительность

Тестировалось на Apple M-series, один поток:

По сравнению с veridex (C++, неточный режим) на том же APK ~300MB:

  • veridex точный: 27s (без отражения через Binder/AIDL)
  • veridex неточный: >32 min (убит, взрыв декартового произведения)
  • dexfinder: 5.4s (оптимизация обратного индекса)

Все опции

Файл конфигурации

Создайте .dexfinder.yaml в корне вашего проекта, чтобы установить значения по умолчанию:```yaml mapping: ./build/outputs/mapping.txt class-filter: "Lcom/mycompany/" api-flags: ./hiddenapi-flags.csv style: java depth: 8 color: auto

root@kitploit:~
Флаги CLI всегда переопределяют значения конфигурационного файла.

## Сборка из исходного кода```bash
git clone https://github.com/JuneLeGency/dexfinder.git
cd dexfinder
go build -o dexfinder ./cmd/dexfinder/
go test ./...

Лицензия

Apache License 2.0


dexfinder

Официальный сайт: junelegency.github.io/dexfinder

Кросс-платформенный инструмент для поиска ссылок на методы и поля в APK/DEX, поддерживает отслеживание цепочек вызовов, деобфускацию ProGuard/R8, обнаружение скрытых API Android.

Основан на принципах Android veridex, переписан и улучшен на Go: более быстрое обнаружение рефлексии, многоуровневое отслеживание цепочек вызовов (veridex — только один уровень), гибкие форматы вывода.

Возможности

  • Сканирование APK/DEX/JAR — анализирует байт-код DEX, извлекает все ссылки на методы/поля/строки
  • Запросы в различных форматах — поддерживает имена классов Java, сигнатуры DEX/JNI, простые ключевые слова
  • Отслеживание цепочек вызовов — восходящий поиск вызывающих сторон на N уровней, объединение в дерево или развернутый список, автоматическое обнаружение рекурсивных циклов
  • Деобфускация ProGuard/R8 — загрузка mapping.txt, отображение исходных имен
  • Обнаружение скрытых API — загрузка hiddenapi-flags.csv, обнаружение blocked/unsupported API
  • Обнаружение рефлексии — перекрестное сопоставление имен классов и строк, поиск скрытых API, вызываемых через рефлексию (совместимо с veridex)
  • Гибкий вывод — форматы text / json / model / html / sarif, макет tree / list, стиль именования java / dex — ортогональная комбинация
  • Цветной вывод в терминале — автоматическое определение TTY, окраска меток, линий дерева, уровней API
  • Сравнение APK — сравнение двух версий APK, обнаружение добавленных/удаленных/измененных ссылок на API
  • HTML-отчет — самодостаточный интерактивный HTML, сворачиваемое дерево, фильтрация поиска, темная тема
  • Вывод SARIF — формат SARIF 2.1.0, поддержка GitHub Code Scanning, VS Code
  • Интеграция CI — --fail-on blocked возвращает ненулевой код выхода при обнаружении ограниченных API
  • Конфигурационный файл — .dexfinder.yaml для проекта, параметры командной строки переопределяют
  • Ноль внешних зависимостей — реализация на чистом Go, встроенный парсер DEX
  • Кроссплатформенность — macOS (Intel / Apple Silicon), Linux (amd64 / arm64), Windows

Установка

Homebrew (macOS / Linux):```bash brew install junelegency/tap/dexfinder

root@kitploit:~
**Установка скрипта** (система автоматического обнаружения):```bash
curl -sSL https://raw.githubusercontent.com/JuneLeGency/dexfinder/main/install.sh | bash

Go Установка:```bash go install github.com/JuneLeGency/dexfinder/cmd/dexfinder@latest

root@kitploit:~
**Загрузка бинарных файлов**: [Releases](https://github.com/JuneLeGency/dexfinder/releases)

## Быстрый старт```bash
# 查看 APK 概况
dexfinder --dex-file app.apk --stats

# 查找所有 getDeviceId 调用(获取 IMEI)
dexfinder --dex-file app.apk --query "getDeviceId"

# 追踪调用链(合并树形视图)
dexfinder --dex-file app.apk --query "getDeviceId" --trace

# 追踪调用链(展开为独立调用栈)
dexfinder --dex-file app.apk --query "getDeviceId" --trace --layout list

# 用精确 JNI 签名查询
dexfinder --dex-file app.apk \
  --query "Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;" \
  --trace --depth 8

Формат запроса (--query)

Управление выводом

Три независимых аспекта, свободно комбинируемых:``` --format (text / json / model / html / sarif) 输出什么 --layout (tree / list) 怎么排列调用链 --style (java / dex) 怎么显示名称 --color (auto / always / never) 终端着色

root@kitploit:~
### `--layout` сравнение (с `--trace`)

**tree** — объединяет общие пути, одно дерево показывает всю картину:```
android.telephony.TelephonyManager.getDeviceId()
└── ...aopsdk...TelephonyManager.getDeviceId(TelephonyManager.java)
    ├── PhoneInfo.getImei(PhoneInfo.java)
    ├── ClientIdHelper.initClientId(ClientIdHelper.java)
    │   └── ContextInfo.<init>(ContextInfo.java)
    └── DeviceInfo.k(DeviceInfo.java)
        └── DeviceInfo.getInstance(DeviceInfo.java)
            ├── TidHelper.getIMEI(TidHelper.java)
            └── DeviceCollector.collectData(DeviceCollector.java)

list — каждая цепочка отображается независимо(стиль Java crash):``` --- Call chain #1 --- at PhoneInfo.getImei(PhoneInfo.java) at ...aopsdk...TelephonyManager.getDeviceId(TelephonyManager.java) at android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java)

--- Call chain #2 --- at ContextInfo.(ContextInfo.java) at ClientIdHelper.initClientId(ClientIdHelper.java) at ...aopsdk...TelephonyManager.getDeviceId(TelephonyManager.java) at android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java)

root@kitploit:~
### `--style` сравнение

**java** (по умолчанию): `com.example.Foo.method(Foo.java)`
**dex**: `Foo.method(Ljava/lang/String;)V`

### JSON вывод```bash
# JSON 树
dexfinder --dex-file app.apk --query "getDeviceId" --trace --format json

# JSON 列表
dexfinder --dex-file app.apk --query "getDeviceId" --trace --format json --layout list

--scope 搜索范围

控制查询匹配哪种引用类型。理解这个参数对正确解读结果至关重要。

callee vs caller 的区别:``` scope=callee: "谁调了 finish()?" onCreate ──调用──→ finish() ← 显示这些调用者 onResume ──调用──→ finish()

scope=caller: "finish() 内部调了什么?" finish() ──调用──→ Log.i() ← 显示这些被调用者 finish() ──调用──→ super.finish()

root@kitploit:~
`--scope=all` (по умолчанию) = `callee` + `string`. Направление `caller` намеренно исключено из умолчания, так как отвечает на совершенно другой вопрос. При необходимости включайте явно с помощью `--scope=caller` или `--scope=everything`.

**Значения меток вывода:**

| Метка | Значение |
|---|---|
| `[METHOD]` | Искомый метод **вызывается кем-то другим**. Строка с отступом — вызывающий. |
| `[FIELD]` | Искомое поле **доступно кем-то другим**. Строка с отступом — обращающийся. |
| `[CALLER→]` | Имя искомого метода встречается в **вызывающем коде**, строка с отступом показывает, какой API он вызывает. |
| `[STRING]` | Константная строка в коде совпадает. Строка с отступом — метод, использующий эту строку. |
| `[STRING_TABLE]` | Строка существует только в таблице строк DEX, в коде нет ссылки `const-string` (возможно, в аннотациях, оптимизирована R8 и т.д.). |

## Дополнительные возможности

### Деобфускация (--mapping)

После загрузки `--mapping` **ввод и вывод** поддерживают оригинальные (необфусцированные) имена.

**Запрос по оригинальному имени → автоматическое преобразование в обфусцированное имя для поиска в DEX:**```bash
# 用原始简短类名查(mapping 内部将 "KotlinCases" 转为 "LJ7;")
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt

# 用原始 Java 全名查
dexfinder --dex-file app.apk --query "com.example.app.utils.Helper" --mapping mapping.txt

# 用混淆名查也正常工作
dexfinder --dex-file app.apk --query "LJ7;" --mapping mapping.txt

Вывод имени после деобфускации:```bash

trace 树形 + 反混淆

dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace

root@kitploit:~
**Показать одновременно обфусцированное и исходное имена:**```bash
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --show-obf --trace
root@kitploit:~
com.example.KotlinCases.fetchLocationAsync(KotlinCases.java)
└── com.example.KotlinCases$testCoroutines$3.invokeSuspend(KotlinCases.java)  [obf: G7.e]

Свободное сочетание с другими параметрами:```bash

原始名 + 展开列表

dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace --layout list

原始名 + DEX 签名风格

dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace --style dex

原始名 + JSON 树 + 显示混淆名

dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --show-obf --trace --format json

原始名 + 反向查看(这个类内部调了什么)

dexfinder --dex-file app.apk --query "com.example.KotlinCases" --mapping mapping.txt --scope caller

root@kitploit:~
**Матрица ввода×вывода:**

| Входной запрос | Без mapping | `--mapping` | `--mapping --show-obf` |
|---|---|---|---|
| Запутанное имя `LJ7;` | ✓ Запутанный вывод | ✓ Деобфусцированный вывод | ✓ Оба рядом |
| Исходное короткое имя `KotlinCases` | ✗ Не найдено | ✓ Автоконвертация + деобфусцированный вывод | ✓ Автоконвертация + оба рядом |
| Исходное полное имя `com.example...` | ✗ Не найдено | ✓ Автоконвертация + деобфусцированный вывод | ✓ Автоконвертация + оба рядом |

### Обнаружение скрытых API```bash
# 下载 CSV(一次性)
curl -o hiddenapi-flags.csv \
  https://dl.google.com/developers/android/baklava/non-sdk/hiddenapi-flags.csv

# 全量检测(直接链接 + 反射检测)
dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv

Поиск строк```bash

搜索代码中的 content:// URI

dexfinder --dex-file app.apk --query "content://com.android.contacts" --scope string

包含被 R8 优化掉的字符串(注解、死代码等)

dexfinder --dex-file app.apk --query "content://com.android.contacts" --scope everything

root@kitploit:~
### 按包名过滤```bash
# 只扫描自己的代码
dexfinder --dex-file app.apk --query "getDeviceId" --class-filter "Lcom/mycompany/"

Совместное использование```bash

反混淆 + JSON 树形输出 + 定位 API 调用 + 过滤自己的代码

dexfinder --dex-file app.apk
--query "android.location.LocationManager#requestLocationUpdates"
--trace --depth 8
--format json --layout tree --style java
--mapping mapping.txt --show-obf
--class-filter "Lcom/mycompany/"

root@kitploit:~
### HTML Отчёт```bash
dexfinder --dex-file app.apk --query "getDeviceId" --trace --format html --output report.html

Открывается в браузере — сворачиваемое дерево вызовов, строка поиска, тёмная тема.

SARIF(GitHub Code Scanning)```bash

dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv --format sarif > results.sarif

root@kitploit:~
### APK 版本对比```bash
dexfinder --dex-file new.apk --diff old.apk --query "getDeviceId"
root@kitploit:~
+ 1 added method(s)
  + Lcom/new/Feature;->trackDevice()V

- 1 removed method(s)
  - Lcom/old/Legacy;->getIMEI()V

Summary: +1 added, -1 removed, ~0 changed

CI 卡点```bash

检测到 blocked API 时 CI 失败

dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv --fail-on blocked

退出码: 0 = 通过, 2 = 有违规

root@kitploit:~
## Производительность

Apple M серии, однопоточный:

| Размер APK | Количество DEX | Количество классов | Ссылки на методы | Сканирование | Hidden API |
|---|---|---|---|---|---|
| ~1 MB | 1 | ~2K | ~18K | **24ms** | — |
| ~10 MB | 2 | ~25K | ~100K | **335ms** | — |
| ~300 MB | 30+ | ~180K | ~1.2M | **3.9s** | **5.4s** |

Сравнение с veridex (C++) на том же ~300MB APK:
- veridex precise: **27s** (не может отслеживать рефлексию Binder/AIDL)
- veridex imprecise: **>32 min** (комбинаторный взрыв, был убит)
- **dexfinder: 5.4s** (оптимизация обратного индекса)

## Все параметры

| Параметр | Описание | Значение по умолчанию |
|---|---|---|
| `--dex-file` | Путь к файлу APK/DEX/JAR ** (обязательно)** | — |
| `--query` | Ключевое слово для поиска (Java / DEX/JNI / простое имя) | — |
| `--trace` | Включить трассировку цепочки вызовов (требует `--query`) | `false` |
| `--depth` | Максимальная глубина цепочки вызовов | `5` |
| `--layout` | Раскладка трассировки: `tree` (объединённое дерево) или `list` (развёрнутый список) | `tree` |
| `--style` | Стиль именования: `java` (читаемый) или `dex` (подпись JNI) | `java` |
| `--format` | Формат вывода: `text`, `json`, `model`, `html`, `sarif` | `text` |
| `--output` | Вывод в файл, а не в stdout | — |
| `--color` | Режим цвета: `auto`, `always`, `never` | `auto` |
| `--mapping` | Путь к ProGuard/R8 mapping.txt | — |
| `--show-obf` | Показывать как обфусцированные, так и деобфусцированные имена | `false` |
| `--api-flags` | Путь к hiddenapi-flags.csv | — |
| `--class-filter` | Фильтр по префиксу дескриптора класса (через запятую) | — |
| `--exclude-api-lists` | Исключённые уровни API | — |
| `--scope` | Область поиска: `all`, `callee`, `caller`, `string`, `string-table`, `everything` | `all` |
| `--diff` | Сравнить с другим APK/DEX, показать различия API | — |
| `--fail-on` | Вернуть ненулевой код выхода при обнаружении API указанного уровня (шлюз CI) | — |
| `--stats` | Показать только сводку статистики | `false` |
| `--version` | Показать номер версии | `false` |

### Файл конфигурации

Создайте `.dexfinder.yaml` в корне проекта, чтобы установить значения по умолчанию:```yaml
mapping: ./build/outputs/mapping.txt
class-filter: "Lcom/mycompany/"
api-flags: ./hiddenapi-flags.csv
style: java
depth: 8
color: auto

Параметры командной строки всегда переопределяют файл конфигурации.

Сборка из исходного кода```bash

git clone https://github.com/JuneLeGency/dexfinder.git cd dexfinder go build -o dexfinder ./cmd/dexfinder/ go test ./...

root@kitploit:~
## 许可证

Apache License 2.0
Скачать инструмент
FormatExampleBehavior
Simple namegetDeviceIdНечеткое совпадение подстроки во всех API
Java classandroid.telephony.TelephonyManagerВсе методы/поля этого класса
Java class#methodandroid.telephony.TelephonyManager#getDeviceIdВсе перегруженные версии этого метода
Java full signature...TelephonyManager#getDeviceId()Точное совпадение + возврат к перегрузкам
DEX/JNI signatureLandroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;Только точное совпадение
ЗначениеОписание
textОбычный текстовый вывод с цветными тегами (по умолчанию)
jsonJSON — результаты сканирования или трассировка с древовидной/списковой структурой
modelСтруктурированный JSON с полными типами MethodInfo/FieldInfo (для IDE/CI)
htmlАвтономный HTML-отчет со сворачиваемыми деревьями и поиском
sarifФормат статического анализа SARIF 2.1.0 (GitHub / VS Code)
ЗначениеЧто ищетНа какой вопрос отвечаетТег вывода
allAPI вызываемых + поля + строки кода"Кто вызывает этот API?" (по умолчанию)[METHOD] [FIELD] [STRING]
calleeТолько сигнатуры целевого API в инструкциях invoke-* / get/put"Кто вызывает этот конкретный метод/поле?"[METHOD] [FIELD]
callerТолько сигнатура вызывающего метода"Что этот метод вызывает внутри?"[CALLER→]
stringСтроковые константы в инструкциях const-string"Где используется эта строка в коде?"[STRING]
string-tableСтроки кода + полная таблица строк DEX"Существует ли эта строка где-либо в DEX? (включает аннотации, мертвый код)"[STRING] [STRING_TABLE]
everythingВсе вышеперечисленное вместеПолная картинавсе теги
Вход запросаБез --mapping--mapping--mapping --show-obf
Обфусцированный: LJ7;✓ обфусцированный вывод✓ деобфусцированный вывод✓ оба имени
Исходный простой: KotlinCases✗ не найдено✓ авто-преобразование, деобф. вывод✓ авто-преобразование, оба имени
Исходный полный: com.example...KotlinCases✗ не найдено✓ авто-преобразование, деобф. вывод✓ авто-преобразование, оба имени
Размер APKФайлы DEXКлассыСсылки на методыСканированиеСкрытый API
~1 MB1~2K~18K24ms—
~10 MB2~25K~100K335ms—
~300 MB30+~180K~1.2M3.9s5.4s
ФлагОписаниеПо умолчанию
--dex-fileAPK/DEX/JAR файл для анализа (обязательно)—
--queryКлючевое слово поиска (Java, DEX/JNI или простое имя)—
--traceВключить трассировку цепочек вызовов (требуется --query)false
--depthМаксимальная глубина цепочки вызовов5
--layoutМакет трассировки: tree или listtree
--styleСтиль имени: java или dexjava
--formatФормат вывода: text, json, model, html, sariftext
--outputЗаписать вывод в файл вместо stdout—
--colorРежим цвета: auto, always, neverauto
--mappingПуть к ProGuard/R8 mapping.txt—
--show-obfПоказывать обфусцированные имена вместе с деобфусцированнымиfalse
--api-flagsПуть к hiddenapi-flags.csv—
--class-filterПрефиксы дескрипторов классов через запятую—
--exclude-api-listsСписки API для исключения из отчета—
--scopeОбласть поиска: all, callee, caller, string, string-table, everythingall
--diffСравнить с другим APK/DEX и показать различия API—
--fail-onВыйти с ненулевым кодом, если найдены скрытые API на этом уровне (CI gate)—
--statsПоказать только сводную статистикуfalse
--versionПоказать версиюfalse
ФорматПримерПоведение
Простое имяgetDeviceIdНечеткое подстроковое совпадение
Имя класса Javaandroid.telephony.TelephonyManagerСовпадение всех методов данного класса
Имя класса Java#метод...TelephonyManager#getDeviceIdСовпадение всех перегрузок данного метода
Полная сигнатура Java...#getDeviceId()Точное совпадение + откат к перегрузкам
DEX/JNI сигнатураLandroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;Точное совпадение
值搜索内容回答的问题输出标签
all被调 API + 字段 + 代码字符串"谁调了这个方法?"(默认)[METHOD] [FIELD] [STRING]
callee仅 invoke-* / get/put 指令中的目标签名"谁调了这个具体方法/字段?"[METHOD] [FIELD]
caller仅调用方法的签名"这个方法内部调了什么?"[CALLER→]
stringconst-string 指令中的字符串常量"这个字符串在代码哪里使用了?"[STRING]
string-table代码字符串 + DEX 完整字符串表"这个字符串是否存在于 DEX 中?"(含注解、死代码)[STRING] [STRING_TABLE]
everything以上全部完整视图全部标签