为什么 clang 使用 ebp 相对偏移量将函数参数放在堆栈上?

逆向工程 拆卸 x86
2021-06-13 07:00:14

我一直在研究 GCC 与 Clang 生成的 x86 32 位代码的反汇编。

环境是在 VMware 中运行的 Ubuntu Server 16.04.2 32 位。

两者都使用相同的选项编译。没有优化,所以没有省略帧指针或类似的东西。唯一的区别是 GCC 是使用 -mpreferred-stack-boundary=2 编译的,以具有 4 字节对齐的堆栈并避免管理堆栈对齐的额外指令。clang 不提供此选项。

在 GCC 反汇编中,函数局部堆栈变量使用 EBP 的负偏移量来引用,而在调用之前放置在堆栈上的函数参数被推入堆栈或使用 ESP 相对正偏移量移入堆栈内存(第一个参数:ESP,第二个参数) :ESP+4,等等...)。

使用 clang,对于相同的源文件,生成的程序集使用 EBP 相对负偏移量访问函数局部变量和访问堆栈头、堆栈头 + 4 等。用于将调用参数放在堆栈上。除了最初的函数序言之外,几乎从未使用过 ESP。我正在查看的反汇编中有几个函数调用。

我不习惯这种表示法,我觉得它有点奇怪,因为从 EBP 到达堆栈头部的实际负偏移值将始终随着堆栈的增长/收缩而变化。而使用 ESP,更直观地知道在调用之前,ESP 的值将是第一个参数,ESP+4 的值将是第二个,等等......

最终我认为结果是相同的,因为任何本地堆栈帧位置都可以通过 EBP 索引,包括堆栈的头部,前提是您知道在任何给定指令中自堆栈帧开始以来分配了多少堆栈内存。

即 ESP = EBP -(目前帧中分配的总字节数)

有什么不同的原因吗?纯粹是一个不同的实现选择?

(我现在手头没有实际的反汇编,但我稍后会编辑问题以添加它)。

海湾合作委员会 5.4

┌ (fcn) sym.check_authentication 89
│   sym.check_authentication (int arg_8h);
│ ; var int local_14h @ ebp-0x14
│ ; var int local_4h @ ebp-0x4
│ ; arg int arg_8h @ ebp+0x8
│ 0x080484cb      55             push ebp
│ 0x080484cc      89e5           mov ebp, esp
│ 0x080484ce      83ec14         sub esp, 0x14
│ 0x080484d1      c745fc000000.  mov dword [ebp - 4], 0
│ 0x080484d8      ff7508         push dword [ebp + 8]
│ 0x080484db      8d45ec         lea eax, [ebp - 0x14]
│ 0x080484de      50             push eax
│ 0x080484df      e89cfeffff     call sym.imp.strcpy
│ 0x080484e4      83c408         add esp, 8
│ 0x080484e7      6820860408     push str.brillig                      ; "brillig" @ 0x8048620
│ 0x080484ec      8d45ec         lea eax, [ebp - 0x14]
│ 0x080484ef      50             push eax
│ 0x080484f0      e86bfeffff     call sym.imp.strcmp
│ 0x080484f5      83c408         add esp, 8
│ 0x080484f8      85c0           test eax, eax
│ 0x080484fa      7507           jne 0x8048503
│ 0x080484fc      c745fc010000.  mov dword [ebp - 4], 1
│ 0x08048503      6828860408     push str.outgrabe                     ; "outgrabe" @ 0x8048628
│ 0x08048508      8d45ec         lea eax, [ebp - 0x14]
│ 0x0804850b      50             push eax
│ 0x0804850c      e84ffeffff     call sym.imp.strcmp
│ 0x08048511      83c408         add esp, 8
│ 0x08048514      85c0           test eax, eax
│ 0x08048516      7507           jne 0x804851f
│ 0x08048518      c745fc010000.  mov dword [ebp - 4], 1
│ 0x0804851f      8b45fc         mov eax, dword [ebp - 4]
│ 0x08048522      c9             leave
└ 0x08048523      c3             ret

叮当 3.8.0

┌ (fcn) sym.check_authentication 121
│   sym.check_authentication (int arg_8h);
│ ; var int local_20h @ ebp-0x20
│ ; var int local_1ch @ ebp-0x1c
│ ; var int local_18h @ ebp-0x18
│ ; var int local_14h @ ebp-0x14
│ ; var int local_4h @ ebp-0x4
│ ; arg int arg_8h @ ebp+0x8
│ 0x080484a0      55             push ebp
│ 0x080484a1      89e5           mov ebp, esp
│ 0x080484a3      83ec28         sub esp, 0x28                         ; '('
│ 0x080484a6      8b4508         mov eax, dword [ebp + 8]              ; [0x8:4]=-1 ; 8(null)
│ 0x080484a9      8d4dec         lea ecx, [ebp - 0x14]
│ 0x080484ac      8945fc         mov dword [ebp - 4], eax
│ 0x080484af      c745e8000000.  mov dword [ebp - 0x18], 0
│ 0x080484b6      8b45fc         mov eax, dword [ebp - 4]
│ 0x080484b9      89e2           mov edx, esp
│ 0x080484bb      894204         mov dword [edx + 4], eax
│ 0x080484be      890a           mov dword [edx], ecx
│ 0x080484c0      894de4         mov dword [ebp - 0x1c], ecx
│ 0x080484c3      e898feffff     call sym.imp.strcpy
│ 0x080484c8      89e1           mov ecx, esp
│ 0x080484ca      8b55e4         mov edx, dword [ebp - 0x1c]
│ 0x080484cd      8911           mov dword [ecx], edx
│ 0x080484cf      c74104608604.  mov dword [ecx + 4], str.brillig      ; [0x8048660:4]=0x6c697262 ; "brillig" @ 0x8048660
│ 0x080484d6      8945e0         mov dword [ebp - 0x20], eax
│ 0x080484d9      e862feffff     call sym.imp.strcmp
│ 0x080484de      83f800         cmp eax, 0
│ 0x080484e1      0f8507000000   jne 0x80484ee
│ 0x080484e7      c745e8010000.  mov dword [ebp - 0x18], 1
│ 0x080484ee      8d45ec         lea eax, [ebp - 0x14]
│ 0x080484f1      89e1           mov ecx, esp
│ 0x080484f3      8901           mov dword [ecx], eax
│ 0x080484f5      c74104688604.  mov dword [ecx + 4], str.outgrabe     ; [0x8048668:4]=0x6774756f ; "outgrabe" @ 0x8048668
│ 0x080484fc      e83ffeffff     call sym.imp.strcmp
│ 0x08048501      83f800         cmp eax, 0
│ 0x08048504      0f8507000000   jne 0x8048511
│ 0x0804850a      c745e8010000.  mov dword [ebp - 0x18], 1
│ 0x08048511      8b45e8         mov eax, dword [ebp - 0x18]
│ 0x08048514      83c428         add esp, 0x28                         ; '('
│ 0x08048517      5d             pop ebp
└ 0x08048518      c3             ret
0个回答
没有发现任何回复~