- 献词
- 致谢
- 前言
- 第一部分 IDA 简介
- 第 1 章 反汇编简介
- 第 2 章 逆向与反汇编工具
- 第 3 章 IDA Pro 背景知识
- 第二部分 IDA 基本用法
- 第 4 章 IDA 入门
- 第 5 章 IDA 数据显示窗口
- 第 6 章 反汇编导航
- 第 7 章 反汇编操作
- 第 8 章 数据类型与数据结构
- 第 9 章 交叉引用与绘图功能
- 第 10 章 IDA 的多种面孔
- 第三部分 IDA 高级应用
- 第 11 章 定制 IDA
- 第 12 章 使用 FLIRT 签名来识别库
- 第 13 章 扩展 IDA 的知识
- 第 14 章 修补二进制文件及其他 IDA 限制
- 第四部分 扩展 IDA 的功能
- 第 15 章 编写 IDA 脚本
- 第 16 章 IDA 软件开发工具包
- 第 17 章 IDA 插件体系结构
- 第 18 章 二进制文件与 IDA 加载器模块
- 第 19 章 IDA 处理器模块
- 第五部分 实际应用
- 第 20 章 编译器变体
- 第 21 章 模糊代码分析
- 第 22 章 漏洞分析
- 第 23 章 实用 IDA 插件
- 第六部分 IDA 调试器
- 第 24 章 IDA 调试器
- 第 25 章 反汇编器/ 调试器集成
- 第 26 章 其他调试功能
- 附录 A 使用 IDA 免费版本 5.0
- 附录 B IDC/SDK 交叉引用
21.4 基于虚拟机的模糊
如本章前面所述(见 21.1.2 节中的“操作码模糊”),一些最复杂的模糊器使用自定义字节码及相关的虚拟机重新实现了原本具有输入接收功能的程序。面对以这种方式模糊的二进制文件,你看到的唯一本机代码为虚拟机。假设你认识到所看到的是软件虚拟机,那么一般而言,完全了解所有这些代码并不能揭示该模糊程序的真实意图。这是因为程序的行为仍然隐藏在必须由虚拟机解释的嵌入式字节码中。要完全了解这个程序,首先你必须定位所有的嵌入式字节码,然后逆向工程虚拟机的指令集,以便能够正确解释该字节码的含义。
作为比较,想象一下,如果你对 Java 一无所知,有人给你一个 Java 虚拟机和一个包含已编译字节码的.class 文件,并问你它们有什么作用。由于缺乏任何文档资料,你可能对字节码文件知之甚少,并且你需要完全逆向工程虚拟机才能了解.class 文件的结构以及如何解释它的内容。对字节码机器语言有一定了解后,接下来你就可以了解.class 文件的作用。
VMProtect 是一款利用非常复杂的基于虚拟机的模糊技术的商业产品。更多是作为一种学术活动,TheHyper 的 HyperUnpackMe21 挑战二进制文件是在模糊中使用虚拟机的一个相当简单的示例,主要的挑战在于定位虚拟机的嵌入式字节码程序并确定每个字节码的含义。在 OpenRCE 上描述 HyperUnpackMe2 的文章2 中,Rolf Rolles 采用的方法是:充分了解虚拟机以构建一个能够反汇编其字节码的处理器模块。然后,他使用该处理器模块来反汇编嵌入到所挑战的二进制文件中的字节码。使用这个方法存在一个小限制,通过它你可以查看 HyperUnpackme2 中的 x86 代码(使用 IDA 的 x86 模块)或虚拟机代码(使用 Rolle 的处理器模块),但不能同时查看这两种代码。为此,你需要创建两个不同的数据库(每个数据库使用不同的处理器模块)。另一种方法是在使用插件的过程中利用定制现有处理器模块的功能(参见 19.5 节),来有效扩展指令集,在其中包括嵌入式虚拟机的所有指令。将这种方法应用于 HyperUnpackMe2,我们就可以在一个数据库中同时查看 x86 代码和虚拟机代码了,如下面的清单所示:
1. HyperUnpackMe2 是一个 crackme。——译者注
2. 参见 http://www.openrce.org/articles/full_view/28 网站的“Defeating HyperUnpackMe2 With an IDA Processor Module ”。
TheHyper:01013B2F ➊ h_pop.l R9 TheHyper:01013B32 h_pop.l R7 TheHyper:01013B35 h_pop.l R5 TheHyper:01013B38 h_mov.l SP, R2 TheHyper:01013B3C h_sub.l SP, 0Ch TheHyper:01013B44 h_pop.l R2 TheHyper:01013B47 h_pop.l R1 TheHyper:01013B4A h_retn 0Ch TheHyper:01013B4A sub_1013919 endp TheHyper:01013B4A TheHyper:01013B4A ; ---------------------------------------------------------- TheHyper:01013B4D dd 24242424h TheHyper:01013B51 dd 0A9A4285Dh ; TAG VALUE TheHyper:01013B55 TheHyper:01013B55 ; ============ S U B R O U T I N E ========================= TheHyper:01013B55 TheHyper:01013B55 ; Attributes: bp-based frame TheHyper:01013B55 TheHyper:01013B55 sub_1013B55 proc near ; DATA XREF: TheHyper:0103AF7A?o TheHyper:01013B55 TheHyper:01013B55 var_8 = dword ptr -8 TheHyper:01013B55 var_4 = dword ptr -4 TheHyper:01013B55 arg_0 = dword ptr 8 TheHyper:01013B55 arg_4 = dword ptr 0Ch TheHyper:01013B55 TheHyper:01013B55 ➋ push ebp TheHyper:01013B56 mov ebp, esp TheHyper:01013B58 sub esp, 8 TheHyper:01013B5B mov eax, [ebp+arg_0] TheHyper:01013B5E mov [esp+8+var_8], eax TheHyper:01013B61 mov [esp+8+var_4], 0 TheHyper:01013B69 push 4 TheHyper:01013B6B push 1000h
其中,从➊处开始的代码被反汇编成 HyperUnpackMe2 字节码,而➋处以后的代码则以 x86 代码显示。
Hex-Rays 预料到了同步显示本机代码和字节码的功能,并在 IDA 5.7 中引入了自定义数据类型和格式。如果 IDA 的内置格式化选项无法满足你的需求,这时就可以使用自定义数据格式。为格式指定(使用脚本或插件)一个菜单名,并指定一个执行格式化的函数,就可以注册新的格式化功能。为某个数据项选择自定义格式后,每次需要显示该数据项,IDA 都会调用格式化函数。如果 IDA 的内置数据类型并不足以表示你在特定二进制文件中遇到的数据,这时就需要用到自定义数据类型。与自定义格式一样,自定义数据类型也使用脚本或插件进行注册。Hex-Rays 示例注册了一个自定义数据类型来指派虚拟机字节码,并通过使用一种自定义数据格式将每个字节码显示为一条指令。这种方法的缺点在于,它需要你定位每条虚拟机指令,并明确更改其数据类型。使用自定义处理器扩展,将单个值自动指派为虚拟机指令可发现每条可到达的指令,因为 IDA 会推动反汇编进程,且处理器扩展会通过它的 custom_emu 实现来发现可到达的新指令。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论