了解最新技术文章
JEB 4.17 附带了一个 Dart AOT(提前)二进制快照助手插件,以帮助分析预编译的 Dart 程序。它的一个常见用例可能是在逆向工程为 Android x86/x64 或 arm/aarch64 平台编译的 Flutter 应用程序时提供指导。
基于 Flutter 的发布模式 Android 应用程序将生成 AOT 快照,而不是像调试模式应用程序可能选择的那样随字节码或 Dart 代码一起提供。AOT 快照包含运行预编译代码所需的 Dart VM 的状态。
该插件支持使用 Dart 2.10 到 2.17 版本编译的 AOT 快照。
快照通常位于lib/<arch>/libapp.so
APK 的文件中。由于 Dart 可能在 Flutter 之外使用,或者由于文件名或位置可能会更改,因此找到此类文件的可靠方法是查找so
导出以下 4 个符号的 ELF:
_kDartVmSnapshotInstructions
_kDartIsolateSnapshotInstructions
_kDartVmSnapshotData
_kDartIsolateSnapshotData
这些XxxSnapshotInstructions
符号指向预编译的机器代码。但是,在处理剥离或混淆的二进制文件时找到一个起点可能会很困难。这些XxxSnapshotData
符号指向将被执行代码访问的 Dart VM 结构和对象。这包括数据元素,例如池字符串或立即值数组。快照数据还包括重要的元数据,这些元数据有助于重组在 AOT 快照中编译的成百上千个例程。
首先,确保您处理的是 Dart AOT 快照或包含预编译 AOT 快照的 Flutter 应用程序。确实存在其他类型的快照,例如 JIT 快照。该插件不为这些提供帮助。在实践中,非 AOT 快照可能相对容易分析,但您不太可能在野外遇到它们。大多数 Dart 代码或 Flutter 应用程序将以发布模式编译和分发。充其量,可能会留下一些符号和可选元数据。在最坏的情况下,大多数都会被混淆(参考 Flutter 的--obfuscate
选项)。
该插件将自动启动并分析 Dart 2.10(~2010 年秋季)到 Dart 2.17(撰写本文时为当前版本)生成的 AOT 快照。分析结果将放置在位于 elf 容器单元下方的文本子单元中。代码单元将被注释(方法将被重命名等),如下一节所述。
AOT 快照包含大量信息。反序列化它们相对复杂,更不用说每个版本的 Dart 都会改变格式这一事实——这意味着当 Dart 2.18+ 版本发布时必须添加支持......该插件不会提取所有可能可用的信息。目前提供的是:
1-有关快照的基本信息,例如版本和功能
2- 库、类和方法的列表
3- 主池字符串的视图
除了静态信息外,该插件还尝试:
1-重命名方法。发布版本将从 ELF 文件中删除方法名称。但是,AOT 快照信息引用了所有 AOT 方法以及它们的名称、类、库等。快照信息中提供的名称将应用于未命名的本机例程。
您将能够找到该main
方法,即所有 Dart 应用程序的入口点。
2-注释对池化字符串的访问。本机代码通过固定寄存器(包含指向池元素的指针数组的地址)访问池项目。以下是最常见架构的寄存器列表:
arm : 寄存器 r5aarch64 : 注册 x27x64 : 寄存器 r15
在 x64 二进制文件上访问的池化字符串在代码单元中标记为元注释,如下所示:
不幸的是,由于 arm64 二进制文件的汇编代码是如何生成的,这些注释无法在此类二进制文件上生成。但是,反编译会产生更易消化的代码,例如:
我们建议分析 x64 或 arm64 二进制文件,而不是它们的 32 位 x86 或 arm 对应文件,因为在后一种情况下插件可能无法正确解析所有内容。特别是,对于最新版本的 Dart(2.16'ish 及更高版本)生成的 arm 32 位快照,函数未正确映射。
可以做更多的事情,特别是与调用约定(用于正确反编译)、伪代码重构和重组(gendec
例如通过 IR 插件)、库代码标记(例如,属于的类及其方法dart::<well_known_namespace>
在视觉上突出)有关。将根据用户的反馈和需求添加此类附加功能。
上一篇:没有了!