Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
 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)))
Exemple #4
0
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)
Exemple #5
0
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)
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
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))
Exemple #10
0
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]")
Exemple #13
0
    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()
Exemple #14
0
 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
Exemple #15
0
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
Exemple #16
0
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}")
Exemple #17
0
    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)
Exemple #18
0
    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)
Exemple #20
0
    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)
Exemple #22
0
    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])
Exemple #23
0
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)
Exemple #25
0
    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)
Exemple #27
0
    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)
Exemple #28
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()