跳过内容

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 工具使用。 这些实用程序包括 rabin2rasm2rahash2radiff2rafind2ragg2rarun2rax2,当然还有 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 命令 icinformation 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 命令 iiinformation 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 书籍