Skip to content

Instantly share code, notes, and snippets.

@hellman
Last active October 4, 2019 08:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hellman/c4dc81e7c13089b42bdb761d4ce442e7 to your computer and use it in GitHub Desktop.
Save hellman/c4dc81e7c13089b42bdb761d4ce442e7 to your computer and use it in GitHub Desktop.
PwnThyBytes 2019 CTF - Primitive Obsession
#!/usr/bin/env python3
'''
time python3 solve.py
35 minutes
'''
import angr
import claripy
import hashlib
# checking functions
subs = [0x4008C5, 0x400912, 0x40097C, 0x4009E6, 0x400A37, 0x400AA7, 0x400AEE, 0x400B3F, 0x400B90, 0x400BDF, 0x400C2F, 0x400C7A, 0x400CCA, 0x400D34, 0x400D95, 0x400DE5, 0x400E4F, 0x400E9B, 0x400F05, 0x400F6F, 0x400FC0, 0x40100C, 0x40105D, 0x4010AE, 0x401100, 0x401152, 0x4011A3, 0x4011F3, 0x40123E, 0x40128D, 0x4012D7, 0x401326, 0x401377, 0x4013C7, 0x401419, 0x40146A, 0x4014B9, 0x40150A, 0x40155A, 0x4015AC, 0x4015F2, 0x401653, 0x4016A4, 0x4016F3, 0x401743, 0x40178F, 0x4017DF, 0x401830, 0x401881, 0x4018D1, 0x40193B, 0x40198C, 0x4019E0, 0x401A31, 0x401A7D, 0x401ACE, 0x401B20, 0x401B6F, 0x401BC7, 0x401C1D, 0x401C6D, 0x401CC3, 0x401D1E, 0x401D7E, 0x401DCF, 0x401E26, 0x401E81, 0x401EDC, 0x401F32, 0x401F87, 0x401FE2, 0x40203E, 0x40209A, 0x4020F5, 0x402152, 0x4021AD, 0x40220A, 0x40225F, 0x4022BC, 0x402317, 0x402373, 0x4023CE, 0x40242B, 0x402486, 0x4024E2, 0x402540, 0x40259D, 0x4025F5, 0x402651, 0x4026AC, 0x402709, 0x40275B, 0x4027B6, 0x40280E, 0x40286B, 0x4028E1, 0x40293C, 0x40299C, 0x4029FC, 0x402A50, 0x402AA8, 0x402B03, 0x402B60, 0x402BB4, 0x402C0C, 0x402C82, 0x402CDE, 0x402D3B, 0x402D98, 0x402DF5, 0x402E51, 0x402EAE, 0x402F0B, 0x402F67, 0x402FBF, 0x40301A, 0x403075, 0x4030D1, 0x403147, 0x4031A4, 0x403201, 0x40325E, 0x4032B9, 0x403314, 0x40336F, 0x4033CA, 0x403422, 0x403477, 0x4034D4, 0x403530, 0x40358B, 0x4035E7, 0x403644, 0x4036A4]
# mov eax, 0 in the checking functions
bad = [0x4008BE,0x40090B,0x400975,0x4009DF,0x400A30,0x400AA0,0x400AE7,0x400B38,0x400B89,0x400BD8,0x400C28,0x400C73,0x400CC3,0x400D2D,0x400D8E,0x400DDE,0x400E48,0x400E94,0x400EFE,0x400F68,0x400FB9,0x401005,0x401056,0x4010A7,0x4010F9,0x40114B,0x40119C,0x4011EC,0x401237,0x401286,0x4012D0,0x40131F,0x401370,0x4013C0,0x401412,0x401463,0x4014B2,0x401503,0x401553,0x4015A5,0x4015EB,0x40164C,0x40169D,0x4016EC,0x40173C,0x401788,0x4017D8,0x401829,0x40187A,0x4018CA,0x401934,0x401985,0x4019D9,0x401A2A,0x401A76,0x401AC7,0x401B19,0x401B68,0x401BC0,0x401C16,0x401C66,0x401CBC,0x401D17,0x401D77,0x401DC8,0x401E1F,0x401E7A,0x401ED5,0x401F2B,0x401F80,0x401FDB,0x402037,0x402093,0x4020EE,0x40214B,0x4021A6,0x402203,0x402258,0x4022B5,0x402310,0x40236C,0x4023C7,0x402424,0x40247F,0x4024DB,0x402539,0x402596,0x4025EE,0x40264A,0x4026A5,0x402702,0x402754,0x4027AF,0x402807,0x402864,0x4028DA,0x402935,0x402995,0x4029F5,0x402A49,0x402AA1,0x402AFC,0x402B59,0x402BAD,0x402C05,0x402C7B,0x402CD7,0x402D34,0x402D91,0x402DEE,0x402E4A,0x402EA7,0x402F04,0x402F60,0x402FB8,0x403013,0x40306E,0x4030CA,0x403140,0x40319D,0x4031FA,0x403257,0x4032B2,0x40330D,0x403368,0x4033C3,0x40341B,0x403470,0x4034CD,0x403529,0x403584,0x4035E0,0x40363D,0x40369D,0x4036F5]
p = angr.Project('./primitive_obsession', load_options={'auto_load_libs': False})
my_buf = 0x43210000
my_rbp = my_buf + 0x130
my_rsp = my_buf - 0x100
# after reading the data
begin = 0x4039BF
# puts flag
target = 0x404A21
state = p.factory.blank_state(addr=begin)
flag = claripy.BVS('flag', 0x104*8)
for i in range(0x104):
c = flag.get_byte(i)
state.solver.add( c <= 126 )
state.solver.add( claripy.Or(c == 0, c==10, c >= 32) )
def byterep(b):
res = ""
for c in b:
res += chr(c) if c <= 126 else "?"
return repr(res)
def at_checking_function(st):
print('function', subs.index(st.addr), "/", len(subs), "states:", {k: len(v) for k, v in sm.stashes.items() if v})
print(st.posix.dumps(1))
f = bytes(st.solver.eval(flag.get_byte(i)) for i in range(0x104))
print(byterep(f))
print()
for sub in subs:
p.hook(sub)(at_checking_function)
state.regs.rbp = my_rbp
state.regs.rsp = my_rsp
state.memory.store(addr=my_buf, data=flag)
sm = p.factory.simulation_manager(state)
sm.explore(find=target, avoid=bad)
print ("========")
print ("FINISHED")
print ("========")
for st in sm.found:
f = bytes(st.solver.eval(flag.get_byte(i)) for i in range(0x104))
print(f.hex())
print(byterep(f))
print("PTBCTF{%s}" % hashlib.sha1(f).hexdigest())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment