def test_se_1(self): binary = BinaryFile(get_full_path("/data/bin/check_serial_1")) arch_info = X86ArchitectureInformation(binary.architecture_mode) functions = [("check_serial", 0x0804841d, 0x08048452)] reil_container = ReilContainerBuilder(binary).build(functions) # Set up initial state initial_state = State(arch_info, mode="initial") # Set up stack esp = 0xffffceec initial_state.write_register("esp", esp) # Set up parameters user_password_addr = 0xdeadbeef user_password_len = 0x6 initial_state.write_memory(esp + 0x4, 4, user_password_addr) # password initial_state.write_memory(esp + 0x0, 4, 0x41414141) # fake return address # Each byte of the password should be an ascii char. for i in xrange(0, user_password_len): value = initial_state.query_memory(user_password_addr + i, 1) initial_state.add_constraint(value.uge(0x21)) initial_state.add_constraint(value.ule(0x7e)) sym_exec = ReilSymbolicEmulator(arch_info) paths = sym_exec.find_address(reil_container, start=0x0804841d, end=0x08048452, find=0x08048451, avoid=[0x0804843b], initial_state=initial_state) # There's only one way to reach 'find' address. self.assertEqual(len(paths), 1) final_state = State(arch_info, mode="final") user_password_expected = bytearray("AAAAAA") user_password = bytearray() se_res = SymExecResult(arch_info, initial_state, paths[0], final_state) for i in xrange(0, user_password_len): value = se_res.query_memory(user_password_addr + i, 1) user_password.append(value) self.assertEqual(user_password, user_password_expected)
def test_se_6(self): binary = BinaryFile(get_full_path("/data/bin/check_serial_6")) arch_info = X86ArchitectureInformation(binary.architecture_mode) functions = [("expand", 0x0804849b, 0x080484dd)] reil_container = ReilContainerBuilder(binary).build(functions) # Set up initial state initial_state = State(arch_info, mode="initial") # Set up stack esp = 0xffffceec initial_state.write_register("esp", esp) # Set up parameters out_array_addr = 0xdeadbeef in_array_addr = 0xdeadbeef + 0x5 initial_state.write_memory(esp + 0x04, 4, out_array_addr) # out initial_state.write_memory(esp + 0x08, 4, in_array_addr) # in initial_state.write_memory(esp + 0x0c, 4, 0xAAAAAAAA) initial_state.write_memory(esp + 0x10, 4, 0xBBBBBBBB) # Set the in array for i, b in enumerate(bytearray("\x02\x03\x05\x07")): initial_state.write_memory(in_array_addr + i, 1, b) # # Set up final state # final_state = State(arch_info, mode="final") # Set the B array for i, b in enumerate(bytearray("\xFC\xFB\xF5\xF7")): final_state.write_memory(out_array_addr + i, 1, b) start_addr = 0x0804849b end_addr = 0x080484dd sym_exec = ReilSymbolicEmulator(arch_info) paths = sym_exec.find_state(reil_container, start=start_addr, end=end_addr, initial_state=initial_state, final_state=final_state) # There's only one way to reach 'find' address. self.assertEqual(len(paths), 1) se_res = SymExecResult(arch_info, initial_state, paths[0], final_state) self.assertEqual(se_res.query_memory(esp + 0x4, 4), 0xdeadbeef) self.assertEqual(se_res.query_memory(esp + 0x8, 4), 0xdeadbef4)
def test_sample_2(self): binary = BinaryFile(get_full_path("/data/bin/x86_sample_2")) strategy = RecursiveDescent(self._disassembler, binary.text_section, self._translator, self._arch_info) recoverer = CFGRecoverer(strategy) # Recover "main" function. bbs, call_targets = recoverer.build(0x0804846d, 0x080484a3) self.assertEqual(len(bbs), 4) cfg = ControlFlowGraph(bbs, name="main") self.assertEqual(cfg.start_address, 0x0804846d) self.assertEqual(cfg.end_address, 0x080484a3) self.assertEqual(len(cfg.basic_blocks), 4) bb_entry = cfg.find_basic_block(0x0804846d) self.assertEqual(len(bb_entry.branches), 2) self.assertEqual(bb_entry.taken_branch, 0x08048491) self.assertEqual(bb_entry.not_taken_branch, 0x0804848a) bb_taken = cfg.find_basic_block(0x08048491) self.assertEqual(len(bb_taken.branches), 1) self.assertEqual(bb_taken.taken_branch, None) self.assertEqual(bb_taken.not_taken_branch, None) self.assertEqual(bb_taken.direct_branch, 0x08048496) bb_not_taken = cfg.find_basic_block(0x0804848a) self.assertEqual(len(bb_not_taken.branches), 1) self.assertEqual(bb_not_taken.taken_branch, None) self.assertEqual(bb_not_taken.not_taken_branch, None) self.assertEqual(bb_not_taken.direct_branch, 0x08048496) # Recover "func_1" function. bbs, call_targets = recoverer.build(0x0804843b, 0x8048453) self.assertEqual(len(bbs), 1) cfg = ControlFlowGraph(bbs, name="main") self.assertEqual(cfg.start_address, 0x0804843b) self.assertEqual(cfg.end_address, 0x8048453) self.assertEqual(len(cfg.basic_blocks), 1) # Recover "func_2" function. bbs, call_targets = recoverer.build(0x08048454, 0x0804846c) self.assertEqual(len(bbs), 1) cfg = ControlFlowGraph(bbs, name="main") self.assertEqual(cfg.start_address, 0x08048454) self.assertEqual(cfg.end_address, 0x0804846c) self.assertEqual(len(cfg.basic_blocks), 1)
def test_emulate_arm(self): binary = BinaryFile(get_full_path("./samples/bin/loop-simple.arm")) arch_mode = ARCH_ARM_MODE_ARM arch_info = ArmArchitectureInformation(arch_mode) ir_emulator = ReilEmulator(arch_info) disassembler = ArmDisassembler(architecture_mode=ARCH_ARM_MODE_ARM) ir_translator = ArmTranslator(architecture_mode=ARCH_ARM_MODE_ARM) emu = Emulator(arch_info, ir_emulator, ir_translator, disassembler) emu.load_binary(binary) emu.emulate(0x10400, 0x10460, {}, None, True)
def test_emulate_x86_64(self): binary = BinaryFile(get_full_path("./samples/bin/loop-simple.x86_64")) arch_mode = ARCH_X86_MODE_64 arch_info = X86ArchitectureInformation(arch_mode) ir_emulator = ReilEmulator(arch_info) disassembler = X86Disassembler(ARCH_X86_MODE_64) ir_translator = X86Translator(ARCH_X86_MODE_64) emu = Emulator(arch_info, ir_emulator, ir_translator, disassembler) emu.load_binary(binary) emu.emulate(0x4004d6, 0x400507, {}, None, False)
def test_sample_1(self): binary = BinaryFile(get_full_path("/data/bin/x86_sample_1")) strategy = RecursiveDescent(self._disassembler, binary.text_section, self._translator, self._arch_info) recoverer = CFGRecoverer(strategy) bbs, call_targets = recoverer.build(0x0804840b, 0x08048438) self.assertEqual(len(bbs), 1) cfg = ControlFlowGraph(bbs, name="main") self.assertEqual(cfg.start_address, 0x0804840b) self.assertEqual(cfg.end_address, 0x08048438) self.assertEqual(len(cfg.basic_blocks), 1)
def main(): # Process program arguments. parser = init_parser() args = parser.parse_args() # Open binary. binary = BinaryFile(args.binary) # Check binary arch and mode. if binary.architecture != ARCH_X86 or \ binary.architecture_mode not in [ARCH_X86_MODE_32, ARCH_X86_MODE_64]: print("[!] Architecture not supported.") sys.exit(1) # Load architecture information for the binary. arch_info = X86ArchitectureInformation(binary.architecture_mode) # Extract entrypoint (in case a starting address was not provided.) start_address = int(args.start_address, 16) if args.start_address else binary.entry_point # Prepare options. options = DotDict({}) options.abort = args.abort options.color = args.color options.verbose = args.verbose print("[+] Loading trace...") asm_trace = parse_trace(args.trace, X86Parser(arch_info.architecture_mode), start_address=start_address) print("[+] Replaying trace...") analyzer = AsmReplayAnalyzer(arch_info, asm_trace, start_address, options) analyzer.run()
def solve(): # # Load binary # binary = BinaryFile("bin/very_success") arch_info = X86ArchitectureInformation(binary.architecture_mode) # Create a REIL container for the function of interest functions = [("sub_401084", 0x00401084, 0x004010de)] reil_container = ReilContainerBuilder(binary).build(functions) # # Set up initial state # initial_state = State(arch_info, mode="initial") # Set up stack esp = 0xffffceec initial_state.write_register("esp", esp) # Set up parameters user_password_addr = 0x00402159 user_password_len = 0x25 ref_key_addr = 0x004010e4 initial_state.write_memory(esp + 0xc, 4, user_password_len) initial_state.write_memory(esp + 0x8, 4, user_password_addr) initial_state.write_memory(esp + 0x4, 4, ref_key_addr) initial_state.write_memory(esp + 0x0, 4, 0x41414141) # return address # Set memory for i in xrange(user_password_len): initial_state.write_memory(ref_key_addr + i, 1, ord(binary.text_section[ref_key_addr + i])) # # Run concolic execution # sym_exec = ReilSymbolicEmulator(arch_info) paths = sym_exec.find_address(reil_container, start=0x00401084, end=0x004010de, find=0x004010d5, avoid=[0x004010d7], initial_state=initial_state) # There's only one way to reach 'find' address. assert len(paths) == 1 # # Query input buffer and print content # final_state = State(arch_info, mode="final") se_res = SymExecResult(arch_info, initial_state, paths[0], final_state) user_password = bytearray() for i in xrange(user_password_len): user_password.append(se_res.query_memory(user_password_addr + i, 1)) print("User password: {}".format(user_password)) assert user_password == bytearray("*****@*****.**")
def solve(): # # Load Binary # binary = BinaryFile("bin/toyproject.exe") arch_info = X86ArchitectureInformation(binary.architecture_mode) # Identify functions of interest functions = [("sub_4010ec", 0x004010ec, 0x004010ec + 0x3a)] # Create a REIL container reil_container_builder = ReilContainerBuilder(binary) reil_container = reil_container_builder.build(functions) # # Set up initial state # initial_state = State(arch_info, mode="initial") # Set up stack esp = 0x00001500 initial_state.write_register("esp", esp) # Set up parameters out_array_addr = esp - 0x25 in_array_addr = 0x4093a8 initial_state.write_memory(esp + 0x0, 4, 0x41414141) # fake return address # TODO: Find a way to mark 'x' and 'y' as symbolic variables. # initial_state.write_memory(esp + 0x4, 4, x) # Mark as Symbolic # initial_state.write_memory(esp + 0x8, 4, y) # Mark as Symbolic # Set the A array in_array_expected = bytearray(__get_in_array()) for i in range(len(in_array_expected)): initial_state.write_memory(in_array_addr + i, 1, in_array_expected[i]) # # Set up final state # final_state = State(arch_info, mode="final") # Set the B array out_array_expected = bytearray(__get_out_array(), encoding='ascii') for i in range(32): # Avoid trivial solution initial_state.write_memory(out_array_addr + i, 1, 0) # Assert final (desired) state final_state.write_memory(out_array_addr + i, 1, out_array_expected[i]) # # Run concolic execution # sym_exec = ReilSymbolicEmulator(arch_info) paths = sym_exec.find_state(reil_container, start=0x004010ec, end=0x0040111d, initial_state=initial_state, final_state=final_state) # There's only one way to reach the final state. # assert len(paths) == 1 print("[+] Number of paths: {}".format(len(paths))) # for index, path in enumerate(paths): # __save_path(path, index) # # Query input buffer and print content # print("A (in) : {:s}".format(" ".join( ["{:02x}".format(b) for b in in_array_expected]))) print("B (out) : {:s}".format(" ".join( ["{:02x}".format(b) for b in out_array_expected]))) if len(paths) > 0: se_res = SymExecResult(arch_info, initial_state, paths[0], final_state) print("x: {0:#010x} ({0:d})".format(se_res.query_memory(esp + 0x4, 4))) print("y: {0:#010x} ({0:d})".format(se_res.query_memory(esp + 0x8, 4))) else: print("[-] State Not Found!")