堆栈平衡

2021年10月25日堆栈148阅读模式

这里有两种情况:如果要返回父程序,则当我们在堆栈中进行堆栈操作的时候,一定要保证在RET这条指令之前,ESP指向的是压入的我们压入的地址。

这句话我是这么理解的,就是当你调用函数的时候,比如使用CALL指令,当使用堆栈的时候,使用前ESP指向那个地址,使用后RET返回前就必须是那个地址,如果不是那个地址,那么堆栈就是不平衡的,程序就崩溃了。

直接上图分析一下:

堆栈平衡

这个程序运行起来以后一定是会崩溃的,在函数执行结束前,它使用了堆栈,向栈顶push了eax的值,使栈顶指针ESP的值-4,这样ret程序就飞了,因为push把它带到了另一个世界。

堆栈平衡

运行结果:

可以看到,反汇编窗口直接没了,原因就是他没有00000003这个地址,程序就这样飞走了,这是第一种情况。

堆栈平衡
如果通过堆栈传递参数了。那么在程序执行完毕后,要平衡因参数导致的堆栈变化

这句话的意思就是,当我们使用堆栈传参的时候,在程序执行完毕后这些参数应该一起被清理掉,也就是加了几条参数,就要在堆栈中加几个地址,这么做可以理解为清理垃圾。

上图分析一波:

这是第一次堆栈传参,在程序执行完毕前,堆栈一直都是平衡的,也没有垃圾可以清理,但如果我们需要接着向堆栈中压入数据,那么程序执行完毕后的垃圾就出现了。

堆栈平衡

这是第二次传参:之前程序执行结束后的参数没有被清理,导致后面的参数直接依次压入栈顶,多使用了两个地址,后边的000000001与000000002我们都不会再用了,但是没有被覆盖掉,这样多几个堆栈传参操作,程序的性能就会越来越差,直至崩溃。

堆栈平衡

如何进行堆栈平衡

这里有两个办法:

外平栈

就是从程序外部加一行代码去平衡堆栈,方法很简单,程序执行结束多用几个地址就多加几个地址。注意观察堆栈的变化。

堆栈平衡

内平栈

就是改变ret返回时esp栈顶指针的变化,用几个参数就加几个地址。注意观察堆栈的变化。

这里向堆栈传递了2个参数,我们在程序执行完毕前加了条ret 8,程序执行完毕后栈顶指针ESP的值就会多+8,这样就完美清理我们传递的那两个参数所占用的地址了。

运行结果:

堆栈平衡

  • 本站文章来自网友投稿、本站原创以及互联网统一发布,部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考。