在IDA中,函数是指一组指令的序列。通常,它对应于高级函数或子程序:
-
它可以从程序的其他地方被调用,通常使用专用的处理器指令; -
它有一个入口和一个或多个出口(返回到调用者的指令); -
它可以接受参数(在寄存器或堆栈中)并可选择性地返回值; -
它可以使用局部(堆栈)变量。
然而,IDA的函数可以将任何任意的指令序列分组,即使这些指令不符合上述标准。唯一的硬性要求是函数必须以有效指令开始。
创建函数
IDA通常会根据调用指令或调试信息自动创建函数,但也可以通过“创建函数”操作(在“编辑 > 函数”或上下文菜单中)或P快捷键手动创建。这只能对不属于函数的指令进行。默认情况下,IDA会跟随交叉引用并尝试自动确定函数边界,但您也可以预先选择一个范围来强制创建函数,例如,如果有一些无效指令或嵌入数据。
函数范围
在最常见的情况下,函数占据一个连续的地址范围,从入口到最后的返回指令。这是通过“编辑函数”对话框(Alt–P)中指定的函数属性中的起始和结束地址。
分块函数
单一范围的函数并不是IDA支持的唯一选项。在实际程序中,函数可能被分成几个不相连的范围。例如,这可能是基于配置文件的优化的结果,它可以将冷(很少执行的)基本块放在二进制文件的一个单独部分,而热(经常执行的)基本块则放在另一个部分。在IDA中,这样的函数被认为由多个块组成(每个块是一个连续的指令范围)。包含函数入口的块称为入口块,而其他的称为尾块或简单地称为尾。
在反汇编视图中,具有附加块的函数在函数入口附近有附加注释,列出属于该函数的尾块。
尾块本身标有“函数块开始”和“函数块结束”注释,说明它们属于哪个函数。这在文本视图中最有用,因为在图形视图中,它们显示为整体函数图的一部分。
有时一个尾块可能被多个函数共享。在这种情况下,其中一个被指定为尾块所有者,其他的被视为附加父级。这样的块将在其所属的每个函数的函数图中出现。
手动管理块
通常,IDA会自动处理分块函数,无论是在自动分析期间检测到它们,还是通过使用其他函数范围元数据(如x64 PE文件中的.pdata
函数描述符或调试信息)。然而,在某些情况下,您可能需要手动添加或删除块,例如修复误报或处理不寻常的编译器优化。
要删除(分离)一个尾块,请将光标放在其中并调用“编辑 > 函数 > 删除函数尾”。如果尾块只有一个所有者,它将立即被删除并转换为独立指令(不属于任何函数)。如果它有多个所有者,IDA会让您选择应从哪个函数中分离。
要将一段指令范围添加为函数的尾块,请选择该范围并调用“编辑 > 函数 > 附加函数尾”,然后选择应将其添加到的函数。这可以多次完成,以将尾块附加到多个函数(在这种情况下,必须再次选择整个尾块)。
学习资源
立即关注【二进制磨剑】公众号
原文始发于微信公众号(二进制磨剑):IDA技巧(86)函数块
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论