- 献词
- 致谢
- 前言
- 第一部分 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 交叉引用
8.5 使用标准结构体
如前所述,IDA 能够识别大量与各种库和 API 函数有关的数据结构。最初创建一个数据库时,IDA 会尝试确定与二进制文件有关的编译器和平台,并加载适当的结构体模板。当 IDA 在反汇编代码清单中操纵结构体时,它会在 Structures 窗口中添加相应的结构体定义。因此,Structures 窗口中显示的是应用于当前二进制文件的已知结构体的子集。除了创建自定义结构体外,你还可以从 IDA 的已知结构体列表中提取出其他标准结构体,并将其添加到 Structures 窗口中。
要添加一个新结构体,首先,在 Structures 窗口中按下 INSERT 键。在图 8-3 的 Create structure/ union 对话框中,包含一个 Add standard structure(添加标准结构体)按钮。单击这个按钮,IDA 将显示与当前编译器(在分析阶段检测出来)和文件格式有关的结构体主列表。这个结构体主列表中还包含通过解析 C 头文件添加到数据库中的结构体。选择结构体对话框如图 8-13 所示,该对话框用于选择添加到 Structures 窗口中的结构体。
图 8-13 选择标准结构体
你可以利用搜索功能,根据部分文本匹配来定位结构体。该对话框还允许你进行前缀匹配。如果你知道某个结构体名称的前几个字符,只需输入这几个字符(它们将出现在对话框底部的状态栏上),列表窗口将跳转到第一个与这个前缀匹配的结构体。选择一个结构体,该结构体及任何嵌套结构体都将添加到 Structures 窗口中。
下面举例说明如何使用标准结构体。假如你想要分析一个 Windows PE 二进制文件的文件头。默认情况下,在创建后,文件头不会立即加载到数据库中。但是,如果你在最初创建数据库时选择 Manual load(手动加载)选项,就可以将文件头加载到数据库中。加载文件头可确保只有与这些头部有关的数据类型才出现在数据库中。多数情况下,文件头不会以任何形式被格式化,因为通常程序并不会直接引用它们自己的文件头。因此,分析器也没有必要对文件头应用结构体模板。
对一个 PE 二进制文件进行一番研究后,你会发现,PE 文件的开头部分是一个名为 IMAGE_DOS_HEADER
的 MS-DOS 头部结构体。另外, IMAGE_DOS_HEADER
中的数据指向一个 IMAGE_NE_HEADER
结构体的位置。它详细说明了 PE 二进制文件的内存布局。选择加载 PE 头部,你将看到类似于下面的未格式化的反汇编代码清单。了解 PE 文件结构的读者会发现,文件的前两个字节是我们熟悉的 MS-DOS 幻数 MZ
。
HEADER:00400000 __ImageBase db 4Dh ; M HEADER:00400001 db 5Ah ; Z HEADER:00400002 db 90h ; É HEADER:00400003 db 0 HEADER:00400004 db 3 HEADER:00400005 db 0 HEADER:00400006 db 0 HEADER:00400007 db 0 HEADER:00400008 db 4 HEADER:00400009 db 0 HEADER:0040000A db 0 HEADER:0040000B db 0 HEADER:0040000C db 0FFh HEADER:0040000D db 0FFh HEADER:0040000E db 0 HEADER:0040000F db 0
格式化这个文件时,你需要一些 PE 文件参考文档帮助你了解每一种数据类型。通过使用结构体模板,IDA 可以将这些字节格式化成一个 IMAGE_DOS_HEADER
结构体,使这些数据更加有用。第一步是根据上面的详细说明,添加标准的 IMAGE_DOS_HEADER
结构体(你可以在打开 IMAGE_NT_HEADER
结构体的同时添加该结构体)。第二步是使用 Edit▶ Struct Var (ALT+Q),将从 _ImageBase
开始的字节转换成一个 IMAGE_DOS_HEADER
结构体。这样,即得到下面的格式化代码:
HEADER:00400000 __ImageBase IMAGE_DOS_HEADER 5A4Dh, 90h, 3, 0, 4, 0, 0FFFFh, 0, 0B8h, \ HEADER:00400000 0, 0, 0, 40h, 0, 0, 0, 0, 0, 80h HEADER:00400040 db 0Eh
如你所见,文件的前 64 (0x40 )个字节已被折叠成一个数据结构,其类型也在反汇编代码清单中注明。但是,除非你对这个特殊的结构体非常熟悉,否则,你仍然无法清楚了解其中每个字段的意义。不过,我们可以展开结构体,使操作更进一步。打开一个结构体的数据项时,IDA 会使用结构体定义中对应的字段名称,对每个字段进行注释。使用数字键盘上的加号键可以打开折叠后的结构体。打开后的结构体如下所示:
HEADER:00400000 __ImageBase dw 5A4Dh ; e_magic HEADER:00400000 dw 90h ; e_cblp HEADER:00400000 dw 3 ; e_cp HEADER:00400000 dw 0 ; e_crlc HEADER:00400000 dw 4 ; e_cparhdr HEADER:00400000 dw 0 ; e_minalloc HEADER:00400000 dw 0FFFFh ; e_maxalloc HEADER:00400000 dw 0 ; e_ss HEADER:00400000 dw 0B8h ; e_sp HEADER:00400000 dw 0 ; e_csum HEADER:00400000 dw 0 ; e_ip HEADER:00400000 dw 0 ; e_cs HEADER:00400000 dw 40h ; e_lfarlc HEADER:00400000 dw 0 ; e_ovno HEADER:00400000 dw 4 dup(0) ; e_res HEADER:00400000 dw 0 ; e_oemid HEADER:00400000 dw 0 ; e_oeminfo HEADER:00400000 dw 0Ah dup(0) ; e_res2 HEADER:00400000 ➊ dd 80h ; e_lfanew HEADER:00400040 db 0Eh
然而, IMAGE_DOS_HEADER
的字段并没有特别有意义的名称,因此,我们在查阅 PE 文件参考文献后才知道:➊处的 e_lfanew
字段表示文件偏移量,在该位置可找到 IMAGE_NT_HEADER
结构体。应用前面讨论的所有步骤,在地址 00400080
(数据库中的第 0x80
字节)处创建一个 IMAGE_NT_ HEADER
结构体,将得到如下所示的格式化后的结构体(仅显示一部分代码):
HEADER:00400080 dd 4550h ; Signature HEADER:00400080 dw 14Ch ; FileHeader.Machine HEADER:00400080 ➊ dw 5 ; FileHeader.NumberOfSections HEADER:00400080 dd 4789ADF1h ; FileHeader.TimeDateStamp HEADER:00400080 dd 1400h ; FileHeader.PointerToSymbolTable HEADER:00400080 dd 14Eh ; FileHeader.NumberOfSymbols HEADER:00400080 dw 0E0h ; FileHeader.SizeOfOptionalHeader HEADER:00400080 dw 307h ; FileHeader.Characteristics HEADER:00400080 dw 10Bh ; OptionalHeader.Magic HEADER:00400080 db 2 ; OptionalHeader.MajorLinkerVersion HEADER:00400080 db 38h ; OptionalHeader.MinorLinkerVersion HEADER:00400080 dd 800h ; OptionalHeader.SizeOfCode HEADER:00400080 dd 800h ; OptionalHeader.SizeOfInitializedData HEADER:00400080 dd 200h ; OptionalHeader.SizeOfUninitializedData HEADER:00400080 dd 1000h ; OptionalHeader.AddressOfEntryPoint HEADER:00400080 dd 1000h ; OptionalHeader.BaseOfCode HEADER:00400080 dd 2000h ; OptionalHeader.BaseOfData HEADER:00400080 ➋ dd 400000h ; OptionalHeader.ImageBase
可见,这里的字段名称更有意义。我们立即发现,该文件由 5 个部分(➊)构成,应该是在虚拟地址 00400000
(➋)被加载到内存中。使用数字键盘上的减号键,可以将打开状态的结构体恢复到折叠状态。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论