Пример #1
0
    def begin_func(self, jitter):
        '''
        Function called by miasm at the begin of every execution of the traced function
        '''
        self.old_ret_addr = jitter.pop_uint64_t()
        jitter.push_uint64_t(0x1337beef)

        self.isTracing = True

        self.current_snapshot = Snapshot(self.abicls, self.machine)

        # Add the breakpoint to watch every memory read and write
        jitter.jit.symbexec.add_read_call(self.read_callback)
        jitter.jit.symbexec.add_write_call(self.write_callback)

        # Called before the execution of each basic bloc
        jitter.exec_cb = self.exec_callback

        for reg_name in self.reg_list:
            self.current_snapshot.add_input_register(
                reg_name, getattr(jitter.cpu, reg_name))

        return True
Пример #2
0
    def begin_func(self, jitter):
        '''
        Function called by miasm at the begin of every execution of the traced function
        '''
        self.old_ret_addr = jitter.pop_uint64_t()
        jitter.push_uint64_t(0x1337beef)

        self.isTracing = True

        self.current_snapshot = Snapshot(self.abicls, self.machine)

        # Add the breakpoint to watch every memory read and write
        jitter.jit.symbexec.add_read_call(self.read_callback)
        jitter.jit.symbexec.add_write_call(self.write_callback)

        # Called before the execution of each basic bloc
        jitter.exec_cb = self.exec_callback

        for reg_name in self.reg_list:
            self.current_snapshot.add_input_register(
                reg_name, getattr(jitter.cpu, reg_name))

        return True
Пример #3
0
    def __parse_pin_output_file(self, traceFile):
        '''Parse the file created by the pintool in order to construct the trace'''

        trace = Trace()

        # Statefull elements
        started = False
        current_image_name = None

        # State machine for parsing
        for line in traceFile:
            infos = line.strip().split(' ')
            entry_type = infos[0]


            # Image loaded in memory
            # IMG <img_name>
            if entry_type == "IMG":
                img_name = infos[1]
                current_image_name = img_name
                continue

            # Symbol entry
            # S <symbol_addr> <symbol_name>
            elif entry_type == 'S':
                assert current_image_name is not None
                symbol_name = infos[2]
                symbol_addr = int(infos[1], 16)
                trace.add_symbol(current_image_name, symbol_name, symbol_addr)
                continue

            values = [int(v, 16) for v in infos[1:]]

            # Start of the learned function
            # Fields are registers value
            if entry_type == 'I':
                if not started:
                    started = True
                    current_snapshot = Snapshot(self.abicls, self.machine)

                for i, reg_name in enumerate(self.reg_list):
                    current_snapshot.add_input_register(reg_name, values[i])

            # Executed instructions address
            elif entry_type == '@':
                if started:
                    current_snapshot.add_executed_instruction(values[0])

            # Memory read access
            # Fields are read address, read size and read value
            elif entry_type == 'R':
                if started:
                    current_snapshot.add_memory_read(
                        values[0], values[1], values[2])

            # Memory write access
            # Fields are writen address, writen size and writen value
            elif entry_type == 'W':
                if started:
                    current_snapshot.add_memory_write(
                        values[0], values[1], values[2])

            # End of the learned function
            # Field are register value
            elif entry_type == 'O':
                if started:
                    for i, reg_name in enumerate(self.reg_list):
                        current_snapshot.add_output_register(
                            reg_name, values[i])

                    # The learned function execution is over
                    # Snapshot can be added to the trace
                    started = False
                    yield current_snapshot

            # Call to a function
            # CALL <caller_addr> <stack pointer>
            elif entry_type == "CALL":
                current_snapshot.add_call(values[0], values[1])

            # Return from a function
            # RET <ret_addr> <stack pointer after> <ret value>
            elif entry_type == "RET":
                current_snapshot.add_ret(values[0], values[1], values[2])
