移动两次,从和移动到同一位置

逆向工程 艾达 拆卸
2021-06-25 07:43:43

我正在尝试反转一个函数,但在函数内部遇到了以下几行:

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax
3. mov     eax, [ebp+var_4]

为什么需要第 3 行?如果我需要保存结果,第 2 行将保存该结果,而 EAX 已包含结果。

2个回答

根本不需要。

但是,某些编译器在未优化的情况下编译时可能会生成该程序集。

例如,gcc -O0生成:(来自 Godbolt

f():
  push rbp
  mov rbp, rsp
  sub rsp, 16
  call fake_heapalloc()
  mov DWORD PTR [rbp-4], eax
  mov eax, DWORD PTR [rbp-4]
  mov edi, eax
  call g(int)
  nop
  leave
  ret

来自 C++ 源代码

int fake_heapalloc();
void g(int i);
void f(){
    int i;
    i=fake_heapalloc();
    g(i);
}

因为它没有优化,所以i存储在堆栈中(而不是在寄存器中),并且会生成进出堆栈代码的冗余移动。


或者,一些程序员可能会手动在那里插入汇编指令......我不知道,这不太可能。

这是为了将值保存在堆栈上,并在注释中已经提到的进一步指令中继续使用该值。如果没有进行优化,就会发生这种情况。

你必须分开看。在伪代码中考虑这一点。

var_4 = HeapAlloc()
func1(var_4)

那么结果将类似于您的汇编器输出,即:

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax
3. mov     eax, [ebp+var_4]
4. push    eax
5. call    func1

在那种情况下,你是对的,价值仍然在eax.

但现在考虑:

var_4 = HeapAlloc()
between_func()
func1(var_4)

汇编器输出将类似于此

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax
3. call    between_func
4. mov     eax, [ebp+var_4]
5. push    eax
6. call    func1

您可以将伪代码行引用到汇编代码的一部分。

var_4 = HeapAlloc()

对应于:

1. call    ds:HeapAlloc
2. mov     [ebp+var_4], eax

between_func()

对应于:

3. call    between_func

func1(var_4)

对应于:

4. mov     eax, [ebp+var_4]
5. push    eax
6. call    func1

如果你省略了between_func()那么你会得到你的结果。最后,这两条指令是独立编译的。

其它你可能感兴趣的问题