检测 IDA 中的递归函数

逆向工程 艾达 idapro插件 职能 调用栈 自动化
2021-06-16 03:44:36

如何在 IDA 中检测/标记递归函数?

简单的方法是检查每个函数的调用列表,如果它调用自身,则它是递归的。我想发表评论或某种指标来帮助我区分这些功能。

2个回答

我缺少 9 点声望,所以很遗憾我无法评论 w_s 的出色回答。;)

为了完整起见,所描述的概念在图论中被称为“Tarjan 算法”,用于寻找强连通分量。

Wikipedia有一个很好的动画,可以帮助您遵循这些步骤。Tarjan 算法

为了研究,这是另一个(更正式的)Python 实现,它是我用来在IDAscope 中查找函数中的循环的实现,但它很容易适用于查找递归函数。

这不是微不足道的任务。如果不考虑间接调用(例如 C++ 中的虚函数)和来自另一个函数的调用,则可以相对容易地做到这一点:

int f() {
    g();
}

int g() {
    f();
}

如果您的一个函数位于另一个二进制文件(例如 dll)中,则可能会复杂得多。所以,有两种方法可以做到,静态和动态方式。

递归装配遍历-静态分析方法

您应该在 IDAPython 中编写传递函数的脚本,并递归处理每个调用。如果您在收集的堆栈中找到当前函数,则该函数是递归的。

非常简单的变体如下所示:

# I didn't check it, use carefully, beware the errors in this code
import idautils
import idc
import idaapi

def handle_function(func_start):
    global stack
    if func_start in stack:
        print "This is recursive function", hex(func_start), Name(func_start)
        for x in stack:
            print "\t", hex(x)
        #insert your renaming here, it should be idc.MakeName
        return

    stack.append(func_start)
    for h in idautils.FuncItems(func_start):
        for r in idautils.XrefsFrom(h, 0):
            if r.type == fl_CF or r.type == fl_CN:
                print hex(h), "-->", hex(r.to)
                if r.to == func_start:
                    # Insert renaming here too for simple recursion
                    print "It is simple recursive function that calls itself directly"
                    return
                else:
                    handle_function(r.to)
    stack = stack[:-1]

for f in idautils.Functions():
    stack = []
    handle_function(f)

断点分析——动态分析方法

用 IDAPython 编写脚本,识别所有函数序言并过滤掉所有不调用任何函数的函数。在每个收集的序言上放置断点并运行程序。每次程序停止时,使用 IDAPython 分析程序的堆栈,以便在堆栈中找到您停止的函数。如果找到,则该函数是递归的。