缓冲区溢出:如何从 ESP 进行相对跳转?

Buffer overflow: How to do a relative jump from ESP?

我正在尝试在堆栈缓冲区溢出方面做一个练习。我正在做一个经典的例子,漏洞允许你覆盖 EIP。我的问题是我只能使用以 00 开头的地址,这意味着我不能覆盖大于 ESP 指向的地址。因此,将 shellcode 放在我用来覆盖 EIP 的地址之后的经典方法是行不通的。相反,我需要将地址之前的 shellcode 放入缓冲区。请看下面的简单图。

<larger stack addresses>  ........... <smaller stack addresses>
    ESP                               Need to jump here somehow
     |                                  |     
     V                                  V
   XXXX|AAAA|AAAA|AAAA|AAAA|AAAA|....|AAAA|AAAA|AAAA|....
     A
     |
     |
    My buffer won't reach any  addresses
    larger than ESP because of the 0 in it...

现在的问题是:我需要搜索的汇编指令是什么,它会跳转到比 ESP 小 200 字节的地址?我不太了解 x86 汇编器。我已经尝试了一切,例如 jmp [ESP-8]、jmp [ESP-16]、...(也有较大的偏移量),然后是 sub ESP、EBX + jmp ESP、xor ESP、EBX + jmp ESP 等等。我应该在这里补充一点,看起来我也可以覆盖 EBX。因此,如果有 sub ESP、EBX + jmp ESP 或类似的东西,那么我可以通过首先从 ESP 中减去偏移量来填充 EBX 到 shellcode 的负偏移量跳转。但是无论我尝试什么,我都找不到模块中的说明。我认为我的主要问题是我不太了解 x86 汇编语言。我在代码中看到了像 jmp DWORD PTR DS:[ESP+8] 这样的指令,并且在谷歌上搜索了一下,我有限的理解告诉我这是数据段中的相对跳转。所以我需要在堆栈段中做这样的事情,理想情况下是从 EBX 寄存器中获取偏移量......这样的事情是否存在?

间接跳转到寄存器中的值不能采用偏移量。您必须在 运行 jmp 指令之前完成所有地址数学运算。无法编码 jmp esp - 200 或类似的东西。

jmp [ESP-8] 将从 [ESP-8] 加载并跳转到该地址。你可以看出它正在加载,因为它有方括号。

所以你应该尝试寻找像

这样的序列
lea   eax, [esp-200]
jmp   eax               # or call eax

sub  esp, 200
jmp  esp

寄存器间接跳转的 AT&T 语法是 jmp *eax,顺便说一句。

这些指令不必相邻;您可能会发现 ret2reg 攻击所需的内容由几条指令分隔,但这更难搜索,因为您需要将搜索限制在解码从 sub、[=18 开始的情况=] 或其他任何东西,并在一定数量的有效指令后到达 jmp,这些指令不会与您正在攻击的 ret 处预期的寄存器值发生故障。您可以尝试从每个可能的 jmp regcall reg 指令之前最多 20 个字节的每个偏移量开始反汇编,并查看是否有任何偏移量产生有效的指令来做一些有趣的事情。

您不一定要找到以 esp 开头的序列;如果指向缓冲区中其他地方的指针存在于另一个寄存器中,您可以查找该寄存器的 jmpcall


执行 sub esp, 200 / jmp esp 会使堆栈指向代码的最低地址,因此 push 将数据写入堆栈不会覆盖在执行到达之前结束代码,这可能是接近或超过原始 esp.

的长代码的问题

堆栈向下增长,但执行会随着地址的增加而上升,因此如果您从 EIP=ESP 开始,只有在 pop 或以其他方式增加 ESP 时才会遇到麻烦。