Пример #4
0
    def __parse_pin_output_file(self, traceFile):
        '''Parse the file created by the pintool in order to construct the trace'''

        # Read the begin of file until the first blank line
        # This correspond to the segment enumeration
        segments = []
        for line in traceFile:
            if line == "\n":
                break

            # Each line begins with the bound of the segment,
            # separated by a '-' and followed by a white space
            segments += [
                tuple(
                    [int(addr, 16) for addr in line.split(' ')[0].split('-')])
            ]

        trace = Trace()
        started = False
        for line in traceFile:
            infos = line.strip().split(' ')
            first_char = infos[0]
            values = [int(v, 16) for v in infos[1:]]

            # Start of the learned function
            # Fields are registers value
            if first_char == 'I':
                if not started:
                    started = True
                    current_snapshot = Snapshot(segments, self.abicls,
                                                self.machine)

                for i, reg_name in enumerate(self.reg_list):
                    current_snapshot.add_input_register(reg_name, values[i])

            # Executed instructions address
            elif first_char == '@':
                if started:
                    current_snapshot.add_executed_instruction(values[0])

            # Memory read access
            # Fields are read address, read size and read value
            elif first_char == 'R':
                if started:
                    current_snapshot.add_memory_read(values[0], values[1],
                                                     values[2])

            # Memory write access
            # Fields are writen address, writen size and writen value
            elif first_char == 'W':
                if started:
                    current_snapshot.add_memory_write(values[0], values[1],
                                                      values[2])

            # End of the learned function
            # Field are register value
            elif first_char == 'O':
                if started:
                    for i, reg_name in enumerate(self.reg_list):
                        current_snapshot.add_output_register(
                            reg_name, values[i])

                    # The learned function execution is over
                    # Snapshot can be added to the trace
                    started = False
                    trace.append(current_snapshot)

        return trace
Пример #5
0
class TracerMiasm(Tracer):
    '''Tracer that uses miasm'''
    def __init__(self, *args, **kwargs):
        super(TracerMiasm, self).__init__(*args, **kwargs)

        self.isTracing = False
        self.trace = None

    def read_callback(self, symb_exec, expr_mem):
        '''Read callback that add the read event to the snapshot'''
        addr = int(expr_mem.ptr)
        size = expr_mem.size / 8
        value = int(symb_exec.cpu.get_mem(addr, size)[::-1].encode("hex"), 16)

        self.current_snapshot.add_memory_read(addr, size, value)

    def write_callback(self, symb_exec, dest, data):
        '''Write callback that add the read event to the snapshot'''
        addr = int(dest.ptr)
        size = data.size / 8
        value = int(data.arg.arg)

        self.current_snapshot.add_memory_write(addr, size, value)

    def exec_callback(self, jitter):
        '''Callback called before each bloc execution'''
        self.current_snapshot.add_executed_instruction(jitter.pc)
        return True

    def begin_func(self, jitter):
        '''
        Function called by miasm at the begin of every execution of the traced function
        '''
        self.old_ret_addr = jitter.pop_uint64_t()
        jitter.push_uint64_t(0x1337beef)

        self.isTracing = True

        self.current_snapshot = Snapshot(self.abicls, self.machine)

        # Add the breakpoint to watch every memory read and write
        jitter.jit.symbexec.add_read_call(self.read_callback)
        jitter.jit.symbexec.add_write_call(self.write_callback)

        # Called before the execution of each basic bloc
        jitter.exec_cb = self.exec_callback

        for reg_name in self.reg_list:
            self.current_snapshot.add_input_register(
                reg_name, getattr(jitter.cpu, reg_name))

        return True

    def end_func(self, jitter):
        '''
        Function called by miasm at the end of every execution of the traced function
        '''

        jitter.pc = self.old_ret_addr

        for reg_name in self.reg_list:
            self.current_snapshot.add_output_register(
                reg_name, getattr(jitter.cpu, reg_name))

        jitter.exec_cb = None

        # Remove memory breakpoints
        jitter.jit.symbexec.remove_read_callback(self.read_callback)
        jitter.jit.symbexec.remove_write_callback(self.write_callback)

        self.trace.append(self.current_snapshot)

        self.isTracing = False

        return True

    def end_do_trace(self, jitter):
        '''
        Function called by miasm at the end of the program's execution
        '''
        jitter.run = False
        return False

    def do_trace(self):
        '''Run miasm and construct the trace'''

        self.trace = Trace()

        # Retrieve miasm tools
        machine = Machine(self.machine)
        jitter = machine.jitter("python")

        # Set the jitter to use our custom emulator
        jitter.jit.symbexec = CustomEmulatedSymbExec(jitter.cpu, jitter.vm,
                                                     jitter.jit.ir_arch, {})
        jitter.jit.symbexec.enable_emulated_simplifications()
        jitter.jit.symbexec.reset_regs()

        elf = vm_load_elf(jitter.vm, open(self.program, "rb").read())

        # Init segment
        jitter.ir_arch.do_stk_segm = True
        jitter.ir_arch.do_ds_segm = True
        jitter.ir_arch.do_str_segm = True
        jitter.ir_arch.do_all_segm = True

        FS_0_ADDR = 0x7ff70000
        jitter.cpu.FS = 0x4
        jitter.cpu.set_segm_base(jitter.cpu.FS, FS_0_ADDR)
        jitter.vm.add_memory_page(FS_0_ADDR + 0x28, PAGE_READ,
                                  "\x42\x42\x42\x42\x42\x42\x42\x42")

        # Init stack and push main args
        jitter.init_stack()
        jitter.push_uint64_t(1)
        jitter.vm.add_memory_page(0x800000, PAGE_READ, self.program)
        jitter.push_uint64_t(0x800000)
        jitter.push_uint64_t(0xDEADDEAD)

        jitter.add_breakpoint(0xDEADDEAD, self.end_do_trace)
        jitter.add_breakpoint(0x1337beef, self.end_func)
        jitter.add_breakpoint(self.address, self.begin_func)

        # Run the execution
        if self.main_address is None:
            jitter.init_run(elf.Ehdr.entry)
        else:
            jitter.init_run(self.main_address)

        jitter.continue_run()
        assert jitter.run == False
        return self.trace
