- 献词
- 致谢
- 前言
- 第一部分 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.2 创建 IDA 结构体
在上一章中,我们见识了 IDA 的数组聚合能力,它通过将一长串的数据声明变成一个反汇编行,简化了反汇编代码清单。在下面几节中,我们将讨论 IDA 如何使用各种工具来改善操纵结构体的代码的可读性。我们的目标是用更具可读性的 [edx+ch8_struct.field5]
替换 [edx+10h]
之类的结构体引用。
只要发现一个程序正操纵某种数据结构,你就需要确定:你是否希望将结构体的字段名称合并到反汇编代码清单中,或者你是否理解分散在代码清单中的所有数字偏移量。有时候,IDA 能够确定程序在调用 C 标准库或 Windows API 的过程中定义了一个结构体。这时,IDA 了解该结构体的具体布局,并且能够将数字偏移量转换成更加符号化的字段名称。这是一种理想化的情形,因为你并没有多少工作要做。在我们初步了解 IDA 如何处理通常的结构体定义后,我们将继续讨论这种情形。
8.2.1 创建一个新的结构体(或联合)
如果程序正使用某个结构体,而 IDA 并不了解其布局,这时,IDA 会提供实用工具以设置该结构体的布局,并将新定义的结构体包含到反汇编代码清单中。IDA 使用 Structures 窗口(如图 8-2 所示)来创建新的结构体。除非结构体已经在 Structures 窗口中列出,否则就无法将结构体包含到反汇编代码清单中。IDA 将自动在 Structures 窗口中列出任何它能够识别、并确定已被一个程序使用的结构体。
图 8-2 Structures 窗口
IDA 之所以在分析阶段无法识别结构体,可能源于两个原因。首先,虽然 IDA 了解某个结构体的布局,但它并没有足够的信息,能够判断程序确实使用了结构体。其次,程序中的结构体可能是一种 IDA 对其一无所知的非标准结构体。在这两种情况下,问题都可以得到解决,且首先从 Structures 窗口下手。
Structures 窗口的前 4 行文本用于提醒用户该窗口中可能进行的操作。我们使用的主要操作包括添加、删除和编辑结构体。添加结构体使用热键 INSERT 启动,它打开如图 8-3 所示的 Create structure/union(创建结构体/联合)对话框。
图 8-3 Create structure/union 对话框
为了创建一个新的结构体,你必须首先在 Structure name(结构体名称)字段中指定结构体的名称。前两个复选框用于决定新结构体在 Structures 窗口中的显示位置,或者是否在窗口中显示新结构体。第三个复选框 Creat union (创建联合),指定你定义的是否为 C 风格联合1 结构体。结构体的大小是它所包含的字段大小的总和,而联合的大小则等于其中最大字段的大小。Add standard structure(添加标准结构体)按钮用于访问 IDA 当前能够识别的全部结构体数据类型。这个按钮的作用将在 8.5 节讨论。指定结构体的名称并单击 OK 按钮后,IDA 将在 Structures 窗口中创建一个空结构体定义,如图 8-4 所示。
1. 联合类似于结构体,其中可能包含许多类型各不相同的具名字段。二者的区别在于,联合中的字段相互重叠,因此,联合的大小等于其中最大字段的大小
图 8-4 空结构体定义
你必须对这个结构体定义进行编辑,以完成对结构体布局的定义。
8.2.2 编辑结构体成员
为了给新结构体添加字段,你必须利用字段创建命令 D、A 和数字键盘上的星号键(*)。最初,你只需要使用 D 命令。不过,它的行为非常依赖于光标的位置。为此,我们建议采用下面的步骤给结构体添加字段。
要给结构体添加新字段,将光标放在结构体定义的最后一行(包含
ends
的那一行)并按下 D 键。这时,IDA 就会在结构体的末尾添加一个新字段。新字段的大小取决于你在数据转盘(参见第 7 章)上选择的第一个大小。最初,字段的名称为field_N
,这里的N
为结构体开头到新字段(如field_0
)开头的数字偏移量。如果需要修改字段的大小,首先将光标放在新字段的名称上,然后重复按下 D 键,使数据转盘上的数据类型开始循环,从而为新字段选择正确的数据大小。另外,你还可以使用 Options▶ Setup Data Types 来指定一个在数据转盘上不存在的大小。如果新字段是一个数组,右击其名称并在上下文菜单中选择 Array,将打开“数组规范”对话框(参见第 7 章)。
要更改一个结构体字段的名称,单击字段名称并按下 N 键,或者右击该名称并在上下文菜单中选择 ReName,然后在输入框中输入一个名称即可。
在你定义自己的结构体时,下面的提示可能会有所帮助。
一个字段的字节偏移量以一个 8 位十六进制值在 Structures 窗口的左侧显示。
每次你添加或删除一个结构体字段,或更改一个现有字段的大小时,结构体的新大小都会在结构体定义的第一行反映出来。
你可以给一个结构体字段添加注释,就像给任何反汇编行添加注释一样。右击(或使用热键)你希望为其添加注释的字段,在上下文菜单中选择一个注释选项即可。
与 Structures 窗口顶部的说明不同的是,只有当一个字段是结构体中的最后一个字段时,使用 U 键才能删除该字段。对于所有其他字段,按下 U 键将取消该字段的定义,这样做仅仅删除了该字段的名称,并没有删除分配给该字段的字节。
你必须对一个结构体定义中的所有字段进行适当的对齐。IDA 并不区分已压缩和未压缩的结构体。为将字段适当对齐,如果你需要填补字节,那么你必须负责添加这些字节。填补字节最好作为适当大小的哑字段添加。在添加额外的字段后,你可以选择取消或保留这些字段的定义。
分配到结构体中间的字节只有在取消关联字段的定义后才能删除,使用 Edit ▶ Shrink Struct Type (缩小结构体类型)即可删除被取消定义的字节。
你也可以在结构体的中间添加新的字节:选择新字节后面的一个字段,然后使用 Edit ▶ Expand Struct Type (扩大结构体类型)在选中的字段前插入一定数量的字节。
如果知道结构体的大小,而不了解它的布局,你需要创建两个字段。第一个字段为一个数组,它的大小为结构体的大小减去 1 个字节(
size-1
);第二个字段应为 1 个字节。创建第二个字段后,取消第一个(数组)字段的定义。这样,结构体的大小被保留下来,随后,当你进一步了解该结构体的布局后,你可以回过头来定义它的字段及其大小。
通过重复应用这些步骤(添加字段,设置字段大小,添加填补字节等),你就可以在 IDA 中创建 ch8_struct
结构体(未压缩版本),如图 8-5 所示。
在这个例子中,IDA 使用了填补字节对字段进行适当对齐,并根据前面例子中的名称重命名字段。值得注意的是,每个字段的偏移量和结构体的总大小(24 字节)仍与前面的例子中的值相同。
图 8-5 手动生成的 ch8_struct
结构体定义
如果你觉得结构体定义在 Structures 窗口中占用了太多空间,你可以选择结构体中的任何字段并按下数字键盘中的减号键,将结构体的定义折叠成一行摘要。一旦结构体获得完整的定义,并且不需要进一步编辑,你就可以将它折叠起来。 ch8_struct
的折叠版本如图 8-6 所示。
图 8-6 折叠版本的结构体定义
绝大多数 IDA 能够识别的结构体都以这种单行方式显示,因为你不需要编辑它们。折叠式显示提供一个提示,即你可以使用数字键盘上的加号键打开结构体定义。另外,双击结构体名称也可以打开该定义。
8.2.3 用栈帧作为专用结构体
你可能已经注意到,结构体定义看起来与函数的详细栈帧视图有些类似。这并非巧合,因为在 IDA 内部,IDA 处理它们的方式完全相同。它们都属于相邻的内存块,能够细分成若干已命名字段,并且每个字段都拥有一个数字偏移量。它们之间的细微区别在于,栈帧以一个帧指针或返回地址为中心,同时使用正值和负值字段偏移量,而结构体仅使用正值偏移量(以结构体开头位置为起始点)。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论