Example #1
0
    def state_entry(self, **kwargs):
        if isinstance(self.proj.loader.main_bin, BackedCGC):
            kwargs['permissions_backer'] = (
                True, self.proj.loader.main_bin.permissions_map)
        kwargs['add_options'] = {o.CGC_ZERO_FILL_UNCONSTRAINED_MEMORY
                                 } | kwargs.get('add_options', set())

        state = super(SimCGC, self).state_entry(**kwargs)

        if isinstance(self.proj.loader.main_bin, BackedCGC):
            for reg, val in self.proj.loader.main_bin.initial_register_values(
            ):
                if reg in state.arch.registers:
                    setattr(state.regs, reg, val)
                elif reg == 'eflags':
                    pass
                elif reg == 'fctrl':
                    state.regs.fpround = (val & 0xC00) >> 10
                elif reg == 'fstat':
                    state.regs.fc3210 = (val & 0x4700)
                elif reg == 'ftag':
                    empty_bools = [((val >> (x * 2)) & 3) == 3
                                   for x in xrange(8)]
                    tag_chars = [
                        claripy.BVV(0 if x else 1, 8) for x in empty_bools
                    ]
                    for i, tag in enumerate(tag_chars):
                        setattr(state.regs, 'fpu_t%d' % i, tag)
                elif reg in ('fiseg', 'fioff', 'foseg', 'fooff', 'fop'):
                    pass
                elif reg == 'mxcsr':
                    state.regs.sseround = (val & 0x600) >> 9
                else:
                    l.error("What is this register %s I have to translate?",
                            reg)

            # Update allocation base
            state.cgc.allocation_base = self.proj.loader.main_bin.current_allocation_base

            # Do all the writes
            writes_backer = self.proj.loader.main_bin.writes_backer
            stdout = 1
            for size in writes_backer:
                if size == 0:
                    continue
                str_to_write = state.posix.files[1].content.load(
                    state.posix.files[1].pos, size)
                a = SimActionData(state,
                                  'file_1_0',
                                  'write',
                                  addr=claripy.BVV(state.posix.files[1].pos,
                                                   state.arch.bits),
                                  data=str_to_write,
                                  size=size)
                state.posix.write(stdout, str_to_write, size)
                state.log.add_action(a)

        else:
            # Set CGC-specific variables
            state.regs.eax = 0
            state.regs.ebx = 0
            state.regs.ecx = 0x4347c000
            state.regs.edx = 0
            state.regs.edi = 0
            state.regs.esi = 0
            state.regs.esp = 0xbaaaaffc
            state.regs.ebp = 0
            state.regs.cc_dep1 = 0x202  # default eflags
            state.regs.cc_op = 0  # OP_COPY
            state.regs.cc_dep2 = 0  # doesn't matter
            state.regs.cc_ndep = 0  # doesn't matter

            # fpu values
            state.regs.mm0 = 0
            state.regs.mm1 = 0
            state.regs.mm2 = 0
            state.regs.mm3 = 0
            state.regs.mm4 = 0
            state.regs.mm5 = 0
            state.regs.mm6 = 0
            state.regs.mm7 = 0
            state.regs.fpu_tags = 0
            state.regs.fpround = 0
            state.regs.fc3210 = 0x0300
            state.regs.ftop = 0

            # sse values
            state.regs.sseround = 0
            state.regs.xmm0 = 0
            state.regs.xmm1 = 0
            state.regs.xmm2 = 0
            state.regs.xmm3 = 0
            state.regs.xmm4 = 0
            state.regs.xmm5 = 0
            state.regs.xmm6 = 0
            state.regs.xmm7 = 0

            # segmentation registers
            state.regs.ds = 0
            state.regs.es = 0
            state.regs.fs = 0
            state.regs.gs = 0
            state.regs.ss = 0
            state.regs.cs = 0

        return state
