def __resolve_loops(self, address, instrs): # Collect labels. idx_by_labels = {} instrs_no_labels = [] curr = 0 for i in instrs: if isinstance(i, ReilLabel): idx_by_labels[i.name] = curr else: instrs_no_labels.append(i) curr += 1 instrs[:] = instrs_no_labels # Resolve instruction addresses and JCC targets. for index, instr in enumerate(instrs): instr.address = to_reil_address(address, index) if instr.mnemonic == ReilMnemonic.JCC: target = instr.operands[2] if isinstance(target, ReilLabel): addr = to_reil_address(address, idx_by_labels[target.name]) size = self._arch_info.address_size + 8 instr.operands[2] = ReilImmediateOperand(addr, size) return instrs
def find_state(self, container, start=None, end=None, avoid=None, initial_state=None, final_state=None): """Execute instructions. """ self.__set_cpu_state(initial_state) # Convert input native addresses to reil addresses. start = to_reil_address(start) if start else None end = to_reil_address(end) if end else None avoid = [to_reil_address(addr) for addr in avoid] if avoid else [] # Load instruction pointer. ip = start if start else container[0].address execution_state = Queue() trace_current = [] trace_final = [] self.__fs_process_container(container, final_state, ip, end, avoid, initial_state, execution_state, trace_current, trace_final) # Only returns when all paths have been visited. assert execution_state.empty() return trace_final
def __execute(self, asm_instr): # Process one assembler instruction. Translate it to REIL instruction and # process each one. instr_container = self.__translate(asm_instr) ip = to_reil_address(asm_instr.address) next_addr = None while ip: # Fetch instruction. try: reil_instr = instr_container.fetch(ip) except ReilContainerInvalidAddressError: next_addr, _ = split_address(ip) break if reil_instr.mnemonic == ReilMnemonic.UNKN: raise InstructionNotImplemented(asm_instr) # Execute instruction. next_ip = self.ir_emulator.single_step(reil_instr) # Update instruction pointer. ip = next_ip if next_ip else instr_container.get_next_address(ip) del instr_container # delete temporal registers regs = self.ir_emulator.registers.keys() for r in regs: if r.startswith("t"): del self.ir_emulator.registers[r] return next_addr if next_addr else asm_instr.address + asm_instr.size
def __execute(self, asm_instr): # Process one assembler instruction. Translate it to REIL instruction and # process each one. instr_container = self.__translate(asm_instr) ip = to_reil_address(asm_instr.address) next_addr = None while ip: # Fetch instruction. try: reil_instr = instr_container.fetch(ip) except ReilContainerInvalidAddressError: next_addr, _ = split_address(ip) break if reil_instr.mnemonic == ReilMnemonic.UNKN: raise InstructionNotImplemented(asm_instr) # Execute instruction. next_ip = self.ir_emulator.single_step(reil_instr) # Update instruction pointer. ip = next_ip if next_ip else instr_container.get_next_address(ip) del instr_container # Execute post instruction handlers handler_fn_post, handler_param_post = self.__instr_handler_post handler_fn_post(self, asm_instr, handler_param_post) # delete temporal registers regs = self.ir_emulator.registers.keys() for r in regs: if r.startswith("t"): del self.ir_emulator.registers[r] return next_addr if next_addr else asm_instr.address + asm_instr.size
def emulate(self, start_addr, end_addr, hooks, max_instrs, print_asm): # Switch arch mode accordingly for ARM base on the start address. if isinstance(self.arch_info, ArmArchitectureInformation): if start_addr & 0x1 == 0x1: start_addr = start_addr & ~0x1 end_addr = end_addr & ~0x1 self._arch_mode = ARCH_ARM_MODE_THUMB else: self._arch_mode = ARCH_ARM_MODE_ARM execution_cache = ExecutionCache() next_addr = start_addr instr_count = 0 asm_instr = None while next_addr != end_addr: if max_instrs and instr_count > max_instrs: break # Process hooks. if next_addr in hooks: logger.debug("Hooking @ {:#x}".format(next_addr)) fn, param, skip, offset = hooks[next_addr] fn(self.ir_emulator, param) # Compute next address after hook. if skip: if isinstance(self.arch_info, X86ArchitectureInformation): # Pop return address from the stack. next_addr = self.ir_emulator.read_memory( self.ir_emulator.registers[self.sp], self.ws) self.ir_emulator.registers[self.sp] += self.ws if isinstance(self.arch_info, ArmArchitectureInformation): # Load return address from the link register. next_addr = self.ir_emulator.registers["r14"] logger.debug("Continuing @ {:#x}".format(next_addr)) try: # Retrieve next instruction from the execution cache. asm_instr, reil_container = execution_cache.retrieve(next_addr) except InvalidAddressError: # Fetch the instruction. encoding = self.__fetch_instr(next_addr) # Decode it. asm_instr = self.disassembler.disassemble( encoding, next_addr, architecture_mode=self._arch_mode) # Translate it. reil_container = self.__build_reil_container(asm_instr) # Add it to the execution cache. execution_cache.add(next_addr, asm_instr, reil_container) # Update the instruction pointer. self.__update_ip(asm_instr) # Execute instruction. if print_asm: print("{:#x} {}".format(asm_instr.address, asm_instr)) target_addr = self.__process_reil_container( reil_container, to_reil_address(next_addr)) # Get next address to execute. next_addr = to_asm_address( target_addr ) if target_addr else asm_instr.address + asm_instr.size # Count instruction. instr_count += 1
def emulate(self, start_addr, end_addr, hooks, max_instrs, print_asm): # Switch arch mode accordingly for ARM base on the start address. if isinstance(self.arch_info, ArmArchitectureInformation): if start_addr & 0x1 == 0x1: start_addr = start_addr & ~0x1 end_addr = end_addr & ~0x1 self._arch_mode = ARCH_ARM_MODE_THUMB else: self._arch_mode = ARCH_ARM_MODE_ARM execution_cache = ExecutionCache() next_addr = start_addr instr_count = 0 asm_instr = None while next_addr != end_addr: if max_instrs and instr_count > max_instrs: break # Process hooks. if next_addr in hooks: logger.debug("Hooking @ {:#x}".format(next_addr)) fn, param, skip, offset = hooks[next_addr] fn(self.ir_emulator, param) # Compute next address after hook. if skip: if isinstance(self.arch_info, X86ArchitectureInformation): # Pop return address from the stack. next_addr = self.ir_emulator.read_memory(self.ir_emulator.registers[self.sp], self.ws) self.ir_emulator.registers[self.sp] += self.ws if isinstance(self.arch_info, ArmArchitectureInformation): # Load return address from the link register. next_addr = self.ir_emulator.registers["r14"] logger.debug("Continuing @ {:#x}".format(next_addr)) try: # Retrieve next instruction from the execution cache. asm_instr, reil_container = execution_cache.retrieve(next_addr) except InvalidAddressError: # Fetch the instruction. encoding = self.__fetch_instr(next_addr) # Decode it. asm_instr = self.disassembler.disassemble(encoding, next_addr, architecture_mode=self._arch_mode) # Translate it. reil_container = self.__build_reil_container(asm_instr) # Add it to the execution cache. execution_cache.add(next_addr, asm_instr, reil_container) # Update the instruction pointer. self.__update_ip(asm_instr) # Execute instruction. if print_asm: print("{:#x} {}".format(asm_instr.address, asm_instr)) target_addr = self.__process_reil_container(reil_container, to_reil_address(next_addr)) # Execute post instruction handlers handler_fn_post, handler_param_post = self.__instr_handler_post handler_fn_post(self, asm_instr, handler_param_post) # Get next address to execute. next_addr = to_asm_address(target_addr) if target_addr else asm_instr.address + asm_instr.size # Count instruction. instr_count += 1