Beispiel #1
0
    def _perform_vex_expr_RdTmp(self, tmp):
        result = super()._perform_vex_expr_RdTmp(tmp)

        # finish it and save the tmp reference
        if o.TRACK_TMP_ACTIONS in self.state.options:
            r = SimActionData(self.state, SimActionData.TMP, SimActionData.READ, tmp=tmp, size=self.irsb.tyenv.sizeof(tmp), data=result)
            self.state.history.add_action(r)
            a = frozenset((r,))
        else:
            a = self.__tmp_deps.get(tmp, frozenset())
        return result, a
Beispiel #2
0
    def _handleWrTmpLoadWithPossibleForwarding(self, state, successors, stmt):
        # we duplicate the processing for WrTmp loads ourselves, because we potentially need to fork during load processing
        # this is basically an inlined version of what goes on in angr for a WrTmp load, patched to handle possible forwarding
        load = stmt.data
        with state.history.subscribe_actions() as data_deps:
            state._inspect('expr', BP_BEFORE, expr=load)
            load_size_bits = pyvex.const.get_type_size(load.type)
            load_size_bytes = load_size_bits // state.arch.byte_width
            with state.history.subscribe_actions() as addr_actions:
                addr = self.handle_expression(state, load.addr)
            if angr.options.UNINITIALIZED_ACCESS_AWARENESS in state.options:
                if getattr(addr._model_vsa, 'uninitialized', False):
                    raise SimUninitializedAccessError('addr', addr)
            if angr.options.DO_LOADS not in state.options:
                results = (state, state.solver.Unconstrained("load_expr_%#x_%d" % (state.scratch.ins_addr, state.scratch.stmt_idx), load_size_bits))
            else:
                results = performLoadWithPossibleForwarding(state, addr, load_size_bytes, load_endness=load.endness)

            for (l_state, l_value) in results:
                if load.type.startswith('Ity_F'):
                    l_value = l_value.raw_to_fp()
                if angr.options.TRACK_MEMORY_ACTIONS in l_state.options:
                    addr_ao = SimActionObject(addr, deps=addr_actions, state=l_state)
                    r = SimActionData(l_state, l_state.memory.id, SimActionData.READ, addr=addr_ao, size=load_size_bits, data=l_value)
                    l_state.history.add_action(r)
                if angr.options.SIMPLIFY_EXPRS in l_state.options:
                    l_value = state.solver.simplify(l_value)
                if l_state.solver.symbolic(l_value) and angr.options.CONCRETIZE in l_state.options:
                    concrete_value = l_state.solver.BVV(l_state.solver.eval(l_value), len(l_value))
                    l_state.add_constraints(l_value == concrete_value)
                    l_value = concrete_value
                l_state._inspect('expr', BP_AFTER, expr=load, expr_result=l_value)
                l_state.scratch.store_tmp(stmt.tmp, l_value, deps=data_deps)

                # now we tell angr about the fork, so it continues executing the state
                if l_state is not state:
                    # For these "new states" (which angr currently doesn't know about), we
                    #   also have to finish the current instruction for the state: we will be
                    #   "branching" to the next instruction, and don't want to skip the rest
                    #   of the VEX statements in this instruction
                    # we do this by executing the entire current irsb (basic block), but with
                    #   arguments to _handle_irsb such that only a few statements (those
                    #   between where we are and where the next instruction starts) are executed
                    (next_instr_addr, next_instr_stmt_idx) = nextInstruction(state.scratch.irsb, stmt)
                    self._handle_irsb(l_state, successors, l_state.scratch.irsb, state.scratch.stmt_idx+1, next_instr_stmt_idx-1 if next_instr_stmt_idx is not None else None, None)

                    # finally, we tell angr about the new state, so it will continue executing it
                    # (and we tell it to start executing at whatever the next instruction is)
                    l.debug("time {}: forking for misforwarding on a load of addr {}".format(state.spec.ins_executed, addr))
                    target = next_instr_addr if next_instr_addr is not None else self.handle_expression(l_state, l_state.scratch.irsb.next)  # if next_instr_addr is None, then target the first instruction of the next irsb
                    jumpkind = 'Ijk_Boring'  # seems like a reasonable choice? what is this used for?
                    guard = claripy.BVV(1, 1)  # boolean True
                    successors.add_successor(l_state, target, guard, jumpkind, add_guard=False, exit_stmt_idx=None, exit_ins_addr=None)
Beispiel #3
0
    def _perform_vex_stmt_Put(self, offset_bundle, data_bundle, **kwargs):
        offset, offset_deps = offset_bundle
        data, data_deps = data_bundle
        # track the put
        if o.TRACK_REGISTER_ACTIONS in self.state.options:
            data_ao = SimActionObject(data, deps=data_deps, state=self.state)
            size_ao = SimActionObject(len(data))
            a = SimActionData(self.state, SimActionData.REG, SimActionData.WRITE, addr=offset, data=data_ao, size=size_ao)
            self.state.history.add_action(a)
        else:
            a = None

        super()._perform_vex_stmt_Put(offset, data, action=a, **kwargs)
Beispiel #4
0
    def _perform_vex_expr_Get(self, offset_bundle, ty, **kwargs):
        offset, offset_deps = offset_bundle
        result = super()._perform_vex_expr_Get(offset, ty, **kwargs)

        if o.TRACK_REGISTER_ACTIONS in self.state.options:
            offset_ao = SimActionObject(offset, deps=offset_deps, state=self.state)
            r = SimActionData(self.state, self.state.registers.id, SimActionData.READ, addr=offset_ao,
                              size=pyvex.get_type_size(ty), data=result
                              )
            self.state.history.add_action(r)
            a = frozenset((r,))
        else:
            a = frozenset()
        return result, a
