十二、反编译和反汇编 Android 应用
Android 应用要么用 Java 编写,要么用 Kotlin 编写。当构建一个应用时,它们被编译成 Dalvik 字节码——用dex
(Dalvik 可执行文件)表示。这个 Dalvik 字节码是二进制的,因此不可读。既然如此,如果逆向工程师想要分析一个已经编译好的 Android 应用,他们只能选择反编译或反汇编 Dalvik 可执行文件。图 12-1 突出显示了创建和逆向工程一个 Android 应用的过程。
图 12-1
软件开发人员和逆向工程流程视图
反编译器 java
第一种选择是使用工具将 Dalvik 字节码反编译成人类可读的 Java。这个 Java 比真正的 Java 更像伪代码,因为它是反编译器对 Dalvik 程序集所代表的内容的“最佳猜测”。虽然 Java 开发人员更熟悉这种视图,但它通常不是最佳选择,因为它不仅不代表实际的应用代码,而且也不可运行或重新编译。像dex2jar
和jadx
这样的工具可以用来反编译 Dalvik 可执行文件。Jadx 可用于将 Jadx 项目导出到 Gradle 项目,进而允许将项目加载到 Android Studio 中。
APKTool 可用于提取。来自 APK 的 dex 文件:
apktool -s d <apk path>
用 JADX 反编译并查看 APK 或 Dex 文件的反编译 Java:
jadx -e <apk or dex file path>
反汇编的 Dalvik 字节码(Smali)
可以使用反汇编器将 Dalvik 字节码还原为人类可读的自身表示,而不是反编译成伪 Java。Dalvik 字节码更常用的这种形式叫做 Smali。对 Smali 来说,反汇编的好处是一个dex
文件可以被反汇编、读取、修改、重组和提交,并且仍然处于完全运行的状态。
apk tool 等工具可以用来反汇编 dalvik 字节码:
apktool d <path>
由于其性质,Smali 比 Java 或 Kotlin 有更大的代码占用空间。例如,以下 Java 中的 Toast 代码(一个简单的 Android 弹出消息)是 Smali 中相同代码的一半大小。
Java:
Context context = getApplicationContext();
CharSequence text = "I'm a Toast";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
型式:T1
.line 13
const-string v0, "I'm a Toast!"
.line 14
.local v0, "text":Ljava/lang/String;
const/4 v1, 0x1
.line 16
.local v1, "duration":I
invoke-virtual {p0}, Lcom/example/simpletoastapp/MainActivity;->getApplicationContext()Landroid/content/Context;
move-result-object v2
move-object v3, v0
check-cast v3, Ljava/lang/CharSequence;
invoke-static {v2, v3, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v2
.line 17
.local v2, "toast":Landroid/widget/Toast;
invoke-virtual {v2}, Landroid/widget/Toast;->show()V
从运行的设备中提取 apk
为了分析(进而反汇编或反编译)一个 Android 应用,您可能需要首先从设备中提取它。ADB shell 可以用来做这件事。
下面使用包管理器列出设备上的所有包 id:
pm list packages
pm list packages | grep chrome
接下来,可以再次使用包管理器列出所需包的基本 APK 的路径(例如包路径是/data/app/com . Android . chrome-6 PIH 3g 1 et 8 uqozatukwptq = =/base . apk):
pm path <Package ID>
查看此命令返回的目录不需要特殊权限。但是,它的父目录(/data/app
)没有非 root 的读取权限,这意味着设备上的应用不能以这种方式枚举。
最后,提取 APK 最简单的方法是使用 adb,如下所示:
adb pull <package base APK path>
还值得记住的是,诸如 APK 囤积者、 1 之类的工具是免费和开源的,可以用于从设备中大量提取 apk。
Footnotes [1](#Fn1_source) [`https://github.com/user1342/APK-Hoarder`](https://github.com/user1342/APK-Hoarder)【APK 囤积者| Github】。于 2020 年 12 月 27 日访问。版权属于:月萌API www.moonapi.com,转载请注明出处