在理论上溢出堆栈..和装配

时间:2013-02-17 19:51:50

标签: assembly stack-overflow buffer-overflow shellcode

假设没有aslr的x86系统我想询问以下内容;

1)理论说当我们执行堆栈溢出攻击时,ebp寄存器指向的值也会被新的返回地址覆盖。

现在,由于我们永远不会回到调用函数,我们并不需要ebp的原始值来恢复先前的堆栈帧,但是,ebp寄存器必须始终指向某处。 eip寄存器开始指向我们的新shellcode后如何设置ebp? 更具体地说,两个汇编指令(leave-ret)中的哪一个引入了另一个微指令,它将ebp恢复到一个值?

2)最后但同样重要的是,我还想问一下,我们如何确保在我们的shellcode需要在堆栈上推送几个值的情况下,这些值不会覆盖shellcode的任何部分?换句话说,我们怎样才能确定任何shellcode生成的变量只会放在shellcode的开头之前,例如介于两者之间?

提前谢谢大家。

2 个答案:

答案 0 :(得分:3)

1.当一个函数被调用时,esp的值被复制到ebp,然后通过减少esp的值来分配该特定函数的堆栈帧(通过ENTER指令或push ebp; mov ebp,esp; sub esp, SIZE;指令序列)。从此时起,esp的值严格向上增长,因此不会干扰当前函数的堆栈帧。

当函数到达它的末尾时,它通过上述步骤释放堆栈帧,但是向后,即通过LEAVE指令,或mov esp, ebp; pop ebp;指令序列。此时,esp的值指向返回地址,这是攻击者想要修改的地址。修改此值后,执行RET指令后,弹出修改后的返回地址,eip现在指向修改后的地址。

2.由于shellcode上面的任何内容已被释放",您只需通过上述相同步骤为shell代码分配堆栈帧。

答案 1 :(得分:1)

回答问题的第2部分:根据您正在进行的系统调用,您可能必须将值放入esp(作为arg数组)。如果这是shellcode的结束那么你就没事了。但是,如果shell代码还有更多,并且您碰巧执行了push esp碰巧指向shellcode的其余部分,则可能会遇到问题(因为那时你会写自己的指示)。一个简单的解决方法是在shellcode的最开始处执行类似sub $0x99, %esp的操作。

编辑(回应评论)

也许我误解了你的问题。当你说'堆栈溢出'时,我认为你的意思是缓冲区溢出。如果我假设正确,请继续阅读。假设你真的在谈论一个经典的粉碎堆栈漏洞(基于您链接到的图片似乎就是这种情况),那么你正在填充一个带有nop雪橇的缓冲区,{{1最后覆盖返回指针。 shell代码是“位置无关代码”。这意味着它是一系列指令,无论寄存器,标志等的当前状态如何都可以执行。

通常,(这也是你发布的链接描述它的方式)你用nops填充缓冲区,然后是shellcode,最后是一个返回地址,指向thop nop sled。执行shellcode指令时,ret中的地址加速为%esp%eip加4(x86中)。问题是,如果您的shellcode有多个%esp指令,则会产生递减 push的副作用。如果你有足够的你的shellcode一直到最后(即与返回地址相邻),那么你最终可能会用%esp指令覆盖你的shellcode。

所以,要真正回答你的问题。不,没有“机制”将shellcode与“其堆栈”分开。这是因为shellcode没有堆栈本身。请记住,它是与位置无关的代码。无论机器状态如何,它都必须能够运行。需要发生的任何堆栈管理必须由shellcode本身执行。这就是为什么我在shellcode的前面建议push如果代码中有很多sub $0x99, %esp语句。另一个选择是确保返回地址(push将指向的地址)与您的shellcode之间有足够的空间。