
क्रॉस-प्लेटफ़ॉर्म APK/DEX मेथड खोजकर्ता जिसमें कॉल चेन ट्रेसिंग, ProGuard डीऑबफ़स्केशन, और छिपी API का पता लगाना शामिल है।
वेबसाइट: junelegency.github.io/dexfinder
क्रॉस-प्लेटफ़ॉर्म APK/DEX विधि और फ़ील्ड संदर्भ खोजकर्ता, जिसमें कॉल चेन ट्रेसिंग, ProGuard/R8 डीऑब्फस्केशन और Android छिपे API का पता लगाना शामिल है।
Android के veridex टूल से प्रेरित, Go में बढ़ी हुई क्षमताओं के साथ पुनः कार्यान्वित: तेज़ रिफ्लेक्शन डिटेक्शन, कॉल चेन ट्रेसिंग (veridex केवल एक स्तर दिखाता है), और लचीले आउटपुट प्रारूप।
--fail-on blocked प्रतिबंधित API मिलने पर गैर-शून्य कोड के साथ बाहर निकलता है.dexfinder.yaml, CLI फ़्लैग ओवरराइड करता हैHomebrew (macOS / Linux):```bash brew install junelegency/tap/dexfinder
**Script** (स्वचालित रूप से 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
**बाइनरी**: [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 स्वचालित रूप से उनका पता लगाता है और उनके बीच रूपांतरण करता है।
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"
## आउटपुट नियंत्रण
तीन स्वतंत्र अक्ष, स्वतंत्र रूप से संयोजनीय:```
--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| मान | उदाहरण | उपयोग मामला |
|---|---|---|
java | com.example.Foo.method(Foo.java) | मानव-पठनीय (डिफ़ॉल्ट) |
dex | Foo.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()
`--scope=all` (डिफ़ॉल्ट) = `callee` + `string`। `caller` दिशा को डिफ़ॉल्ट से जानबूझकर बाहर रखा गया है क्योंकि यह एक मौलिक रूप से भिन्न प्रश्न का उत्तर देता है। जब आपको इसकी आवश्यकता हो, तो स्पष्ट रूप से `--scope=caller` या `--scope=everything` का उपयोग करें।
**आउटपुट टैग को समझना:**
| Tag | Meaning |
|---|---|
| `[METHOD]` | एक विधि **जिसे कॉल किया जा रहा है** आपकी क्वेरी से मेल खाती है (callee match)। इंडेंट की गई पंक्तियाँ caller हैं। |
| `[FIELD]` | एक फ़ील्ड **जिसे एक्सेस किया जा रहा है** आपकी क्वेरी से मेल खाती है। इंडेंट की गई पंक्तियाँ accessors हैं। |
| `[CALLER→]` | एक **कॉल करने वाली विधि** आपकी क्वेरी से मेल खाती है। इंडेंट की गई पंक्ति दिखाती है कि वह किस API को कॉल कर रही है। |
| `[STRING]` | कोड में एक स्ट्रिंग स्थिरांक आपकी क्वेरी से मेल खाता है। इंडेंट की गई पंक्तियाँ वह स्थान हैं जहाँ इसका उपयोग किया गया है। |
| `[STRING_TABLE]` | स्ट्रिंग DEX स्ट्रिंग तालिका में मौजूद है लेकिन कोड में `const-string` संदर्भ नहीं है (एनोटेशन में हो सकता है, R8 द्वारा ऑप्टिमाइज़ किया गया हो, आदि)। |
## उदाहरण
### 1. APK सांख्यिकी स्कैन करें```bash
dexfinder --dex-file app.apk --stats
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
dexfinder --dex-file app.apk --query "requestLocationUpdates"
[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
### 3. कॉल चेन ट्रेस करें — ट्री दृश्य```bash
dexfinder --dex-file app.apk \
--query "Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;" \
--trace --depth 5
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)
dexfinder --dex-file app.apk
--query "Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String;"
--trace --depth 5 --layout list
--- 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)
### 5. DEX हस्ताक्षर शैली के साथ अनुरेखण```bash
dexfinder --dex-file app.apk --query "getDeviceId" --trace --depth 3 --style dex
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
dexfinder --dex-file app.apk --query "getDeviceId" --trace --depth 2 --format json
```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)" }
]}
]
}
}]
}
dexfinder --dex-file app.apk --query "getDeviceId" --trace --depth 2 --format json --layout list
```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)"]
]
}]
}
dexfinder --dex-file app.apk --query "getDeviceId" --trace --format model | jq '.call_chains[0]'
```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
}
--mapping के साथ, इनपुट और आउटपुट दोनों मूल (अस्पष्टीकृत) नामों का समर्थन करते हैं।
मूल नाम से क्वेरी → DEX खोज के लिए अस्पष्टीकृत नाम में स्वतः रूपांतरित होता है:```bash
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt
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
# Tree trace with deobfuscated names
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace --depth 3
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
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]
**अन्य फ़्लैग के साथ सभी संयोजन:**```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
इनपुट × आउटपुट मैट्रिक्स:
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
#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
### 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
[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)
dexfinder --dex-file app.apk --query "getDeviceId" --class-filter "Lcom/mycompany/"
dexfinder --dex-file app.apk --query "getDeviceId" --class-filter "Lcom/mycompany/,Lcom/mylib/"
### 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/"
dexfinder --dex-file app.apk --query "getDeviceId" --trace --format html --output report.html
किसी भी ब्राउज़र में खुलता है — संकुचित कॉल ट्री, खोज बार, डार्क थीम।
### 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]"
dexfinder --dex-file new.apk --diff old.apk --query "getDeviceId"
Summary: +1 added, -1 removed, ~0 changed
### 17. CI gate --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-श्रृंखला, एकल थ्रेड पर बेंचमार्क:
समान ~300MB APK पर veridex (C++, अपरिशुद्ध मोड) की तुलना में:
डिफ़ॉल्ट सेट करने के लिए अपने प्रोजेक्ट रूट में .dexfinder.yaml बनाएं:```yaml
mapping: ./build/outputs/mapping.txt
class-filter: "Lcom/mycompany/"
api-flags: ./hiddenapi-flags.csv
style: java
depth: 8
color: auto
CLI फ़्लैग्स हमेशा कॉन्फ़िग फ़ाइल मानों को ओवरराइड करते हैं।
## स्रोत से निर्माण```bash
git clone https://github.com/JuneLeGency/dexfinder.git
cd dexfinder
go build -o dexfinder ./cmd/dexfinder/
go test ./...
Apache License 2.0
आधिकारिक वेबसाइट: junelegency.github.io/dexfinder
क्रॉस-प्लेटफ़ॉर्म APK/DEX विधि और फ़ील्ड संदर्भ खोजक, कॉल चेन ट्रैकिंग, ProGuard/R8 डी-ऑबफ़स्केशन, Android Hidden API डिटेक्शन को सपोर्ट करता है।
Android veridex के सिद्धांत पर आधारित, Go में पुनः कार्यान्वित और उन्नत: तेज़ परावर्तन डिटेक्शन, बहु-स्तरीय कॉल चेन ट्रैकिंग (veridex केवल एक स्तर), लचीला आउटपुट प्रारूप।
--fail-on blocked प्रतिबंधित API का पता चलने पर गैर-शून्य निकास कोड लौटाता है.dexfinder.yaml प्रोजेक्ट डिफ़ॉल्ट कॉन्फ़िगरेशन, कमांड-लाइन तर्कों द्वारा ओवरराइडHomebrew (macOS / Linux):```bash brew install junelegency/tap/dexfinder
**स्क्रिप्ट इंस्टॉलेशन** (स्वचालित जाँच प्रणाली):```bash
curl -sSL https://raw.githubusercontent.com/JuneLeGency/dexfinder/main/install.sh | bash
Go स्थापना:```bash go install github.com/JuneLeGency/dexfinder/cmd/dexfinder@latest
**बाइनरी डाउनलोड**: [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) 终端着色
### `--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)
### `--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 बनाम caller का अंतर:``` scope=callee: "谁调了 finish()?" onCreate ──调用──→ finish() ← 显示这些调用者 onResume ──调用──→ finish()
scope=caller: "finish() 内部调了什么?" finish() ──调用──→ Log.i() ← 显示这些被调用者 finish() ──调用──→ super.finish()
`--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
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace
**सम्मिलित नाम और मूल नाम एक साथ प्रदर्शित करें:**```bash
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --show-obf --trace
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
dexfinder --dex-file app.apk --query "KotlinCases" --mapping mapping.txt --trace --style dex
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
**इनपुट × आउटपुट मैट्रिक्स:**
| क्वेरी इनपुट | कोई मैपिंग नहीं | `--mapping` | `--mapping --show-obf` |
|---|---|---|---|
| अस्पष्ट नाम `LJ7;` | ✓ अस्पष्ट आउटपुट | ✓ विपरीत अस्पष्टीकरण आउटपुट | ✓ दोनों एक साथ |
| मूल संक्षिप्त नाम `KotlinCases` | ✗ नहीं मिला | ✓ स्वचालित रूपांतरण + विपरीत अस्पष्टीकरण आउटपुट | ✓ स्वचालित रूपांतरण + दोनों एक साथ |
| मूल पूरा नाम `com.example...` | ✗ नहीं मिला | ✓ स्वचालित रूपांतरण + विपरीत अस्पष्टीकरण आउटपुट | ✓ स्वचालित रूपांतरण + दोनों एक साथ |
### छिपा एपीआई पता लगाना```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
dexfinder --dex-file app.apk --query "content://com.android.contacts" --scope string
dexfinder --dex-file app.apk --query "content://com.android.contacts" --scope everything
### पैकेज नाम के अनुसार फ़िल्टर करें```bash
# 只扫描自己的代码
dexfinder --dex-file app.apk --query "getDeviceId" --class-filter "Lcom/mycompany/"
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/"
### HTML रिपोर्ट```bash
dexfinder --dex-file app.apk --query "getDeviceId" --trace --format html --output report.html
浏览器打开即用——可折叠调用树、搜索栏、暗色主题。
dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv --format sarif > results.sarif
### APK संस्करण तुलना```bash
dexfinder --dex-file new.apk --diff old.apk --query "getDeviceId"
+ 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
dexfinder --dex-file app.apk --api-flags hiddenapi-flags.csv --fail-on blocked
## प्रदर्शन
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
कमांड लाइन तर्क हमेशा कॉन्फ़िगरेशन फ़ाइलों को ओवरराइड करते हैं।
git clone https://github.com/JuneLeGency/dexfinder.git cd dexfinder go build -o dexfinder ./cmd/dexfinder/ go test ./...
## लाइसेंस
Apache License 2.0
| प्रारूप | उदाहरण | व्यवहार |
|---|
| सरल नाम | getDeviceId | सभी API में फजी सबस्ट्रिंग मिलान |
| जावा वर्ग | android.telephony.TelephonyManager | उस वर्ग के सभी विधियाँ/फ़ील्ड्स |
| जावा वर्ग#विधि | android.telephony.TelephonyManager#getDeviceId | उस विधि के सभी ओवरलोड |
| जावा पूर्ण हस्ताक्षर | ...TelephonyManager#getDeviceId() | सटीक + ओवरलोड फ़ॉलबैक |
| DEX/JNI हस्ताक्षर | Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String; | केवल सटीक मिलान |
| मान | विवरण |
|---|
text | प्लेन टेक्स्ट आउटपुट जिसमें रंगीन टैग होते हैं (डिफ़ॉल्ट) |
json | JSON — स्कैन परिणाम या ट्रेस जिसमें ट्री/लिस्ट लेआउट होता है |
model | संरचित JSON जिसमें पूर्ण MethodInfo/FieldInfo प्रकार होते हैं (IDE/CI के लिए) |
html | स्व-निहित HTML रिपोर्ट जिसमें संकुचित होने वाले ट्री और खोज सुविधा होती है |
sarif | SARIF 2.1.0 स्थैतिक विश्लेषण प्रारूप (GitHub / VS Code) |
| मान | यह क्या खोजता है | यह किस प्रश्न का उत्तर देता है | आउटपुट टैग |
|---|
all | कॉल किए गए APIs + फ़ील्ड + कोड स्ट्रिंग्स | "यह एपीआई कौन कॉल करता है?" (डिफ़ॉल्ट) | [METHOD] [FIELD] [STRING] |
callee | केवल invoke-* / get/put निर्देशों में लक्ष्य API हस्ताक्षर | "यह विशिष्ट विधि/फ़ील्ड कौन कॉल करता है?" | [METHOD] [FIELD] |
caller | केवल कॉल करने वाली विधि का हस्ताक्षर | "यह विधि आंतरिक रूप से क्या कॉल करती है?" | [CALLER→] |
string | const-string निर्देशों में स्ट्रिंग स्थिरांक | "यह स्ट्रिंग कोड में कहाँ उपयोग की गई है?" | [STRING] |
string-table | कोड स्ट्रिंग्स + पूर्ण DEX स्ट्रिंग तालिका | "क्या यह स्ट्रिंग DEX में कहीं मौजूद है?" (एनोटेशन, मृत कोड शामिल है) | [STRING] [STRING_TABLE] |
everything | उपरोक्त सभी का संयोजन | पूरी तस्वीर | सभी टैग |
| क्वेरी इनपुट | कोई मैपिंग नहीं | --mapping | --mapping --show-obf |
|---|
अस्पष्ट: LJ7; | ✓ अस्पष्ट आउटपुट | ✓ डीऑबफस्केटेड आउटपुट | ✓ दोनों नाम |
मूल सरल: KotlinCases | ✗ नहीं मिला | ✓ स्वचालित रूपांतरण, डीऑबफस्केटेड आउटपुट | ✓ स्वचालित रूपांतरण, दोनों नाम |
मूल पूर्ण: com.example...KotlinCases | ✗ नहीं मिला | ✓ स्वचालित रूपांतरण, डीऑबफस्केटेड आउटपुट | ✓ स्वचालित रूपांतरण, दोनों नाम |
| APK आकार | DEX फ़ाइलें | क्लासेज़ | विधि संदर्भ | स्कैन | छिपा API |
|---|
| ~1 MB | 1 | ~2K | ~18K | 24ms | — |
| ~10 MB | 2 | ~25K | ~100K | 335ms | — |
| ~300 MB | 30+ | ~180K | ~1.2M | 3.9s | 5.4s |
| Flag | विवरण | डिफ़ॉल्ट |
|---|
--dex-file | विश्लेषण करने के लिए APK/DEX/JAR फ़ाइल (आवश्यक) | — |
--query | खोज कीवर्ड (Java, DEX/JNI, या सरल नाम) | — |
--trace | कॉल श्रृंखला ट्रेसिंग सक्षम करें (--query आवश्यक है) | false |
--depth | अधिकतम कॉल श्रृंखला गहराई | 5 |
--layout | ट्रेस लेआउट: tree या list | tree |
--style | नाम शैली: java या dex | 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 |
| 格式 | 示例 | 行为 |
|---|
| 简单名称 | 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→] |
string | const-string निर्देश में स्ट्रिंग स्थिरांक | "यह स्ट्रिंग कोड में कहाँ उपयोग की गई है?" | [STRING] |
string-table | कोड स्ट्रिंग + DEX पूर्ण स्ट्रिंग तालिका | "क्या यह स्ट्रिंग DEX में मौजूद है?" (एनोटेशन, मृत कोड सहित) | [STRING] [STRING_TABLE] |
everything | उपरोक्त सभी | पूर्ण दृश्य | सभी लेबल |