基本的hello world栈操作麻烦

逆向工程 C 静态分析 海湾合作委员会 英特尔
2021-06-21 12:13:46

我是逆向工程的初学者,作为初学者,我开始阅读初学者逆向工程”
这是书中的 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, 0FFFFFFF0h
  • sub 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


注释:我对英语很抱歉,如果我问了一些愚蠢的问题,这本书不够清楚,而且我未能在网上找到解释。

1个回答

它不在add第一个操作码中。它是and因此它将清除地址中最后一个字节的低半字节。这就是对齐的完成方式,而不是通过添加任何内容。直到你sub16 岁以后才有空间放置局部变量。

为什么需要修改EBP的值?

我们EBP用来存储初始ESP值。EBP指向当前堆栈帧。这是使用函数创建的局部变量的地方。在我们修改之前将EBP它存储在堆栈中,以便我们可以在离开函数之前恢复它。