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
|
from angr_targets.memory_map import MemoryMap
from miasm.core.locationdb import LocationDB
from miasm.expression.expression import Expr, ExprOp, ExprId, ExprLoc, \
ExprInt, ExprMem, ExprCompose, \
ExprSlice, ExprCond
from miasm.expression.simplifications import expr_simp_explicit
class MiasmProgramState:
def __init__(self,
regs: dict[ExprId, ExprInt],
mem: list[tuple[MemoryMap, bytes]]
):
self.regs = regs
self.memory = mem
def _find_mem_map(self, addr: int) \
-> tuple[MemoryMap, bytes] | tuple[None, None]:
for m, data in self.memory:
if addr >= m.start_address and addr < m.end_address:
return m, data
return None, None
def read_memory(self, addr: int, size: int) -> bytes:
res = bytes()
while size > 0:
m, data = self._find_mem_map(addr)
if m is None:
raise AttributeError(f'No memory mapping contains the address {addr}.')
assert(m is not None and data is not None)
read_off = addr - m.start_address
read_size = min(size, m.end_address - addr)
assert(read_off + read_size <= len(data))
res += data[read_off:read_off+read_size]
size -= read_size
addr += read_size
return res
def eval_expr(expr: Expr, conc_state: MiasmProgramState, loc_db) -> int:
# Most of these implementation are just copy-pasted members of
# `SymbolicExecutionEngine`.
expr_to_visitor = {
ExprInt: _eval_exprint,
ExprId: _eval_exprid,
ExprLoc: _eval_exprloc,
ExprMem: _eval_exprmem,
ExprSlice: _eval_exprslice,
ExprCond: _eval_exprcond,
ExprOp: _eval_exprop,
ExprCompose: _eval_exprcompose,
}
visitor = expr_to_visitor.get(expr.__class__, None)
if visitor is None:
raise TypeError("Unknown expr type")
ret = visitor(expr, conc_state, loc_db)
ret = expr_simp_explicit(ret)
assert(ret is not None)
return ret
def _eval_exprint(expr: ExprInt, _, __: LocationDB):
"""Evaluate an ExprInt using the current state"""
return expr
def _eval_exprid(expr: ExprId, state: MiasmProgramState, _):
"""Evaluate an ExprId using the current state"""
return state.regs[expr]
def _eval_exprloc(expr: ExprLoc, _, loc_db: LocationDB):
"""Evaluate an ExprLoc using the current state"""
offset = loc_db.get_location_offset(expr.loc_key)
if offset is not None:
return ExprInt(offset, expr.size)
return expr
def _eval_exprmem(expr: ExprMem, state: MiasmProgramState, loc_db: LocationDB):
"""Evaluate an ExprMem using the current state.
This function first evaluates the memory pointer value.
"""
# TODO: Implement cases with more than 64 bytes.
#
# The symbolic memory class used in SymbolicExecutionEngine may return
# ExprCompose objects here. Maybe I should use that.
assert(expr.size <= 64)
assert(expr.size % 8 == 0)
addr = eval_expr(expr.ptr, state, loc_db)
ret = state.read_memory(int(addr), int(expr.size / 8))
assert(len(ret) * 8 == expr.size)
return ExprInt(int.from_bytes(ret, byteorder='little'), expr.size)
def _eval_exprcond(expr, state: MiasmProgramState, loc_db: LocationDB):
"""Evaluate an ExprCond using the current state"""
cond = eval_expr(expr.cond, state, loc_db)
src1 = eval_expr(expr.src1, state, loc_db)
src2 = eval_expr(expr.src2, state, loc_db)
return ExprCond(cond, src1, src2)
def _eval_exprslice(expr, state: MiasmProgramState, loc_db: LocationDB):
"""Evaluate an ExprSlice using the current state"""
arg = eval_expr(expr.arg, state, loc_db)
return ExprSlice(arg, expr.start, expr.stop)
def _eval_exprop(expr, state: MiasmProgramState, loc_db: LocationDB):
"""Evaluate an ExprOp using the current state"""
args = []
for oarg in expr.args:
arg = eval_expr(oarg, state, loc_db)
args.append(arg)
return ExprOp(expr.op, *args)
def _eval_exprcompose(expr, state: MiasmProgramState, loc_db: LocationDB):
"""Evaluate an ExprCompose using the current state"""
args = []
for arg in expr.args:
args.append(eval_expr(arg, state, loc_db))
return ExprCompose(*args)
|