MASTG-TOOL-0028: Android 版 radare2
radare2 (r2) 是一个流行的开源逆向工程框架,用于反汇编、调试、修补和分析二进制文件,它是可脚本化的,并且支持包括 Android 和 iOS 应用在内的许多架构和文件格式。 对于 Android,支持 Dalvik DEX(odex、multidex)、ELF(可执行文件、.so、ART)和 Java(JNI 和 Java 类)。 它还包含几个有用的脚本,可以在移动应用程序分析期间为您提供帮助,因为它提供了低级的反汇编和安全的静态分析,当传统工具失败时,这些非常方便。
radare2 实现了一个丰富的命令行界面 (CLI),您可以在其中执行上述任务。 但是,如果您不太习惯使用 CLI 进行逆向工程,您可能需要考虑使用 Web UI(通过 -H
标志)或更方便的 Qt 和 C++ GUI 版本,称为 iaito。 请记住,CLI,更具体地说是其可视模式及其脚本编写功能(r2pipe),是 radare2 的核心力量,绝对值得学习如何使用它。
安装 radare2¶
请参阅 radare2 的官方安装说明。 我们强烈建议始终从 GitHub 版本安装 radare2,而不是通过 APT 等常见软件包管理器安装。 Radare2 处于非常活跃的开发阶段,这意味着第三方存储库通常已过时。
使用 radare2¶
radare2 框架包含一组小型实用程序,可以从 r2 shell 中使用,也可以独立作为 CLI 工具使用。 这些实用程序包括 rabin2
、rasm2
、rahash2
、radiff2
、rafind2
、ragg2
、rarun2
、rax2
,当然还有 r2
,它是主要的实用程序。
例如,您可以使用 rafind2
直接从编码的 Android Manifest (AndroidManifest.xml) 中读取字符串
# Permissions
$ rafind2 -ZS permission AndroidManifest.xml
# Activities
$ rafind2 -ZS activity AndroidManifest.xml
# Content providers
$ rafind2 -ZS provider AndroidManifest.xml
# Services
$ rafind2 -ZS service AndroidManifest.xml
# Receivers
$ rafind2 -ZS receiver AndroidManifest.xml
或者使用 rabin2 获取有关二进制文件的信息。
使用主 r2
实用程序访问 r2 shell。 您可以像加载任何其他二进制文件一样加载 DEX 二进制文件
r2 classes.dex
输入 r2 -h
查看所有可用选项。 一个非常常用的标志是 -A
,它会在加载目标二进制文件后触发分析。 但是,应谨慎使用此方法,并且仅用于小型二进制文件,因为它非常耗时和资源。 您可以在 反汇编本机代码 中了解更多信息。
进入 r2 shell 后,您还可以访问其他 radare2 实用程序提供的功能。 例如,运行 i
将打印二进制文件的信息,就像 rabin2 -I
一样。
要打印所有字符串,请使用 rabin2 -Z
或 r2 shell 中的命令 iz
(或不太冗长的 izq
)。
[0x000009c8]> izq
0xc50 39 39 /dev/com.koushikdutta.superuser.daemon/
0xc79 25 25 /system/app/Superuser.apk
...
0xd23 44 44 5UJiFctbmgbDoLXmpL12mkno8HT4Lv8dlat8FxR2GOc=
0xd51 32 32 8d127684cbc37c17616d806cf50473cc
0xd76 6 6 <init>
0xd83 10 10 AES error:
0xd8f 20 20 AES/ECB/PKCS7Padding
0xda5 18 18 App is debuggable!
0xdc0 9 9 CodeCheck
0x11ac 7 7 Nope...
0x11bf 14 14 Root detected!
大多数时候,您可以在命令后附加特殊选项,例如 q
以使命令不那么冗长(安静),或者 j
以 JSON 格式给出输出(使用 ~{}
美化 JSON 字符串)。
[0x000009c8]> izj~{}
[
{
"vaddr": 3152,
"paddr": 3152,
"ordinal": 1,
"size": 39,
"length": 39,
"section": "file",
"type": "ascii",
"string": "L2Rldi9jb20ua291c2hpa2R1dHRhLnN1cGVydXNlci5kYWVtb24v"
},
{
"vaddr": 3193,
"paddr": 3193,
"ordinal": 2,
"size": 25,
"length": 25,
"section": "file",
"type": "ascii",
"string": "L3N5c3RlbS9hcHAvU3VwZXJ1c2VyLmFwaw=="
},
您可以使用 r2 命令 ic
(information classes - 信息类)打印类名及其方法。
[0x000009c8]> ic
...
0x0000073c [0x00000958 - 0x00000abc] 356 class 5 Lsg/vantagepoint/uncrackable1/MainActivity
:: Landroid/app/Activity;
0x00000958 method 0 pC Lsg/vantagepoint/uncrackable1/MainActivity.method.<init>()V
0x00000970 method 1 P Lsg/vantagepoint/uncrackable1/MainActivity.method.a(Ljava/lang/String;)V
0x000009c8 method 2 r Lsg/vantagepoint/uncrackable1/MainActivity.method.onCreate (Landroid/os/Bundle;)V
0x00000a38 method 3 p Lsg/vantagepoint/uncrackable1/MainActivity.method.verify (Landroid/view/View;)V
0x0000075c [0x00000acc - 0x00000bb2] 230 class 6 Lsg/vantagepoint/uncrackable1/a :: Ljava/lang/Object;
0x00000acc method 0 sp Lsg/vantagepoint/uncrackable1/a.method.a(Ljava/lang/String;)Z
0x00000b5c method 1 sp Lsg/vantagepoint/uncrackable1/a.method.b(Ljava/lang/String;)[B
您可以使用 r2 命令 ii
(information imports - 信息导入)打印导入的方法。
[0x000009c8]> ii
[Imports]
Num Vaddr Bind Type Name
...
29 0x000005cc NONE FUNC Ljava/lang/StringBuilder.method.append(Ljava/lang/String;) Ljava/lang/StringBuilder;
30 0x000005d4 NONE FUNC Ljava/lang/StringBuilder.method.toString()Ljava/lang/String;
31 0x000005dc NONE FUNC Ljava/lang/System.method.exit(I)V
32 0x000005e4 NONE FUNC Ljava/lang/System.method.getenv(Ljava/lang/String;)Ljava/lang/String;
33 0x000005ec NONE FUNC Ljavax/crypto/Cipher.method.doFinal([B)[B
34 0x000005f4 NONE FUNC Ljavax/crypto/Cipher.method.getInstance(Ljava/lang/String;) Ljavax/crypto/Cipher;
35 0x000005fc NONE FUNC Ljavax/crypto/Cipher.method.init(ILjava/security/Key;)V
36 0x00000604 NONE FUNC Ljavax/crypto/spec/SecretKeySpec.method.<init>([BLjava/lang/String;)V
检查二进制文件的一种常用方法是搜索某些内容,导航到该内容并将其可视化以解释代码。 使用 radare2 查找内容的方法之一是通过过滤特定命令的输出,即使用 ~
加上关键字(~+
用于不区分大小写)来 grep 它们。 例如,我们可能知道应用程序正在验证某些内容,我们可以检查所有 radare2 标志,看看在哪里可以找到与“verify”相关的内容。
加载文件时,radare2 会标记它能够找到的所有内容。 这些标记的名称或引用称为标志。 您可以通过命令
f
访问它们。
在这种情况下,我们将使用关键字“verify”来 grep 这些标志
[0x000009c8]> f~+verify
0x00000a38 132 sym.Lsg_vantagepoint_uncrackable1_MainActivity.method. \
verify_Landroid_view_View__V
0x00000a38 132 method.public.Lsg_vantagepoint_uncrackable1_MainActivity. \
Lsg_vantagepoint_uncrackable1
_MainActivity.method.verify_Landroid_view_View__V
0x00001400 6 str.verify
看来我们在 0x00000a38 中找到了一个方法(被标记了两次),在 0x00001400 中找到了一个字符串。 让我们通过使用它的标志导航(寻址)到该方法
[0x000009c8]> s sym.Lsg_vantagepoint_uncrackable1_MainActivity.method. \
verify_Landroid_view_View__V
当然,您也可以使用 r2 的反汇编程序功能,并使用命令 pd
(或者如果您知道您已经位于一个函数中,则使用 pdf
)打印反汇编代码。
[0x00000a38]> pd
r2 命令通常接受选项(参见 pd?
),例如,您可以通过在命令 pd N
中附加一个数字 ("N") 来限制显示的指令码。
您可能不想只将反汇编代码打印到控制台,而是想通过键入 V
进入所谓的 可视模式。
默认情况下,您将看到十六进制视图。 通过键入 p
,您可以切换到不同的视图,例如反汇编视图
Radare2 提供了一个 图形模式,对于跟踪代码的流程非常有用。 您可以通过键入 V
从可视模式访问它
这只是 radare2 的一些命令的选集,可以开始从 Android 二进制文件中获取一些基本信息。 Radare2 非常强大,并且有数十个命令,您可以在 radare2 命令文档中找到它们。 在本指南中,radare2 将用于不同的目的,例如逆向代码、调试或执行二进制分析。 我们还将结合其他框架使用它,尤其是 Frida(有关更多信息,请参阅 r2frida 部分)。
请参阅 反汇编本机代码 了解有关在 Android 上使用 radare2 的更详细信息,尤其是在分析本机库时。 您可能还想阅读 官方 radare2 书籍。