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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
import miasm2.jitter.jitcore as jitcore
import miasm2.expression.expression as m2_expr
import miasm2.jitter.csts as csts
from miasm2.expression.simplifications import expr_simp
from miasm2.ir.symbexec import symbexec
################################################################################
# Util methods for Python jitter #
################################################################################
def update_cpu_from_engine(cpu, exec_engine):
"""Updates @cpu instance according to new CPU values
@cpu: JitCpu instance
@exec_engine: symbexec instance"""
for symbol in exec_engine.symbols:
if isinstance(symbol, m2_expr.ExprId):
if hasattr(cpu, symbol.name):
value = exec_engine.symbols.symbols_id[symbol]
if not isinstance(value, m2_expr.ExprInt):
raise ValueError("A simplification is missing: %s" % value)
setattr(cpu, symbol.name, value.arg.arg)
else:
raise NotImplementedError("Type not handled: %s" % symbol)
def update_engine_from_cpu(cpu, exec_engine):
"""Updates CPU values according to @cpu instance
@cpu: JitCpu instance
@exec_engine: symbexec instance"""
for symbol in exec_engine.symbols:
if isinstance(symbol, m2_expr.ExprId):
if hasattr(cpu, symbol.name):
value = m2_expr.ExprInt_fromsize(symbol.size,
getattr(cpu, symbol.name))
exec_engine.symbols.symbols_id[symbol] = value
else:
raise NotImplementedError("Type not handled: %s" % symbol)
################################################################################
# Python jitter Core #
################################################################################
class JitCore_Python(jitcore.JitCore):
"JiT management, using Miasm2 Symbol Execution engine as backend"
def __init__(self, ir_arch, bs=None):
super(JitCore_Python, self).__init__(ir_arch, bs)
self.symbexec = None
self.ir_arch = ir_arch
def load(self):
"Preload symbols according to current architecture"
symbols_init = {}
for r in self.ir_arch.arch.regs.all_regs_ids_no_alias:
symbols_init[r] = self.ir_arch.arch.regs.regs_init[r]
self.symbexec = symbexec(self.ir_arch, symbols_init,
func_read = self.func_read,
func_write = self.func_write)
def func_read(self, expr_mem):
"""Memory read wrapper for symbolic execution
@expr_mem: ExprMem"""
addr = expr_mem.arg.arg.arg
size = expr_mem.size / 8
value = self.vmmngr.vm_get_mem(addr, size)
return m2_expr.ExprInt_fromsize(expr_mem.size,
int(value[::-1].encode("hex"), 16))
def func_write(self, symb_exec, dest, data, mem_cache):
"""Memory read wrapper for symbolic execution
@symb_exec: symbexec instance
@dest: ExprMem instance
@data: Expr instance
@mem_cache: dict"""
# Get the content to write
data = expr_simp(data)
if not isinstance(data, m2_expr.ExprInt):
raise NotImplementedError("A simplification is missing: %s" % data)
to_write = data.arg.arg
# Format information
addr = dest.arg.arg.arg
size = data.size / 8
content = hex(to_write).replace("0x", "").replace("L", "")
content = "0" * (size * 2 - len(content)) + content
content = content.decode("hex")[::-1]
# Write in VmMngr context
self.vmmngr.vm_set_mem(addr, content)
def jitirblocs(self, label, irblocs):
"""Create a python function corresponding to an irblocs' group.
@label: the label of the irblocs
@irblocs: a gorup of irblocs
"""
def myfunc(cpu, vmmngr):
"""Execute the function according to cpu and vmmngr states
@cpu: JitCpu instance
@vm: VmMngr instance
"""
# Keep current location in irblocs
cur_label = label
loop = True
# Required to detect new instructions
offsets_jitted = set()
# Get exec engine
exec_engine = self.symbexec
# For each irbloc inside irblocs
while loop is True:
# Get the current bloc
loop = False
for irb in irblocs:
if irb.label == cur_label:
loop = True
break
# Irblocs must end with returning an ExprInt instance
assert(loop is not False)
# Refresh CPU values according to @cpu instance
update_engine_from_cpu(cpu, exec_engine)
# Execute current ir bloc
for ir, line in zip(irb.irs, irb.lines):
# For each new instruction (in assembly)
if line.offset not in offsets_jitted:
offsets_jitted.add(line.offset)
# Log registers values
if self.log_regs:
update_cpu_from_engine(cpu, exec_engine)
cpu.vm_dump_gpregs()
# Log instruction
if self.log_mn:
print "%08x %s" % (line.offset, line)
# Check for memory exception
if (vmmngr.vm_get_exception() != 0):
update_cpu_from_engine(cpu, exec_engine)
return line.offset
# Eval current instruction (in IR)
exec_engine.eval_ir(ir)
# Check for memory exception which do not update PC
if (vmmngr.vm_get_exception() & csts.EXCEPT_DO_NOT_UPDATE_PC != 0):
update_cpu_from_engine(cpu, exec_engine)
return line.offset
# Get next bloc address
ad = expr_simp(exec_engine.eval_expr(self.ir_arch.IRDst))
# Updates @cpu instance according to new CPU values
update_cpu_from_engine(cpu, exec_engine)
# Manage resulting address
if isinstance(ad, m2_expr.ExprInt):
return ad.arg.arg
elif isinstance(ad, m2_expr.ExprId):
cur_label = ad.name
else:
raise NotImplementedError("Type not handled: %s" % ad)
# Associate myfunc with current label
self.lbl2jitbloc[label.offset] = myfunc
def jit_call(self, label, cpu, vmmngr):
"""Call the function label with cpu and vmmngr states
@label: function's label
@cpu: JitCpu instance
@vm: VmMngr instance
"""
# Get Python function corresponding to @label
fc_ptr = self.lbl2jitbloc[label]
# Update memory state
self.vmmngr = vmmngr
# Execute the function
return fc_ptr(cpu, vmmngr)
|