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
|
from miasm.core.locationdb import LocationDB, LocKey
from miasm.expression.expression import Expr, ExprOp, ExprId, ExprLoc, \
ExprInt, ExprMem, ExprCompose, \
ExprSlice, ExprCond
from miasm.expression.simplifications import expr_simp_explicit
from snapshot import ProgramState
def simp_segm(expr_simp, expr: ExprOp):
"""Simplify a segmentation expression to an addition of the segment
register's base value and the address argument.
"""
import miasm.arch.x86.regs as regs
base_regs = {
regs.FS: ExprId('fs_base', 64),
regs.GS: ExprId('gs_base', 64),
}
if expr.op == 'segm':
segm, addr = expr.args
assert(segm == regs.FS or segm == regs.GS)
return expr_simp(base_regs[segm] + addr)
return expr
# The expression simplifier used in this module
expr_simp = expr_simp_explicit
expr_simp.enable_passes({ExprOp: [simp_segm]})
class MiasmConcreteState:
miasm_flag_aliases = {
'NF': 'SF',
'I_F': 'IF',
'IOPL_F': 'IOPL',
'I_D': 'ID',
}
def __init__(self, state: ProgramState, loc_db: LocationDB):
self.state = state
self.loc_db = loc_db
def resolve_register(self, regname: str) -> int:
regname = regname.upper()
if regname in self.miasm_flag_aliases:
regname = self.miasm_flag_aliases[regname]
return self.state.read(regname)
def resolve_memory(self, addr: int, size: int) -> bytes:
return self.state.read_memory(addr, size)
def resolve_location(self, loc: LocKey) -> int | None:
return self.loc_db.get_location_offset(loc)
def eval_expr(expr: Expr, conc_state: MiasmConcreteState) -> 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)
ret = expr_simp(ret)
assert(ret is not None)
return ret
def _eval_exprint(expr: ExprInt, _):
"""Evaluate an ExprInt using the current state"""
return expr
def _eval_exprid(expr: ExprId, state: MiasmConcreteState):
"""Evaluate an ExprId using the current state"""
val = state.resolve_register(expr.name)
return ExprInt(val, expr.size)
def _eval_exprloc(expr: ExprLoc, state: MiasmConcreteState):
"""Evaluate an ExprLoc using the current state"""
offset = state.resolve_location(expr.loc_key)
if offset is not None:
return ExprInt(offset, expr.size)
return expr
def _eval_exprmem(expr: ExprMem, state: MiasmConcreteState):
"""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)
ret = state.resolve_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: MiasmConcreteState):
"""Evaluate an ExprCond using the current state"""
cond = eval_expr(expr.cond, state)
src1 = eval_expr(expr.src1, state)
src2 = eval_expr(expr.src2, state)
return ExprCond(cond, src1, src2)
def _eval_exprslice(expr, state: MiasmConcreteState):
"""Evaluate an ExprSlice using the current state"""
arg = eval_expr(expr.arg, state)
return ExprSlice(arg, expr.start, expr.stop)
def _eval_exprop(expr, state: MiasmConcreteState):
"""Evaluate an ExprOp using the current state"""
args = []
for oarg in expr.args:
arg = eval_expr(oarg, state)
args.append(arg)
return ExprOp(expr.op, *args)
def _eval_exprcompose(expr, state: MiasmConcreteState):
"""Evaluate an ExprCompose using the current state"""
args = []
for arg in expr.args:
args.append(eval_expr(arg, state))
return ExprCompose(*args)
|