- 献词
- 致谢
- 前言
- 第一部分 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 交叉引用
14.1 隐藏的补丁程序菜单
如第 11 章所述,Edit ▶Patch Program 菜单是 GUI 版本的 IDA 的一项隐藏功能,用户需要编辑 idagui.cfg 配置文件才能激活该菜单(默认情况下,控制台版本的 IDA 的 Patch 菜单是可用的)。Edit ▶Patch Program 子菜单中的可用选项如图 14-1 所示。
图 14-1 Patch program 子菜单
其中的每一个菜单项均表明,你能够以某种有趣的方式修改二进制文件。具体来说,这些选项提供了 3 种修改数据库的方法。实际上,与其他任何菜单项相比,这些菜单项能够更清楚地区分 IDA 数据库与创建该数据库的二进制文件之间的区别。创建一个数据库后,IDA 绝不会再次引用最初的二进制文件。鉴于此,这个菜单更适合叫做 修补数据库 。
但是,尽管如此,图 14-1 中的菜单项仍然提供了一种最直接的方法,让你观察你对最初的二进制文件所作的任何更改所造成的影响。在本章后面,我们将讨论如何导出你所作的修改,并最终利用这些信息来修补二进制文件。
14.1.1 更改数据库字节
Edit ▶Patch Program▶Change Byte 菜单项用于编辑 IDA 数据库中的字节值。相关的字节编辑对话框如图 14-2 所示。
图 14-2 Patch Bytes 对话框
这个对话框显示了从光标所在位置开始的 16 个字节的值。你可以更改对话框中显示的部分或全部字节,但是,如果不关闭该对话框,将光标重新定位到一个新的数据库位置,并重新打开该对话框,你将不能修改这 16 个字节以外的其他字节。注意,这个对话框还显示你所更改的字节的虚拟地址和“文件偏移量”值。“文件偏移量”值是你所修改的字节在最初的二进制文件中的十六进制偏移量。由于 IDA 在数据库中保留每个字节在最初文件中的偏移量信息,如果希望为最初的二进制文件开发补丁,就可以利用这些信息。最后,无论你如何修改数据库中的字节,对话框的 Original value 字段将始终显示最初加载到数据库中的字节值。IDA 不能自动恢复你对最初的字节值所作的修改,不过,你可以创建一段 IDA 脚本来完成这个任务。
IDA 5.5 引入了一个功能更加强大的十六进制窗口(参见第 5 章),为编辑数据库字节提供了一种更好的解决方案。有了这个集成式十六进制编辑功能,用户很少需要使用 IDA 的“更改字节”功能。
14.1.2 更改数据库中的字
相比于字节修补功能,IDA 的字修补功能的作用更加有限。IDA 的 Patch Word 对话框如 图 14-3 所示,它一次只能修补一个 2 字节的字。
图 14-3 Patch Word 对话框
和修补字节对话框一样,该对话框显示了所修改的字的虚拟地址和文件偏移量。需要记住的是,这里的字值使用底层处理器的自然字节顺序显示。例如,在 x86 反汇编代码清单中,字被当做“小端”值处理,而在 MIPS 反汇编代码清单中,字被当做“大端”值处理。在输入新的字值时,请记住这一点。与修补字节对话框相同,不论你使用修补字对话框修改过多少次字的值,Original value 字段将始终显示从原始二进制文件中加载的初始值。与字节编辑一样,在 IDA 的 Hex View 窗口中执行编辑更容易。
14.1.3 使用汇编对话框
“修补程序”菜单中最有趣的功能,可能要数“汇编”选项(Edit ▶Patch Program ▶Assemble )。遗憾的是,这项功能并非对所有处理器类型有效,因为它取决于当前的处理器模块是否拥有一个内部汇编器。例如,x86 处理器模块支持汇编,而 MIPS 处理器模块却不支持汇编。如果缺乏汇编器,你将收到一条错误消息,它指出:“对不起,本处理器模块不支持这种汇编器。”
利用“汇编”选项可以输入使用一个内部汇编器汇编的汇编语言语句。然后,IDA 会将得到的指令字节写入当前的屏幕位置。用于输入指令的 Assemble instruction 对话框如图 14-4 所示。
图 14-4 Assemble instruction 对话框
在 Instruction 输入框中,一次可以输入一条指令。IDA x86 处理器模块的汇编器组件接受在 x86 反汇编代码清单中使用的语法。单击 OK(或按下 ENTER 键)后,IDA 将汇编你输入的指令,并将对应的指令字节输入数据库中,这些指令字节的起始地址为 Address 字段中显示的虚拟地址。内部 IDA 汇编器可在指令中使用符号名称,只要程序中存在这些名称即可。诸如 mov [ebp+var_4]
、 eax
和 call sub_401896
之类的语法都属于合法语法,汇编器能够正确解析符号引用。
输入一条指令后,该对话框仍处于打开状态,并准备在紧接输入的前一条指令之后的虚拟地址上接受另一条新指令。在你输入其他指令后,该对话框将在 Previous line 字段中显示你输入的前一条指令。
输入新指令时,必须注意指令对齐。如果你正输入的指令的长度与它所替代的指令的长度不同,就特别需要注意指令对齐。如果新指令比它所替代的指令短,那么,你需要考虑如何处理旧指令剩下的多余字节(插入 NOP1 指令是一种可行的解决办法)。如果新指令长于它所替代的指令,IDA 将覆盖后面指令的字节,以满足新指令需要。这样做可能会对你的操作造成巨大影响,因此,在使用汇编器修改程序字节时,必须仔细规划。你可以把汇编器看做是一个始终处于覆盖模式的字处理器。如果不覆盖现有的指令,你很难为新指令“开辟”空间。
1. NOP 表示 no operation(无操作),在填充程序中的空间时,经常使用这种指令。
需要记住的是,IDA 的数据库修补功能仅限于能够轻松融入现有数据库空间的小型简单补丁。如果补丁需要大量的补充空间,你就需要在最初的二进制文件中查找尚未使用的空间。这些空间通常表现为填充字节,汇编器插入这些填充字节的目的是为了将二进制文件的不同节与特殊的文件边界对齐。例如,在许多 Windows PE 文件中,每个程序节的起始文件偏移量必须是 512 字节的整数倍。如果某节占用的空间不是 512 字节的整数倍,则必须对它填充,从而为下一节提供一个 512 字节的边界。下面这个 PE 文件的反汇编代码清单即证实了这种情况:
.text:0040963E ; [00000006 BYTES: COLLAPSED FUNCTION RtlUnwind. PRESS KEYPAD "+" TO EXPAND] .text:00409644 ➊ align 200h .text:00409644 _text ends .text:00409644 .idata:0040A000 ; Section 2. (virtual address 0000A000)
在这个代码清单中,IDA 使用一个对齐指令(➊)指出该节被填充到一个 512 字节( 200h
)的边界,其起始地址为 .text:00409644
,其终点为下一个整数倍的 512 字节, . text:00409800
。通常,编译器会用零填满填充区域,在十六进制窗口中,这个区域将突出显示。在这个特殊的二进制文件中,文件中的空间足够插入最大为 444(0x1BC=409800h 409644h)字节的补丁数据,这些数据将覆盖 .text
节末尾的一部分或全部以零填充的区域。你可以对函数进行修补,以跳转到二进制文件的这个区域,执行新插入的程序指令,然后跳回最初的函数。
需要注意的是,该二进制文件的下一节, .idata
节,它的起始地址实际上为 .idata:0040A000
。之所以出现这种情况,是因为内存对齐(而非文件对齐)限制要求 PE 区域采用 4Kb (一个内存页)的边界。理论上,你可以在 00409800~0040A00
0 的内存范围内插入额外的 2048 字节的补丁数据。但是,你很难完成上述操作,因为在这个可执行文件的磁盘映像中,并不存在与这个内存范围对应的字节。为了利用这片空间,你要做的不只是覆盖最初的二进制文件中的一些节。首先,在现有的 .text
节末尾与 .idata
节开头之间插入一个 2048 字节的数据块。其次,我们需要在 PE 文件头中调整 .text
节的大小。最后,我们需要在 PE 文件头中调整 .idata
及随后的所有节的位置,以反映一个事实,即随后的所有节现在均被后移了 2048 字节。这些更改听起来可能并不十分复杂,但它们需要操作者极其注意细节,并精通 PE 文件的格式。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论