背景
当源码的函数中使用了结构体类型的变量时,反汇编代码中对于结构体中成员的获取往往都是通过一个指针 + offset
来获取的。对于阅读源码静态分析极其麻烦,因此需要创建数据结构简化分析。
结构体变量实例:
步骤
快照 (可选)
快照是IDA提供的一个保存分析现场的功能,通过创建、恢复这种成对的操作可以恢复一些错误的操作,或者无法挽救的操作,使得分析现场恢复到一开始的时候。
- 创建快照
使用快捷键Ctrl+Shift+W
唤起IDB快照窗口,为当前IDB快照起个名字后点击OK
- 恢复快照
使用快捷键Ctrl+Shift+T
唤出IDB快照弹窗。双击提示是否恢复IDB快照,点击YES还原IDB初始状态。
创建结构体
快捷键指南
快捷键 | 作用 |
---|---|
Insert/Delete键 | 创建和删除结构体 (切换到StructuresTab->Edit-> Add Struct Type) |
D/A/*键 | 添加不同类型的结构体成员,这里要注意光标位置不同D键的作用也不同 |
N键 | 对结构体或结构体成员重命名 |
U键 | 删除结构体成员(只有当一个字段是结构体中的最后一个字段时,使用U键才能删除该字段。对于所有其他字段,按下U键将取消该字段的定义,这样做仅仅删除了该字段的名称,并没有删除分配给该字段的字节) |
Shift+F1 | 打开本地类型窗口 |
分析结构体大小
创建自定义结构体第一步就是确定结构体的大小,只有确定了大小,才能进一步创建结构体
- 一般在初始化结构体的地方有通过memcpy设置结构体大小
分析结构体布局
通过静态代码分析获取布局,一般是在operator new()
函数后面的第一个sub函数
技巧:
如果只知道结构体的大小,而不了解它的布局。可以通过创建两个字段,第一个字段为一个数组,它的大小为结构体的大小减去1个字节(size-1);第二个字段应为1个字节。创建第二个字段后,取消第一个(数组)字段的定义。这样,结构体的大小被保留下来,随后,当你进一步了解该结构体的布局后,你可以回过头来定义它的字段及其大小。
手动定义
根据具体场景,手动为每一个偏移创建IDA结构体,适用于获取信息较少的静态分析
- 打开创建结构体的 Subview,点击工具栏
View->Open Subview->Structures( Shift + F9)
- 按键盘
Ins
弹出结构体的创建窗口,输入自定义名称
- 在结构体的
ends
行,按键盘D
键,创建新的结构体成员 - 把光标移动到该成员上,按D键改变该成员的数据类型,可改变的数据类型有db(byte),dw(word),dd(dword),dq(qword),按A键可以设置为字符串,按*键可以设置为数组,按N键可以重命名成员,按U键删除成员
- 删除中间字段: 分配到结构体中间的字节只有在取消关联字段的定义后才能删除(按U键),使用
Edit -> Shrink Struct Type
(缩小结构体类型)即可删除被取消定义的字节 - 增加中间字段: 选择新字节后面的一个字段,然后使用
Edit -> Expand Struct Type
(扩大结构体类型)在选中的字段前插入一定数量的字节。
快速定义(可选)
使用C语音语法进行快速定义并创建IDA结构体,适用于有源码的情况
- 使用File --> Load File --> Parse C Header File
如果一切正常,IDA会通知你Compilation successful。如果解析器遇到任何问题,IDA将会在输出窗口中显示错误消息。
使用结构体输入代码,适用于已经解析出结构体且成员字段都是基础数据类型的情况
- View -->Open Subviews -->Local Types 输入结构体声明代码
修改变量类型
- 找到IDA对应的结构体变量 -> 右键-> Convert to struct * -> 选择自定义结构体 -> 点击OK(或F5刷新)
- 修改反编译代码中该成员的类型,按 y 修改为 struct name