ctf pwn学习栈平衡问题

做了buuctf上的ciscn_2019_en_2
我写的是libc泄露puts构造ROP链的方式
但是看writeup时发现其他人的payload中加了ret维持栈平衡,但很多都没去描述都只是放上了exp
后来学习了知道内平衡ret维持
我的问题是:1.看到有说高版本的libc需要栈平衡的?那么怎么分析什么题目我需要用到栈平衡呢?而且内外平衡和调用约定要怎么区分
2.我看到不同的payload中有的用的ROPgaget 中的ret地址,有的用的__libc_csu_init函数的地址,还有用的__libc_csu_init函数里ret的地址,我的理解是有ret就能平衡栈是这样吗?随便一个ret都可以平衡栈吗?

首先,我们需要明白栈平衡问题在哪些情况下会出现。这通常发生在对函数进行调用时。当你在ROP中使用了某个函数时,它可能会期待有一定数量的参数被推入栈中。如果你没有提供足够的参数,当函数返回时,它可能会从栈中弹出错误的地址,这就会破坏你的ROP链。

1.关于你的第一个问题,是否需要栈平衡主要取决于你的ROP链中包含的函数以及它们需要的参数数量。这没有直接关系与libc版本,但是某些函数在不同的libc版本中可能需要不同的参数数量。如果你在一个ROP链中使用了一个函数,并且没有为它提供足够的参数,你就需要在调用该函数之前向栈中推入一些值,以保证函数返回时栈是平衡的。对于内外平衡和调用约定的区分,内平衡通常指的是在一个函数内部,局部变量、参数和返回地址等都正常使用和恢复,使得栈保持平衡。而调用约定则更多关乎函数调用前后,栈的状态如何改变,即函数如何接收参数(如通过寄存器或栈),以及如何返回结果等。

2.关于第二个问题,使用ret来平衡栈的基本思路是对的。实际上,你所说的"ret地址"就是一个简单的ret指令的地址。ret指令实质上是将栈顶的值弹出并跳转到那个地址。因此,如果你在ROP链中插入了一个ret指令,它就会从栈中弹出一个值并跳转到那个地址。这样就达到了“平衡栈”的效果。你可以使用任何包含ret指令的地址来达到这个效果,不一定非要使用ROPgaget中的ret地址或者是__libc_csu_init函数的地址。只要你确保在ret指令执行后,栈顶的值是你期望的下一个gadget的地址,就可以保证你的ROP链会正确执行。