angr 9.2.135__py3-none-manylinux2014_x86_64.whl → 9.2.136__py3-none-manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/__init__.py +3 -7
- angr/analyses/analysis.py +4 -0
- angr/analyses/backward_slice.py +1 -2
- angr/analyses/binary_optimizer.py +3 -4
- angr/analyses/bindiff.py +4 -6
- angr/analyses/boyscout.py +1 -3
- angr/analyses/callee_cleanup_finder.py +4 -4
- angr/analyses/calling_convention/calling_convention.py +4 -3
- angr/analyses/calling_convention/fact_collector.py +0 -1
- angr/analyses/cdg.py +1 -2
- angr/analyses/cfg/cfb.py +1 -3
- angr/analyses/cfg/cfg.py +2 -2
- angr/analyses/cfg/cfg_base.py +37 -35
- angr/analyses/cfg/cfg_emulated.py +1 -1
- angr/analyses/cfg/cfg_fast.py +62 -15
- angr/analyses/cfg/cfg_fast_soot.py +1 -1
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +2 -0
- angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +46 -10
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +5 -1
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +50 -14
- angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +24 -5
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +2 -5
- angr/analyses/congruency_check.py +2 -3
- angr/analyses/data_dep/data_dependency_analysis.py +2 -2
- angr/analyses/ddg.py +1 -4
- angr/analyses/decompiler/ail_simplifier.py +3 -4
- angr/analyses/decompiler/clinic.py +42 -7
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +2 -2
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +2 -2
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +1 -1
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
- angr/analyses/decompiler/structuring/phoenix.py +1 -1
- angr/analyses/disassembly.py +5 -5
- angr/analyses/fcp/__init__.py +4 -0
- angr/analyses/fcp/fcp.py +429 -0
- angr/analyses/identifier/identify.py +1 -3
- angr/analyses/loopfinder.py +4 -3
- angr/analyses/patchfinder.py +1 -1
- angr/analyses/propagator/engine_base.py +4 -3
- angr/analyses/propagator/propagator.py +14 -53
- angr/analyses/reassembler.py +1 -2
- angr/analyses/s_propagator.py +1 -3
- angr/analyses/soot_class_hierarchy.py +1 -2
- angr/analyses/stack_pointer_tracker.py +18 -2
- angr/analyses/static_hooker.py +1 -2
- angr/analyses/typehoon/simple_solver.py +2 -2
- angr/analyses/variable_recovery/variable_recovery_fast.py +1 -2
- angr/analyses/veritesting.py +4 -7
- angr/analyses/vfg.py +1 -1
- angr/analyses/vsa_ddg.py +1 -2
- angr/block.py +3 -2
- angr/callable.py +1 -3
- angr/calling_conventions.py +3 -3
- angr/codenode.py +5 -1
- angr/concretization_strategies/__init__.py +1 -83
- angr/concretization_strategies/any.py +2 -1
- angr/concretization_strategies/any_named.py +1 -1
- angr/concretization_strategies/base.py +81 -0
- angr/concretization_strategies/controlled_data.py +2 -1
- angr/concretization_strategies/eval.py +2 -1
- angr/concretization_strategies/logging.py +3 -1
- angr/concretization_strategies/max.py +2 -1
- angr/concretization_strategies/nonzero.py +2 -1
- angr/concretization_strategies/nonzero_range.py +2 -1
- angr/concretization_strategies/norepeats.py +2 -1
- angr/concretization_strategies/norepeats_range.py +2 -1
- angr/concretization_strategies/range.py +2 -1
- angr/concretization_strategies/signed_add.py +2 -1
- angr/concretization_strategies/single.py +2 -1
- angr/concretization_strategies/solutions.py +2 -1
- angr/concretization_strategies/unlimited_range.py +2 -1
- angr/engines/__init__.py +8 -5
- angr/engines/engine.py +3 -5
- angr/engines/failure.py +4 -5
- angr/engines/procedure.py +5 -7
- angr/engines/soot/expressions/__init__.py +22 -23
- angr/engines/soot/expressions/base.py +4 -4
- angr/engines/soot/expressions/invoke.py +1 -2
- angr/engines/soot/statements/__init__.py +9 -10
- angr/engines/soot/values/__init__.py +9 -10
- angr/engines/soot/values/arrayref.py +3 -3
- angr/engines/soot/values/instancefieldref.py +3 -2
- angr/engines/successors.py +7 -6
- angr/engines/syscall.py +4 -6
- angr/engines/unicorn.py +3 -2
- angr/engines/vex/claripy/ccall.py +8 -10
- angr/engines/vex/claripy/datalayer.py +4 -5
- angr/exploration_techniques/__init__.py +0 -2
- angr/exploration_techniques/spiller.py +1 -3
- angr/exploration_techniques/stochastic.py +2 -3
- angr/factory.py +3 -9
- angr/knowledge_plugins/cfg/cfg_model.py +20 -17
- angr/knowledge_plugins/functions/function.py +70 -73
- angr/knowledge_plugins/functions/function_manager.py +8 -7
- angr/knowledge_plugins/functions/function_parser.py +1 -1
- angr/knowledge_plugins/functions/soot_function.py +16 -16
- angr/knowledge_plugins/propagations/propagation_model.py +4 -5
- angr/knowledge_plugins/propagations/states.py +0 -511
- angr/procedures/libc/memcpy.py +4 -4
- angr/procedures/procedure_dict.py +3 -2
- angr/protos/__init__.py +2 -5
- angr/protos/cfg_pb2.py +21 -18
- angr/protos/function_pb2.py +17 -14
- angr/protos/primitives_pb2.py +44 -39
- angr/protos/variables_pb2.py +36 -31
- angr/protos/xrefs_pb2.py +15 -12
- angr/sim_procedure.py +15 -16
- angr/sim_variable.py +13 -1
- angr/simos/__init__.py +2 -0
- angr/simos/javavm.py +4 -6
- angr/simos/xbox.py +32 -0
- angr/state_plugins/__init__.py +0 -2
- angr/state_plugins/callstack.py +4 -4
- angr/state_plugins/cgc.py +3 -2
- angr/state_plugins/gdb.py +6 -5
- angr/state_plugins/globals.py +1 -2
- angr/state_plugins/heap/heap_brk.py +1 -2
- angr/state_plugins/history.py +10 -12
- angr/state_plugins/inspect.py +3 -5
- angr/state_plugins/libc.py +2 -2
- angr/state_plugins/log.py +8 -10
- angr/state_plugins/loop_data.py +1 -2
- angr/state_plugins/posix.py +7 -7
- angr/state_plugins/preconstrainer.py +2 -3
- angr/state_plugins/scratch.py +5 -8
- angr/state_plugins/sim_action.py +3 -3
- angr/state_plugins/solver.py +8 -3
- angr/state_plugins/symbolizer.py +5 -4
- angr/state_plugins/uc_manager.py +3 -3
- angr/state_plugins/unicorn_engine.py +5 -1
- angr/state_plugins/view.py +3 -5
- angr/storage/file.py +3 -5
- angr/storage/memory_mixins/address_concretization_mixin.py +2 -2
- angr/storage/memory_mixins/bvv_conversion_mixin.py +3 -3
- angr/storage/memory_mixins/clouseau_mixin.py +1 -3
- angr/storage/memory_mixins/name_resolution_mixin.py +1 -3
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +13 -15
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +1 -22
- angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +3 -4
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +4 -2
- angr/storage/memory_mixins/smart_find_mixin.py +1 -1
- angr/storage/memory_mixins/underconstrained_mixin.py +1 -1
- angr/storage/memory_mixins/unwrapper_mixin.py +1 -3
- angr/utils/enums_conv.py +28 -12
- angr/utils/segment_list.py +25 -22
- angr/utils/timing.py +18 -1
- angr/vaults.py +5 -6
- {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/METADATA +6 -6
- {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/RECORD +160 -159
- {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/WHEEL +1 -1
- angr/analyses/propagator/outdated_definition_walker.py +0 -159
- angr/analyses/propagator/tmpvar_finder.py +0 -18
- angr/engines/concrete.py +0 -180
- angr/exploration_techniques/symbion.py +0 -80
- angr/state_plugins/concrete.py +0 -295
- {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/LICENSE +0 -0
- {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/entry_points.txt +0 -0
- {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/top_level.txt +0 -0
angr/analyses/fcp/fcp.py
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Any
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
|
|
6
|
+
import networkx
|
|
7
|
+
import pyvex
|
|
8
|
+
import claripy
|
|
9
|
+
|
|
10
|
+
from angr.utils.bits import s2u
|
|
11
|
+
from angr.block import Block
|
|
12
|
+
from angr.analyses.analysis import Analysis
|
|
13
|
+
from angr.analyses import AnalysesHub
|
|
14
|
+
from angr.knowledge_plugins.functions import Function
|
|
15
|
+
from angr.codenode import BlockNode, HookNode
|
|
16
|
+
from angr.engines.light import SimEngineNostmtVEX, SimEngineLight, SpOffset, RegisterOffset
|
|
17
|
+
from angr.calling_conventions import SimStackArg, default_cc
|
|
18
|
+
from angr.analyses.propagator.vex_vars import VEXReg, VEXTmp
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SV:
|
|
22
|
+
"""
|
|
23
|
+
SizedValue: A faster implementation of claripy.ast.BV.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
__slots__ = ("bits", "value")
|
|
27
|
+
|
|
28
|
+
def __init__(self, value, bits):
|
|
29
|
+
self.value = value
|
|
30
|
+
self.bits = bits
|
|
31
|
+
|
|
32
|
+
def __eq__(self, other):
|
|
33
|
+
return isinstance(other, SV) and self.value == other.value and self.bits == other.bits
|
|
34
|
+
|
|
35
|
+
def __hash__(self):
|
|
36
|
+
return hash((self.value, self.bits))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class FCPState:
|
|
40
|
+
"""
|
|
41
|
+
The abstract state for FastConstantPropagation.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
__slots__ = (
|
|
45
|
+
"bp_value",
|
|
46
|
+
"callee_stored_regs",
|
|
47
|
+
"regs",
|
|
48
|
+
"simple_stack",
|
|
49
|
+
"sp_value",
|
|
50
|
+
"stack",
|
|
51
|
+
"tmps",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def __init__(self):
|
|
55
|
+
self.tmps = {}
|
|
56
|
+
self.simple_stack = {}
|
|
57
|
+
|
|
58
|
+
self.regs: dict[int, SV] = {}
|
|
59
|
+
self.stack: dict[int, SV] = {}
|
|
60
|
+
self.sp_value = 0
|
|
61
|
+
self.bp_value = 0
|
|
62
|
+
|
|
63
|
+
def register_read(self, offset, size_in_bytes: int) -> int | None:
|
|
64
|
+
if offset in self.regs:
|
|
65
|
+
v = self.regs[offset]
|
|
66
|
+
if v.bits == size_in_bytes * 8:
|
|
67
|
+
return v.value
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
def register_written(self, offset: int, size_in_bytes: int, value: int | None):
|
|
71
|
+
if value is None:
|
|
72
|
+
to_remove = set()
|
|
73
|
+
for off, v in self.regs.items():
|
|
74
|
+
if (off <= offset < off + v.bits // 8) or (offset <= off < offset + size_in_bytes):
|
|
75
|
+
to_remove.add(off)
|
|
76
|
+
for off in to_remove:
|
|
77
|
+
del self.regs[off]
|
|
78
|
+
else:
|
|
79
|
+
self.regs[offset] = SV(value, size_in_bytes * 8)
|
|
80
|
+
|
|
81
|
+
def stack_read(self, offset: int, size_int_bytes: int) -> int | None:
|
|
82
|
+
if offset in self.stack:
|
|
83
|
+
v = self.stack[offset]
|
|
84
|
+
if v.bits == size_int_bytes * 8:
|
|
85
|
+
return v.value
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
def stack_written(self, offset: int, size_int_bytes: int, value: int | None):
|
|
89
|
+
if value is None:
|
|
90
|
+
to_remove = set()
|
|
91
|
+
for off, v in self.stack.items():
|
|
92
|
+
if (off <= offset < off + v.bits // 8) or (offset <= off < offset + size_int_bytes):
|
|
93
|
+
to_remove.add(off)
|
|
94
|
+
for off in to_remove:
|
|
95
|
+
del self.stack[off]
|
|
96
|
+
else:
|
|
97
|
+
self.stack[offset] = SV(value, size_int_bytes * 8)
|
|
98
|
+
|
|
99
|
+
def copy(self, with_tmps: bool = False) -> FCPState:
|
|
100
|
+
new_state = FCPState()
|
|
101
|
+
new_state.stack = self.stack.copy()
|
|
102
|
+
new_state.regs = self.regs.copy()
|
|
103
|
+
new_state.sp_value = self.sp_value
|
|
104
|
+
new_state.bp_value = self.bp_value
|
|
105
|
+
new_state.simple_stack = self.simple_stack.copy()
|
|
106
|
+
if with_tmps:
|
|
107
|
+
new_state.tmps = self.tmps.copy()
|
|
108
|
+
return new_state
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
binop_handler = SimEngineNostmtVEX[FCPState, claripy.ast.BV, FCPState].binop_handler
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class SimEngineFCPVEX(
|
|
115
|
+
SimEngineNostmtVEX[FCPState, SpOffset | RegisterOffset | int, None],
|
|
116
|
+
SimEngineLight[type[FCPState], SpOffset | RegisterOffset | int, Block, None],
|
|
117
|
+
):
|
|
118
|
+
"""
|
|
119
|
+
THe engine for FastConstantPropagation.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def __init__(self, project, bp_as_gpr: bool, replacements: dict[int, dict], load_callback: Callable | None = None):
|
|
123
|
+
self.bp_as_gpr = bp_as_gpr
|
|
124
|
+
self.replacements = replacements
|
|
125
|
+
self._load_callback = load_callback
|
|
126
|
+
self.base_state = None
|
|
127
|
+
super().__init__(project)
|
|
128
|
+
|
|
129
|
+
def _allow_loading(self, addr: int, size: int) -> bool:
|
|
130
|
+
if self._load_callback is None:
|
|
131
|
+
return True
|
|
132
|
+
return self._load_callback(addr, size)
|
|
133
|
+
|
|
134
|
+
def _process_block_end(self, stmt_result: list, whitelist: set[int] | None) -> None:
|
|
135
|
+
if self.block.vex.jumpkind == "Ijk_Call":
|
|
136
|
+
self.state.register_written(self.arch.ret_offset, self.arch.bytes, None)
|
|
137
|
+
|
|
138
|
+
def _top(self, bits: int):
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
def _is_top(self, expr: Any) -> bool:
|
|
142
|
+
raise NotImplementedError
|
|
143
|
+
|
|
144
|
+
def _handle_conversion(self, from_size: int, to_size: int, signed: bool, operand: pyvex.IRExpr) -> Any:
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
def _handle_stmt_Put(self, stmt):
|
|
148
|
+
v = self._expr(stmt.data)
|
|
149
|
+
if stmt.offset == self.arch.sp_offset and isinstance(v, SpOffset):
|
|
150
|
+
self.state.sp_value = v.offset
|
|
151
|
+
elif stmt.offset == self.arch.bp_offset and not self.bp_as_gpr and isinstance(v, SpOffset):
|
|
152
|
+
self.state.bp_value = v.offset
|
|
153
|
+
elif isinstance(v, int):
|
|
154
|
+
size = stmt.data.result_size(self.tyenv) // self.arch.byte_width
|
|
155
|
+
codeloc = self._codeloc()
|
|
156
|
+
self.state.register_written(stmt.offset, size, v)
|
|
157
|
+
if stmt.offset != self.arch.ip_offset:
|
|
158
|
+
self.replacements[codeloc][VEXReg(stmt.offset, size)] = v
|
|
159
|
+
else:
|
|
160
|
+
size = stmt.data.result_size(self.tyenv) // self.arch.byte_width
|
|
161
|
+
self.state.register_written(stmt.offset, size, None)
|
|
162
|
+
|
|
163
|
+
def _handle_stmt_Store(self, stmt: pyvex.IRStmt.Store):
|
|
164
|
+
addr = self._expr(stmt.addr)
|
|
165
|
+
if isinstance(addr, SpOffset):
|
|
166
|
+
data = self._expr(stmt.data)
|
|
167
|
+
if isinstance(data, int):
|
|
168
|
+
self.state.stack_written(addr.offset, stmt.data.result_size(self.tyenv) // self.arch.byte_width, data)
|
|
169
|
+
else:
|
|
170
|
+
self.state.stack_written(addr.offset, stmt.data.result_size(self.tyenv) // self.arch.byte_width, None)
|
|
171
|
+
|
|
172
|
+
def _handle_stmt_WrTmp(self, stmt: pyvex.IRStmt.WrTmp):
|
|
173
|
+
if isinstance(stmt.data, pyvex.IRExpr.Binop) and not (
|
|
174
|
+
stmt.data.op.startswith("Iop_Add")
|
|
175
|
+
or stmt.data.op.startswith("Iop_Sub")
|
|
176
|
+
or stmt.data.op.startswith("Iop_And")
|
|
177
|
+
):
|
|
178
|
+
return
|
|
179
|
+
v = self._expr(stmt.data)
|
|
180
|
+
if v is not None:
|
|
181
|
+
self.state.tmps[stmt.tmp] = v
|
|
182
|
+
if isinstance(v, int):
|
|
183
|
+
codeloc = self._codeloc()
|
|
184
|
+
self.replacements[codeloc][VEXTmp(stmt.tmp)] = v
|
|
185
|
+
|
|
186
|
+
def _handle_expr_Const(self, expr: pyvex.IRExpr.Const):
|
|
187
|
+
return expr.con.value
|
|
188
|
+
|
|
189
|
+
def _handle_expr_GSPTR(self, expr):
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
def _handle_expr_Get(self, expr) -> SpOffset | None:
|
|
193
|
+
if expr.offset == self.arch.sp_offset:
|
|
194
|
+
return SpOffset(self.arch.bits, self.state.sp_value, is_base=False)
|
|
195
|
+
if expr.offset == self.arch.bp_offset and not self.bp_as_gpr:
|
|
196
|
+
return SpOffset(self.arch.bits, self.state.bp_value, is_base=False)
|
|
197
|
+
size = expr.result_size(self.tyenv) // self.arch.byte_width
|
|
198
|
+
v = self.state.register_read(expr.offset, size)
|
|
199
|
+
if v is not None:
|
|
200
|
+
codeloc = self._codeloc()
|
|
201
|
+
self.replacements[codeloc][VEXReg(expr.offset, size)] = v
|
|
202
|
+
return v
|
|
203
|
+
|
|
204
|
+
def _handle_expr_GetI(self, expr):
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
def _handle_expr_ITE(self, expr):
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
def _handle_expr_Load(self, expr) -> int | SpOffset | None:
|
|
211
|
+
addr = self._expr(expr.addr)
|
|
212
|
+
if isinstance(addr, SpOffset):
|
|
213
|
+
return self.state.stack.get(addr.offset)
|
|
214
|
+
if isinstance(addr, int):
|
|
215
|
+
size = expr.result_size(self.tyenv) // self.arch.byte_width
|
|
216
|
+
if self._allow_loading(addr, size):
|
|
217
|
+
# Try loading from the state
|
|
218
|
+
if self.base_state is not None:
|
|
219
|
+
data = self.base_state.memory.load(addr, size, endness=expr.endness)
|
|
220
|
+
if not data.symbolic:
|
|
221
|
+
return data.args[0]
|
|
222
|
+
else:
|
|
223
|
+
try:
|
|
224
|
+
return self.project.loader.memory.unpack_word(addr, size=size, endness=expr.endness)
|
|
225
|
+
except KeyError:
|
|
226
|
+
pass
|
|
227
|
+
return None
|
|
228
|
+
|
|
229
|
+
def _handle_expr_RdTmp(self, expr):
|
|
230
|
+
return self.state.tmps.get(expr.tmp, None)
|
|
231
|
+
|
|
232
|
+
def _dummy_handler(self, expr): # pylint:disable=unused-argument,no-self-use
|
|
233
|
+
return None
|
|
234
|
+
|
|
235
|
+
_handle_expr_VECRET = _dummy_handler
|
|
236
|
+
_handle_expr_CCall = _dummy_handler
|
|
237
|
+
_handle_expr_Unop = _dummy_handler
|
|
238
|
+
_handle_expr_Triop = _dummy_handler
|
|
239
|
+
|
|
240
|
+
@binop_handler
|
|
241
|
+
def _handle_binop_Add(self, expr):
|
|
242
|
+
op0, op1 = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
243
|
+
if isinstance(op0, SpOffset) and isinstance(op1, int):
|
|
244
|
+
return SpOffset(op0.bits, s2u(op0.offset + op1, op0.bits), is_base=op0.is_base)
|
|
245
|
+
if isinstance(op1, SpOffset) and isinstance(op0, int):
|
|
246
|
+
return SpOffset(op1.bits, s2u(op1.offset + op0, op1.bits), is_base=op1.is_base)
|
|
247
|
+
if isinstance(op0, int) and isinstance(op1, int):
|
|
248
|
+
mask = (1 << expr.result_size(self.tyenv)) - 1
|
|
249
|
+
return (op0 + op1) & mask
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
@binop_handler
|
|
253
|
+
def _handle_binop_Sub(self, expr):
|
|
254
|
+
op0, op1 = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
255
|
+
if isinstance(op0, SpOffset) and isinstance(op1, int):
|
|
256
|
+
return SpOffset(op0.bits, s2u(op0.offset - op1, op0.bits), is_base=op0.is_base)
|
|
257
|
+
if isinstance(op1, SpOffset) and isinstance(op0, int):
|
|
258
|
+
return SpOffset(op1.bits, s2u(op1.offset - op0, op1.bits), is_base=op1.is_base)
|
|
259
|
+
if isinstance(op0, int) and isinstance(op1, int):
|
|
260
|
+
mask = (1 << expr.result_size(self.tyenv)) - 1
|
|
261
|
+
return (op0 - op1) & mask
|
|
262
|
+
return None
|
|
263
|
+
|
|
264
|
+
@binop_handler
|
|
265
|
+
def _handle_binop_And(self, expr):
|
|
266
|
+
op0, op1 = self._expr(expr.args[0]), self._expr(expr.args[1])
|
|
267
|
+
if isinstance(op0, SpOffset):
|
|
268
|
+
return op0
|
|
269
|
+
if isinstance(op1, SpOffset):
|
|
270
|
+
return op1
|
|
271
|
+
if isinstance(op0, int) and isinstance(op1, int):
|
|
272
|
+
return op0 & op1
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class FastConstantPropagation(Analysis):
|
|
277
|
+
"""
|
|
278
|
+
An extremely fast constant propagation analysis that finds function-wide constant values with potentially high
|
|
279
|
+
false negative rates.
|
|
280
|
+
"""
|
|
281
|
+
|
|
282
|
+
def __init__(
|
|
283
|
+
self,
|
|
284
|
+
func: Function,
|
|
285
|
+
blocks: set[Block] | None = None,
|
|
286
|
+
vex_cross_insn_opt: bool = False,
|
|
287
|
+
load_callback: Callable | None = None,
|
|
288
|
+
):
|
|
289
|
+
self.function = func
|
|
290
|
+
self._blocks = blocks
|
|
291
|
+
self._vex_cross_insn_opt = vex_cross_insn_opt
|
|
292
|
+
self._load_callback = load_callback
|
|
293
|
+
|
|
294
|
+
self.replacements = {}
|
|
295
|
+
|
|
296
|
+
self._analyze()
|
|
297
|
+
|
|
298
|
+
def _analyze(self):
|
|
299
|
+
# traverse the function graph, collect registers and stack variables that are written to
|
|
300
|
+
func_graph = self.function.graph
|
|
301
|
+
func_graph_with_callees = self.function.transition_graph
|
|
302
|
+
startpoint = self.function.startpoint
|
|
303
|
+
bp_as_gpr = self.function.info.get("bp_as_gpr", False)
|
|
304
|
+
replacements = defaultdict(dict)
|
|
305
|
+
engine = SimEngineFCPVEX(self.project, bp_as_gpr, replacements, load_callback=self._load_callback)
|
|
306
|
+
init_state = FCPState()
|
|
307
|
+
if self.project.arch.call_pushes_ret:
|
|
308
|
+
init_state.sp_value = self.project.arch.bytes
|
|
309
|
+
init_state.bp_value = init_state.sp_value
|
|
310
|
+
|
|
311
|
+
sorted_nodes = reversed(list(networkx.dfs_postorder_nodes(func_graph, startpoint)))
|
|
312
|
+
block_addrs = None
|
|
313
|
+
if self._blocks:
|
|
314
|
+
block_addrs = {b.addr for b in self._blocks}
|
|
315
|
+
|
|
316
|
+
states: dict[BlockNode, FCPState] = {}
|
|
317
|
+
for node in sorted_nodes:
|
|
318
|
+
preds = func_graph.predecessors(node)
|
|
319
|
+
input_states = [states[pred] for pred in preds if pred in states]
|
|
320
|
+
state = init_state.copy() if not input_states else self._merge_states(input_states)
|
|
321
|
+
|
|
322
|
+
if self._blocks and node.addr not in block_addrs:
|
|
323
|
+
# skip this block
|
|
324
|
+
states[node] = state
|
|
325
|
+
continue
|
|
326
|
+
|
|
327
|
+
# process the block
|
|
328
|
+
if isinstance(node, BlockNode) and node.size == 0:
|
|
329
|
+
continue
|
|
330
|
+
if isinstance(node, HookNode):
|
|
331
|
+
# attempt to convert it into a function
|
|
332
|
+
if self.kb.functions.contains_addr(node.addr):
|
|
333
|
+
node = self.kb.functions.get_by_addr(node.addr)
|
|
334
|
+
else:
|
|
335
|
+
continue
|
|
336
|
+
if isinstance(node, Function):
|
|
337
|
+
if node.calling_convention is not None and node.prototype is not None:
|
|
338
|
+
# consume args and overwrite the return register
|
|
339
|
+
self._handle_function(state, node)
|
|
340
|
+
continue
|
|
341
|
+
|
|
342
|
+
block = self.project.factory.block(node.addr, size=node.size, cross_insn_opt=self._vex_cross_insn_opt)
|
|
343
|
+
engine.process(state, block=block)
|
|
344
|
+
|
|
345
|
+
# if the node ends with a function call, call _handle_function
|
|
346
|
+
succs = list(func_graph_with_callees.successors(node))
|
|
347
|
+
if any(isinstance(succ, (Function, HookNode)) for succ in succs):
|
|
348
|
+
callee = next(succ for succ in succs if isinstance(succ, (Function, HookNode)))
|
|
349
|
+
if isinstance(callee, HookNode):
|
|
350
|
+
# attempt to convert it into a function
|
|
351
|
+
if self.kb.functions.contains_addr(callee.addr):
|
|
352
|
+
callee = self.kb.functions.get_by_addr(callee.addr)
|
|
353
|
+
else:
|
|
354
|
+
callee = None
|
|
355
|
+
state = self._handle_function(state, callee)
|
|
356
|
+
|
|
357
|
+
states[node] = state
|
|
358
|
+
|
|
359
|
+
self.replacements = replacements
|
|
360
|
+
|
|
361
|
+
@staticmethod
|
|
362
|
+
def _merge_states(states: list[FCPState]) -> FCPState:
|
|
363
|
+
state = FCPState()
|
|
364
|
+
to_drop = set()
|
|
365
|
+
common_keys = set.intersection(*[set(s.regs) for s in states])
|
|
366
|
+
for s in states:
|
|
367
|
+
for offset, value in s.regs.items():
|
|
368
|
+
if offset in common_keys:
|
|
369
|
+
if offset in state.regs:
|
|
370
|
+
if state.regs[offset] != value:
|
|
371
|
+
to_drop.add(offset)
|
|
372
|
+
else:
|
|
373
|
+
state.regs[offset] = value
|
|
374
|
+
for offset in to_drop:
|
|
375
|
+
del state.regs[offset]
|
|
376
|
+
|
|
377
|
+
to_drop = set()
|
|
378
|
+
common_keys = set.intersection(*[set(s.stack) for s in states])
|
|
379
|
+
for s in states:
|
|
380
|
+
for offset, value in s.stack.items():
|
|
381
|
+
if offset in common_keys:
|
|
382
|
+
if offset in state.stack:
|
|
383
|
+
if state.stack[offset] != value:
|
|
384
|
+
to_drop.add(offset)
|
|
385
|
+
else:
|
|
386
|
+
state.stack[offset] = value
|
|
387
|
+
for offset in to_drop:
|
|
388
|
+
del state.stack[offset]
|
|
389
|
+
|
|
390
|
+
for s in states:
|
|
391
|
+
state.sp_value = max(state.sp_value, s.sp_value)
|
|
392
|
+
state.bp_value = max(state.bp_value, s.bp_value)
|
|
393
|
+
return state
|
|
394
|
+
|
|
395
|
+
def _handle_function(self, state: FCPState, func: Function | None) -> FCPState:
|
|
396
|
+
|
|
397
|
+
if func is None or func.calling_convention is None:
|
|
398
|
+
cc = default_cc(self.project.arch.name)
|
|
399
|
+
else:
|
|
400
|
+
cc = func.calling_convention
|
|
401
|
+
|
|
402
|
+
out_state = state.copy()
|
|
403
|
+
if func is not None and func.prototype is not None:
|
|
404
|
+
arg_locs = None
|
|
405
|
+
try:
|
|
406
|
+
arg_locs = cc.arg_locs(func.prototype)
|
|
407
|
+
except (TypeError, ValueError):
|
|
408
|
+
arg_locs = None
|
|
409
|
+
|
|
410
|
+
if None in arg_locs:
|
|
411
|
+
arg_locs = None
|
|
412
|
+
|
|
413
|
+
if arg_locs is not None:
|
|
414
|
+
for arg_loc in arg_locs:
|
|
415
|
+
for loc in arg_loc.get_footprint():
|
|
416
|
+
if isinstance(loc, SimStackArg):
|
|
417
|
+
sp_value = out_state.sp_value
|
|
418
|
+
if sp_value is not None:
|
|
419
|
+
out_state.stack_read(sp_value + loc.stack_offset, loc.size)
|
|
420
|
+
|
|
421
|
+
# clobber caller-saved regs
|
|
422
|
+
for reg_name in cc.CALLER_SAVED_REGS:
|
|
423
|
+
offset = self.project.arch.registers[reg_name][0]
|
|
424
|
+
out_state.register_written(offset, self.project.arch.registers[reg_name][1], None)
|
|
425
|
+
|
|
426
|
+
return out_state
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
AnalysesHub.register_default("FastConstantPropagation", FastConstantPropagation)
|
|
@@ -10,7 +10,7 @@ from networkx import NetworkXError
|
|
|
10
10
|
from .errors import IdentifierException
|
|
11
11
|
from .functions import Functions
|
|
12
12
|
from .runner import Runner
|
|
13
|
-
from angr.analyses import Analysis
|
|
13
|
+
from angr.analyses import Analysis, AnalysesHub
|
|
14
14
|
from angr import options
|
|
15
15
|
from angr.errors import AngrError, SimSegfaultError, SimEngineError, SimMemoryError, SimError
|
|
16
16
|
|
|
@@ -822,6 +822,4 @@ class Identifier(Analysis):
|
|
|
822
822
|
return symbolic_state
|
|
823
823
|
|
|
824
824
|
|
|
825
|
-
from angr.analyses import AnalysesHub
|
|
826
|
-
|
|
827
825
|
AnalysesHub.register_default("Identifier", Identifier)
|
angr/analyses/loopfinder.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
2
4
|
import logging
|
|
3
5
|
|
|
4
6
|
import networkx
|
|
7
|
+
|
|
8
|
+
from angr.analyses import AnalysesHub
|
|
5
9
|
from . import Analysis
|
|
6
|
-
import contextlib
|
|
7
10
|
|
|
8
11
|
l = logging.getLogger(name=__name__)
|
|
9
12
|
|
|
@@ -165,6 +168,4 @@ class LoopFinder(Analysis):
|
|
|
165
168
|
return outtop, outall
|
|
166
169
|
|
|
167
170
|
|
|
168
|
-
from angr.analyses import AnalysesHub
|
|
169
|
-
|
|
170
171
|
AnalysesHub.register_default("LoopFinder", LoopFinder)
|
angr/analyses/patchfinder.py
CHANGED
|
@@ -34,7 +34,7 @@ class OverlappingFunctionsAnalysis(Analysis):
|
|
|
34
34
|
func_max_addr = max((block.addr + block.size) for block in func.blocks)
|
|
35
35
|
addr_to_func_max_addr[func.addr] = (func, func_max_addr)
|
|
36
36
|
|
|
37
|
-
for idx, (addr, (
|
|
37
|
+
for idx, (addr, (_func, max_addr)) in enumerate(addr_to_func_max_addr.items()):
|
|
38
38
|
for other_addr in addr_to_func_max_addr.islice(idx + 1):
|
|
39
39
|
if other_addr >= max_addr:
|
|
40
40
|
break
|
|
@@ -19,13 +19,16 @@ l = logging.getLogger(name=__name__)
|
|
|
19
19
|
class SimEnginePropagatorBaseMixin(
|
|
20
20
|
Generic[StateType, DataType_co, BlockType], SimEngineLight[StateType, DataType_co, BlockType, StateType]
|
|
21
21
|
): # pylint:disable=abstract-method
|
|
22
|
+
"""
|
|
23
|
+
The base class for the propagator VEX engine.
|
|
24
|
+
"""
|
|
25
|
+
|
|
22
26
|
def __init__(
|
|
23
27
|
self,
|
|
24
28
|
project: Project,
|
|
25
29
|
stack_pointer_tracker=None,
|
|
26
30
|
propagate_tmps=True,
|
|
27
31
|
reaching_definitions: ReachingDefinitionsModel | None = None,
|
|
28
|
-
immediate_stmt_removal: bool = False,
|
|
29
32
|
bp_as_gpr: bool = False,
|
|
30
33
|
):
|
|
31
34
|
super().__init__(project)
|
|
@@ -36,9 +39,7 @@ class SimEnginePropagatorBaseMixin(
|
|
|
36
39
|
self._load_callback = None
|
|
37
40
|
self._propagate_tmps: bool = propagate_tmps
|
|
38
41
|
self._reaching_definitions = reaching_definitions
|
|
39
|
-
self._immediate_stmt_removal = immediate_stmt_removal
|
|
40
42
|
self.bp_as_gpr = bp_as_gpr
|
|
41
|
-
self.stmts_to_remove = set()
|
|
42
43
|
|
|
43
44
|
# Used in the AIL engine
|
|
44
45
|
self._stack_pointer_tracker = stack_pointer_tracker
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pylint:disable=isinstance-second-argument-not-valid-type
|
|
2
2
|
from __future__ import annotations
|
|
3
|
-
from typing import Any
|
|
3
|
+
from typing import Any
|
|
4
4
|
import logging
|
|
5
5
|
import time
|
|
6
6
|
import contextlib
|
|
@@ -12,16 +12,12 @@ import pyvex
|
|
|
12
12
|
from angr.code_location import CodeLocation
|
|
13
13
|
from angr.analyses import ForwardAnalysis, visitors
|
|
14
14
|
from angr.knowledge_plugins.propagations.propagation_model import PropagationModel
|
|
15
|
-
from angr.knowledge_plugins.propagations.
|
|
16
|
-
from angr.knowledge_plugins.propagations.states import PropagatorAILState, PropagatorVEXState, PropagatorState
|
|
15
|
+
from angr.knowledge_plugins.propagations.states import PropagatorVEXState, PropagatorState
|
|
17
16
|
from angr import sim_options
|
|
18
17
|
from angr.analyses import register_analysis
|
|
19
18
|
from angr.analyses.analysis import Analysis
|
|
20
19
|
from .engine_vex import SimEnginePropagatorVEX
|
|
21
20
|
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from angr.analyses.reaching_definitions.reaching_definitions import ReachingDefinitionsModel
|
|
24
|
-
|
|
25
21
|
|
|
26
22
|
_l = logging.getLogger(name=__name__)
|
|
27
23
|
|
|
@@ -31,8 +27,7 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
31
27
|
PropagatorAnalysis implements copy propagation. It propagates values (either constant values or variables) and
|
|
32
28
|
expressions inside a block or across a function.
|
|
33
29
|
|
|
34
|
-
PropagatorAnalysis supports
|
|
35
|
-
propagator performs both constant propagation and copy propagation of depth-N expressions.
|
|
30
|
+
PropagatorAnalysis only supports VEX. For AIL, please use SPropagator.
|
|
36
31
|
|
|
37
32
|
PropagatorAnalysis performs certain arithmetic operations between constants, including but are not limited to:
|
|
38
33
|
|
|
@@ -66,8 +61,6 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
66
61
|
gp: int | None = None,
|
|
67
62
|
cache_results: bool = False,
|
|
68
63
|
key_prefix: str | None = None,
|
|
69
|
-
reaching_definitions: ReachingDefinitionsModel | None = None,
|
|
70
|
-
immediate_stmt_removal: bool = False,
|
|
71
64
|
profiling: bool = False,
|
|
72
65
|
):
|
|
73
66
|
if block is None and func is not None:
|
|
@@ -95,11 +88,9 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
95
88
|
self._do_binops = do_binops
|
|
96
89
|
self._store_tops = store_tops
|
|
97
90
|
self._vex_cross_insn_opt = vex_cross_insn_opt
|
|
98
|
-
self._immediate_stmt_removal = immediate_stmt_removal
|
|
99
91
|
self._gp = gp
|
|
100
92
|
self._prop_key_prefix = key_prefix
|
|
101
93
|
self._cache_results = cache_results
|
|
102
|
-
self._reaching_definitions = reaching_definitions
|
|
103
94
|
self._initial_codeloc: CodeLocation
|
|
104
95
|
self.stmts_to_remove: set[CodeLocation] = set()
|
|
105
96
|
if self.flavor == "function":
|
|
@@ -167,7 +158,6 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
167
158
|
# pyright says pylint is wrong about this
|
|
168
159
|
self._engine_vex = SimEnginePropagatorVEX( # pylint: disable=abstract-class-instantiated
|
|
169
160
|
project=self.project,
|
|
170
|
-
reaching_definitions=self._reaching_definitions,
|
|
171
161
|
bp_as_gpr=bp_as_gpr,
|
|
172
162
|
)
|
|
173
163
|
|
|
@@ -176,7 +166,6 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
176
166
|
|
|
177
167
|
# performance counters
|
|
178
168
|
self._analyzed_states: int = 0
|
|
179
|
-
self._analyzed_statements: int = 0
|
|
180
169
|
|
|
181
170
|
self._analyze()
|
|
182
171
|
|
|
@@ -188,12 +177,12 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
188
177
|
elapsed = time.perf_counter_ns() / 1000000 - start
|
|
189
178
|
if self.flavor == "function":
|
|
190
179
|
_l.warning("%r:", self._function)
|
|
180
|
+
_l.warning(" Blocks: %d", len(self._function.block_addrs_set))
|
|
191
181
|
else:
|
|
192
182
|
_l.warning("%r:", self._block)
|
|
193
|
-
_l.warning(" Time elapsed: %
|
|
183
|
+
_l.warning(" Time elapsed: %0.02f milliseconds", elapsed)
|
|
194
184
|
_l.warning(" Cache used: %s", cache_used)
|
|
195
185
|
_l.warning(" Analyzed states: %d", self._analyzed_states)
|
|
196
|
-
_l.warning(" Analyzed statements: %d", self._analyzed_statements)
|
|
197
186
|
|
|
198
187
|
@property
|
|
199
188
|
def prop_key(self) -> tuple[str | None, str, int, bool, bool, bool]:
|
|
@@ -232,7 +221,6 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
232
221
|
def _initial_abstract_state(self, node):
|
|
233
222
|
self._initial_state = PropagatorVEXState.initial_state(
|
|
234
223
|
self.project,
|
|
235
|
-
rda=self._reaching_definitions,
|
|
236
224
|
only_consts=self._only_consts,
|
|
237
225
|
gp=self._gp,
|
|
238
226
|
do_binops=self._do_binops,
|
|
@@ -261,7 +249,6 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
261
249
|
if state is not self._initial_state:
|
|
262
250
|
# make a copy of the state if it's not the initial state
|
|
263
251
|
state = state.copy()
|
|
264
|
-
state._equivalence.clear()
|
|
265
252
|
state.init_replacements()
|
|
266
253
|
else:
|
|
267
254
|
# clear self._initial_state so that we *do not* run this optimization again!
|
|
@@ -284,10 +271,6 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
284
271
|
)
|
|
285
272
|
state.filter_replacements()
|
|
286
273
|
|
|
287
|
-
if self._immediate_stmt_removal:
|
|
288
|
-
self.stmts_to_remove |= engine.stmts_to_remove
|
|
289
|
-
engine.stmts_to_remove = set()
|
|
290
|
-
|
|
291
274
|
self.model.node_iterations[block_key] += 1
|
|
292
275
|
self.model.states[block_key] = state
|
|
293
276
|
self.model.block_initial_reg_values.update(state.block_initial_reg_values)
|
|
@@ -297,35 +280,19 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
297
280
|
else:
|
|
298
281
|
PropagatorState.merge_replacements(self.model.replacements, state._replacements)
|
|
299
282
|
|
|
300
|
-
self.model.equivalence |= state._equivalence
|
|
301
|
-
|
|
302
283
|
# TODO: Clear registers according to calling conventions
|
|
303
284
|
|
|
304
285
|
if self.model.node_iterations[block_key] < self._max_iterations:
|
|
305
286
|
return None, state
|
|
306
287
|
return False, state
|
|
307
288
|
|
|
308
|
-
def _process_input_state_for_successor(self, node, successor, input_state:
|
|
309
|
-
if self._only_consts:
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
input_state.store_register(
|
|
316
|
-
reg_atom,
|
|
317
|
-
PropValue(
|
|
318
|
-
claripy.BVV(reg_value.value, reg_value.bits),
|
|
319
|
-
offset_and_details={0: Detail(reg_atom.size, reg_value, self._initial_codeloc)},
|
|
320
|
-
),
|
|
321
|
-
)
|
|
322
|
-
return input_state
|
|
323
|
-
elif isinstance(input_state, PropagatorVEXState):
|
|
324
|
-
key = node.addr, successor.addr
|
|
325
|
-
if key in self.model.block_initial_reg_values:
|
|
326
|
-
input_state: PropagatorVEXState = input_state.copy()
|
|
327
|
-
for reg_offset, reg_size, value in self.model.block_initial_reg_values[key]:
|
|
328
|
-
input_state.store_register(reg_offset, reg_size, claripy.BVV(value, reg_size * 8))
|
|
289
|
+
def _process_input_state_for_successor(self, node, successor, input_state: PropagatorVEXState):
|
|
290
|
+
if self._only_consts and isinstance(input_state, PropagatorVEXState):
|
|
291
|
+
key = node.addr, successor.addr
|
|
292
|
+
if key in self.model.block_initial_reg_values:
|
|
293
|
+
input_state: PropagatorVEXState = input_state.copy()
|
|
294
|
+
for reg_offset, reg_size, value in self.model.block_initial_reg_values[key]:
|
|
295
|
+
input_state.store_register(reg_offset, reg_size, claripy.BVV(value, reg_size * 8))
|
|
329
296
|
return input_state
|
|
330
297
|
|
|
331
298
|
def _intra_analysis(self):
|
|
@@ -361,14 +328,8 @@ class PropagatorAnalysis(ForwardAnalysis, Analysis): # pylint:disable=abstract-
|
|
|
361
328
|
for codeloc in list(self.model.replacements.keys()):
|
|
362
329
|
filtered_rep = {}
|
|
363
330
|
for k, v in self.model.replacements[codeloc].items():
|
|
364
|
-
if isinstance(v, claripy.ast.Base):
|
|
365
|
-
|
|
366
|
-
if not PropagatorState.is_top(v):
|
|
367
|
-
filtered_rep[k] = v
|
|
368
|
-
else:
|
|
369
|
-
# AIL expressions
|
|
370
|
-
if not PropagatorAILState.is_top(v):
|
|
371
|
-
filtered_rep[k] = v
|
|
331
|
+
if isinstance(v, claripy.ast.Base) and not PropagatorState.is_top(v):
|
|
332
|
+
filtered_rep[k] = v
|
|
372
333
|
self.model.replacements[codeloc] = filtered_rep
|
|
373
334
|
|
|
374
335
|
if self._cache_results:
|
angr/analyses/reassembler.py
CHANGED
|
@@ -12,6 +12,7 @@ import cle
|
|
|
12
12
|
import networkx
|
|
13
13
|
import pyvex
|
|
14
14
|
|
|
15
|
+
from angr.analyses import AnalysesHub
|
|
15
16
|
from . import Analysis
|
|
16
17
|
from .cfg.cfg_emulated import CFGEmulated
|
|
17
18
|
from .ddg import DDG
|
|
@@ -2896,6 +2897,4 @@ class Reassembler(Analysis):
|
|
|
2896
2897
|
return None
|
|
2897
2898
|
|
|
2898
2899
|
|
|
2899
|
-
from angr.analyses import AnalysesHub
|
|
2900
|
-
|
|
2901
2900
|
AnalysesHub.register_default("Reassembler", Reassembler)
|