[pwn]对于64位程序exp运行报错timeout: the monitored command dumped core\n

前言

这个问题本来是因为NKCTF中的几道题目,本地是可以的但是远程就是timeout,后来通过其他办法解决了,但是已经看到了这个堆栈的平衡的问题,这里就总结一下吧,万一以后能用到呢。

堆栈平衡

64位程序相对于32位程序多了堆栈需要平衡的问题

  • 如果要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入栈中的地址。
  • 如果通过堆栈传递参数了,那么在函数执行完毕后,要平衡参数导致的堆栈变化。

含义:

  • 当函数在一步步执行的时候 一直到ret执行之前,堆栈栈顶的地址 一定要是call指令的下一个地址。
  • 函数执行前一直到函数执行结束,函数里面的堆栈是要保持不变的。
  • 如果堆栈变化了,那么,要在ret执行前将堆栈恢复成原来的样子。

解决办法

最主要的办法就是通过ret来让堆栈重新平衡

调用system函数的栈对齐问题

这个问题是exp写到后面遇到的问题,东西不多,我就和远程报错总结到一起了,希望以后能找到吧

为什么执行system函数要栈对齐

  • 其实啊,64位ubuntu18以上系统调用system函数时是需要栈对齐的。再具体一点就是64位下system函数有个movaps指令,这个指令要求内存地址必须16字节对齐
  • 因为64位程序的地址是8字节的,而十六进制又是满16就会进位,因此我们看到的栈地址末尾要么是0要么是8。
  • 只有当地址的末尾是0的时候,才算是与16字节对齐了,如果末尾是8的话,那就是没有对齐。而我们想要在ubuntu18以上的64位程序中执行system函数,必须要在执行system地址末尾是0。

解决办法

  • 去将system函数地址+1此处的+1,即是把地址+1,也可以理解为+1是为了跳过一条栈操作指令(我们的目的就是跳过一条栈操作指令,使rsp十六字节对齐跳过一条指令,自然就是把8变成0了)。但又一个问题就是,本来+1是为了跳过一条栈操作指令,但是你也不知道下一条指令是不是栈操作指令,如果不是栈操作指令的话(你加一之后有可能正好是mov这种指令,也有可能人家指令是好几个字节,你加一之后也没有到下一个指令呢),+1也是徒劳的,要么就继续+1,一直加到遇见一条栈操作指令为止(看别的师傅说最大加16次就能成功,不过我不知道为啥)
  • 直接在调用system函数地址之前去调用一个ret指令。因为本来现在是没有对齐的,那我现在直接执行一条对栈操作指令(ret指令等同于pop rip,该指令使得rsp+8,从而完成rsp16字节对齐),这样system地址所在的栈地址就是0结尾,从而完成了栈对齐。

上面是直接复制的这位师傅的博客https://www.cnblogs.com/ZIKH26/articles/15996874.html