本文主要摘自《IDA权威指南》,IDA pro作为一种重要的反汇编工具被安全研究员们广泛使用,熟练掌握其使用和脚本的编写也是逆向分析的必修课之一,本文主要总结了一些IDA的使用技巧。第六章以前的内容主要介绍了反汇编的概念、其他反汇编工具、背景知识以及基本用法,在本文中将不再赘述。IDA脚本的编写将在下一篇推文中详述,敬请期待。
双击导航
跳转到地址
快捷键G
跳转的回退和前进
快捷键ESC
快捷键Ctrl+enter
栈帧
调用约定
调用约定指定调用方放置被调函数所需参数的具体位置,如将参数放置在哪些寄存器和栈中,同样,调用约定也指定谁(调用函数P还是被调函数Q)负责在函数结束时,回收这些参数。
cdecl(c调用约定)
stdecl(std调用约定)
局部变量的访问
基于esp [esp+?]
基于ebp [ebp +/- ?]
栈视图
双击栈帧变量进入详细视图
db/dw/dd/dq: 1/2/4/8
s: 被保存的寄存器(如ebp)
r: 返回地址
重命名变量
快捷键N,然后输入新名字,如果输入空白,则生成默认名称
添加注释
快捷键":",然后输入注释内容,按住ctrl+enter结束编辑
反汇编代码显示的调整
Option->General->IDA option->Disassembly选项卡
Display disassembly line parts
如果想要显示反汇编代码对应的原始字节码,就修改Numbers of opcode bytes为一个大数,例如100
格式化指令操作数
符号化(右键,Symbolic constant)
或者右键转成其他进制数
数据与代码的互相转换
格式化数据转为函数
Edit->Function->Create Function
取消对函数、代码或者数据的定义,还原为原始字节码
快捷键U
将原始字节码转换为代码
快捷键C
将原始字节码转换为数据
快捷键D
指定栈上变量的数据类型
双击栈变量进入详细视图,然后对要修改的变量连续按d,依次是按1->2->4->8来轮转对应的数据类型
定义数组
IDA构建的反汇编代码在对数组信息的处理上尤为不足,例如a[2]
可能被表示为*(a+2)
这样的通过首元素地址+偏移的指针引用形式,此时我们可以为这样的代码创建一个数组出来。
首先修改数组中的第一个元素的大小和类型为合适的值,例如如果是一个string str[10]
的数组,首先应该把第一个元素的类型指定为string,然后再edit->Array
,因为我们创建出的数组的类型是由第一个元素的类型决定的。
这里可能会用到定义一个结构体变量
快捷键alt+Q
随后我们在弹出的窗口填上我们创建的数组的大小即可,例如有20个元素,就填20
建立结构体
点击菜单栏的view
,选择open subviews
,打开结构体窗口(或者使用快捷键shift+F9)。点击insert按键(或者右键空白处点击add struct type
)即可添加自定义的结构体。如下图所示:
右键创建好的结构体,可以发现菜单里的创建数据、结构体、string类型等元素的操作,读者可以自行尝试。同时我们可以使用N键对成员进行重命名,美化反汇编效果。
导入结构体
当我们拥有源代码时,我们可以从header文件中直接导入结构体信息,快捷键Ctrl + F9 选择我们要导入的文件:
点击确定后发现struct窗口并没有什么变化,此时用快捷键shift+F1打开local types
窗口,发现导入的数据其实在这里。这样我们在创建结构体的时候点击add standard struct
就可以创建从头文件中导入的结构体了。
Bindiff插件使用
以rwctf2022- FLAG为例,简单来说就是我们有了一个自己编译的带符号信息的附件,我们用ida为它生成数据库(i64/idb),然后关闭并打开我们的目标文件,依次点击edit-plugins-bindiff,选择第一个diff database,选择我们刚刚生成的数据库文件。
等待分析完成后效果如下所示
我们只保留绿色的similarity窗口,其中比较关键的信息有:
单行颜色:越绿表示相似度最高,越红表示相似度越低
similarity:[0,1]区间的值,指明new 与 old 的相似度。1表示完全一样。
Confidence实际代表了识别算法的强弱。高Similarity、低Confidence表示一个弱算法找到一个强匹配 低Similarity、高Confidence表示一个强算法找到一个弱匹配
经过分析验证后我们可以选中一条函数并右键,选择Import symbols
导入符号,这样可以大大减少我们逆向的难度。
交叉引用使用的目的一般是看某个变量在什么地方被使用,以及某个函数在什么地方被调用。
快捷键x或者ctrl+x
另外关于函数调用还有一种方法可以看
在反汇编或者反编译窗口选中某个函数
ctrl+1
来选择打开一个Function Calls
subview,该窗口上半部分列出的是该函数被哪些函数调用;下半部分列出的是该函数调用了哪些函数。
在Function Calls
subview右键可以选择是否勾选synchronized
,如果勾选了,那么这个窗口的内容将随着被选中的函数变化而变化。
所以如果想检查某个危险函数的所有调用,建议取消勾选。
让我们来回顾一下,这篇文章我们学习了反汇编导航中跳转的快捷键、栈帧、调用约定、局部变量的访问、怎样进入栈视图。还学习了反汇编的一些操作,大家可以自己总结成cheat sheet。接下来数据类型和数据结构部分,怎样建立和导入结构体,bindiff的使用。最后是交叉引用,函数调用的查看方法。希望大家都掌握了,我们下篇文章见。