def runmips(code): output = [] def hook_interrupt(uc, intno, user_data): from unicorn.mips_const import UC_MIPS_REG_2, UC_MIPS_REG_4 from unicorn.mips_const import UC_MIPS_REG_5, UC_MIPS_REG_6 if intno != 17: uc.emu_stop() raise Exception("Unknwon Interrupt") v0 = uc.reg_read(UC_MIPS_REG_2) if v0 == 4004: # SYS_WRITE a0 = uc.reg_read(UC_MIPS_REG_4) a1 = uc.reg_read(UC_MIPS_REG_5) a2 = uc.reg_read(UC_MIPS_REG_6) try: buf = uc.mem_read(a1, a2) if a0 == 1: user_data.extend(map(chr, buf)) uc.reg_write(UC_MIPS_REG_2, a2) except UcError: uc.emu_stop() raise Error("Segmentation fault") elif v0 == 4001: uc.emu_stop() else: uc.emu_stop() raise Error("Unknown system call") mu = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN) mu.mem_map(ADDRESS, 0x1000) mu.mem_write(ADDRESS, code) mu.hook_add(UC_HOOK_INTR, hook_interrupt, output) mu.emu_start(ADDRESS, ADDRESS + len(code)) return ''.join(output)
def runarm64(code): output = [] def hook_interrupt(uc, intno, user_data): from unicorn.arm64_const import UC_ARM64_REG_X0, UC_ARM64_REG_X1 from unicorn.arm64_const import UC_ARM64_REG_X2, UC_ARM64_REG_X8 if intno != 2: uc.emu_stop() raise Exception("Unknwon Interrupt") x8 = uc.reg_read(UC_ARM64_REG_X8) if x8 == 64: # SYS_WRITE x0 = uc.reg_read(UC_ARM64_REG_X0) x1 = uc.reg_read(UC_ARM64_REG_X1) x2 = uc.reg_read(UC_ARM64_REG_X2) try: buf = uc.mem_read(x1, x2) if x0 == 1: user_data.extend(map(chr, buf)) uc.reg_write(UC_ARM64_REG_X0, x2) except UcError: uc.emu_stop() raise Error("Segmentation fault") elif x8 == 93: uc.emu_stop() else: uc.emu_stop() raise Error("Unknown system call") mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM) mu.mem_map(ADDRESS, 0x1000) mu.mem_write(ADDRESS, code) mu.hook_add(UC_HOOK_INTR, hook_interrupt, output) mu.emu_start(ADDRESS, ADDRESS + len(code)) return ''.join(output)
def set_exits(self, uc: Uc, base_address: int, exits: List[int]): """ We replace all hooks and exits with syscalls since they should be rare in kernel code. Then, when we encounter a syscall, we figure out if a syscall or exit occurred. This can also be used to add additional hooks in the future. :param uc: Unicorn instance :param exits: The exit counts :param base_address: the address we're mapping """ arch = self.arch # TODO: This only works for X64! if exits is None: self._deferred_exits.append(base_address) else: if len(exits) <= 1: # No need to patch anything, uc supports a single exit. return if len(exits) > 1: if arch == X64: for end_addr in exits: if self.get_base(end_addr) == base_address: print( "[*] Setting exit 0x{:016x}".format(end_addr)) # Abusing the syscall opcode for exits. # Just make sure the whole opcode will fit here by trying to map the end addr. self.map_page( uc, end_addr + len(x64utils.SYSCALL_OPCODE)) uc.mem_write(end_addr, x64utils.SYSCALL_OPCODE) else: raise (ValueError( "Multiple exits are not yet supported for arch {} - {}" .format(arch, exits)))
def runX86_64(code): from unicorn.x86_const import UC_X86_INS_SYSCALL output = [] def hook_syscall(uc, user_data): from unicorn.x86_const import UC_X86_REG_RAX, UC_X86_REG_RDI from unicorn.x86_const import UC_X86_REG_RSI, UC_X86_REG_RDX rax = uc.reg_read(UC_X86_REG_RAX) if rax == 1: rdi = uc.reg_read(UC_X86_REG_RDI) rsi = uc.reg_read(UC_X86_REG_RSI) rdx = uc.reg_read(UC_X86_REG_RDX) try: buf = uc.mem_read(rsi, rdx) if rdi == 1: user_data.extend(map(chr, buf)) uc.reg_write(UC_X86_REG_RAX, rdx) except UcError: uc.emu_stop() raise Error("Segmentation fault") elif rax == 60: uc.emu_stop() else: raise Error("Unknown system call") mu = Uc(UC_ARCH_X86, UC_MODE_64) mu.mem_map(ADDRESS, 0x1000) mu.mem_write(ADDRESS, code) mu.hook_add(UC_HOOK_INSN, hook_syscall, output, 1, 0, UC_X86_INS_SYSCALL) mu.emu_start(ADDRESS, ADDRESS + len(code)) return ''.join(output)
def runX86(code): output = [] def hook_interrupt(uc, intno, user_data): from unicorn.x86_const import UC_X86_REG_EAX, UC_X86_REG_EBX from unicorn.x86_const import UC_X86_REG_ECX, UC_X86_REG_EDX if intno != 0x80: uc.emu_stop() raise Error("Unknwon Interrupt") eax = uc.reg_read(UC_X86_REG_EAX) if eax == 4: # SYS_WRITE ebx = uc.reg_read(UC_X86_REG_EBX) ecx = uc.reg_read(UC_X86_REG_ECX) edx = uc.reg_read(UC_X86_REG_EDX) try: buf = uc.mem_read(ecx, edx) if ebx == 1: user_data.extend(map(chr, buf)) uc.reg_write(UC_X86_REG_EAX, edx) except UcError: uc.emu_stop() raise Error("Segmentation fault") elif eax == 1: uc.emu_stop() else: raise Error("Unknown system call") mu = Uc(UC_ARCH_X86, UC_MODE_32) mu.mem_map(ADDRESS, 0x1000) mu.mem_write(ADDRESS, code) mu.hook_add(UC_HOOK_INTR, hook_interrupt, output) mu.emu_start(ADDRESS, ADDRESS + len(code)) return ''.join(output)
def __init__(self, vfs_root=None, vfp_inst_set=False): # Unicorn. self.mu = Uc(UC_ARCH_ARM, UC_MODE_ARM) # Intergrated Debugger. self.dbg = udbg.UnicornDebugger(self.mu) self.mu.emu = self if vfp_inst_set: self._enable_vfp() # Android self.system_properties = { "libc.debug.malloc.options": "", "ro.build.version.sdk": "24", "ro.product.cpu.abi": "armeabi-v7a", "init.svc.vbox86-setup": "", "init.svc.droid4x": "" } # Stack. self.mu.mem_map(config.STACK_ADDR, config.STACK_SIZE) self.mu.reg_write(UC_ARM_REG_SP, config.STACK_ADDR + config.STACK_SIZE) # Executable data. self.modules = Modules(self) self.memory = Memory(self) # CPU self.interrupt_handler = InterruptHandler(self.mu) self.syscall_handler = SyscallHandlers(self.interrupt_handler) self.syscall_hooks = SyscallHooks(self.mu, self.syscall_handler) # Hooker self.mu.mem_map(config.HOOK_MEMORY_BASE, config.HOOK_MEMORY_SIZE) self.hooker = Hooker(self, config.HOOK_MEMORY_BASE, config.HOOK_MEMORY_SIZE) # File System if vfs_root is not None: self.vfs = VirtualFileSystem(vfs_root, self, self.syscall_handler) else: self.vfs = None # JavaVM self.java_classloader = JavaClassLoader() self.java_vm = JavaVM(self, self.java_classloader, self.hooker) # add system classes self.java_classloader.add_class(String.java_lang_String) # Native self.native_memory = NativeMemory(self.mu, config.HEAP_BASE, config.HEAP_SIZE, self.syscall_handler, self.vfs) self.native_hooks = NativeHooks(self, self.native_memory, self.modules, self.hooker)
def __init__(self): # Initialize unicorn. self.mu = Uc(UC_ARCH_ARM, UC_MODE_ARM) # Initialize stack. self.mu.mem_map(config.STACK_ADDR, config.STACK_SIZE) self.mu.reg_write(UC_ARM_REG_SP, config.STACK_ADDR + config.STACK_SIZE) self.modules = Modules(self) self.memory = Memory(self)
def speculate_instruction(emulator: Uc, address, size, model) -> None: # reached max spec. window? skip if len(model.checkpoints) >= model.nesting: return # decode the instruction code = emulator.mem_read(address, size) flags = emulator.reg_read(UC_X86_REG_EFLAGS) rcx = emulator.reg_read(UC_X86_REG_RCX) target, will_jump, is_loop = X86UnicornCond.decode(code, flags, rcx) # not a a cond. jump? ignore if not target: return # LOOP instructions must also decrement RCX if is_loop: emulator.reg_write(UC_X86_REG_RCX, rcx - 1) # Take a checkpoint next_instr = address + size + target if will_jump else address + size model.checkpoint(emulator, next_instr) # Simulate misprediction if will_jump: emulator.reg_write(UC_X86_REG_RIP, address + size) else: emulator.reg_write(UC_X86_REG_RIP, address + size + target)
def syscall_exit_hook( uc: Uc, user_data: Tuple[List[int], Callable[[int], None]]) -> None: """ Syscalls rarely happen, so we use them as speedy-ish hook hack for additional exits. """ exits, abort_func = user_data address = uc.reg_read(UC_X86_REG_RIP) print("Run over at {0:x}".format(address)) if address in exits: # print("Run over at {0:x}".format(address)) uc.emu_stop() abort_func(0) return # could add other hooks here print("No handler for syscall insn at {0:x}".format(address))
def place_input(ucf: Unicorefuzz, uc: Uc, input: bytes) -> None: """ Places the input in memory and alters the input. This is an example for sk_buff in openvsswitch """ if len(input) < 1500: import os os._exit(0) rdx = uc.reg_read(UC_X86_REG_RDX) # struct sk_buff* skb ucf.map_page(uc, rdx) # ensure sk_buf is mapped data_ptr = struct.unpack("<Q", uc.mem_read(rdx + 0xD0, 8))[0] ucf.map_page(uc, data_ptr) # ensure the buffer is mapped uc.mem_write(data_ptr, input) # insert afl input
def __init__(self, vfs_root: str = None, vfp_inst_set: bool = False): # Unicorn. self.mu = Uc(UC_ARCH_ARM, UC_MODE_ARM) if vfp_inst_set: self._enable_vfp() # Android self.system_properties = {"libc.debug.malloc.options": ""} # Stack. self.mu.mem_map(STACK_ADDR, STACK_SIZE) self.mu.reg_write(UC_ARM_REG_SP, STACK_ADDR + STACK_SIZE) # Executable data. self.modules = Modules(self) self.memory_manager = MemoryManager(self.mu) # CPU self.interrupt_handler = InterruptHandler(self.mu) self.syscall_handler = SyscallHandlers(self.interrupt_handler) self.syscall_hooks = SyscallHooks(self.mu, self.syscall_handler, self.modules) self.syscall_hooks_memory = SyscallHooksMemory(self.mu, self.memory_manager, self.syscall_handler) # File System if vfs_root is not None: self.vfs = VirtualFileSystem(vfs_root, self.syscall_handler) else: self.vfs = None # Hooker self.mu.mem_map(HOOK_MEMORY_BASE, HOOK_MEMORY_SIZE) self.hooker = Hooker(self, HOOK_MEMORY_BASE, HOOK_MEMORY_SIZE) # JavaVM self.java_classloader = JavaClassLoader() self.java_vm = JavaVM(self, self.java_classloader, self.hooker) # Native self.native_hooks = NativeHooks(self, self.memory_manager, self.modules, self.hooker) # Tracer self.tracer = Tracer(self.mu, self.modules) # Thread. self._setup_thread_register()
def main(): mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB) mu.last_instr = "" setup_hooks(mu) load_mem(mu, 0x9FD6, 0x9FF8 - 0x9FD6) load_mem(mu, 0x35000, 0x4000) sram_addr = 0x20000000 & PAGE_MASK sram_size = ((0x40000) & PAGE_MASK) + PAGE_SIZE mu.mem_map(sram_addr, sram_size) setup_stack(mu) # mu.reg_write(UC_ARM_REG_R0, gps_cfg['addr']) print("[Starting Emulation]") mu.emu_start(0x0369E0 | 1, 0x369FE) with open("data_0x200000D8_7bc.bin", "wb") as fh: mem = mu.mem_read(0x200000D8, 0x7BC) fh.write(mem) fh.close() print("[Done]")
def __init__(self, firmware: Firmware = None, state: CpuState = None, verbose=0, init=True): self.firmware = firmware self.uc = Uc(UC_ARCH_ARM, UC_MODE_THUMB) self.cs = Cs(CS_ARCH_ARM, CS_MODE_THUMB) self.cs.detail = True self.state = state self.has_error = None self.last_addr = None self.ready = False self.context = None self.verbose = verbose if init: self.init()
def angr_load_mapped_pages( self, uc: Uc, state: angr.SimState ) -> List[Tuple[int, int, int]]: """ Loads all currently mapped unicorn mem regions into angr :param uc: The uc instance to load from :param state: the angr instance to load to :returns Lst of pages mapped """ mapped = [] for begin, end, perms in uc.mem_regions(): mapped += (begin, end - begin + 1, perms) angr_store_mem(state, begin, bytes(uc.mem_read(begin, end - begin + 1))) return mapped
def hook_code(uc: unicorn.Uc, address, size, user_data): inst_code = uc.mem_read(address, size) for inst in cs.disasm(inst_code, size): # 判断是否保存有上次的指令,有的话,则先打印上次的指令,并且查询上次的第一个寄存器的新数值 if globalData.has_pre and globalData.pre_regname: regindex = reg_names[globalData.pre_regname.upper()] regvalue = uc.reg_read(regindex) globalData.pre_codestr += "\t//%s=0x%x" % (globalData.pre_regname, regvalue) print(globalData.pre_codestr) globalData.pre_codestr = "" globalData.has_pre = False # 监控我关心的内存空间,如果发生变动会再打印 if len(globalData.watch_addrs) > 0: for i, v in globalData.watch_addrs.items(): idata = uc.mem_read(i, 0x10) buf = binascii.b2a_hex(idata) hexstr = buf.decode(encoding="utf-8") if globalData.watch_addrs[i] == hexstr: continue globalData.watch_addrs[i] = hexstr print("0x%x\t%s" % (i, hexstr)) # 拼接当前行的汇编指令 opstr = "0x%x:\t%s\t%s" % (address, inst.mnemonic, inst.op_str) # 从当前行指令中匹配出所有的寄存器 res = re.findall(r'[^0]([wx][0-9]+)', " " + inst.op_str, re.I | re.M) # 如果有多个寄存器,取第一个为数值被改变的寄存器 if len(res) > 0: globalData.pre_regname = res[0] res = list(set(res)) # 如果有sp寄存器,则单独插入 if "sp" in inst.op_str: res.append("sp") # 如果没有寄存器,则不需要记录为上次的,直接打印即可 if len(res) <= 0: has_pre = False print(opstr) continue # 记录数据为上次的指令 fenge = "\t\t------" curreg = "" for regname in res: regindex = reg_names[regname.upper()] regvalue = uc.reg_read(regindex) curreg += "%s=0x%x\t" % (regname, regvalue) globalData.pre_codestr = opstr + fenge + curreg globalData.has_pre = True
def create_emulator(arch, mode, state) -> IEmuHelper: """ Factory method for constructing the appropriate IEmuHelper """ from unicorn import Uc, UC_ARCH_ARM, UC_ARCH_MIPS, UC_ARCH_X86 from unicorn.unicorn import UcError try: uc = Uc(arch, mode) arch = uc._arch if arch == UC_ARCH_X86 and state.bits == 32: from .x86 import x86EmuHelper return x86EmuHelper(uc, state) if arch == UC_ARCH_X86 and state.bits == 64: from .x86 import x86_64EmuHelper return x86_64EmuHelper(uc, state) elif arch == UC_ARCH_ARM: from .arm import ArmEmuHelper return ArmEmuHelper(uc, state) elif arch == UC_ARCH_MIPS: from .mips import MipsEmuHelper return MipsEmuHelper(uc, state) else: raise ZelosLoadException( f"Unsupported architecture {arch} {state.bits}") except UcError: raise ZelosLoadException( f"Custom unicorn does not support the arch/mode/bits" + f" {arch}/{mode}/{state.bits}")
def uc(self) -> Uc: endian = { QL_ENDIAN.EB: UC_MODE_BIG_ENDIAN, QL_ENDIAN.EL: UC_MODE_LITTLE_ENDIAN }[self.endian] return Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + endian)
def test_memory_manager_map_anywhere(self): mm = Memory(Uc(UC_ARCH_X86, UC_MODE_32), None, 32) address1 = mm.map_anywhere(0x1000, "name1", "size1") self.assertEqual( mm.memory_info[address1], Section(mm.emu, address1, 0x1000, "name1", "size1", ""), ) address2 = mm.map_anywhere(0x2000, "name2", "size2") self.assertEqual( mm.memory_info[address1], Section(mm.emu, address1, 0x1000, "name1", "size1", ""), ) self.assertEqual( mm.memory_info[address2], Section(mm.emu, address2, 0x2000, "name2", "size2", ""), ) mm.unmap(address1, 0x1000) self.assertNotIn(address1, mm.memory_info) self.assertEqual( mm.memory_info[address2], Section(mm.emu, address2, 0x2000, "name2", "size2", ""), )
def __init__(self, vfs_root=None, vfp_inst_set=False): # Unicorn. self.mu = Uc(UC_ARCH_ARM, UC_MODE_ARM) if vfp_inst_set: self._enable_vfp() # Android self.system_properties = {} # Stack. self.mu.mem_map(config.STACK_ADDR, config.STACK_SIZE) self.mu.reg_write(UC_ARM_REG_SP, config.STACK_ADDR + config.STACK_SIZE) # Executable data. self.modules = Modules(self) self.memory = Memory(self) # CPU self.interrupt_handler = InterruptHandler(self.mu) self.syscall_handler = SyscallHandlers(self.interrupt_handler) self.syscall_hooks = SyscallHooks(self.mu, self.syscall_handler) # File System if vfs_root is not None: self.vfs = VirtualFileSystem(vfs_root, self.syscall_handler) else: self.vfs = None # Hooker self.mu.mem_map(config.HOOK_MEMORY_BASE, config.HOOK_MEMORY_SIZE) self.hooker = Hooker(self, config.HOOK_MEMORY_BASE, config.HOOK_MEMORY_SIZE) # JavaVM self.java_classloader = JavaClassLoader() self.java_vm = JavaVM(self, self.java_classloader, self.hooker) # Native self.native_memory = NativeMemory(self.mu, config.HEAP_BASE, config.HEAP_SIZE, self.syscall_handler) self.native_hooks = NativeHooks(self, self.native_memory, self.modules, self.hooker) # Tracer self.tracer = Tracer(self.mu, self.modules)
def test_setip_after_emustop(self): record = [] uc = Uc(UC_ARCH_X86, UC_MODE_32) def hook(uc, address, size, userdata): record.append(address) def hook_stop(uc, address, size, userdata): if address == 0x1002: uc.emu_stop() uc.reg_write(UC_X86_REG_EIP, 0x1006) uc.mem_map(0, 0x2000) uc.hook_add(UC_HOOK_CODE, hook) uc.hook_add(UC_HOOK_CODE, hook_stop) uc.emu_start(0x1000, 0x1008) self.assertListEqual(record, [0x1000, 0x1002, 0x1006])
def dbg_hook_memory_access(uc: Uc, access, address, size, value, data): if access == UC_MEM_WRITE: print("Write: addr=0x{0:016x} size={1} data=0x{2:016x}".format( address, size, value)) elif access == UC_HOOK_MEM_READ: print("Read: addr=0x{0:016x} size={1} data=0x{2:016x}".format( address, size, struct.unpack("B", uc.mem_read(address, size))[0])) print(access, address, size, value, data)
def test_hooks(self): record = [] def hook(uc, address, size, userdata): record.append(address) uc = Uc(UC_ARCH_X86, UC_MODE_32) uc.mem_map(0, 0x2000) uc.hook_add(UC_HOOK_CODE, hook) uc.emu_start(0x1000, 0x1006) self.assertListEqual(record, [0x1000, 0x1002, 0x1004])
class Emulator: """ :type filename str :type mu Uc :type memory Memory """ def __init__(self): # Initialize unicorn. self.mu = Uc(UC_ARCH_ARM, UC_MODE_ARM) # Initialize stack. self.mu.mem_map(config.STACK_ADDR, config.STACK_SIZE) self.mu.reg_write(UC_ARM_REG_SP, config.STACK_ADDR + config.STACK_SIZE) self.modules = Modules(self) self.memory = Memory(self) def load_library(self, filename): return self.modules.load_module(filename)
def load_mem(mu: Uc, addr, size): filename = "7.4AT-02+V2.001.EFM.bin" data = None with open(filename, "rb") as fh: fh.seek(addr) data = fh.read(size) _addr = addr & PAGE_MASK _size = ((size) & PAGE_MASK) + PAGE_SIZE print(f"[+] Mapping Memory:\n\tAddress: {_addr:08X}\n\tSize: {_size:X}") mu.mem_map(_addr, _size) load_addr = addr load_size = size print( f"[>] Loading Memory:\n\tAddress: {load_addr:08X}\n\tSize: {load_size:X}" ) mu.mem_write(load_addr, data)
def uc(self) -> Uc: mode = UC_MODE_ARM if self._init_endian == QL_ENDIAN.EB: mode += UC_MODE_BIG_ENDIAN if self._init_thumb: mode += UC_MODE_THUMB return Uc(UC_ARCH_ARM, mode)
def test_exception_in_hook(self): uc = Uc(UC_ARCH_X86, UC_MODE_64) uc.mem_map(CODE_ADDR, 0x1000) uc.mem_write(CODE_ADDR, CODE) counter = HookCounter() uc.hook_add(UC_HOOK_CODE, counter.good_code_hook, begin=CODE_ADDR, end=CODE_ADDR + len(CODE)) uc.hook_add(UC_HOOK_CODE, counter.bad_code_hook, begin=CODE_ADDR, end=CODE_ADDR + len(CODE)) self.assertRaises(ValueError, uc.emu_start, CODE_ADDR, CODE_ADDR + len(CODE)) # Make sure hooks calls finish before raising (hook_calls == 2) self.assertEqual(counter.hook_calls, 2)
def speculate_instruction(emulator: Uc, address, size, model) -> None: # reached max spec. window? skip if len(model.checkpoints) >= model.nesting: return if model.previous_store[0]: store_addr = model.previous_store[0] old_value = bytes(model.previous_store[2]) new_is_signed = model.previous_store[3] < 0 new_value = (model.previous_store[3]). \ to_bytes(model.previous_store[1], byteorder='little', signed=new_is_signed) # store a checkpoint model.checkpoint(emulator, address) # cancel the previous store but preserve its value emulator.mem_write(store_addr, old_value) model.store_logs[-1].append((store_addr, new_value)) model.previous_store = (0, 0, 0, 0)
def map_page(self, uc: Uc, addr: int) -> None: """ Maps a page at addr in the harness, asking probe_wrapper. :param uc: The unicore :param addr: The address """ page_size = self.config.PAGE_SIZE base_address = self.get_base(addr) if base_address not in self._mapped_page_cache.keys(): input_file_name = os.path.join(self.requestdir, "{:016x}".format(addr)) dump_file_name = os.path.join(self.statedir, "{:016x}".format(base_address)) if os.path.isfile(dump_file_name + REJECTED_ENDING): print("CAN I HAZ EXPLOIT?") os.kill(os.getpid(), signal.SIGSEGV) if not os.path.isfile(dump_file_name): open(input_file_name, "a").close() print("mapping {}".format(hex(base_address))) while 1: try: if os.path.isfile(dump_file_name + REJECTED_ENDING): print("CAN I HAZ EXPLOIT?") os.kill(os.getpid(), signal.SIGSEGV) with open(dump_file_name, "rb") as f: content = f.read() if len(content) < page_size: time.sleep(0.001) continue self._mapped_page_cache[base_address] = content uc.mem_map(base_address, len(content)) uc.mem_write(base_address, content) self.set_exits(uc, base_address, self.exits) return except IOError: pass except UcError as ex: return except Exception as ex: # todo this should never happen if we don't map like idiots print( "map_page_blocking failed: base address=0x{:016x} ({})" .format(base_address, ex))
def hook_instr(mu: Uc, address, size, user_data): # BL sha1sum # if address == 0x0369F6: # mu.reg_write(UC_ARM_REG_PC, address + size) # if address == 0x369F8: # d = input() # if d: # dump_hex_buf(mu, 0x200000D8, 128) if address >= 0x3642A and address <= 0x3658A: # input() pass if address >= 0x0369E0 and address <= 0x36A00: print(">>> Tracing instruction at 0x%X, instruction size = 0x%X" % (address, size)) R0 = mu.reg_read(UC_ARM_REG_R0) R1 = mu.reg_read(UC_ARM_REG_R1) R2 = mu.reg_read(UC_ARM_REG_R2) R3 = mu.reg_read(UC_ARM_REG_R3) R4 = mu.reg_read(UC_ARM_REG_R4) PC = mu.reg_read(UC_ARM_REG_PC) print(f"R0: {R0:08X} R1: {R1:08X} R2: {R2:08X} " f"R3: {R3:08X} R4: {R4:08X} PC: {PC:08X}") mem = mu.mem_read(address, size) for i in cs.disasm(mem, address): print(f" 0x{i.address:08X}:\t{i.mnemonic}\t{i.op_str}") # if i.mnemonic == "blx": # print(f"[-] Skipping call to {R1:08X}") # mu.reg_write(UC_ARM_REG_PC, address + size + 1) print() # dump_hex_buf(mu, R0, R1) mu.last_instr = ( f">>> Tracing instruction at 0x{address:08X}, instruction size = 0x{size:X}\n" ) R0 = mu.reg_read(UC_ARM_REG_R0) R1 = mu.reg_read(UC_ARM_REG_R1) R2 = mu.reg_read(UC_ARM_REG_R2) R3 = mu.reg_read(UC_ARM_REG_R3) R4 = mu.reg_read(UC_ARM_REG_R4) PC = mu.reg_read(UC_ARM_REG_PC) mu.last_instr += (f"R0: {R0:08X} R1: {R1:08X} R2: {R2:08X} " f"R3: {R3:08X} R4: {R4:08X} PC: {PC:08X}\n") # branch = False mem = mu.mem_read(address, size) for i in cs.disasm(mem, address): mu.last_instr += f" 0x{i.address:08X}:\t{i.mnemonic}\t{i.op_str}\n"
def hook_bss_access(uc: Uc, access, address, size, value, data): # check rwdata range if bss_section_start <= address < bss_section_end: if stage == 0: # entryBB if access == UC_MEM_READ and size == 4 and struct.unpack( "<I", uc.mem_read(address, size))[0] == 0: decryptStatus.add(address) print("READ: address:0x{0:016x} is decryptStatus".format( address)) elif stage == 1: # decryptBB pass elif stage == 2: # originalBB if access == UC_MEM_WRITE and size == 4 and value == 1: print("WRITE: address:0x{0:016x} is decryptStatus".format( address)) if address in decryptStatus: decryptStatus.remove(address) uc.emu_stop()