每条指令的作用:
push eip+4;
- 这条指令将当前指令指针寄存器(
eip
)加上 4 的值压入栈中。这里的eip+4
实际上是下一条指令的地址(假设没有其他的分支跳转或中断),因为eip
指向当前正在执行的指令的地址。这样做通常是为了将返回地址(即函数调用指令的下一条指令地址)保存到栈中,以便函数调用完成后可以正确地返回。
- 这条指令将当前指令指针寄存器(
push ebp;
- 这条指令将当前基指针寄存器(
ebp
)的值压入栈中。ebp
通常用于指向当前栈帧的基址,因此将其值保存下来是为了在函数调用完成后能够恢复到调用函数之前的栈帧状态。
- 这条指令将当前基指针寄存器(
mov ebp, esp;
- 这条指令将栈指针寄存器(
esp
)的值复制到基指针寄存器(ebp
)。这意味着函数的栈帧基址现在被设置为当前栈顶的位置。之后,函数可以通过ebp
寄存器访问其局部变量和参数。
- 这条指令将栈指针寄存器(
这段代码的整体作用是设置一个新的栈帧,使得函数可以在其局部变量和参数上进行操作,同时保留调用函数前的栈帧状态,以便在函数返回时能够恢复原始状态。
主要通过两次leave ret指令得到目的,最主要是要得到ebp值也就是栈底的地址,来更精确地进行两次leave,第一次的leave是输入后的自带leave,第二次的leave是我们自己导入的leave,做完之后就按着输入顺序一一调取按顺序进行。之后执行之前相当于一串函数,执行ret gift
main
的操作,执行gitf时进行压栈,rsp下移到main,gift结束时执行main。
32位模板:
1 | payload1 = p32(write_plt_addr) + p32(main_addr) + p32(1) //#此前为需要执行的命令 |
64位模板(仅参考):
1 | payload=(p64(gift)+p64(main)).ljust(0x30,b'\x00')# 依次是需要执行的命令进行ret2libc |
rbp=gift 图误
1 | leave=mov esp,ebp; pop ebp; |