Example #2
0
    def _merge_paths(self, base_path, merge_info_list):
        def find_real_ref(ref, ref_list):
            """
            Returns the last element r in ref_list that satisfies r == ref
            """
            for r in reversed(ref_list):
                if r == ref:
                    return r
            return None

        # Perform merging
        all_outputs = []
        # Merge all outputs together into all_outputs
        # The order must be kept since actions should be applied one by one in order
        # Complexity of the current implementation sucks...
        # TODO: Optimize the complexity of the following loop
        for _, _, outputs in merge_info_list:
            for ref in reversed(outputs):
                if ref not in all_outputs:
                    all_outputs.append(ref)

        all_outputs = reversed(all_outputs)
        merged_path = base_path.copy()  # We make a copy first
        # merged_path.actions = [ ]
        merged_path.trim_history()
        merged_path.history._events = ()
        # merged_path.events = [ ]
        merged_state = merged_path.state
        merged_path.info['actionqueue_list'].append(
            self._new_actionqueue(
                (merged_path.addr,
                 self._get_last_actionqueue(merged_path).id)))

        for ref in all_outputs:
            last_ip = None

            all_values = []
            all_guards = []

            for _, merge_info in enumerate(merge_info_list):
                final_path, _, outputs = merge_info

                # First we should build the value
                if ref in outputs:
                    # Find the real ref
                    real_ref = find_real_ref(ref, outputs)

                    # Read the final value
                    if real_ref.type == 'mem':
                        v = real_ref.value

                    elif real_ref.type == 'reg':
                        v = real_ref.value

                    elif real_ref.type.startswith('file'):
                        v = real_ref.value

                    else:
                        raise VeritestingError('FINISH ME')

                    if real_ref.type == 'reg' and real_ref.offset == self.project.arch.ip_offset:
                        # Sanity check!
                        if last_ip is None:
                            last_ip = v
                        else:
                            if merged_state.se.is_true(last_ip != v,
                                                       exact=False):
                                raise VeritestingError(
                                    "We don't want to merge IP - something is seriously wrong"
                                )

                    # Then we build one more layer of our ITETree
                    guards = final_path.info['guards']
                    guard = merged_state.se.And(
                        *guards) if guards else merged_state.se.true

                    all_values.append(v)
                    all_guards.append(guard)

            max_value_size = max([v.size() for v in all_values])

            # Optimization: if all values are of the same size, we can remove one to reduce the number of ITEs
            # FIXME: this optimization doesn't make sense at all.
            #sizes_of_value = set([ v.size() for v in all_values ])
            #if len(sizes_of_value) == 1 and len(all_values) == len(merge_info_list):
            #    all_values = all_values[ 1 : ]
            #    all_guards = all_guards[ 1 : ]

            # Write the output to merged_state

            merged_actions = []
            if real_ref.type == 'mem':
                for actual_addr in real_ref.actual_addrs:
                    # Create the merged_action, and memory.store_cases will fill it up
                    merged_action = SimActionData(merged_state,
                                                  'mem',
                                                  'write',
                                                  addr=merged_state.se.BVV(
                                                      actual_addr,
                                                      self.project.arch.bits),
                                                  size=max_value_size)
                    merged_state.memory.store_cases(actual_addr,
                                                    all_values,
                                                    all_guards,
                                                    endness='Iend_BE',
                                                    action=merged_action)

                    merged_actions.append(merged_action)

            elif real_ref.type == 'reg':
                if real_ref.offset != self.project.arch.ip_offset:
                    # Create the merged_action, and memory.store_cases will fill it up
                    merged_action = SimActionData(merged_state,
                                                  'reg',
                                                  'write',
                                                  addr=real_ref.offset,
                                                  size=max_value_size)
                    merged_state.registers.store_cases(real_ref.offset,
                                                       all_values,
                                                       all_guards,
                                                       endness='Iend_BE',
                                                       action=merged_action)
                else:
                    # Create the merged_action, and memory.store_cases will fill it up
                    merged_action = SimActionData(merged_state,
                                                  'reg',
                                                  'write',
                                                  addr=real_ref.offset,
                                                  size=max_value_size)
                    merged_state.registers.store(real_ref.offset,
                                                 last_ip,
                                                 action=merged_action)
                merged_actions.append(merged_action)

            elif real_ref.type.startswith('file'):
                # No matter it's a read or a write, we should always write it at the desired place
                # However, we don't have to create the SimAction here
                for actual_addr in real_ref.actual_addrs:
                    # FIXME: We assume no new files were opened
                    file_id = real_ref.type[real_ref.type.index('_') + 1:]
                    file_id = merged_state.posix.filename_to_fd(
                        file_id[:file_id.index('_')])
                    merged_action = SimActionData(merged_state,
                                                  real_ref.type,
                                                  real_ref.action,
                                                  addr=actual_addr,
                                                  size=max_value_size)
                    merged_state.posix.files[file_id].content.store_cases(
                        actual_addr,
                        all_values,
                        all_guards,
                        endness='Iend_BE',
                        action=merged_action)

                    merged_actions.append(merged_action)

            else:
                l.error('Unsupported Ref type %s in path merging',
                        real_ref.type)

            if merged_actions:
                for merged_action in merged_actions:
                    merged_path.history._events += (merged_action, )
                    self._get_last_actionqueue(merged_path).actions.append(
                        merged_action)

        # Merge *all* actions
        """
        for i, merge_info in enumerate(merge_info_list):
            final_path, _, _ = merge_info

            guards = final_path.info['guards']
            guard = merged_state.se.And(*guards) if guards else None

            for action in final_path.actions:
                if action.type == 'tmp':
                    continue
                # Encode the constraint into action.condition
                action = action.copy()
                if guard is not None:
                    if action.condition is None:
                        action.condition = action._make_object(guard)
                    else:
                        action.condition.ast = merged_state.se.And(action.condition.ast, guard)
                if 'actions' not in merged_path.info:
                    merged_path.info['actions'] = [ ]

                merged_path.info['actions'].append(action)
        """

        # Fix trace of the merged path
        merged_path.history.addr = -1
        merged_path.history._runstr = 'Veritesting'

        # Add extra constraints from original paths to the merged path
        # It's really important to not lose them. Yan has a lot to say about it.
        all_constraints = []
        for final_path, _, _ in merge_info_list:
            if final_path.info['guards']:
                se = final_path.state.se
                guards = final_path.info['guards']

                # There are also some extra constraints that are encoded in SimActionConstraint objects
                # We don't want to lose them for sure.
                #
                # constraints = [ ]
                #for a in [ b for b in final_path.actions if b.type == 'constraint' ]:
                #    if not final_path.state.se.is_true(a.constraint.ast):
                #        print "CONSTRAINT: ", a.constraint.ast, "CONDITION: ", a.condition
                #        __import__('ipdb').set_trace()
                constraints = [(a.constraint if a.condition is None else
                                se.And(a.constraint, a.condition))
                               for a in final_path.actions
                               if a.type == 'constraint']
                all_constraints.append(se.And(*(guards + constraints)))
        if all_constraints:
            merged_state.add_constraints(merged_state.se.Or(*all_constraints))

        # Fixing the callstack of the merged path
        merged_path.callstack = merge_info_list[0][0].callstack

        # Fix the loop_ctrs
        new_loop_ctrs = defaultdict(int)
        for final_path, _, _ in merge_info_list:
            for loop_head_addr, looping_times in final_path.info[
                    'loop_ctrs'].iteritems():
                if looping_times > new_loop_ctrs[loop_head_addr]:
                    new_loop_ctrs[loop_head_addr] = looping_times
        merged_path.info['loop_ctrs'] = new_loop_ctrs

        #
        # Clean the stage
        #

        if 'guards' in merged_path.info:
            del merged_path.info['guards']

        # Clear the Path._run, otherwise Path.successors will not generate a new run
        merged_path._run = None

        return merged_path
