
أداة بحث عبر الأنظمة الأساسية عن الطرق (methods) في ملفات APK/DEX مع تتبع سلسلة الاستدعاءات، وإزالة تشويش ProGuard، واكتشاف الواجهات البرمجية المخفية.
English | 中文 | الموقع الإلكتروني

الموقع الإلكتروني: junelegency.github.io/dexfinder
أداة عبر الأنظمة الأساسية للبحث عن مراجع الدوال والحقول في APK/DEX مع تتبع سلاسل الاستدعاء، وإزالة التعتيم ProGuard/R8، واكتشاف واجهات برمجة التطبيقات المخفية في Android.
مستوحاة من أداة veridex الخاصة بـ Android، وأُعيد تنفيذها بلغة Go مع قدرات محسّنة: كشف الانعكاس بشكل أسرع، تتبع سلسلة الاستدعاءات (veridex يُظهر مستوى واحدًا فقط)، وتنسيقات إخراج مرنة.
--fail-on blocked يخرج برمز غير صفري عند العثور على واجهات API المقيدة.dexfinder.yaml للإعدادات الافتراضية للمشروع، مع إمكانية تجاوز عن طريق علامات CLIHomebrew (macOS / Linux):```bash brew install junelegency/tap/dexfinder
**البرنامج النصي** (يكتشف تلقائيًا نظام التشغيل/الهندسة):```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
**ثنائي**: تنزيل من [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 بالكشف التلقائي والتحويل بينها.
| الصيغة | مثال | السلوك |
|---|---|---|
| اسم بسيط | getDeviceId | مطابقة جزئية غير دقيقة عبر جميع واجهات API |
| كلاس Java | android.telephony.TelephonyManager | جميع دوال/حقول ذلك الكلاس |
| كلاس#دالة في Java | android.telephony.TelephonyManager#getDeviceId | جميع التحميلات الزائدة لتلك الدالة |
| التوقيع الكامل في Java | ...TelephonyManager#getDeviceId() | مطابقة تامة مع الرجوع إلى التحميلات الزائدة |
| توقيع DEX/JNI | Landroid/telephony/TelephonyManager;->getDeviceId()Ljava/lang/String; | مطابقة تامة فقط |
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| القيمة | الوصف |
|---|---|
text | إخراج نصي عادي مع وسوم ملونة (الافتراضي) |
json | JSON — نتائج المسح أو التتبع بتنسيق شجري/قائمة |
model | JSON منظم مع أنواع MethodInfo/FieldInfo كاملة (لبيئات التطوير/التكامل المستمر) |
html | تقرير HTML مستقل مع أشجار قابلة للطي وبحث |
sarif | تنسيق تحليل ثابت SARIF 2.1.0 (GitHub / VS Code) |
--layout (يُستخدم مع --trace)| القيمة | الوصف |
|---|---|
tree | شجرة مدمجة — مسارات الاستدعاء المشتركة مطوية في شجرة واحدة (الافتراضي) |
list | قائمة مسطحة — كل سلسلة استدعاء فريدة تظهر كمكدس مستقل |
--style| القيمة | مثال | حالة الاستخدام |
|---|---|---|
java | com.example.Foo.method(Foo.java) | قابل للقراءة البشرية (الافتراضي) |
dex | Foo.method(Ljava/lang/String;)V | تحليل دقيق للتوقيعات |
--scope (نطاق البحث)يتحكم في نوع المراجع التي يطابقها الاستعلام. هذا أمر بالغ الأهمية لفهم النتائج.
| القيمة | ما يبحث عنه | السؤال الذي يجيب عليه | الوسم الناتج |
|---|---|---|---|
all | واجهات برمجة التطبيقات المستدعاة + الحقول + سلاسل النص | "من يستدعي هذه الواجهة البرمجية؟" (الافتراضي) | [METHOD] [FIELD] [STRING] |
callee | توقيعات واجهة برمجة التطبيقات المستهدفة فقط في تعليمات invoke-* / get/put | "من يستدعي هذه الطريقة/الحقل بالتحديد؟" | [METHOD] [FIELD] |
caller | توقيع الطريقة المستدعية فقط | "ما الذي تستدعيه هذه الطريقة داخليًا؟" | [CALLER→] |
string | ثوابت النص في تعليمات const-string | "أين يُستخدم هذا النص في الكود؟" | [STRING] |
string-table | نصوص الكود + جدول النص الكامل لـ DEX | "هل هذا النص موجود في أي مكان في DEX؟" (يشمل التعليقات التوضيحية، الكود الميت) | [STRING] [STRING_TABLE] |
everything | جميع ما سبق مجتمعًا | الصورة الكاملة | جميع الوسوم |
فهم الفرق بين 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()
`--scope=all` (الافتراضي) = `callee` + `string`. يتم استبعاد اتجاه `caller` عمدًا من الافتراضي لأنه يجيب على سؤال مختلف جوهريًا. استخدم `--scope=caller` أو `--scope=everything` صراحةً عندما تحتاج ذلك.
**فهم وسوم المخرجات:**
| الوسم | المعنى |
|---|---|
| `[METHOD]` | طريقة **يتم استدعاؤها** تطابق استعلامك (مطابقة المستدعى). الأسطر المسننة هي المستدعون. |
| `[FIELD]` | حقل **يتم الوصول إليه** يطابق استعلامك. الأسطر المسننة هي الوصولات. |
| `[CALLER→]` | طريقة **مستدعية** تطابق استعلامك. يظهر السطر المسنن ما هي واجهة API التي تستدعيها. |
| `[STRING]` | ثابت نصي في الكود يطابق استعلامك. الأسطر المسننة هي مكان استخدامه. |
| `[STRING_TABLE]` | النص موجود في جدول النصوص DEX ولكن ليس له مرجع `const-string` في الكود (قد يكون في التعليقات التوضيحية، أو تم تحسينه بواسطة R8، إلخ). |
## أمثلة