在反编译庞大的 Android APK 时,标准流程就是等待。我们等待工具吃掉数 GB 的内存,完全展开产物,并花费数十分钟构建庞大的全局索引和交叉引用……这一切只是为了确保后续的代码搜索足够快,但矛盾就在这里。编译后的产物本身已经高度结构化,现代反编译器却从不利用这一点,它们浪费大量时间和内存,在已经结构化的数据之上重建一个臃肿的代码关系数据库。这种工程方法违背常识。当我可以在毫秒内直接从 APK 中提取任意代码关系时,这种预处理还有任何价值吗?
与其强迫反编译器进行繁重的预处理,我们选择直接将编译后的产物当作数据库来查询。我们构建了一个无状态、零开销的引擎,可以按需在毫秒内提取和搜索代码。在本次简报中,我们将探讨绕过传统瓶颈所需的底层工程。我们将演示如何通过直接在 Deflate 比特流内部进行探测来放弃完全展开,构建密集的 Huffman 查找表以提取核心元数据,而不触碰无关的数据块。此外,我们将解释 R8 编译器的优化细节,特别是确定性常量重定位和指令去重如何留下高度集中的物理布局,我们将这种编译器行为武器化,以执行闪电般的跨 DEX 代码搜索。为了将这些原始字节码偏移映射回方法,我们设计了一个 O(1) 指令定位原语,实现常数时间的方法解析,而无需构建繁重的映射表。最后,在命中目标时,Droid ASC 仅提取特定的字节码及其依赖项,在内存中动态重建一个最小且自洽的 DEX,以实现即时反编译。
我们将针对一个 352MB 的商业 APK 现场演示这一架构。Droid ASC 在 1.79 秒内执行全局交叉引用搜索,并在 177 毫秒内反编译目标类,仅使用 141MB 内存。通过将产物视为只读数据库并以零预处理方式运行,我们让反编译器回归其核心本质。它不再是一个臃肿的索引工具,而是一个闪电般快速的按需反编译引擎,从根本上重新定义了我们分析编译代码的方式。

https://github.com/user-attachments/assets/4c4a6813-8561-490c-a573-ef113da861b6
# from PyPI
pip install droidasc
# or from source
pip install .
安装后,droidasc CLI 命令即可全局使用:
usage: droidasc [-h] {getclass,listclass,getmanifest,findrefs} ...
ASC tooling entry.
positional arguments:
{getclass,listclass,getmanifest,findrefs}
getclass Locate the target class in APK, extract one DEX in memory, then decompile.
listclass List classes defined across all DEX entries in APK.
getmanifest Decode AndroidManifest.xml from APK and print it as XML.
findrefs Find code references for string/type/method/field across all DEX entries in APK.
options:
-h, --help show this help message and exit
examples:
droidasc app.apk --gui
droidasc getclass app.apk Lcom/poc/Main; -o Main.java
droidasc getclass app.apk com.poc.Main --threads 16
droidasc listclass app.apk -o classes.txt
droidasc listclass app.apk --prefix com.poc
droidasc getmanifest app.apk -o AndroidManifest.xml
droidasc findrefs app.apk string token -o string_refs.txt
droidasc findrefs app.apk type com.poc.Main
droidasc findrefs app.apk method onCreate --class com.poc.Main
droidasc findrefs app.apk method notify --class MainActivity --fuzzy-class -o method_refs.txt
droidasc findrefs app.apk field apiKey -o field_refs.txt
listclass 按 APK/DEX 定义顺序打印 Dalvik 类描述符,每行一个。
使用 -o 时,输出将写入指定文件而不是 stdout。
--prefix com.poc 按 Lcom/poc 过滤;已经规范化的前缀如
Lcom/poc 保持不变。
你也可以像以前一样使用 python main.py —— 它会委托给同一个入口点。
| 赞助者 | 金额 |
|---|---|
| HTTChina | 5000¥ |
| c01ns | 11.9¥ |
| gguowang AND cococount | 2¥ |
| Ylarod | 50.11¥ |
感谢所有赞助者的支持!
ASC 的构建初衷是希望它能真正帮助每个人改进逆向工程工作流——从加速繁琐的部分到让不可能的事情变得习以为常。
感谢 Androguard 项目 为 Droid ASC 提供了所使用的 Android 逆向工程和 DEX 分析基础。