我是逆向工程的初学者,作为初学者,我开始阅读“初学者逆向工程”。
这是书中的 hello world 程序(摘自第 3 章第 12 页):
现在让我们尝试在 Linux 的 GCC 4.4.1 编译器中编译相同的 C/C++ 代码: gcc 1.c -o 1 接下来,在 IDA 反汇编器的帮助下,让我们看看 main() 函数是如何创建的。IDA 与 MSVC 一样,使用 Intel-syntax5。
main proc near
var_10 = dword ptr -10h
push ebp
mov ebp, esp
and esp, 0FFFFFFF0h
sub esp, 10h
mov eax, offset aHelloWorld ; "hello, world\n"
mov [esp+10h+var_10], eax
call _printf
mov eax, 0
leave
retn
main endp
有两行我根本不明白:
and esp, 0FFFFFFF0hsub esp, 10h
根据我在书中的理解,我们0FFFFFFF0h向 ESP添加(等于 -16)值,以便将堆栈与 16 字节边界对齐以进行优化。
我的问题是:为什么我们添加 -16 然后减去 16 到堆栈中?对我来说似乎毫无意义,我们不能直接减去32吗?其次,如果我理解得很好:
- 程序以 EBP = ESP 开始,因为堆栈中没有任何内容。
- 然后 EBP 被压入堆栈。假设程序是 64 位,ESP 现在是 EBP - 8(因为是 64 位)。所以现在我们有了 ESP != EBP。
- 然后我们将ESP的内容复制到EBP中。所以我们有 EBP = ESP,EBP = fristEBP(程序开始时的 EBP)- 8。
为什么需要修改EBP的值?PUSH 指令应该更改 ESP 的值,而不是 EBP,那么为什么不在函数 prolog 处修改 EBP 值会出现任何问题?
所以现在我们有 EBP = ESP,并且两者都是 fristEBP(程序启动时的 EBP) - 8。所以现在我们将 -16 添加到堆栈中,所以 ESP 变为 ESP - 16(ESP - 24,如果我们认为我们已经一直将 -8 添加到堆栈中)。
-24 与 16 字节边界有什么关系?为什么我们再次从堆栈中减去 16 sub esp, 10h?
注释:我对英语很抱歉,如果我问了一些愚蠢的问题,这本书不够清楚,而且我未能在网上找到解释。