对函数入口处使用的 edx 和 eax 寄存器的值感到困惑

逆向工程 艾达 登记 调用约定
2021-06-22 05:53:48

我目前正在使用 IDA 来反汇编一个注册机。eaxedx寄存器被赋予值之前的特定函数的前几行中,它们的内容被移动到堆栈变量var_40var_44

这是所述函数的初始程序集列表:

var_44= dword ptr -44h
var_40= dword ptr -40h

push    ebp
mov     ebp, esp
add     esp, 0FFFFFFA8h
push    esi
push    edi
mov     [ebp+var_44], edx
mov     [ebp+var_40], eax

我想知道EAX的值是什么EDX

它们是否默认为 0,因为它们以前没有使用过,这只是局部变量的初始化?IDA 声明了其他堆栈变量,我只提到了它们var_40var_44因为它们是我难以理解的变量

任何帮助将不胜感激。

2个回答

TL;DR:寄存器用于将调用函数之间的参数传递给被调用者。为了理解它们的值,您需要在调用之前查看代码。

由于您已经提到从寄存器中存储的数据然后用于在调用之前初始化另一个寄存器,因此这是使用寄存器在函数之间传递数据的情况。

这可能看起来有点像在重新调整回调用者之前保存寄存器以便恢复它们,但是根据 OP,值不会函数返回附近的堆栈 ( var_44, var_40)复制回来此外,eax几乎从不保留寄存器,因此不太可能出现这种情况。

什么是调用约定

调用约定是参数在调用者和被调用者函数之间传递的方式。在调用被调用函数之前,调用函数是否将参数存储在堆栈、寄存器或其他任何地方,以便被调用函数读取它们。

一旦我们知道什么是调用约定,就会产生一个问题:谁定义了哪些可用的调用约定是可用的,以及选择在函数之间使用的调用约定。显然,如果调用者和被调用者假设不同的调用约定代码将中断,我们可能会遇到段错误。

尽管在同一个编译器同时构建被调用者和调用者的情况下,这个问题似乎微不足道,但由不同的编译器编译不同的二进制文件可能会使事情复杂化。

您可能想阅读更多有关您进行逆向工程的编译器/架构所使用的调用约定的信息

fastcall 调用约定

有很多x86 调用约定,其中一些彼此相似但被不同的编译器使用,但 x64 调用约定更加标准化。

最初,调用约定严重依赖堆栈并且所有参数都通过它传递,但是出于性能原因,寄存器使用变得更加频繁,因为它避免了额外的内存写入。由于并非所有数据都可以使用寄存器(和其他原因)存储,因此这些是混合调用约定。

这些混合调用约定通常称为“fastcall”,因为通过避免不需要的堆栈写入速度更快。有几种 x86 快速调用约定,具体取决于使用的编译器。虽然有几个调用约定使用了eaxand edx,但这里要注意的重要一点是它们用于调用函数先前设置的值

在函数调用之前检查 edx 和 eax 的值是什么。由于这些寄存器在被移入变量之前没有被清除,因此它们现有的值可能只是被使用并转移到局部变量中。