- 献词
- 致谢
- 前言
- 第一部分 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.3 使用结构体模板
有两种方法可对反汇编代码清单中的结构体定义加以利用。首先,你可以重新格式化内存引用,将类似于 [ebx+8]
的数字结构体偏移量转换成诸如 [ebx+ch8_struct.field4]
之类的符号式引用,从而提高它们的可读性。后一种符号式引用提供了更多有关引用内容的信息。因为 IDA 使用一种层次表示法,因此,你可以清楚地知道,程序访问的是什么类型的结构体,访问的是该结构体中的哪一个字段。当程序通过指针来引用结构体时,这种应用结构体模板的技术最有用。第二种应用结构体模板的方法是,提供其他可应用于栈和全局变量的数据类型。
为了理解如何将结构体定义应用于指令操作数,我们把每个定义看成类似于一组枚举常量。例如,图 8-5 中 ch8_struct
的定义可以用下面的伪 C 代码表示:
enum { ch8_struct.field1 = 0, ch8_struct.field2 = 4, ch8_struct.field3 = 6, ch8_struct.field4 = 8, ch8_struct.field5 = 16 };
对于这样一个定义,你可将操作数中使用的任何常量值转换成其对应的符号形式。如图 8-7 是一个正在进行中的此类操作。内存引用 [ecx+10h]
可能访问的是 ch8_struct
中的 field5
字段。
图 8-7 应用结构体偏移量
在图 8-7 中,右击 10h,即可在上下文菜单中看到 Structure offset(结构体偏移量)选项,它提供 3 种形式对指令操作数进行格式化。这 3 种形式全部是从包含一个偏移量为 16 的字段的结构体集合中提取出来的。
作为格式化内存引用的另一种方法,可以将栈和全局变量格式化成整个结构体。要将栈变量格式化成结构体,双击该变量,打开详细栈帧视图,然后使用 Edit ▶ Struct Var (ALT+Q)命令显示一组已知的结构体,如图 8-8 所示。
图 8-8 选择结构体对话框
选择其中一个结构体,可将栈中对应的字节数组合成对应的结构体类型,并将所有相关内存引用重新格式化成结构体引用。下面的代码摘自前面分析的栈分配的结构体示例:
.text:00401006 mov [ebp+var_18], 10 .text:0040100D mov [ebp+var_14], 20 .text:00401013 mov [ebp+var_12], 30 .text:00401017 mov [ebp+var_10], 40 .text:0040101E fld ds:dbl_40B128 .text:00401024 fstp [ebp+var_8]
记得前面得出结论, var_18
实际上是一个大小为 24 字节的结构体的第一个字段。上述代码的详细栈帧如图 8-9 所示。
图 8-9 格式化之前的栈分配的结构体
选择 var_18
并将其格式化成 ch8_struct
(Edit ▶ Struct Var),会将以 var_18
开头的 24 个字节( ch8_struct
的大小)折叠成一个变量,并得到如图 8-10 所示的重新格式化后的栈窗口。在这个例子中,对 var_18
应用结构体模板将生成一条警告消息,指出在将 var_18
转换为结构体的过程中,有一些变量将会遭到破坏。基于我们前面的分析,我们已经意识到这种情况,因此,我们只需认可该警告消息,完成操作即可。
图 8-10 格式化之后的栈分配的结构体
重新格式化之后,IDA 认识到,任何对分配给 var_18
的 24 个字节块的内存引用,都必须引用该结构体中的一个字段。如果 IDA 发现这样一个引用,它会尽一切努力,将这个内存引用与结构体变量中的一个已定义的字段关联起来。在这个特例中,反汇编代码清单会自动进行重新格式化,以合并结构体布局,如下所示:
.text:00401006 mov [ebp+var_18.field1], 10 .text:0040100D mov [ebp+var_18.field2], 20 .text:00401013 mov [ebp+var_18.field3], 30 .text:00401017 mov [ebp+var_18.field4], 40 .text:0040101E fld ds:dbl_40B128 .text:00401024 fstp [ebp+var_18.field5]
在反汇编代码清单中使用结构体表示法的好处在于,它从总体上提高了反汇编代码清单的可读性。在重新格式化后的窗口中使用字段名称,能够更加准确地反映源代码是如何操纵数据的。
将全局变量格式化成结构体的过程与格式化栈变量所使用的过程几乎完全相同。要进行格式化,选择要格式化的变量,或者表示结构体开头部分的地址,再使用 Edit ▶ Struct Var (ALT+Q)选择合适的结构体类型即可。作为针对未定义的全局数据(不是栈数据)的备选方案,你可以使用 IDA 的上下文菜单选择要查看的结构体选项,并选择要应用于所选地址的可用结构体模板。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论