您的漏洞利用负载最终会出现在堆栈上,因为您溢出了堆栈上的缓冲区,这也是您控制返回地址的方式。
ESP 直接指向有效负载的开头(在ret您正在攻击的函数中执行之后),因为您将有效负载放在覆盖堆栈上返回地址的 4 个字节之后。 ret将 4(或 8)个字节弹出到 EIP 中,让 ESP 指向紧随其后的有效负载。
但是你不知道 ESP 在那一点上会有什么价值,因为堆栈 ASLR 以及导致这一点的不同调用堆栈深度可能会改变地址。 所以你不能硬编码一个正确的返回地址。
但是,如果在进程内存中的固定(非 ASLRed)地址处有字节解码为jmp esp或任何位置,您可以call esp将该地址硬编码为您的漏洞利用中的返回地址。执行将到那里,然后到您的有效负载。
事实上经常出现这种情况:一些 DLL 没有为其代码启用 ASLR,并且主可执行文件的代码也可能没有经过 ASLRed。
所有代码的代码 ASLR都会阻止jmp esp攻击,除非攻击者可以导致目标进程泄漏地址。
请注意,对于 64 位代码,您不太可能使用jmp rsp基于字符串的缓冲区溢出,因为代码地址将包含一些前导0字节。
因此,jmp esp与重复猜测返回地址(使用非常大的 NOP sled)相比,它为您提供了更可靠的利用。
每次你错了,重复猜测都会使目标进程崩溃,但是jmp esp第一次尝试就可以给你很大的成功机会。这将避免留下崩溃日志。它还可以击败一个入侵检测系统,该系统会寻找崩溃的服务器进程并阻止来自您的 IP 地址或类似地址的连接。
请注意,当程序正常执行时,您要查找的 2 字节指令可以作为另一条指令的一部分出现,或者作为静态数据(尤其是只读数据通常在可执行页面中)出现。所以你只需要搜索2字节的序列,而不是jmp esp反汇编程序。编译器永远不会使用jmp esp,因此您不会以那种方式找到它。
更一般地说,任何以任何寄存器中的缓冲区指针结尾的函数(例如,来自 amemcpy或特别是)都可以通过查找指令strcpy来允许ret2reg攻击。jmp eax
这可以在 64 位模式下工作,其中地址有一些高位零字节;如果strcpy's 的尾随零为您写入那个高地址字节,则您的漏洞利用字符串的结尾可能是覆盖堆栈上的返回地址的非零地址字节。
在这种情况下,可执行有效负载将位于返回地址之前,位于缓冲区中函数留下寄存器指向的位置。(如果寄存器中有任何有用的指向缓冲区的指针,通常是缓冲区的开头)。