该程序显示在类似的线程here中。
假设我的操作系统没有实现ASLR或其他缓冲区溢出保护。
长话短说,作者是从一个父进程派生一个子进程,并将父进程创建的缓冲区传递给子进程,以覆盖子堆栈上的返回地址,从而派生一个shell。到目前为止一切顺利。
我不理解的是,返回地址是在父进程中计算的,即:
ret = (unsigned int) &i - offset; // Set return address
这个返回地址是父进程的堆栈地址,但是子进程有自己的堆栈,即地址空间作者如何得出结论,上面计算的ret
将是子堆栈帧上nop-sleds / shell的近似位置,因为这两个堆栈是不同的,不相关?
为了进行实验,我尝试暂时关闭ASLR,使用gdb
单独调试这些程序,发现当我在main
函数上设置断点时,$ESP
总是指向父进程的0xffffd02c
和子进程的0xffffd04c
。
1条答案
按热度按时间pieyvz9o1#
这两个进程的堆栈是不相关的,但它们具有相同的地址(虚拟地址)。操作系统将所有用户进程的堆栈放置在同一地址(如果没有ASLR)。即使一个程序调用了另一个程序。这实际上是一个伟大的调试帮助10年前!
当你知道这一点,你如何确定“神奇的”地址?你可以写一个程序,打印一个堆栈变量的地址,然后把这个“神奇的”地址写在纸上,用它来进行所有的攻击。但更好的是,如果您从自己的程序中调用可利用的程序,那么您的程序中已经有了那个“神奇的地址”。