Snippets

XOR Hex Flare-On 2017 Challenge 3 Solution

Updated by XOR Hex

File greek_to_me_angr7.py Modified

  • Ignore whitespace
  • Hide word diff
 #!/usr/bin/env python2
 
 '''
+Author: @XOR_Hex
+#flareon4
+Challenge 3
+
 ' Three parts
 ' 0) Dump the ASM from IDA, Start @ 0x40107C and the length is 0x79 (see box @ loc_401029)
 '      bytes = idaapi.get_many_bytes(0x40107C, 0x79)
Created by XOR Hex

File greek_to_me_angr7.py Added

  • Ignore whitespace
  • Hide word diff
+#!/usr/bin/env python2
+
+'''
+' Three parts
+' 0) Dump the ASM from IDA, Start @ 0x40107C and the length is 0x79 (see box @ loc_401029)
+'      bytes = idaapi.get_many_bytes(0x40107C, 0x79)
+'      with open('/home/firefly/buffer.asm', 'wb') as f:
+'            f.write(bytes)
+' 1) Figure out what byte the code needs to be xor'ed with.  Last word must match 0xfb5eL (loop at 401039, comparison check: 40105E)
+'    Code to be xor'ed and add'ed is located at 40107C and the length is 0x79 (see box @ loc_401029)
+'    To determine the input byte the modified (xord + add) bytes have to be passed through sub_4011E6 before the comparison check can be done
+' 2) After the check passes the state memory from angr needs to be interpreted as code, so use capstone
+'    The op_str from capstone contains what looks like ASCII characters...
+' 3) Take the capstone output and interpret the ASCII codes to get the flag
+'''
+
+import angr
+import sys
+
+p = angr.Project('greek_to_me.exe', load_options={'auto_load_libs': False})
+f2 = None
+
+# Interate through all of the possible byte values to find the correct "user" input to de-mask the flag
+for buf in xrange(0x100):
+
+    print("Trying buf = {0}".format(buf))
+
+    # Variable to store the bits written to disk using IDA
+    asm = None
+    # Store the output from the first de-obfuscation routine
+    b2 = []
+    # Read in bytes written to file from IDA
+    with open('greek_to_me_buffer.asm', 'rb') as f:
+        asm = f.read()
+
+    # Re-implement loc_401039
+    dl = buf 
+    for byte in asm:
+        bl = ord(byte)
+        bl = bl ^ dl
+        bl = bl & 0xff
+        bl = bl + 0x22
+        bl = bl & 0xff
+        b2.append(bl)
+
+
+    # Set up angr to "run" sub_4011E6 
+    s = p.factory.blank_state(addr=0x4011E6)
+    s.mem[s.regs.esp+4:].dword = 1    # Angr memory location to hold the xor'ed and add'ed bytes
+    s.mem[s.regs.esp+8:].dword = 0x79 # Length of ASM
+    
+    # Copy bytes output from loc_401039 into address 0x1 so Angr can run it
+    asm = ''.join(map(lambda x: chr(x), b2))
+    s.memory.store(1, s.se.BVV(int(asm.encode('hex'), 16), 0x79 * 8 ))
+
+    # Create a simulation manager...
+    #import pdb; pdb.set_trace()
+    simgr = p.factory.simulation_manager(s)
+
+    # Tell Angr where to go, though there is only one way through this function, 
+    # we just need to stop after ax is set
+    simgr.explore(find=0x401268)
+    
+    # Once ax is set, check to see if the value in ax matches the comparison value
+    for found in simgr.found:
+        #import pdb; pdb.set_trace()
+        print('        ax = %s' % hex(found.state.solver.eval(found.state.regs.ax)))
+        # Comparison check
+        if hex(found.state.solver.eval(found.state.regs.ax)) == '0xfb5eL':
+            # Upon success, dump the asm
+            code = ("%x" % found.state.solver.eval_upto(found.state.memory.load(1, 0x79), 1)[0]).decode('hex')
+            print('\n        Winner is: {0}\n\n'.format(buf))
+            print('          %s' % code)
+            bl = None
+            dl = None
+            flag = []
+            # Using capstone, interpret the ASM
+            from capstone import *
+            md = Cs(CS_ARCH_X86, CS_MODE_32)
+            for i in md.disasm(code, 0x1000):
+                flag_char = None
+                # The if statements do the work of interpreting the ASCII codes to their value counterpart
+                if i.op_str.split(',')[0].startswith("byte ptr"):
+                   flag_char = chr(long(i.op_str.split(',')[1], 16)) 
+                if i.op_str.split(',')[0].startswith('bl'):
+                    bl = chr(long(i.op_str.split(',')[1], 16))  
+                if i.op_str.split(',')[0].startswith('dl'):
+                    dl = chr(long(i.op_str.split(',')[1], 16))  
+                if i.op_str.split(',')[1].strip() == 'dl':
+                    flag_char = dl
+                if i.op_str.split(',')[1].strip() == 'bl':
+                    flag_char = bl 
+                
+                if (flag_char):
+                    flag.append(flag_char.strip())
+
+                print("          0x%x\t%s\t%s\t%s" %(i.address, i.mnemonic, i.op_str, flag_char))
+
+            print('\n\n')
+            print(''.join(flag))
+
+            sys.exit(0)