Linux 系统调用较少膨胀

在 32 位 Linux 中,系统调用通常是通过使用 sysenter 指令完成的(我说通常是因为较旧的程序使用现已弃用的 int 0x80)但是,这可能占用程序中相当多的空间,因此有一些方法可以偷工减料以缩短和加快速度。
这通常是 32 位 Linux 上系统调用的布局:

mov eax, <System call number>
mov ebx, <Argument 1> ;If applicable
mov ecx, <Argument 2> ;If applicable
mov edx, <Argument 3> ;If applicable
push <label to jump to after the syscall>
push ecx
push edx
push ebp
mov ebp, esp
sysenter

这是非常正确的! 但是我们可以采取一些技巧来避免这种混乱。
第一种是将 ebp 设置为 esp 的值减去 3 个 32 位寄存器的大小,即 12 个字节。这很好,只要你可以用垃圾覆盖 ebp,edx 和 ecx(例如,无论如何你将直接将值移入这些寄存器),我们可以使用 LEA 指令执行此操作,这样我们就不需要了影响 ESP 本身的价值。

mov eax, <System call number>
mov ebx, <Argument 1>
mov ecx, <Argument 2>
mov edx, <Argument 3>
push <label to jump to after the syscall>
lea ebp, [esp-12]
sysenter

但是,我们还没有完成,如果系统调用是 sys_exit,我们就可以转义不向堆栈推送任何东西!

mov eax, 1
xor ebx, ebx ;Set the exit status to 0
mov ebp, esp
sysenter