-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecution.py
More file actions
145 lines (105 loc) · 4.15 KB
/
Copy pathexecution.py
File metadata and controls
145 lines (105 loc) · 4.15 KB
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
"""
Module contains functions to symbolically execute REIL instructions
Top Level Interface:
state.step(): symbollically execute a single instruction on the state
state.execute(): symbolically execute basic block on the state
"""
from handlers import *
from reil.definitions import *
class state:
def __init__(self):
"""
Class to represent a single symbolic state of program
Attributes:
#registers = dictionary of Z3 BitVecRef/BitVecVal
#temp_registers = dictionary of Z3 BitVecRef/BitVecVal
#memory = dictionary of Z3 BitVecRef/BitVecVal
#Solver: allows for solving by using z3, might be refactored to elsewhere
"""
self.registers = {}
self.temp_registers = {} #Temporary registers used by REIL
self.memory = {}
self.solver = Solver()
def update_reg(self,reg, expr):
"""
If register reg exists in state, update it, if not, add it
Expr is a Z3 bit vector
Updates state
"""
if reg.name in self.registers:
self.registers[reg.name] = expr
else:
self.registers.update({reg.name:expr})
def update_temp(self,reg, expr):
"""Update temporary register reg to expr """
if reg.name in self.temp_registers:
self.temp_registers[reg.name] = expr
else:
self.temp_registers.update({reg.name:expr})
def update_mem(self,addr, expr):
"""Update memory at addr to expr """
if str(addr.value) in self.memory:
self.memory[str(addr.value)] = expr
else:
self.memory.update({str(addr.value):expr})
def update_state(self,output,expr):
"""Update state variable output refers to"""
if type(output) == RegisterOperand:
self.update_reg(output, expr)
elif type(output) == TemporaryOperand:
self.update_temp(output, expr)
elif type(output) == ImmediateOperand:
self.update_mem(output, expr)
def fetch_reg(self, reg):
"""Returns register if it exists, else returns fresh BitVec"""
if reg.name in self.registers:
return self.registers[reg.name]
else:
return BitVec(reg.name,reg.size)
def fetch_temp(self, reg):
"""Returns temporary register if it exists, else returns fresh BitVec"""
if reg.name in self.temp_registers:
return self.temp_registers[reg.name]
else:
return BitVec(reg.name,reg.size)
def fetch_mem(self, addr):
"""Returns memory cell if it exists, else returns fresh BitVec"""
if addr in self.memory:
return self.memory[str(addr.value)]
else:
return BitVec(str(addr.value), addr.size)
def fetch_op_mem(self, op):
"""
Fetch operand from current state, interpret immediate values as memory accesses
Immediate values are interpreted as memory accesses only in ldm (load from memory)
"""
if type(op) == RegisterOperand:
return self.fetch_reg(op)
elif type(op) == TemporaryOperand:
return self.fetch_temp(op)
elif type(op) == ImmediateOperand:
return self.fetch_mem(op)
return 0
def fetch_op_lit(self, op):
"""
Fetch operand from current state, interpret immediate values as literals
This is called in all handlers but ldm(load from memory)
"""
if type(op) == RegisterOperand:
return self.fetch_reg(op)
elif type(op) == TemporaryOperand:
return self.fetch_temp(op)
elif type(op) == ImmediateOperand:
return BitVecVal(op.value, op.size)
return 0
def step(self, il_ins):
"""Symbolically execute a single REIL instruction """
ins_handler[il_ins.opcode](self, il_ins)
def execute(self, instructions):
"""
Execute a basic block of instructions over the state
Alters the state of the state object (self)
"""
for ins in instructions:
for il_ins in ins.il_instructions:
self.step(il_ins)