Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
dexfinder — 크로스 플랫폼 APK/DEX 메서드 파인더: 호출 체인 추적, ProGuard 난독 해제 및 숨겨진 API 탐지 기능 | Kitploit
도구/GitHubGitHub/junelegency/dexfinder
Android SecurityStatic AnalysisVulnerability AnalysisCode AnalysisReverse EngineeringInformation GatheringDevSecOpsMobile SecurityBinary Analysis
GitHubjunelegency/dexfinder

dexfinder

크로스 플랫폼 APK/DEX 메서드 파인더: 호출 체인 추적, ProGuard 난독 해제 및 숨겨진 API 탐지 기능

92104개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기

dexfinder

영어 | 중국어 | 웹사이트 dexfinder demo


웹사이트: 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 이름 스타일 — 모두 직교적으로 조합 가능.
  • 컬러 터미널 출력 — 태그, 트리 연결선, API 레벨에 대해 자동 감지된 ANSI 색상 사용.
  • APK 비교 — 두 APK/DEX 버전을 비교하여 추가/제거/변경된 API 참조를 탐지합니다.
  • HTML 보고서 — 접이식 트리, 검색, 다크 테마가 포함된 독립형 인터랙티브 HTML.
  • SARIF 출력 — GitHub 코드 스캐닝, VS Code, CI 파이프라인을 위한 SARIF 2.1.0.
  • CI 통합 — --fail-on blocked 플래그로 제한된 API가 발견되면 0이 아닌 종료 코드 반환.
  • 설정 파일 — 프로젝트 기본값을 위한 .dexfinder.yaml, CLI 플래그로 재정의 가능.
  • 외부 의존성 없음 — 순수 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 설치:```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 (검색 범위)

쿼리가 어떤 종류의 참조와 일치하는지 제어합니다. 결과를 이해하는 데 중요합니다.

호출 대상과 호출자 이해하기:``` 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 일치). 들여쓰기된 줄은 호출자(caller)입니다. |
| `[FIELD]` | 쿼리와 일치하는 **접근되는** 필드. 들여쓰기된 줄은 접근자(accessor)입니다. |
| `[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 crash style)```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 출력 — tree```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 keys, 등)```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-시리즈, 단일 스레드에서 벤치마크:

동일한 ~300MB APK를 veridex (C++, 비정밀 모드)와 비교:

  • 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 ./...

License

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 감지 시 0이 아닌 종료 코드 반환
  • 설정 파일 — .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 --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 — 트리/리스트 레이아웃으로 스캔 결과 또는 추적
modelMethodInfo/FieldInfo 타입이 포함된 구조화된 JSON (IDE/CI용)
html접을 수 있는 트리와 검색 기능이 포함된 독립형 HTML 보고서
sarifSARIF 2.1.0 정적 분석 형식 (GitHub / VS Code)
값검색 대상답변하는 질문출력 태그
all호출 대상 API + 필드 + 코드 문자열"이 API를 호출하는 곳은?" (기본값)[METHOD] [FIELD] [STRING]
calleeinvoke-* / 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출력을 stdout 대신 파일로 쓰기—
--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가 발견되면 0이 아닌 종료 코드 반환 (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]
calleeinvoke-* / get/put 명령어의 대상 서명만"이 특정 메서드/필드를 누가 호출했나요?"[METHOD] [FIELD]
caller호출 메서드의 서명만"이 메서드 내부에서 무엇을 호출했나요?"[CALLER→]
stringconst-string 명령어의 문자열 상수"이 문자열이 코드 어디에서 사용되었나요?"[STRING]
string-table코드 문자열 + DEX 전체 문자열 테이블"이 문자열이 DEX에 존재하나요?"(주석, 데드 코드 포함)[STRING] [STRING_TABLE]
everything위 모든 것전체 뷰모든 레이블