Пример #6
0
class TracerMiasm(Tracer):

    '''Tracer that uses miasm'''

    def __init__(self, *args, **kwargs):
        super(TracerMiasm, self).__init__(*args, **kwargs)

        self.isTracing = False
        self.trace = None

    def read_callback(self, symb_exec, expr_mem):
        '''Read callback that add the read event to the snapshot'''
        addr = int(expr_mem.ptr)
        size = expr_mem.size / 8
        value = int(symb_exec.cpu.get_mem(addr, size)[::-1].encode("hex"), 16)

        self.current_snapshot.add_memory_read(addr, size, value)

    def write_callback(self, symb_exec, dest, data):
        '''Write callback that add the read event to the snapshot'''
        addr = int(dest.ptr)
        size = data.size / 8
        value = int(data.arg.arg)

        self.current_snapshot.add_memory_write(addr, size, value)

    def exec_callback(self, jitter):
        '''Callback called before each bloc execution'''
        self.current_snapshot.add_executed_instruction(jitter.pc)
        return True

    def begin_func(self, jitter):
        '''
        Function called by miasm at the begin of every execution of the traced function
        '''
        self.old_ret_addr = jitter.pop_uint64_t()
        jitter.push_uint64_t(0x1337beef)

        self.isTracing = True

        self.current_snapshot = Snapshot(self.abicls, self.machine)

        # Add the breakpoint to watch every memory read and write
        jitter.jit.symbexec.add_read_call(self.read_callback)
        jitter.jit.symbexec.add_write_call(self.write_callback)

        # Called before the execution of each basic bloc
        jitter.exec_cb = self.exec_callback

        for reg_name in self.reg_list:
            self.current_snapshot.add_input_register(
                reg_name, getattr(jitter.cpu, reg_name))

        return True

    def end_func(self, jitter):
        '''
        Function called by miasm at the end of every execution of the traced function
        '''

        jitter.pc = self.old_ret_addr

        for reg_name in self.reg_list:
            self.current_snapshot.add_output_register(
                reg_name, getattr(jitter.cpu, reg_name))

        jitter.exec_cb = None

        # Remove memory breakpoints
        jitter.jit.symbexec.remove_read_callback(self.read_callback)
        jitter.jit.symbexec.remove_write_callback(self.write_callback)

        self.trace.append(self.current_snapshot)

        self.isTracing = False

        return True

    def end_do_trace(self, jitter):
        '''
        Function called by miasm at the end of the program's execution
        '''
        jitter.run = False
        return False

    def do_trace(self):
        '''Run miasm and construct the trace'''

        self.trace = Trace()

        # Retrieve miasm tools
        machine = Machine(self.machine)
        jitter = machine.jitter("python")

        # Set the jitter to use our custom emulator
        jitter.jit.symbexec = CustomEmulatedSymbExec(
            jitter.cpu, jitter.vm, jitter.jit.ir_arch, {})
        jitter.jit.symbexec.enable_emulated_simplifications()
        jitter.jit.symbexec.reset_regs()

        elf = vm_load_elf(jitter.vm, open(self.program, "rb").read())

        # Init segment
        jitter.ir_arch.do_stk_segm = True
        jitter.ir_arch.do_ds_segm = True
        jitter.ir_arch.do_str_segm = True
        jitter.ir_arch.do_all_segm = True

        FS_0_ADDR = 0x7ff70000
        jitter.cpu.FS = 0x4
        jitter.cpu.set_segm_base(jitter.cpu.FS, FS_0_ADDR)
        jitter.vm.add_memory_page(
            FS_0_ADDR + 0x28, PAGE_READ, "\x42\x42\x42\x42\x42\x42\x42\x42")

        # Init stack and push main args
        jitter.init_stack()
        jitter.push_uint64_t(1)
        jitter.vm.add_memory_page(0x800000, PAGE_READ, self.program)
        jitter.push_uint64_t(0x800000)
        jitter.push_uint64_t(0xDEADDEAD)

        jitter.add_breakpoint(0xDEADDEAD, self.end_do_trace)
        jitter.add_breakpoint(0x1337beef, self.end_func)
        jitter.add_breakpoint(self.address, self.begin_func)

        # Run the execution
        if self.main_address is None:
            jitter.init_run(elf.Ehdr.entry)
        else:
            jitter.init_run(self.main_address)

        jitter.continue_run()
        assert jitter.run == False
        return self.trace
