Example #1
0
 def __init__(self, exe):
     self.loader = loader.load(exe)
     self.entry = self.loader.entry
     self.arch_name = arch.map(self.loader.arch)
     self.os_name = self.loader.os
     self.arch, self.os = arch.find(self.arch_name, self.os_name)
     if not self.arch:
         raise NotImplementedError('Unsupported arch: %s' % self.arch_name)
     if not self.os:
         raise NotImplementedError('Unsupported OS: %s' % self.os_name)
     self.bsz = self.arch.bits / 8
     self.uc = Unicorn(self.arch)
Example #2
0
 def __init__(self, exe):
     self.loader = loader.load(exe)
     self.entry = self.loader.entry
     self.arch_name = arch.map(self.loader.arch)
     self.arch = arch.find(self.arch_name)
     if not self.arch:
         raise NotImplementedError("Unsupported Unicorn arch: %s" % self.arch)
     self.bsz = self.arch.bits / 8
     self.uc = Unicorn(self.arch)
Example #3
0
File: cls.py Project: eqv/usercorn
 def __init__(self, exe):
     self.loader = loader.load(exe)
     self.entry = self.loader.entry
     self.arch_name = arch.map(self.loader.arch)
     self.os_name = self.loader.os
     self.arch, self.os = arch.find(self.arch_name, self.os_name)
     if not self.arch:
         raise NotImplementedError('Unsupported arch: %s' % self.arch_name)
     if not self.os:
         raise NotImplementedError('Unsupported OS: %s' % self.os_name)
     self.bsz = self.arch.bits / 8
     self.uc = Unicorn(self.arch)
