IDA 8.0 的发布说明中提到了函数外联。那么什么是函数外联,以及如何在IDA中处理它们呢?
函数外联是一种优化技术,通过识别重复出现的机器代码序列,并用调用包含这些操作序列的新函数来替换每个实例,从而节省代码大小。它可以被视为共享函数尾部优化的扩展,不仅共享尾部,还共享函数的任意公共部分。
函数外联示例
例如,这里是iOS的debugserver
中的一个函数,其中包含一些对外联片段的调用:
第一个片段除了返回指令外只包含两个指令,所以可能看起来节省不多,但通过查看交叉引用,你会发现它在许多地方被使用:
因此,整个程序中累积的节省可能相当可观。
在反编译器中处理外联函数
如果我们反编译该函数,对外联片段的调用将按原样显示,并且它们使用或设置的寄存器将显示为可能未定义(橙色):
要告诉反编译器这些调用应该内联到函数体中,所有的OUTLINED_FUNCTION_NN
都应该标记为外联代码。这可以通过编辑函数(Alt–P)对话框手动完成:
添加的属性也显示在列表中:
一旦所有外联函数都被标记,反编译器将它们内联,并且不再有可能未定义的变量:
自动化外联函数处理
如果你有一个包含数百或数千个函数的大型二进制文件,手动标记外联函数可能会变得相当乏味。在这种情况下,编写一个小脚本可能会加快速度。例如,如果你有符号并且外联函数有已知的命名模式,以下Python代码片段应该有效:
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
import idautils
import ida_name
import ida_funcs
for f in idautils.Functions():
nm = ida_name.get_name(f)
if nm.startswith("_OUTLINED_FUNCTION") or nm.find(".cold.") != -1:
print ("%08X: %s"% (f, nm))
pfn = ida_funcs.get_func(f)
pfn.flags |= idaapi.FUNC_OUTLINE
ida_funcs.update_func(pfn)
可以通过文件 > 脚本命令…(Shift+F2)执行
学习资源
立即关注【二进制磨剑】公众号
原文始发于微信公众号(二进制磨剑):IDA技巧(106)函数外联
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论