def get_arch(binary): if binary.architecture == ARCH_X86: return X86ArchitectureInformation(binary.architecture_mode) elif binary.architecture == ARCH_ARM: return ArmArchitectureInformation(binary.architecture_mode) else: raise Exception("Architecture not supported.")
def __init__(self, architecture_mode): super(X86Translator, self).__init__() # Set *Architecture Mode*. The translation of each instruction # into the REIL language is based on this. self._arch_mode = architecture_mode # An instance of *ArchitectureInformation*. self._arch_info = X86ArchitectureInformation(architecture_mode) self._builder = ReilBuilder() self._registers = RegisterTranslator(self._arch_info) self._reg_acc_translator = X86OperandAccessTranslator(self._arch_info) self._flags = FlagTranslator(self._arch_info) self._flag_translator = X86FlagTranslator(self._flags) # Special registers. if self._arch_mode == ARCH_X86_MODE_32: self._sp = self._registers.esp self._bp = self._registers.ebp self._ip = self._registers.eip if self._arch_mode == ARCH_X86_MODE_64: self._sp = self._registers.rsp self._bp = self._registers.rbp self._ip = self._registers.rip # Word size. self._ws = ReilImmediateOperand(self._arch_info.address_size // 8, self._arch_info.address_size)
def setUp(self): self._arch_info = X86ArchitectureInformation(ARCH_X86_MODE_32) self._emulator = ReilEmulator(self._arch_info) self._asm_parser = X86Parser(ARCH_X86_MODE_32) self._translator = X86Translator(ARCH_X86_MODE_32)
def __init__(self, ir_name_generator, architecture_mode): super(X86TranslationBuilder, self).__init__(ir_name_generator, X86ArchitectureInformation(architecture_mode)) self._regs_mapper = self._arch_info.alias_mapper self._regs_size = self._arch_info.registers_size
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 __init__(self, binary): self.__binary = binary self.__arch_mode = self.__binary.architecture_mode self.__arch = X86ArchitectureInformation(self.__arch_mode) self.__disassembler = X86Disassembler(self.__arch_mode) self.__translator = X86Translator(self.__arch_mode) self.__bb_builder = CFGRecoverer( RecursiveDescent(self.__disassembler, self.__binary.text_section, self.__translator, self.__arch))
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 setUp(self): self._address_size = 32 self._parser = ReilParser() self._solver = SmtSolver() self._translator = SmtTranslator(self._solver, self._address_size) self._arch_info = X86ArchitectureInformation(ARCH_X86_MODE_32) self._translator.set_arch_alias_mapper(self._arch_info.alias_mapper) self._translator.set_arch_registers_size(self._arch_info.registers_size)
def setUp(self): self.arch_mode = ARCH_X86_MODE_64 self.arch_info = X86ArchitectureInformation(self.arch_mode) self.x86_parser = X86Parser(self.arch_mode) self.x86_translator = X86Translator(self.arch_mode) self.reil_emulator = ReilEmulator(self.arch_info) self.context_filename = "failing_context.data"
def __init__(self, architecture_mode): global arch_info, modifier_size arch_info = X86ArchitectureInformation(architecture_mode) self._cache = {} modifier_size["far ptr"] = arch_info.architecture_size modifier_size["far"] = arch_info.architecture_size modifier_size["ptr"] = arch_info.architecture_size
def __init__(self, architecture_mode): super(X86Disassembler, self).__init__() arch_mode_map = { ARCH_X86_MODE_32: CS_MODE_32, ARCH_X86_MODE_64: CS_MODE_64 } self._arch_mode = architecture_mode self._arch_info = X86ArchitectureInformation(architecture_mode) self._parser = X86Parser(architecture_mode) self._disassembler = Cs(CS_ARCH_X86, arch_mode_map[architecture_mode])
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 __init__(self, binary, symbols): self.__binary = binary self.__arch_mode = self.__binary.architecture_mode self.__arch = X86ArchitectureInformation(self.__arch_mode) self.__disassembler = X86Disassembler(self.__arch_mode) self.__translator = X86Translator(self.__arch_mode) self.__bb_builder = CFGRecoverer( RecursiveDescent(self.__disassembler, self.__binary.text_section, self.__translator, self.__arch)) self.__container = {} self.__symbols = symbols self.__symbols_by_addr = {} for name, start, end in symbols: self.__symbols_by_addr[start] = (name, end)
def setUp(self): self._arch_info = X86ArchitectureInformation(ARCH_X86_MODE_32) self._smt_solver = SmtSolver() self._smt_translator = SmtTranslator(self._smt_solver, self._arch_info.address_size) self._smt_translator.set_arch_alias_mapper( self._arch_info.alias_mapper) self._smt_translator.set_arch_registers_size( self._arch_info.registers_size) self._x86_parser = X86Parser(ARCH_X86_MODE_32) self._x86_translator = X86Translator(ARCH_X86_MODE_32) self._code_analyzer = CodeAnalyzer(self._smt_solver, self._smt_translator, self._arch_info)
def __init__(self, architecture_mode): super(X86Translator, self).__init__() # Set *Architecture Mode*. The translation of each instruction # into the REIL language is based on this. self._arch_mode = architecture_mode # An instance of *ArchitectureInformation*. self._arch_info = X86ArchitectureInformation(architecture_mode) # An instance of a *VariableNamer*. This is used so all the # temporary REIL registers are unique. self._ir_name_generator = VariableNamer("t", separator="") self._builder = ReilBuilder() self._flags = { "af": ReilRegisterOperand("af", 1), "cf": ReilRegisterOperand("cf", 1), "df": ReilRegisterOperand("df", 1), "of": ReilRegisterOperand("of", 1), "pf": ReilRegisterOperand("pf", 1), "sf": ReilRegisterOperand("sf", 1), "zf": ReilRegisterOperand("zf", 1), } if self._arch_mode == ARCH_X86_MODE_32: self._sp = ReilRegisterOperand("esp", 32) self._bp = ReilRegisterOperand("ebp", 32) self._ip = ReilRegisterOperand("eip", 32) self._ws = ReilImmediateOperand(4, 32) # word size elif self._arch_mode == ARCH_X86_MODE_64: self._sp = ReilRegisterOperand("rsp", 64) self._bp = ReilRegisterOperand("rbp", 64) self._ip = ReilRegisterOperand("rip", 64) self._ws = ReilImmediateOperand(8, 64) # word size
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 setUp(self): self._arch_mode = ARCH_X86_MODE_32 self._arch_info = X86ArchitectureInformation(self._arch_mode) self._disassembler = X86Disassembler(ARCH_X86_MODE_32) self._translator = X86Translator(ARCH_X86_MODE_32)
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!")