gpt4 book ai didi

c - 如何将反汇编的C代码划分为函数?

转载 作者:可可西里 更新时间:2023-11-01 13:28:48 25 4
gpt4 key购买 nike

我有一个创建 win32 进程的 .text 段转储的应用程序。然后它在基本 block 上划分代码。基本 block 是一组总是一个接一个地执行的指令(跳转总是这些基本 block 的最后一条指令)。这是一个例子:

Basic block 1
mov ecx, dword ptr [ecx]
test ecx, ecx
je 00401013h

Basic block 2
mov eax, dword ptr [ecx]
call dword ptr [eax+08h]

Basic block 3
test eax, eax
je 0040100Ah

Basic block 4
mov edx, dword ptr [eax]
push 00000001h
mov ecx, eax
call dword ptr [edx]

Basic block 5
ret 000008h

现在我想在函数中对这些基本 block 进行分组 - 说出哪些基本 block 构成了一个函数。算法是什么?我必须记住,一个函数中可能有许多 ret 指令。如何检测fast_call函数?

最佳答案

将 block 分组为函数的最简单算法是:

  1. 记下用call some_address 调用的所有地址说明
  2. 如果这样地址之后的第一个 block 以ret结尾,你已经完成了这个功能,否则
  3. 跟随 block 中的跳转到另一个 block ,依此类推,直到您已经跟随所有可能的执行路径(记住条件跳转,每个条件跳转将路径分成两部分)并且所有路径都以 ret 结束。 .您需要识别组织循环的跳转,这样您的程序本身就不会因进入无限循环而挂起

问题:

  1. 许多调用可以通过从内存中读取函数指针来间接进行,例如你会有 call [some_address]而不是 call some_address
  2. 可以对计算出的地址进行一些间接调用
  3. 在返回前调用其他函数的函数可能有 jump some_address而不是 call some_address紧接着是 ret
  4. call some_address可以用 push some_address 的组合来模拟+ ret或者 push some_address + jmp some_other_address
  5. 一些函数可能在它们的末尾共享代码(例如,它们有不同的入口点,但一个或多个导出点是相同的)

您可以使用一些启发式方法通过查找最常见的序言指令序列来确定函数从何处开始:

push ebp
mov ebp, esp

同样,如果函数是在抑制帧指针的情况下编译的,这可能不起作用(即它们可能会使用 esp 而不是 ebp 来访问它们在堆栈上的参数)。

编译器(例如 MSVC++)也可以用 int 3 填充函数间空间指令,这也可以作为即将开始的功能的提示。

至于区分各种调用约定,可能最简单的方法是看符号(当然,如果你有的话)。 MSVC++ generates different name prefixes and suffixes, e.g. :

  • _function - cdecl
  • _function@number - 标准调用
  • @function@number - 快速调用

如果您无法从符号中提取此信息,则必须分析代码以查看参数是如何传递给函数的,以及函数或它们的调用者是否将它们从堆栈中移除。

关于c - 如何将反汇编的C代码划分为函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14755935/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com