Example #4
0
File: cls.py Project: eqv/usercorn
class UserCorn:
    def __init__(self, exe):
        self.loader = loader.load(exe)
        self.entry = self.loader.entry
        self.arch_name = arch.map(self.loader.arch)
        self.os_name = self.loader.os
        self.arch, self.os = arch.find(self.arch_name, self.os_name)
        if not self.arch:
            raise NotImplementedError('Unsupported arch: %s' % self.arch_name)
        if not self.os:
            raise NotImplementedError('Unsupported OS: %s' % self.os_name)
        self.bsz = self.arch.bits / 8
        self.uc = Unicorn(self.arch)

    def symbolicate(self, addr):
        matches = self.loader.symbolicate(addr)
        if matches:
            # TODO pick the smallest matching symbol?
            # or indicate when you're inside multiple symbols?
            dist = sorted(matches.keys())[0]
            name = matches[dist][0]
            return '%s+0x%02x' % (name, dist)
        return '0x%x' % addr

    def map_segments(self):
        # merge overlapping segments
        segments = [align(addr, size, grow=True) for addr, size, _ in self.loader.segments()]
        merged = []
        for addr, size in segments:
            left = addr
            right = addr + size
            for a2, s2 in merged:
                if (addr >= a2 and addr <= a2 + s2) or (addr < a2 and addr + size > a2):
                    left = min(a2, addr)
                    right = max(right, a2 + s2)
                    merged.remove((a2, s2))
            merged.append((left, right - left))

        for addr, size in merged:
            self.uc.mem_map(addr, size)

        for addr, size, data in self.loader.segments():
            # FIXME: weird, if I don't touch the data before write it segfaults on ARM
            # Issue #15
            binascii.hexlify(data)
            self.uc.mem_write(addr, data)
        # TODO: ask loader for stack size/location
        self.stack = self.uc.mmap(STACK_SIZE, addr_hint=STACK_BASE)
        self.uc.reg_write(self.arch.sp, self.stack + STACK_SIZE - self.bsz)

    def write_argv(self, argv):
        size = sum([len(a) + 1 for a in argv])
        argv_addr = self.uc.mmap(size)
        pos = argv_addr + size
        addrs = []
        for arg in reversed(argv):
            asz = len(arg) + 1
            self.uc.mem_write(pos - asz, arg)
            pos -= asz
            addrs.append(pos)
        for addr in [0] + addrs:
            self.uc.push(addr)
        return argv_addr

    # hooks

    def hook_mem_invalid(self, uc, access, address, size, value, user_data):
        if access == UC_MEM_WRITE:
            print ">>> Memory fault on WRITE at 0x%x, data size = %u, data value = 0x%x" % (address, size, value)
            self.uc.mem_map(address, 2 * 1024 * 1024)
            return True
        else:
            print ">>> Memory fault on READ at 0x%x, data size = %u" % (address, size)
            # stop emulation
            return False

    def hook_block(self, uc, addr, size, user_data):
        name = self.symbolicate(addr)
        print ">>> Basic block at %s, block size = 0x%x <<<" % (name, size)
        self.uc.print_changed_regs()
        self.uc.print_dis(addr, size)

    def hook_code(self, uc, addr, size, user_data):
        if size > 128:
            print 'Makeshift SIGILL'
            sys.exit(1)
        self.uc.print_dis(addr, size)

    def hook_mem_access(self, uc, access, addr, size, value, user_data):
        if access == UC_MEM_WRITE:
            print 'W @0x%x 0x%x = 0x%x' % (addr, size, value)
        else:
            print ('R @0x%x 0x%x =' % (addr, size)), self.uc.mem_hex(addr, size)

    def hook_syscall(self, mu, user_data):
        self.os.syscall(self.uc)

    def hook_intr(self, mu, intno, user_data):
        self.os.interrupt(self.uc, intno)

    def run(self, *argv):
        self.map_segments()
        if self.uc.reg_read(self.arch.sp) == 0:
            print 'Warning: sp == 0.'

        # self.uc.hook_add(UC_HOOK_BLOCK, self.hook_block)
        # self.uc.hook_add(UC_HOOK_CODE, self.hook_code)
        self.uc.hook_add(UC_HOOK_INTR, self.hook_intr)
        self.uc.hook_add(UC_HOOK_MEM_INVALID, self.hook_mem_invalid)
        self.uc.hook_add(UC_HOOK_INSN, self.hook_syscall, None, UC_X86_INS_SYSCALL)
        # self.uc.hook_add(UC_HOOK_MEM_READ_WRITE, self.hook_mem_access)

        # put argv into target memory
        self.uc.push(0) # envp
        argv_addr = self.write_argv(argv)
        self.uc.push(len(argv)) # argc
        argv_size = sum([len(a) + 1 for a in argv]) + self.bsz * (len(argv) + 1)
        print '[argv @0x%x]' % (argv_addr), self.uc.mem_hex(argv_addr, argv_size)

        print '[entry point @0x%x]' % (self.entry)
        self.uc.print_dis(self.entry, 64)
        stack_size = self.stack + STACK_SIZE - self.uc.reg_read(self.arch.sp)
        sp = self.uc.reg_read(self.arch.sp)
        print ('[initial stack @0x%x]' % sp), self.uc.mem_hex(sp, stack_size)

        print '====================================='
        print '==== Program output begins here. ===='
        print '====================================='
        self.uc.emu_start(self.entry, 0)
