在C语言中,联合体是一种类似于结构体的类型,但其所有成员(可能是不同类型)共享同一块内存,彼此重叠。它们被用于需要以不同方式解释相同数据的场合,或者在存储不同类型的数据时节省内存(这在脚本引擎等中很常见)。IDA和反编译器完全支持联合体,并在标准类型库中包含了常用的联合体定义,因此它们可能已经存在于分析的二进制文件中。
创建联合体
在汇编级别的联合体可以通过在“结构”窗口中启用“创建联合体”复选框来创建。
你也可以使用本地类型编辑器,通过C语法创建联合体。
在反汇编中使用联合体
在反汇编中,联合体的使用方式类似于结构体。例如,当一个成员被作为寄存器的偏移量引用时,你可以使用上下文菜单的“结构偏移”子菜单或T快捷键。不同之处在于,你可能会看到同一偏移量的多个“路径”,代表替代的联合体成员,因此你可以选择最适合特定用例的一个。
示例:OLE自动化
OLE自动化是一个基于COM的API集合,常用于在微软及其他应用中实现脚本功能。其使用的基本类型之一是VARIANT,也称为VARIANTARG
结构,它通过在其中嵌入不同类型字段的联合体来包含不同类型的值。
例如,如果我们有一条指令mov eax, [edx+8]
,并且我们知道edx
指向一个VARIANTARG
实例,使用T在第二个操作数上会显示联合体字段的多个版本,因此我们可以选择最相关的一个以适应特定的代码路径。
更改使用的联合体字段
在你(或IDA)选择了一个联合体字段后,你可以通过再次进行结构选择来更改它(例如T快捷键)。但如果父结构应保持不变,你可以通过使用命令编辑 > 结构 > 选择联合体成员…(快捷键Alt–Y)来仅更改联合体成员。当一个嵌入联合体的结构被放置在堆栈上时,这尤其有用,因为你不能在那里使用正常的结构偏移命令(指令内的偏移量基于堆栈或帧指针,而不是指向结构的开头)。
联合体在反编译器中的应用
由于反编译器可以进行数据流分析,在许多情况下,它可以通过匹配代码使用的变量的预期类型来选择最合适的联合体字段。例如,在下面的代码片段中,反编译器为传递给SysAllocString
的参数选择了正确的字段,因为它知道该函数期望一个const OLECHAR *
类型的参数,这与联合体的BSTR bstrVal
字段兼容。
然而,对于另一个引用,选择了iVal
字段。虽然它在用例中是兼容的(与零比较),但通过查看代码,很明显代码正在解释一个布尔变体值(这可以通过将数字11替换为符号常量VT_BOOL
来更清楚地表示)。这意味着boolVal
是一个更合乎逻辑的选择,我们可以通过上下文菜单中的“选择联合体字段…”或与反汇编相同的Alt–Y快捷键来选择它。
更多文章
立即关注【二进制磨剑】公众号
原文始发于微信公众号(二进制磨剑):IDA 技巧(75) IDA 中使用联合体
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论