Пример #7
0
    def __parse_pin_output_file(self, traceFile):
        '''Parse the file created by the pintool in order to construct the trace'''

        trace = Trace()

        # Statefull elements
        started = False
        current_image_name = None

        # State machine for parsing
        for line in traceFile:
            infos = line.strip().split(' ')
            entry_type = infos[0]

            # Image loaded in memory
            # IMG <img_name>
            if entry_type == "IMG":
                img_name = infos[1]
                current_image_name = img_name
                continue

            # Symbol entry
            # S <symbol_addr> <symbol_name>
            elif entry_type == 'S':
                assert current_image_name is not None
                symbol_name = infos[2]
                symbol_addr = int(infos[1], 16)
                trace.add_symbol(current_image_name, symbol_name, symbol_addr)
                continue

            values = [int(v, 16) for v in infos[1:]]

            # Start of the learned function
            # Fields are registers value
            if entry_type == 'I':
                if not started:
                    started = True
                    current_snapshot = Snapshot(self.abicls, self.machine)

                for i, reg_name in enumerate(self.reg_list):
                    current_snapshot.add_input_register(reg_name, values[i])

            # Executed instructions address
            elif entry_type == '@':
                if started:
                    current_snapshot.add_executed_instruction(values[0])

            # Memory read access
            # Fields are read address, read size and read value
            elif entry_type == 'R':
                if started:
                    current_snapshot.add_memory_read(values[0], values[1],
                                                     values[2])

            # Memory write access
            # Fields are writen address, writen size and writen value
            elif entry_type == 'W':
                if started:
                    current_snapshot.add_memory_write(values[0], values[1],
                                                      values[2])

            # End of the learned function
            # Field are register value
            elif entry_type == 'O':
                if started:
                    for i, reg_name in enumerate(self.reg_list):
                        current_snapshot.add_output_register(
                            reg_name, values[i])

                    # The learned function execution is over
                    # Snapshot can be added to the trace
                    started = False
                    yield current_snapshot

            # Call to a function
            # CALL <caller_addr> <stack pointer>
            elif entry_type == "CALL":
                current_snapshot.add_call(values[0], values[1])

            # Return from a function
            # RET <ret_addr> <stack pointer after> <ret value>
            elif entry_type == "RET":
                current_snapshot.add_ret(values[0], values[1], values[2])