def test_pe(self): try: from pyopenreil.utils import bin_PE self._run_test(lambda abi: abi.cdecl, ARCH_X86, bin_PE.Reader(self.file_path(self.PE_NAME)), self.PE_ADDR) except ImportError, why: print '[!]', str(why)
def test(self): # test input data for RC4 encryption test_key = 'somekey' test_val = 'bar' # load PE image of test program reader = bin_PE.Reader(self.BIN_PATH) tr = CodeStorageTranslator(reader) def code_optimization(addr): # construct dataflow graph for given function dfg = DFGraphBuilder(tr).traverse(addr) # run some basic optimizations dfg.eliminate_dead_code() dfg.constant_folding() dfg.eliminate_subexpressions() # store resulting instructions dfg.store(tr.storage) code_optimization(self.RC4_SET_KEY) code_optimization(self.RC4_CRYPT) # create CPU and ABI cpu = Cpu(self.ARCH) abi = Abi(cpu, tr) # allocate buffers for arguments of emulated functions ctx = abi.buff(256 + 4 * 2) val = abi.buff(test_val) # emulate rc4_set_key() function call abi.cdecl(self.RC4_SET_KEY, ctx, test_key, len(test_key)) # emulate rc4_crypt() function call abi.cdecl(self.RC4_CRYPT, ctx, val, len(test_val)) # read results of RC4 encryption val = abi.read(val, len(test_val)) print 'Encrypted value:', repr(val) # check for correct result assert val == '\x38\x88\xBC'
def test(self): # load PE image of test program reader = bin_PE.Reader(self.BIN_PATH) tr = CodeStorageTranslator(reader) # construct dataflow graph for given function dfg = DFGraphBuilder(tr).traverse(self.PROC_ADDR) insn_before = tr.size() # run some basic optimizations dfg.eliminate_dead_code() dfg.constant_folding() dfg.eliminate_subexpressions() dfg.store(tr.storage) insn_after = tr.size() print tr.storage print '%d instructions before optimization and %d after\n' % \ (insn_before, insn_after) # create CPU and ABI cpu = Cpu(self.ARCH) abi = Abi(cpu, tr) testval = 11 # int fib(int n); ret = abi.cdecl(self.PROC_ADDR, testval) cpu.dump() print '%d number in Fibonacci sequence is %d' % (testval + 1, ret) assert ret == 144
def keygen(kao_binary_path, kao_installation_ID): ''' Assembly code of serial number check from Kao's Toy Project binary, X and Y contains serial number that was entered by user. .text:004010EC check_serial proc near .text:004010EC .text:004010EC ciphered = byte ptr -21h .text:004010EC X = dword ptr 8 .text:004010EC Y = dword ptr 0Ch .text:004010EC .text:004010EC push ebp .text:004010ED mov ebp, esp .text:004010EF add esp, 0FFFFFFDCh .text:004010F2 mov ecx, 20h .text:004010F7 mov esi, offset installation_ID .text:004010FC lea edi, [ebp+text_ciphered] .text:004010FF mov edx, [ebp+X] .text:00401102 mov ebx, [ebp+Y] .text:00401105 .text:00401105 loc_401105: .text:00401105 lodsb .text:00401106 sub al, bl .text:00401108 xor al, dl .text:0040110A stosb .text:0040110B rol edx, 1 .text:0040110D rol ebx, 1 .text:0040110F loop loc_401105 .text:00401111 mov byte ptr [edi], 0 .text:00401114 push offset text_valid ; "0how4zdy81jpe5xfu92kar6cgiq3lst7" .text:00401119 lea eax, [ebp+text_ciphered] .text:0040111C push eax .text:0040111D call lstrcmpA .text:00401122 leave .text:00401123 retn 8 .text:00401123 check_serial endp ''' # address of the check_serial() function check_serial = 0x004010EC # address of the strcmp() call inside check_serial() stop_at = 0x0040111D # address of the global buffer with installation ID installation_ID = 0x004093A8 # load Kao's PE binary from pyopenreil.utils import bin_PE tr = CodeStorageTranslator(bin_PE.Reader(kao_binary_path)) # Construct DFG, run all available code optimizations # and update storage with new function code. dfg = DFGraphBuilder(tr).traverse(check_serial) dfg.optimize_all(tr.storage) print tr.get_func(check_serial) # create CPU and ABI cpu = Cpu(ARCH_X86) abi = VM.Abi(cpu, tr, no_reset=True) # hardcoded ciphered text constant from Kao's binary out_data = '0how4zdy81jpe5xfu92kar6cgiq3lst7' in_data = '' try: # convert installation ID into the binary form for s in kao_installation_ID.split('-'): in_data += struct.pack('L', int(s[:8], 16)) in_data += struct.pack('L', int(s[8:], 16)) assert len(in_data) == 32 except: raise Exception('Invalid instllation ID string') # copy installation ID into the emulator's memory for i in range(32): cpu.mem.store(installation_ID + i, U8, cpu.mem._Val(U8, 0, ord(in_data[i]))) ret, ebp = 0x41414141, 0x42424242 # create stack with symbolic arguments for check_serial() stack = abi.pushargs(( Val(exp = SymVal('ARG_0', U32)), \ Val(exp = SymVal('ARG_1', U32)) )) # dummy return address stack.push(Val(ret)) # initialize emulator's registers cpu.reg('ebp', Val(ebp)) cpu.reg('esp', Val(stack.top)) # run until stop try: cpu.run(tr, check_serial, stop_at=[stop_at]) except VM.CpuStop as e: print 'STOP at', hex(cpu.reg('eip').get_val()) # get Z3 expressions list for current CPU state state = cpu.to_z3() cpu.dump(show_all=True) # read symbolic expressions for contents of the output buffer addr = cpu.reg('eax').val data = cpu.mem.read(addr.val, 32) for i in range(32): print '*' + hex(addr.val + i), '=', data[i].exp # create SMT solver solver = z3.Solver() for i in range(32): # add constraint for each output byte solver.add( data[i].to_z3(state, U8) == z3.BitVecVal(ord(out_data[i]), 8)) # solve constraints solver.check() # get solution model = solver.model() # get and print serial number serial = map(lambda d: model[d].as_long(), model.decls()) serial[1] = serial[0] ^ serial[1] print '\nSerial number: %s\n' % '-'.join( ['%.8X' % serial[0], '%.8X' % serial[1]]) return serial assert False
from pyopenreil.REIL import * from pyopenreil.symbolic import * from pyopenreil.VM import * from pyopenreil.utils import bin_PE # VA's of required functions and variables check_serial = 0x004010EC installation_ID = 0x004093A8 # create translator instance tr = CodeStorageTranslator(bin_PE.Reader('toyproject.exe')) # construct data flow graph of check_serial() function dfg = DFGraphBuilder(tr).traverse(check_serial) # Run all available code optimizations and update # storage with new function code. dfg.optimize_all(tr.storage) # print generated IR code print tr.get_func(check_serial)