Last active
October 4, 2019 08:37
-
-
Save hellman/c4dc81e7c13089b42bdb761d4ce442e7 to your computer and use it in GitHub Desktop.
PwnThyBytes 2019 CTF - Primitive Obsession
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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