Source code for angr.state_plugins.scratch

import logging

import claripy

from .plugin import SimStatePlugin


l = logging.getLogger(name=__name__)


[docs]class SimStateScratch(SimStatePlugin): """ Implements the scratch state plugin. """
[docs] def __init__(self, scratch=None): super().__init__() # info on the current run self.irsb = None self.bbl_addr = None self.stmt_idx = None self.last_ins_addr = None self.ins_addr = None self.sim_procedure = None self.bbl_addr_list = None self.stack_pointer_list = None self.executed_pages_set = None # information on exits *from* this state self.jumpkind = None self.guard = claripy.true self.target = None self.source = None self.exit_stmt_idx = None self.exit_ins_addr = None self.executed_block_count = 0 # the number of blocks that was executed here self.executed_syscall_count = 0 # the number of system calls that was executed here self.executed_instruction_count = -1 # the number of instructions that was executed self.avoidable = True # information on VEX temps of this IRSB self.temps = [] self.tyenv = None # dirtied addresses, for dealing with self-modifying code self.dirty_addrs = set() self.num_insns = 0 # pcode IR-relative jumps self.statement_offset = 0 if scratch is not None: self.temps = list(scratch.temps) self.tyenv = scratch.tyenv self.jumpkind = scratch.jumpkind self.guard = scratch.guard self.target = scratch.target self.source = scratch.source self.exit_stmt_idx = scratch.exit_stmt_idx self.exit_ins_addr = scratch.exit_ins_addr self.executed_block_count = scratch.executed_block_count self.executed_syscall_count = scratch.executed_syscall_count self.executed_instruction_count = scratch.executed_instruction_count self.executed_pages_set = scratch.executed_pages_set self.irsb = scratch.irsb self.bbl_addr = scratch.bbl_addr self.stmt_idx = scratch.stmt_idx self.last_ins_addr = scratch.last_ins_addr self.ins_addr = scratch.ins_addr self.sim_procedure = scratch.sim_procedure self.bbl_addr_list = scratch.bbl_addr_list self.stack_pointer_list = scratch.stack_pointer_list self.statement_offset = scratch.statement_offset # priveleges self._priv_stack = [False]
@property def priv(self): return self._priv_stack[-1]
[docs] def push_priv(self, priv): self._priv_stack.append(priv)
[docs] def pop_priv(self): self._priv_stack.pop() if len(self._priv_stack) == 0: raise SimValueError("Priv stack is empty")
[docs] def set_tyenv(self, tyenv): self.tyenv = tyenv self.temps = [None] * len(tyenv.types)
[docs] def tmp_expr(self, tmp): """ Returns the Claripy expression of a VEX temp value. :param tmp: the number of the tmp :param simplify: simplify the tmp before returning it :returns: a Claripy expression of the tmp """ self.state._inspect("tmp_read", BP_BEFORE, tmp_read_num=tmp) try: v = self.temps[tmp] if v is None: raise SimMissingTempError( "VEX temp variable %d does not exist. This is usually the result of an incorrect slicing." % tmp ) except IndexError: raise SimMissingTempError("Accessing a temp that is illegal in this tyenv") self.state._inspect("tmp_read", BP_AFTER, tmp_read_expr=v) return v
# pylint:disable=unused-argument
[docs] def store_tmp(self, tmp, content, reg_deps=None, tmp_deps=None, deps=None, **kwargs): """ Stores a Claripy expression in a VEX temp value. If in symbolic mode, this involves adding a constraint for the tmp's symbolic variable. :param tmp: the number of the tmp :param content: a Claripy expression of the content :param reg_deps: the register dependencies of the content :param tmp_deps: the temporary value dependencies of the content """ self.state._inspect("tmp_write", BP_BEFORE, tmp_write_num=tmp, tmp_write_expr=content) tmp = self.state._inspect_getattr("tmp_write_num", tmp) content = self.state._inspect_getattr("tmp_write_expr", content) if o.SYMBOLIC_TEMPS not in self.state.options: # Non-symbolic self.temps[tmp] = content else: # Symbolic self.state.add_constraints(self.temps[tmp] == content) # get the size, and record the write if o.TRACK_TMP_ACTIONS in self.state.options: data_ao = SimActionObject(content, reg_deps=reg_deps, tmp_deps=tmp_deps, deps=deps, state=self.state) r = SimActionData( self.state, SimActionData.TMP, SimActionData.WRITE, tmp=tmp, data=data_ao, size=content.length ) self.state.history.add_action(r) self.state._inspect("tmp_write", BP_AFTER)
@SimStatePlugin.memo def copy(self, memo): # pylint: disable=unused-argument return SimStateScratch(scratch=self)
[docs] def merge(self, others, merge_conditions, common_ancestor=None): # pylint: disable=unused-argument return False
[docs] def widen(self, others): # pylint: disable=unused-argument return False
[docs] def clear(self): s = self.state j = self.jumpkind self.__init__() self.state = s self.jumpkind = j # preserve jumpkind - "what is the previous jumpkind" is an important question sometimes
# pylint:disable=wrong-import-position from .sim_action import SimActionObject, SimActionData from ..errors import SimValueError, SimMissingTempError from .. import sim_options as o from .inspect import BP_AFTER, BP_BEFORE from ..sim_state import SimState SimState.register_default("scratch", SimStateScratch)