Redexer 是一个用于操作 Android 应用二进制的重工程工具。 该工具能够将 DEX 文件解析为内存中的数据结构; 推断应用使用某些权限时的参数(我们称此功能为 RefineDroid); 修改该数据结构并重新生成输出 DEX 文件(我们称这些功能为 Dr. Android,即 Dalvik 重写工具)。
该工具在 OCaml 4.09.0 和 Ruby 1.8.6(7) 下测试通过, 因此你需要安装它们(或更高版本)。
为了操作 DEX 格式中的 SHA-1 签名(哈希), 我们通过 ocamlfind/findlib(一个 OCaml 库管理器)使用 OCaml SHA 库。 安装这两者的最简单方法是使用 OPAM(一个 OCaml 包管理器),它包含 这两个包——OPAM ocamlfind 和 OPAM sha。
你也可以直接构建和/或安装这两个包。 如果你使用的是 Linux 机器,很容易找到发行版。
否则(例如使用 Mac),你需要自行构建。
你可以在此处找到原始源代码:这里。
通过运行 make 构建,并将结果目录链接到 ocamlfind 的根 site-lib 目录;或者使用 sudo make install。
如果你使用的是 PC,你需要先安装 ocamlfind/findlib 和 FlexDLL。请确保你的环境变量 设置正确,如下所示:
OCAMLLIB=C:\OCaml\lib
CAML_LD_LIBRARY_PATH=%OCAMLLIB%\stublibs
FLEXLINKFLAGS=-L%MinGW%\lib -L%MinGW%\lib\gcc\mingw32\N.N.N
OPAM 包:
Android SDK(或源码)
为了解包和重新打包 APK 文件,我们使用 apktool,一个开源 APK
重工程工具。由于它使用 aapt(Android Asset Packaging Tool),
你需要安装 Android SDK 或源码。此外,我们还使用
zipalign(同样来自 Android SDK)来优化重写后的应用。
你可以通过将以下内容添加到你的配置文件中来设置 Android 基础工具的路径:
ANDROID_HOME=$HOME/android-sdk # 你自己的路径!
export ANDROID_HOME
PATH=$PATH:$ANDROID_HOME/tools
PATH=$PATH:$ANDROID_HOME/platform-tools
PATH=$PATH:$ANDROID_HOME/build-tools/19.0.0 # 已安装的版本号
export PATH
主脚本使用 Ruby 编写,需要 RubyGems(一个 Ruby 包管理器) 和 Nokogiri(一个用于操作清单文件的 XML 库)。
如果你想查看图形(例如调用图、控制流图、 支配树等),你需要安装 graphviz dot。
要构建 redexer,只需 make!你可以在顶层目录看到 redexer 二进制文件。
$ make (clean)
在使用该工具之前,用户需要自行安装 apktool 的最新平台文件。 例如,你需要执行
$ java -jar tools/apktool.jar if [合适的平台文件]
你也可以生成 HTML 格式的 API 文档。
$ make api
你可以查看该工具提供的所有选项:
$ ruby scripts/cmd.rb -h
$ ruby scripts/cmd.rb --help
类似于 Android SDK 的 dexdump,redexer 允许你以 YAML 格式查看给定 dex 文件的内部结构。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd unparse [--to blah.yml]
此选项转储指定方法的指令。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd dump_method --mtd cls.mtd
此功能用于测试 redexer 的解析和转储模块。 它可能生成一个相同的 dex 文件。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd id [--to blah.dex]
你还可以查看 dex 文件的基本统计信息,例如指令数。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd info
此选项打印 dex 文件中定义的所有类名。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd classes
这在搜索特定的第三方库时可能很有用,例如:
$ ruby scripts/cmd.rb target.(apk|dex) --cmd classes | egrep 'apache'
此选项打印 dex 文件中的 API 使用情况。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd api [--sdk android.]
$ ruby scripts/cmd.rb target.(apk|dex) --cmd api --sdk com.facebook.
你难道不好奇在 Dalvik 字节码中某些操作码的使用频率有多低吗? 它将显示所有操作码的直方图,或者你可以查看指定操作码在给定应用中的使用频率。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd opstat [--op opcode1,opcode2,...]
例如,
$ ruby scripts/cmd.rb ~/apps/top24/com.whatsapp.apk --cmd opstat
$ ruby scripts/cmd.rb ~/apps/top24/com.whatsapp.apk --cmd opstat --op div-int/lit16,nop
此选项执行基于传播的 Intent 解析分析, 并打印 Activity 类之间的转换关系。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd intent
此选项生成一个 PDF 文件,描绘给定文件的调用图。 如果你不指定 PDF 名称,将使用 cg.pdf。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd cg [--to blah.pdf] [--no-pdf]
此选项生成一个 PDF 文件,显示给定方法的控制流图。 在类名后附加方法名,用点分隔:class_name.method_name
$ ruby scripts/cmd.rb target.(apk|dex) --cmd cfg --mtd cls.mtd [--to blah.pdf] [--no-pdf]
此选项与上述功能类似,区别在于它描绘(后)支配树。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd (p)dom --mtd cls.mtd [--to blah.pdf] [--no-pdf]
此选项执行经典的后向数据流分析。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd live --mtd cls.mtd
此选项执行经典的前向数据流分析。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd const --mtd cls.mtd
此选项执行经典的前向数据流分析。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd reach --mtd cls.mtd
此选项查找类依赖关系。
$ ruby scripts/cmd.rb target.(apk|dex) --cmd dependants --mtd cls.mtd
此选项打印给定 APK 的启动 Activity 名称。
$ ruby scripts/cmd.rb target.apk --cmd launcher
此选项让你了解哪些组件对外暴露。
$ ruby scripts/cmd.rb target.apk --cmd exported
这些选项打印清单中声明的 Android 基本组件。
$ ruby scripts/cmd.rb target.apk --cmd [activity | service | provider | receiver]
此选项探索资源中的布局定义并打印自定义视图。
$ ruby scripts/cmd.rb target.apk --cmd custom_views
此选项探索资源中的布局定义并打印 Fragment 元素。
$ ruby scripts/cmd.rb target.apk --cmd fragments
此选项探索资源中的布局定义并打印按钮, 以及它们的 id(或文本)和回调方法(如果存在)。
$ ruby scripts/cmd.rb target.apk --cmd buttons
此选项打印 APK 使用的权限。
$ ruby scripts/cmd.rb target.apk --cmd permissions
此选项打印 APK 所需的 SDK 版本。
$ ruby scripts/cmd.rb target.apk --cmd sdk
如果你不想解包 APK 文件, 实际上,你可以通过命令组合实现相同的结果:
$ aapt dump badging target.apk | grep 'targetSdkVersion' | tr -dc 0-9.\\n
此选项将生成一个打印简单消息的 dex 文件。 该 dex 文件仅使用 redexer 的 API 创建。
$ ruby scripts/cmd.rb --cmd hello
检查其内部。
$ dexdump -d results/classes.dex
如果你感兴趣,可以按如下方式测试该 dex 文件。 假设已设置 ANDROID_SDK 的路径。
// 创建一个适合 dalvik VM 的临时 jar
$ aapt add temp.jar results/classes.dex
// (可选)如果你没有制作 avd,请先制作。
$ android create avd -n myAVD1 -t android-8
// 启动你的模拟器
$ emulator -avd myAVD1 &
// 推送临时 jar
$ adb push temp.jar /data
// 连接到 adb shell
$ adb shell
// 最后,运行 dex
# /system/bin/dalvikvm -Xbootclasspath:/system/framework/core.jar \
-classpath /data/temp.jar Hello
Hello, DEX
#
这是重写功能的一个变体。使用此功能,你可以从特定视角记录应用行为。
提供了预构建的日志库 dex 文件:data/logging.dex。如果你想添加
更多功能或实用工具,请按如下方式构建:
$ cd logging
$ gradle copyDex
$ cd ..
然后,使用以下命令:
$ ruby scripts/cmd.rb target.apk --cmd logging
trim.py 可以捕获被检测应用的调用-返回序列。 (你应该先使用 redexer 对被测应用进行插桩。)
如果日志足够短,即手机(或模拟器)可以将所有信息保存在内存中, 你可以使用脚本的离线模式:
$ ./scripts/trim.py -d
请注意,所有命令行参数都将传递给 adb logcat,并且
默认情况下,会传递 org.umd.logging:I *:S 以过滤掉不相关的日志。
如果日志溢出,你应该使用在线模式:
$ ./scripts/trim.py
该脚本会捕获键盘中断,因此你可以通过 Ctrl+C 结束日志记录。
在两种模式下,日志都保存在 log.txt 中,并同时显示在屏幕上。 因此,收集日志后,你可能需要移动该文件,例如:
$ mv log.txt app.scenario.txt
上述日志功能是通用的,因为你可以指定在方法级别记录什么。
(有关更多详细信息,请参阅 logging 模块。)
但是,这有时过于冗长,可能导致性能下降。
此功能专为仅记录用户交互而设计。使用此功能,
你只能捕获与 UI 相关的事件。类似地,提供了预构建的日志库 dex 文件:
data/logging-ui.dex。如果你想修改 UI 信息的详细程度,
请按如下方式构建:
$ cd logging-ui
$ gradle copyDex
$ cd ..
然后,使用以下命令:
$ ruby scripts/cmd.rb target.apk --cmd logging_ui
日志库继承自 Android 的无障碍服务,需要用户明确同意。
因此,安装重写后的 APK 后,请前往
设置/无障碍 并打开 UI Logging 服务。
(此步骤类似于打开设备调试模式。)
在 logcat 中,标签为 org.umd.logging_ui.* 的消息是用户
与被测应用之间的交互。
此选项查找指向目标方法调用的组件转换路径。
$ ruby scripts/cmd.rb target.apk --cmd directed
你可以在 data/directed.txt 中指定要调用的目标方法。
这些组件转换路径用于驱动应用测试第三方库中的安全漏洞。 更多细节描述于以下论文:
* Brahmastra: Driving Apps to Test the Security of Third-Party Components.
R. Bhoraskar, et al., In 23rd Usenix Security Symposium (Security '14).
withTimeout.rb 可以自动为应用构建跳过文件。此脚本 以特定超时运行 cmd.rb,用于限制对任何单个类进行插桩的时间。 这是一个临时的变通方法,用于处理在插桩过程中偶尔出现的 陷入循环的类。当此脚本发现崩溃的类时,会将其添加到跳过文件中, 并从中断处继续。withTimeout 终止后,数据目录中会有一个名为 [apk名称]-skip.txt 的文件,可用于为该 APK 构建完全插桩的应用。 要使用 withTimeout,只需调用
$ ruby scripts/withTimeout.rb TIMEOUT COMMANDS
其中 TIMEOUT 是你想要的超时时间(以秒为单位,建议 300), COMMANDS 是你通常会传递给 scripts/cmd.rb 的 APK 的所有常规命令行输入。