我已经浏览了很多网络,仍然无法理解它的工作方式
此链接也没有成功: How does a NOP sled work?
好的,假设我们在函数char a[8];
中有一个缓冲区foo()
并且foo()
的堆栈帧看起来像这样(32位):
现在,我们想要做的是覆盖'return'值,在调用foo()
时保存在堆栈中
他们说问题是,我们无法预测保存的“返回”值的位置
但为什么呢?例如,如果函数foo()
具有在所有其他局部变量之前定义的缓冲区,如上图所示,那么我们总是知道我们需要填充为缓冲区分配的8个字节,然后是4个字节的已保存的EBP然后我们得到了“回归”
或者,如果在缓冲区之前定义了其他局部变量,比如2个整数,那么我们考虑为缓冲区分配8个字节,然后考虑这2个本地整数的8个字节,然后是4个字节的已保存EBP,然后我们得到“返回”
我们总是知道从溢出的缓冲区中保存的“返回”有多远,不是吗? :/
如果我们不这样做,请解释。那是我的问题1。
我的问题2是,好吧,我们假设我们不知道'return'的值保存在哪里。然后,如果我们在shellcode之前有大量的NOP,我们很有可能将NOP(即0x90)值写入'return'的位置,从而覆盖原始值
现在,当函数foo()
返回时,0x90的值被加载到EIP(指令指针)而不是恢复其正常流程,程序将从地址0x90执行,不是吗?
我想我在这里误解了一些东西
请不要关闭我的问题,即使有一个类似的问题,我在一开始就提供了链接, 我想这个问题会更全面,更清晰
答案 0 :(得分:0)
首先我们假设没有地址空间随机化,堆栈是可执行的。
我们总是知道从溢出的缓冲区中保存的“返回”有多远,不是吗? :/
不,我们不知道。局部变量与保存的EBP和返回地址之间存在未指定数量的填充字节。这个字节数可能取决于编译器版本。
然后,如果我们在shellcode之前有大量的NOP,我们很有可能将NOP(即0x90)值写入'return'的位置,从而覆盖原始值
我们的想法是在返回地址后面包含所有NOP值。这样我们就可以用堆栈中shellcode的“近似”地址覆盖返回地址。确切的shellcode地址可能取决于操作系统版本,但也取决于程序参数以及环境变量的大小和数量,因为它们位于堆栈地址空间中。