Example #5
0
class UserCorn:
    def __init__(self, exe):
        self.loader = loader.load(exe)
        self.entry = self.loader.entry
        self.arch_name = arch.map(self.loader.arch)
        self.arch = arch.find(self.arch_name)
        if not self.arch:
            raise NotImplementedError("Unsupported Unicorn arch: %s" % self.arch)
        self.bsz = self.arch.bits / 8
        self.uc = Unicorn(self.arch)

    def symbolicate(self, addr):
        matches = self.loader.symbolicate(addr)
        if matches:
            # TODO pick the smallest matching symbol?
            # or indicate when you're inside multiple symbols?
            dist = sorted(matches.keys())[0]
            sym = matches[dist][0]
            return "%s+0x%02x" % (sym.name, dist)
        return "0x%x" % addr

    def map_segments(self):
        for addr, size, data in self.loader.segments():
            self.uc.mem_map(addr, size)
            self.uc.mem_write(addr, data)
        # TODO: ask loader for stack size/location
        self.stack = self.uc.mmap(STACK_SIZE, STACK_BASE)
        self.uc.reg_write(self.arch.sp, self.stack + STACK_SIZE - self.bsz)

    def write_argv(self, argv):
        size = sum([len(a) + 1 for a in argv])
        argv_addr = self.uc.mmap(size)
        pos = argv_addr + size
        addrs = []
        for arg in reversed(argv):
            asz = len(arg) + 1
            self.uc.mem_write(pos - asz, arg)
            pos -= asz
            addrs.append(pos)
        for addr in [0] + addrs:
            self.uc.push(addr)
        return argv_addr

    # hooks

    def hook_mem_invalid(self, uc, access, address, size, value, user_data):
        if access == UC_MEM_WRITE:
            print (">>> Memory fault on WRITE at 0x%x, data size = %u, data value = 0x%x" % (address, size, value))
            self.uc.mem_map(address, 2 * 1024 * 1024)
            return True
        else:
            # stop emulation
            return False

    def hook_block(self, uc, address, size, user_data):
        name = self.symbolicate(address)
        print (">>> Basic block at %s, block size = 0x%x <<<" % (name, size))
        self.uc.print_changed_regs()

    def hook_code(self, uc, addr, size, user_data):
        if size > 128:
            print "Makeshift SIGILL"
            sys.exit(1)
        print ">",
        self.uc.print_dis(addr, size)

    def hook_mem_access(self, uc, access, addr, size, value, user_data):
        if access == UC_MEM_WRITE:
            print "W @0x%x 0x%x = 0x%x" % (addr, size, value)
        else:
            print ("R @0x%x 0x%x =" % (addr, size)), self.uc.mem_hex(addr, size)

    def hook_syscall(self, mu, user_data):
        self.arch.syscall(self.uc)

    def hook_intr(self, mu, intno, user_data):
        self.arch.interrupt(self.uc, intno)

    def run(self, *argv):
        self.map_segments()
        # self.uc.hook_add(UC_HOOK_BLOCK, self.hook_block)
        # self.uc.hook_add(UC_HOOK_CODE, self.hook_code)
        self.uc.hook_add(UC_HOOK_INTR, self.hook_intr)
        self.uc.hook_add(UC_HOOK_MEM_INVALID, self.hook_mem_invalid)
        self.uc.hook_add(UC_HOOK_INSN, self.hook_syscall, None, X86_INS_SYSCALL)
        # self.uc.hook_add(UC_HOOK_MEM_READ_WRITE, self.hook_mem_access)

        # put argv into target memory
        self.uc.push(0)  # envp
        argv_addr = self.write_argv(argv)
        self.uc.push(len(argv))  # argc
        argv_size = sum([len(a) + 1 for a in argv]) + self.bsz * (len(argv) + 1)
        print "[argv]", self.uc.mem_hex(argv_addr, argv_size)

        print "[entry point]"
        self.uc.print_dis(self.entry, 64)
        print "[initial stack]", self.uc.mem_hex(self.uc.reg_read(self.arch.sp), 64)

        print "====================================="
        print "==== Program output begins here. ===="
        print "====================================="
        self.uc.emu_start(self.entry, 0)