Beispiel #5
0
    def _handleLoadGWithPossibleForwarding(self, state, successors, stmt):
        # Like for WrTmpLoads, we also duplicate the processing for LoadG's ourselves, because we potentially need to fork during load processing
        # this is again basically an inlined version of what goes on in angr for a LoadG, patched to handle possible forwarding
        with state.history.subscribe_actions() as addr_deps:
            addr = self.handle_expression(state, stmt.addr)
        with state.history.subscribe_actions() as alt_deps:
            alt = self.handle_expression(state, stmt.alt)
        with state.history.subscribe_actions() as guard_deps:
            guard = self.handle_expression(state, stmt.guard)
        if guard is not None and state.solver.satisfiable(extra_constraints=[claripy.Not(guard)]):
            raise ValueError("not implemented yet: conditional load with condition that could be false")

        read_type, converted_type = stmt.cvt_types
        read_size_bits = pyvex.const.get_type_size(read_type)
        converted_size_bits = pyvex.const.get_type_size(converted_type)
        read_size = read_size_bits // state.arch.byte_width

        results = performLoadWithPossibleForwarding(state, addr, read_size, load_endness=stmt.end)

        for (l_state, l_value) in results:
            if read_size_bits == converted_size_bits:
                converted_expr = l_value
            elif "S" in stmt.cvt:
                converted_expr = l_value.sign_extend(converted_size_bits - read_size_bits)
            elif "U" in stmt.cvt:
                converted_expr = l_value.zero_extend()
            else:
                raise SimStatementError("Unrecognized IRLoadGOp %s!" % stmt.cvt)
            l_value = l_state.solver.If(guard != 0, converted_expr, alt)
            l_state.scratch.store_tmp(stmt.dst, l_value, deps=addr_deps + alt_deps + guard_deps)
            if angr.options.TRACK_MEMORY_ACTIONS in l_state.options:
                data_ao = SimActionObject(converted_expr)
                alt_ao = SimActionObject(alt, deps=alt_deps, state=l_state)
                addr_ao = SimActionObject(addr, deps=addr_deps, state=l_state)
                guard_ao = SimActionObject(guard, deps=guard_deps, state=l_state)
                size_ao = SimActionObject(converted_size_bits)
                r = SimActionData(l_state, l_state.memory.id, SimActionData.READ, addr=addr_ao, data=data_ao, condition=guard_ao, size=size_ao, fallback=alt_ao)
                l_state.history.add_action(r)

            # for comments on the below, see comments in our handling of WrTmp loads above
            if l_state is not state:
                (next_instr_addr, next_instr_stmt_idx) = nextInstruction(state.scratch.irsb, stmt)
                self._handle_irsb(l_state, successors, l_state.scratch.irsb, state.scratch.stmt_idx+1, next_instr_stmt_idx-1 if next_instr_stmt_idx is not None else None, None)

                l.debug("time {}: forking for misforwarding on a load of addr {}".format(state.spec.ins_executed, addr))
                target = next_instr_addr if next_instr_addr is not None else self.handle_expression(l_state, l_state.scratch.irsb.next)  # if next_instr_addr is None, then target the first instruction of the next irsb
                jumpkind = 'Ijk_Boring'  # seems like a reasonable choice? what is this used for?
                guard = claripy.BVV(1, 1)  # boolean True
                successors.add_successor(l_state, target, guard, jumpkind, add_guard=False, exit_stmt_idx=None, exit_ins_addr=None)
Beispiel #6
0
    def _perform_vex_expr_Load(self, addr_bundle, ty, end, **kwargs):
        addr, addr_deps = addr_bundle
        result = super()._perform_vex_expr_Load(addr, ty, end, **kwargs)

        if o.TRACK_MEMORY_ACTIONS in self.state.options:
            addr_ao = SimActionObject(addr, deps=addr_deps, state=self.state)
            r = SimActionData(self.state,
                              self.state.memory.id,
                              SimActionData.READ,
                              addr=addr_ao,
                              size=pyvex.get_type_size(ty),
                              data=result)
            self.state.history.add_action(r)
            a = frozenset((r, ))
        else:
            a = frozenset()
        return result, a
Beispiel #7
0
    def _perform_vex_stmt_Store(self, addr_bundle, data_bundle, end, condition=None, **kwargs):
        addr, addr_deps = addr_bundle
        data, data_deps = data_bundle

        if condition is not None:
            condition, condition_deps = condition
        else:
            condition_deps = None

        # track the write
        if o.TRACK_MEMORY_ACTIONS in self.state.options and addr_deps is not None:
            data_ao = SimActionObject(data, deps=data_deps, state=self.state)
            addr_ao = SimActionObject(addr, deps=addr_deps, state=self.state)
            size_ao = SimActionObject(len(data))
            cond_ao = SimActionObject(condition, deps=condition_deps, state=self.state) if condition_deps is not None else None
            a = SimActionData(self.state, SimActionData.MEM, SimActionData.WRITE, data=data_ao, size=size_ao, addr=addr_ao, condition=cond_ao)
            self.state.history.add_action(a)
        else:
            a = None

        super()._perform_vex_stmt_Store(addr, data, end, action=a, condition=condition, **kwargs)