Ejemplo n.º 1
0
    def prune_snapshots(self):
        '''Prune available snapshots according to the pruning politics'''

        self.logger.info("Parsing and prunning snapshots: strategy %s, " \
                         "with %d elements keeped each time",
                         config.prune_strategy,
                         config.prune_keep)
        trace = Trace()
        ignored = None

        # Prune depending on the strategy
        if config.prune_strategy == "branch":
            ignored = 0
            already_keeped = {} # path -> seen number
            for snapshot in self.trace_iter:
                # TODO use abi
                if self.avoid_null and snapshot.output_reg["RAX"] == 0:
                    ignored += 1
                    continue

                path = frozenset(snapshot.paths.edges())
                current = already_keeped.get(path, 0)
                if current < config.prune_keep:
                    # not enough sample of this current snapshot branch coverage
                    trace.append(snapshot)
                else:
                    ignored += 1
                already_keeped[path] = current + 1
                if config.prune_keep_max and len(trace) >= config.prune_keep_max:
                    self.logger.info("Max number of snapshot reached!")
                    break

        elif config.prune_strategy == "keepall":
            # Do not remove any snapshot
            trace = list(self.trace_iter)
            ignored = 0
        elif config.prune_strategy == "keep":
            # Remove all snapshot but one or a few (according to config)
            for i, snapshot in xrange(self.trace):
                trace.append(snapshot)
                if len(trace) >= config.prune_keep:
                    break
        else:
            raise ValueError("Unsupported strategy type: %s" % config.prune_strategy)

        self.trace = trace
        if ignored is None:
            ignored = "unknown"
        self.logger.info("Keeped: %d, Ignored: %s", len(self.trace),
                         ignored)

        # If the trace is empty, test can not be created
        if not self.trace:
            raise RuntimeError(
                "Test can not be created: function seems not to be called or " \
                "the prune politic is too restrictive")
Ejemplo n.º 2
0
    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)

        for addr, info in jitter.vm.get_all_memory().iteritems():
            self.segments += [(addr, addr + info['size'])]

        jitter.continue_run()
        assert jitter.run == False
        return self.trace
Ejemplo n.º 3
0
Archivo: learn.py Proyecto: ufwt/Sibyl
    def prune_snapshots(self):
        '''Prune available snapshots according to the pruning politics'''

        self.logger.info("Parsing and prunning snapshots: strategy %s, " \
                         "with %d elements keeped each time",
                         config.prune_strategy,
                         config.prune_keep)
        trace = Trace()
        ignored = None

        # Prune depending on the strategy
        if config.prune_strategy == "branch":
            ignored = 0
            already_keeped = {}  # path -> seen number
            for snapshot in self.trace_iter:
                # TODO use abi
                if self.avoid_null and snapshot.output_reg["RAX"] == 0:
                    ignored += 1
                    continue

                path = frozenset(snapshot.paths.edges())
                current = already_keeped.get(path, 0)
                if current < config.prune_keep:
                    # not enough sample of this current snapshot branch coverage
                    trace.append(snapshot)
                else:
                    ignored += 1
                already_keeped[path] = current + 1
                if config.prune_keep_max and len(
                        trace) >= config.prune_keep_max:
                    self.logger.info("Max number of snapshot reached!")
                    break

        elif config.prune_strategy == "keepall":
            # Do not remove any snapshot
            trace = list(self.trace_iter)
            ignored = 0
        elif config.prune_strategy == "keep":
            # Remove all snapshot but one or a few (according to config)
            for i, snapshot in xrange(self.trace):
                trace.append(snapshot)
                if len(trace) >= config.prune_keep:
                    break
        else:
            raise ValueError("Unsupported strategy type: %s" %
                             config.prune_strategy)

        self.trace = trace
        if ignored is None:
            ignored = "unknown"
        self.logger.info("Keeped: %d, Ignored: %s", len(self.trace), ignored)

        # If the trace is empty, test can not be created
        if not self.trace:
            raise RuntimeError(
                "Test can not be created: function seems not to be called or " \
                "the prune politic is too restrictive")
Ejemplo n.º 4
0
Archivo: pin.py Proyecto: cea-sec/Sibyl
    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])
Ejemplo n.º 5
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
Ejemplo n.º 6
0
Archivo: pin.py Proyecto: unixsec/Sibyl
    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])