在程序中,有些函数不会返回到调用者:众所周知的例子包括 C 运行时函数如 exit()
、abort()
、assert()
,以及其他许多函数。现代编译器可以利用这一知识来更好地优化代码:例如,通常会跟随这些函数调用的代码不需要生成,从而减少程序的大小。其他无条件调用不返回函数的函数也会变成不返回函数,这可以带来进一步的优化。
众所周知的函数
IDA 使用函数名来标记众所周知的不返回函数。这些名称的列表存储在文件 cfg/noret.cfg
中,如果需要,可以编辑该文件以添加更多名称:
手动标记不返回函数
除了编辑 noret.cfg
,你还可以在个案基础上手动标记一个函数为不返回。这可以通过编辑函数属性来完成:在主菜单中选择 Edit > Functions > Edit Function…,在上下文菜单中选择 Edit Function… 或使用 Alt
–P
快捷键。
另一种选择是编辑函数的原型并添加 __noreturn
关键字。
识别不返回调用
错误识别的不返回调用可能导致分析过程中出现各种问题:函数被过早截断;反编译的伪代码缺少函数的大部分内容等。一个选项是检查每个被调用的函数,看看它是否设置了 Does not return 标志(或在注释中提到 Attributes: noreturn
),但如果调用很多,这可能需要很长时间。因此,有一些更容易发现的指示器:
-
在文本视图中,查找调用后的虚线;它表示代码流中断,这意味着执行在调用后不继续,即 不返回。
-
在图形视图中,当一个以调用结束的节点没有出边时,这意味着调用不返回。
-
在伪代码中,这并不总是显而易见,但对不返回函数的调用通常会结束一个复合语句或整个函数。如果函数看起来异常短小,你也可以切换到反汇编查看上述迹象。
启用或禁用不返回分析
如果你发现 IDA 对不返回函数的处理不适合你的特定二进制文件或二进制文件集,你可以将其关闭。这可以在初始加载时或之后的分析选项的第一组中完成。相反,你可以为默认不启用的处理器启用它。
如果你需要为所有新数据库永久启用或禁用它,请编辑 ida.cfg
中的 ANALYSIS
值以包含或不包含 AF_ANORET
标志。注意:你应该在 #ifdef
下为特定处理器编辑该值。
原文始发于微信公众号(二进制磨剑):IDA 技巧(126)不返回的函数
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论