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 检测功能

查看仓库
921034个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

dexfinder

英语 | 中文 | 网站 dexfinder 演示


网站: junelegency.github.io/dexfinder

跨平台 APK/DEX 方法和字段引用查找工具,支持调用链追踪、ProGuard/R8 反混淆以及 Android 隐藏 API 检测。

灵感来源于 Android 的 veridex 工具,使用 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,树 / 列表布局,java / dex 名称风格——全部正交可选
  • 彩色终端输出 — 自动检测 ANSI 颜色,用于标签、树形连接线和 API 级别
  • APK 差异比较 — 比较两个 APK/DEX 版本,检测新增/删除/更改的 API 引用
  • HTML 报告 — 自包含交互式 HTML,可折叠树、搜索和深色主题
  • SARIF 输出 — 支持 SARIF 2.1.0,用于 GitHub Code Scanning、VS Code 和 CI 流水线
  • 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:~
**脚本**(auto-detects OS/arch):```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:~
**二进制文件**: 从 [Releases](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 标志接受多种输入样式。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 与 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]` | 一个**被调用**的方法匹配你的查询(被调用者匹配)。缩进行为调用者。 |
| `[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. 使用 --fail-on 的 CI 门控```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 系列单线程上进行的基准测试:

与 veridex(C++,不精确模式)在相同的约 300MB APK 上比较:

  • 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 flags 始终覆盖配置文件的值。

## 从源代码构建```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 反混淆、Android Hidden API 检测。

基于 Android veridex 原理,用 Go 重新实现并增强:更快的反射检测、多层调用链追踪(veridex 仅一层)、灵活的输出格式。

特性

  • APK/DEX/JAR 扫描 — 解析 DEX 字节码,提取所有方法/字段/字符串引用
  • 多格式查询 — 支持 Java 类名、DEX/JNI 签名、简单关键字
  • 调用链追踪 — 向上追溯 N 层调用者,合并树或展开列表,自动检测递归环
  • ProGuard/R8 反混淆 — 加载 mapping.txt,显示原始名称
  • Hidden 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...` | ✗ 找不到 | ✓ 自动转换 + 反混淆输出 | ✓ 自动转换 + 两者并列 |

### Hidden 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 分钟**(笛卡尔积爆炸,被 kill)
- **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
下载工具
格式示例行为
简单名称getDeviceId对所有的API执行模糊子串匹配
Java 类android.telephony.TelephonyManager该类的所有方法/字段
Java 类#方法android.telephony.TelephonyManager#getDeviceId该方法的所有重载
Java 完整签名...TelephonyManager#getDeviceId()精确匹配 + 重载回退
DEX/JNI 签名Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;仅精确匹配
值描述
text带彩色标签的纯文本输出(默认)
jsonJSON — 扫描结果或带有树形/列表布局的跟踪
model包含完整 MethodInfo/FieldInfo 类型的结构化 JSON(适用于 IDE/CI)
html自包含 HTML 报告,带有可折叠树和搜索功能
sarifSARIF 2.1.0 静态分析格式(GitHub / VS Code)
值搜索内容回答的问题输出标签
all被调用 API + 字段 + 代码字符串“谁调用了这个 API?”(默认)[METHOD] [FIELD] [STRING]
callee仅 invoke-* / get/put 指令中的目标 API 签名“谁调用了这个特定方法/字段?”[METHOD] [FIELD]
caller仅调用方法的签名“这个方法内部调用了什么?”[CALLER→]
stringconst-string 指令中的字符串常量“这个字符串在代码中哪里被使用?”[STRING]
string-table代码字符串 + 完整 DEX 字符串表“这个字符串在 DEX 中的任何地方存在吗?”(包括注解、死代码)[STRING] [STRING_TABLE]
everything以上所有组合全貌所有标签
查询输入无映射--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-file要分析的 APK/DEX/JAR 文件 (必需)—
--query搜索关键词(Java、DEX/JNI 或简单名称)—
--trace启用调用链追踪(需要 --query)false
--depth最大调用链深度5
--layout追踪布局:tree 或 listtree
--style名称风格:java 或 dexjava
--format输出格式:text、json、model、html、sariftext
--output将输出写入文件而非标准输出—
--color颜色模式:auto、always、neverauto
--mappingProGuard/R8 mapping.txt 路径—
--show-obf显示混淆名称及其去混淆对应false
--api-flagshiddenapi-flags.csv 路径—
--class-filter以逗号分隔的类描述符前缀—
--exclude-api-lists从报告中排除的 API 列表—
--scope搜索范围:all、callee、caller、string、string-table、everythingall
--diff与另一个 APK/DEX 比较并显示 API 差异—
--fail-on若发现此级别的隐藏 API 则退出码非零(CI 门禁)—
--stats仅显示摘要统计信息false
--version显示版本false
格式示例行为
简单名称getDeviceId模糊子串匹配
Java 类名android.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以上全部完整视图全部标签