Example #6
0
class UserCorn:
    def __init__(self, exe):
        self.loader = loader.load(exe)
        self.entry = self.loader.entry
        self.arch_name = arch.map(self.loader.arch)
        self.os_name = self.loader.os
        self.arch, self.os = arch.find(self.arch_name, self.os_name)
        if not self.arch:
            raise NotImplementedError('Unsupported arch: %s' % self.arch_name)
        if not self.os:
            raise NotImplementedError('Unsupported OS: %s' % self.os_name)
        self.bsz = self.arch.bits / 8
        self.uc = Unicorn(self.arch)

    def symbolicate(self, addr):
        matches = self.loader.symbolicate(addr)
        if matches:
            # TODO pick the smallest matching symbol?
            # or indicate when you're inside multiple symbols?
            dist = sorted(matches.keys())[0]
            name = matches[dist][0]
            return '%s+0x%02x' % (name, dist)
        return '0x%x' % addr

    def map_segments(self):
        for addr, size, data in self.loader.segments():
            self.uc.mem_map(addr, size)
            # FIXME: weird, if I don't touch the data before write it segfaults on ARM
            # Issue #15
            binascii.hexlify(data)
            self.uc.mem_write(addr, data)
        # TODO: ask loader for stack size/location
        self.stack = self.uc.mmap(STACK_SIZE, addr_hint=STACK_BASE)
        self.uc.reg_write(self.arch.sp, self.stack + STACK_SIZE - self.bsz)

    def write_argv(self, argv):
        size = sum([len(a) + 1 for a in argv])
        argv_addr = self.uc.mmap(size)
        pos = argv_addr + size
        addrs = []
        for arg in reversed(argv):
            asz = len(arg) + 1
            self.uc.mem_write(pos - asz, arg)
            pos -= asz
            addrs.append(pos)
        for addr in [0] + addrs:
            self.uc.push(addr)
        return argv_addr

    # hooks

    def hook_mem_invalid(self, uc, access, address, size, value, user_data):
        if access == UC_MEM_WRITE:
            print(
                ">>> Memory fault on WRITE at 0x%x, data size = %u, data value = 0x%x"
                % (address, size, value))
            self.uc.mem_map(address, 2 * 1024 * 1024)
            return True
        else:
            # stop emulation
            return False

    def hook_block(self, uc, address, size, user_data):
        name = self.symbolicate(address)
        print(">>> Basic block at %s, block size = 0x%x <<<" % (name, size))
        self.uc.print_changed_regs()

    def hook_code(self, uc, addr, size, user_data):
        if size > 128:
            print 'Makeshift SIGILL'
            sys.exit(1)
        print '>',
        self.uc.print_dis(addr, size)

    def hook_mem_access(self, uc, access, addr, size, value, user_data):
        if access == UC_MEM_WRITE:
            print 'W @0x%x 0x%x = 0x%x' % (addr, size, value)
        else:
            print('R @0x%x 0x%x =' % (addr, size)), self.uc.mem_hex(addr, size)

    def hook_syscall(self, mu, user_data):
        self.os.syscall(self.uc)

    def hook_intr(self, mu, intno, user_data):
        self.os.interrupt(self.uc, intno)

    def run(self, *argv):
        self.map_segments()
        if self.uc.reg_read(self.arch.sp) == 0:
            print 'Warning: sp == 0.'

        # self.uc.hook_add(UC_HOOK_BLOCK, self.hook_block)
        # self.uc.hook_add(UC_HOOK_CODE, self.hook_code)
        self.uc.hook_add(UC_HOOK_INTR, self.hook_intr)
        self.uc.hook_add(UC_HOOK_MEM_INVALID, self.hook_mem_invalid)
        self.uc.hook_add(UC_HOOK_INSN, self.hook_syscall, None,
                         X86_INS_SYSCALL)
        # self.uc.hook_add(UC_HOOK_MEM_READ_WRITE, self.hook_mem_access)

        # put argv into target memory
        self.uc.push(0)  # envp
        argv_addr = self.write_argv(argv)
        self.uc.push(len(argv))  # argc
        argv_size = sum([len(a) + 1
                         for a in argv]) + self.bsz * (len(argv) + 1)
        print '[argv]', self.uc.mem_hex(argv_addr, argv_size)

        print '[entry point]'
        self.uc.print_dis(self.entry, 64)
        print '[initial stack]', self.uc.mem_hex(
            self.uc.reg_read(self.arch.sp), 64)

        print '====================================='
        print '==== Program output begins here. ===='
        print '====================================='
        self.uc.emu_start(self.entry, 0)