-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
scratch.py
171 lines (142 loc) · 6.22 KB
/
scratch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import logging
l = logging.getLogger(name=__name__)
import claripy
from .plugin import SimStatePlugin
class SimStateScratch(SimStatePlugin):
def __init__(self, scratch=None):
SimStatePlugin.__init__(self)
# 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
#
# Java VM related variables
#
self.invoke = None
self.invoke_target = None
self.invoke_return_variable = None
self.invoke_return_target = None
self.invoke_expr = None
self.invoke_has_native_target = None
if scratch is not None:
self.temps.update(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.invoke = scratch.invoke
self.invoke_target = scratch.invoke_target
self.invoke_return_variable = scratch.invoke_return_variable
self.invoke_return_target = scratch.invoke_return_target
self.invoke_expr = scratch.invoke_expr
self.invoke_has_native_target = scratch.invoke_has_native_target
# priveleges
self._priv_stack = [False]
@property
def priv(self):
return self._priv_stack[-1]
def push_priv(self, priv):
self._priv_stack.append(priv)
def pop_priv(self):
self._priv_stack.pop()
if len(self._priv_stack) == 0:
raise SimValueError("Priv stack is empty")
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)
v = self.temps.get(tmp, None)
if v is None:
raise SimValueError('VEX temp variable %d does not exist. This is usually the result of an incorrect '
'slicing.' % tmp
)
self.state._inspect('tmp_read', BP_AFTER, tmp_read_expr=v)
return v
def store_tmp(self, tmp, content, reg_deps=None, tmp_deps=None, action_holder=None):
"""
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)
r = SimActionData(self.state, SimActionData.TMP, SimActionData.WRITE, tmp=tmp, data=data_ao, size=content.length)
if action_holder is None:
self.state.history.add_event(r)
else:
action_holder.append(r)
self.state._inspect('tmp_write', BP_AFTER)
@SimStatePlugin.memo
def copy(self, memo): # pylint: disable=unused-argument
return SimStateScratch(scratch=self)
def merge(self, others, merge_conditions, common_ancestor=None): # pylint: disable=unused-argument
return False
def widen(self, others): # pylint: disable=unused-argument
return False
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
from .sim_action import SimActionObject, SimActionData
from ..errors import SimValueError
from .. import sim_options as o
from .inspect import BP_AFTER, BP_BEFORE
from angr.sim_state import SimState
SimState.register_default('scratch', SimStateScratch)