Example #3
0
    def state_entry(self, **kwargs):
        state = super(SimCGC, self).state_entry(**kwargs)

        if isinstance(self.proj.loader.main_bin, BackedCGC):
            for reg, val in self.proj.loader.main_bin.initial_register_values(
            ):
                if reg in state.arch.registers:
                    setattr(state.regs, reg, val)
                elif reg == 'eflags':
                    pass
                elif reg == 'fctrl':
                    state.regs.fpround = (val & 0xC00) >> 10
                elif reg == 'fstat':
                    state.regs.fc3210 = (val & 0x4700)
                elif reg == 'ftag':
                    empty_bools = [((val >> (x * 2)) & 3) == 3
                                   for x in xrange(8)]
                    tag_chars = [
                        state.BVV(0 if x else 1, 8) for x in empty_bools
                    ]
                    for i, tag in enumerate(tag_chars):
                        setattr(state.regs, 'fpu_t%d' % i, tag)
                elif reg in ('fiseg', 'fioff', 'foseg', 'fooff', 'fop'):
                    pass
                elif reg == 'mxcsr':
                    state.regs.sseround = (val & 0x600) >> 9
                else:
                    l.error("What is this register %s I have to translate?",
                            reg)

            # Do all the writes
            writes_backer = self.proj.loader.main_bin.writes_backer
            stdout = 1
            for size in writes_backer:
                if size == 0:
                    continue
                str_to_write = state.posix.files[1].content.load(
                    state.posix.files[1].pos, size)
                a = SimActionData(state,
                                  'file_1_0',
                                  'write',
                                  addr=state.BVV(state.posix.files[1].pos,
                                                 state.arch.bits),
                                  data=str_to_write,
                                  size=size)
                state.posix.write(stdout, str_to_write, size)
                state.log.add_action(a)

        else:
            # Set CGC-specific variables
            state.regs.eax = 0
            state.regs.ebx = 0
            state.regs.ecx = 0
            state.regs.edx = 0
            state.regs.edi = 0
            state.regs.esi = 0
            state.regs.esp = 0xbaaaaffc
            state.regs.ebp = 0
            #state.regs.eflags = s.BVV(0x202, 32)

            # fpu values
            state.regs.mm0 = 0
            state.regs.mm1 = 0
            state.regs.mm2 = 0
            state.regs.mm3 = 0
            state.regs.mm4 = 0
            state.regs.mm5 = 0
            state.regs.mm6 = 0
            state.regs.mm7 = 0
            state.regs.fpu_tags = 0
            state.regs.fpround = 0
            state.regs.fc3210 = 0x0300
            state.regs.ftop = 0

            # sse values
            state.regs.sseround = 0
            state.regs.xmm0 = 0
            state.regs.xmm1 = 0
            state.regs.xmm2 = 0
            state.regs.xmm3 = 0
            state.regs.xmm4 = 0
            state.regs.xmm5 = 0
            state.regs.xmm6 = 0
            state.regs.xmm7 = 0

        return state