angr 9.2.130__py3-none-win_amd64.whl → 9.2.132__py3-none-win_amd64.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/analysis.py +6 -2
- angr/analyses/cfg/cfg_emulated.py +5 -5
- angr/analyses/cfg/cfg_fast.py +2 -2
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +139 -94
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +1 -1
- angr/analyses/ddg.py +14 -11
- angr/analyses/decompiler/ail_simplifier.py +3 -2
- angr/analyses/decompiler/block_simplifier.py +10 -21
- angr/analyses/decompiler/clinic.py +361 -8
- angr/analyses/decompiler/condition_processor.py +12 -10
- angr/analyses/decompiler/dephication/graph_rewriting.py +1 -1
- angr/analyses/decompiler/dephication/rewriting_engine.py +169 -45
- angr/analyses/decompiler/dephication/seqnode_dephication.py +5 -4
- angr/analyses/decompiler/optimization_passes/__init__.py +0 -3
- angr/analyses/decompiler/optimization_passes/const_derefs.py +1 -0
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +41 -16
- angr/analyses/decompiler/optimization_passes/engine_base.py +261 -83
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +173 -35
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +5 -2
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +39 -19
- angr/analyses/decompiler/peephole_optimizations/__init__.py +5 -1
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +3 -1
- angr/analyses/decompiler/peephole_optimizations/bswap.py +10 -6
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +100 -19
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +17 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +42 -3
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +4 -2
- angr/analyses/decompiler/peephole_optimizations/rol_ror.py +37 -10
- angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
- angr/analyses/decompiler/presets/fast.py +0 -2
- angr/analyses/decompiler/presets/full.py +0 -2
- angr/analyses/decompiler/ssailification/rewriting.py +1 -2
- angr/analyses/decompiler/ssailification/rewriting_engine.py +140 -57
- angr/analyses/decompiler/ssailification/ssailification.py +2 -1
- angr/analyses/decompiler/ssailification/traversal.py +4 -6
- angr/analyses/decompiler/ssailification/traversal_engine.py +125 -42
- angr/analyses/decompiler/structured_codegen/c.py +79 -16
- angr/analyses/decompiler/structuring/phoenix.py +40 -14
- angr/analyses/decompiler/structuring/structurer_nodes.py +9 -0
- angr/analyses/deobfuscator/irsb_reg_collector.py +29 -60
- angr/analyses/deobfuscator/string_obf_finder.py +2 -2
- angr/analyses/init_finder.py +47 -22
- angr/analyses/propagator/engine_base.py +21 -14
- angr/analyses/propagator/engine_vex.py +149 -179
- angr/analyses/propagator/propagator.py +10 -28
- angr/analyses/propagator/top_checker_mixin.py +211 -5
- angr/analyses/propagator/vex_vars.py +1 -1
- angr/analyses/reaching_definitions/dep_graph.py +1 -1
- angr/analyses/reaching_definitions/engine_ail.py +304 -329
- angr/analyses/reaching_definitions/engine_vex.py +243 -229
- angr/analyses/reaching_definitions/function_handler.py +3 -3
- angr/analyses/reaching_definitions/rd_state.py +37 -32
- angr/analyses/s_propagator.py +38 -5
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +9 -5
- angr/analyses/typehoon/simple_solver.py +16 -7
- angr/analyses/typehoon/translator.py +8 -0
- angr/analyses/typehoon/typeconsts.py +10 -2
- angr/analyses/typehoon/typehoon.py +4 -1
- angr/analyses/typehoon/typevars.py +9 -7
- angr/analyses/variable_recovery/engine_ail.py +296 -256
- angr/analyses/variable_recovery/engine_base.py +137 -116
- angr/analyses/variable_recovery/engine_vex.py +175 -185
- angr/analyses/variable_recovery/irsb_scanner.py +49 -38
- angr/analyses/variable_recovery/variable_recovery.py +28 -5
- angr/analyses/variable_recovery/variable_recovery_base.py +32 -33
- angr/analyses/variable_recovery/variable_recovery_fast.py +2 -2
- angr/analyses/xrefs.py +46 -19
- angr/annocfg.py +19 -14
- angr/block.py +4 -9
- angr/calling_conventions.py +1 -1
- angr/engines/engine.py +30 -14
- angr/engines/light/__init__.py +11 -3
- angr/engines/light/engine.py +1003 -1185
- angr/engines/pcode/cc.py +2 -0
- angr/engines/successors.py +13 -9
- angr/engines/vex/claripy/datalayer.py +1 -1
- angr/engines/vex/claripy/irop.py +14 -3
- angr/engines/vex/light/slicing.py +2 -2
- angr/exploration_techniques/__init__.py +1 -124
- angr/exploration_techniques/base.py +126 -0
- angr/exploration_techniques/bucketizer.py +1 -1
- angr/exploration_techniques/dfs.py +3 -1
- angr/exploration_techniques/director.py +2 -3
- angr/exploration_techniques/driller_core.py +1 -1
- angr/exploration_techniques/explorer.py +4 -2
- angr/exploration_techniques/lengthlimiter.py +2 -1
- angr/exploration_techniques/local_loop_seer.py +2 -1
- angr/exploration_techniques/loop_seer.py +5 -5
- angr/exploration_techniques/manual_mergepoint.py +2 -1
- angr/exploration_techniques/memory_watcher.py +3 -1
- angr/exploration_techniques/oppologist.py +4 -5
- angr/exploration_techniques/slicecutor.py +4 -2
- angr/exploration_techniques/spiller.py +1 -1
- angr/exploration_techniques/stochastic.py +2 -1
- angr/exploration_techniques/stub_stasher.py +2 -1
- angr/exploration_techniques/suggestions.py +3 -1
- angr/exploration_techniques/symbion.py +3 -1
- angr/exploration_techniques/tech_builder.py +2 -1
- angr/exploration_techniques/threading.py +4 -7
- angr/exploration_techniques/timeout.py +4 -2
- angr/exploration_techniques/tracer.py +4 -3
- angr/exploration_techniques/unique.py +3 -2
- angr/exploration_techniques/veritesting.py +1 -1
- angr/knowledge_plugins/key_definitions/atoms.py +2 -2
- angr/knowledge_plugins/key_definitions/live_definitions.py +16 -13
- angr/knowledge_plugins/propagations/states.py +13 -8
- angr/knowledge_plugins/variables/variable_manager.py +23 -9
- angr/lib/angr_native.dll +0 -0
- angr/sim_manager.py +1 -3
- angr/sim_state.py +39 -41
- angr/sim_type.py +5 -0
- angr/sim_variable.py +29 -28
- angr/utils/bits.py +17 -0
- angr/utils/formatting.py +4 -1
- angr/utils/orderedset.py +4 -1
- angr/utils/ssa/__init__.py +21 -3
- {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/METADATA +6 -6
- {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/RECORD +125 -124
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +0 -223
- angr/analyses/propagator/engine_ail.py +0 -1562
- angr/storage/memory_mixins/__init__.pyi +0 -48
- {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/LICENSE +0 -0
- {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/WHEEL +0 -0
- {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/entry_points.txt +0 -0
- {angr-9.2.130.dist-info → angr-9.2.132.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/analyses/analysis.py
CHANGED
|
@@ -20,6 +20,7 @@ from rich import progress
|
|
|
20
20
|
from angr.misc.plugins import PluginVendor, VendorPreset
|
|
21
21
|
from angr.misc.ux import deprecated
|
|
22
22
|
from angr.misc import telemetry
|
|
23
|
+
from angr.misc.testing import is_testing
|
|
23
24
|
|
|
24
25
|
if TYPE_CHECKING:
|
|
25
26
|
from angr.knowledge_base import KnowledgeBase
|
|
@@ -190,11 +191,14 @@ class AnalysisFactory(Generic[A]):
|
|
|
190
191
|
|
|
191
192
|
def prep(
|
|
192
193
|
self,
|
|
193
|
-
fail_fast=
|
|
194
|
+
fail_fast: bool | None = None,
|
|
194
195
|
kb: KnowledgeBase | None = None,
|
|
195
196
|
progress_callback: Callable | None = None,
|
|
196
197
|
show_progressbar: bool = False,
|
|
197
198
|
) -> type[A]:
|
|
199
|
+
if fail_fast is None:
|
|
200
|
+
fail_fast = is_testing
|
|
201
|
+
|
|
198
202
|
@functools.wraps(self._analysis_cls.__init__)
|
|
199
203
|
@t.start_as_current_span(self._analysis_cls.__name__)
|
|
200
204
|
def wrapper(*args, **kwargs):
|
|
@@ -253,7 +257,7 @@ class AnalysisFactory(Generic[A]):
|
|
|
253
257
|
return wrapper # type: ignore
|
|
254
258
|
|
|
255
259
|
def __call__(self, *args, **kwargs) -> A:
|
|
256
|
-
fail_fast = kwargs.pop("fail_fast",
|
|
260
|
+
fail_fast = kwargs.pop("fail_fast", is_testing)
|
|
257
261
|
kb = kwargs.pop("kb", self._project.kb)
|
|
258
262
|
progress_callback = kwargs.pop("progress_callback", None)
|
|
259
263
|
show_progressbar = kwargs.pop("show_progressbar", False)
|
|
@@ -2972,7 +2972,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
2972
2972
|
# Skip this IRSB
|
|
2973
2973
|
l.debug("Caught a SimIRSBError %s. Don't panic, this is usually expected.", ex)
|
|
2974
2974
|
inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
|
|
2975
|
-
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
2975
|
+
sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
|
|
2976
2976
|
|
|
2977
2977
|
except SimIRSBError:
|
|
2978
2978
|
exception_info = sys.exc_info()
|
|
@@ -2980,28 +2980,28 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
2980
2980
|
# does not support. I'll create a terminating stub there
|
|
2981
2981
|
l.debug("Caught a SimIRSBError during CFG recovery. Creating a PathTerminator.", exc_info=True)
|
|
2982
2982
|
inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
|
|
2983
|
-
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
2983
|
+
sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
|
|
2984
2984
|
|
|
2985
2985
|
except claripy.ClaripyError:
|
|
2986
2986
|
exception_info = sys.exc_info()
|
|
2987
2987
|
l.debug("Caught a ClaripyError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
|
|
2988
2988
|
# Generate a PathTerminator to terminate the current path
|
|
2989
2989
|
inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
|
|
2990
|
-
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
2990
|
+
sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
|
|
2991
2991
|
|
|
2992
2992
|
except SimError:
|
|
2993
2993
|
exception_info = sys.exc_info()
|
|
2994
2994
|
l.debug("Caught a SimError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
|
|
2995
2995
|
# Generate a PathTerminator to terminate the current path
|
|
2996
2996
|
inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
|
|
2997
|
-
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
2997
|
+
sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
|
|
2998
2998
|
|
|
2999
2999
|
except AngrExitError:
|
|
3000
3000
|
exception_info = sys.exc_info()
|
|
3001
3001
|
l.debug("Caught a AngrExitError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
|
|
3002
3002
|
# Generate a PathTerminator to terminate the current path
|
|
3003
3003
|
inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
|
|
3004
|
-
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
3004
|
+
sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
|
|
3005
3005
|
|
|
3006
3006
|
except AngrError:
|
|
3007
3007
|
exception_info = sys.exc_info()
|
angr/analyses/cfg/cfg_fast.py
CHANGED
|
@@ -3068,10 +3068,10 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
3068
3068
|
irsb = self.project.factory.block(irsb.addr, size=irsb.size, opt_level=1, cross_insn_opt=False).vex
|
|
3069
3069
|
|
|
3070
3070
|
# try to resolve the jump target
|
|
3071
|
-
simsucc = self.project.factory.default_engine.process(self._initial_state, irsb, force_addr=addr)
|
|
3071
|
+
simsucc = self.project.factory.default_engine.process(self._initial_state, block=irsb, force_addr=addr)
|
|
3072
3072
|
if len(simsucc.successors) == 1:
|
|
3073
3073
|
ip = simsucc.successors[0].ip
|
|
3074
|
-
if isinstance(ip, claripy.ast.
|
|
3074
|
+
if isinstance(ip, claripy.ast.BV):
|
|
3075
3075
|
target_addr = ip.concrete_value
|
|
3076
3076
|
obj = self.project.loader.find_object_containing(target_addr, membership_check=False)
|
|
3077
3077
|
if (obj is not None and obj is not self.project.loader.main_object) or self.project.is_hooked(
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# pylint:disable=wrong-import-position,wrong-import-order
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
import enum
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Literal, cast
|
|
5
5
|
from collections.abc import Sequence
|
|
6
|
+
from collections import defaultdict, OrderedDict
|
|
6
7
|
import logging
|
|
7
8
|
import functools
|
|
8
|
-
from collections import defaultdict, OrderedDict
|
|
9
9
|
|
|
10
10
|
import pyvex
|
|
11
11
|
import claripy
|
|
@@ -18,15 +18,18 @@ from angr.code_location import CodeLocation
|
|
|
18
18
|
from angr.concretization_strategies import SimConcretizationStrategyAny
|
|
19
19
|
from angr.knowledge_plugins.cfg import IndirectJump, IndirectJumpType
|
|
20
20
|
from angr.engines.vex.claripy import ccall
|
|
21
|
-
from angr.engines.light import
|
|
21
|
+
from angr.engines.light import SimEngineNostmtVEX, SpOffset, RegisterOffset
|
|
22
22
|
from angr.errors import AngrError, SimError
|
|
23
23
|
from angr.blade import Blade
|
|
24
24
|
from angr.annocfg import AnnotatedCFG
|
|
25
25
|
from angr.exploration_techniques.slicecutor import Slicecutor
|
|
26
26
|
from angr.exploration_techniques.local_loop_seer import LocalLoopSeer
|
|
27
27
|
from angr.exploration_techniques.explorer import Explorer
|
|
28
|
+
from angr.project import Project
|
|
28
29
|
from angr.utils.constants import DEFAULT_STATEMENT
|
|
29
30
|
from angr.analyses.propagator.vex_vars import VEXReg
|
|
31
|
+
from angr.analyses.propagator.top_checker_mixin import ClaripyDataVEXEngineMixin
|
|
32
|
+
from angr.engines.vex.claripy.datalayer import value
|
|
30
33
|
from .resolver import IndirectJumpResolver
|
|
31
34
|
from .propagator_utils import PropagatorLoadCallback
|
|
32
35
|
|
|
@@ -113,12 +116,14 @@ class JumpTargetBaseAddr:
|
|
|
113
116
|
Model for jump targets and their data origin.
|
|
114
117
|
"""
|
|
115
118
|
|
|
116
|
-
def __init__(
|
|
119
|
+
def __init__(
|
|
120
|
+
self, stmt_loc, stmt: pyvex.stmt.IRStmt, tmp: int, base_addr: int | None = None, tmp_1: int | None = None
|
|
121
|
+
):
|
|
117
122
|
self.stmt_loc = stmt_loc
|
|
118
123
|
self.stmt = stmt
|
|
119
|
-
self.tmp
|
|
124
|
+
self.tmp = tmp
|
|
120
125
|
self.tmp_1 = tmp_1
|
|
121
|
-
self.base_addr
|
|
126
|
+
self.base_addr = base_addr
|
|
122
127
|
|
|
123
128
|
assert base_addr is not None or tmp_1 is not None
|
|
124
129
|
|
|
@@ -144,16 +149,17 @@ class ConstantValueManager:
|
|
|
144
149
|
"mapping",
|
|
145
150
|
)
|
|
146
151
|
|
|
147
|
-
def __init__(self, project, kb, func: Function):
|
|
152
|
+
def __init__(self, project: Project, kb, func: Function):
|
|
148
153
|
self.project = project
|
|
149
154
|
self.kb = kb
|
|
150
155
|
self.func = func
|
|
151
156
|
|
|
152
|
-
self.mapping = None
|
|
157
|
+
self.mapping: dict[Any, dict[Any, claripy.ast.Base]] | None = None
|
|
153
158
|
|
|
154
159
|
def reg_read_callback(self, state: SimState):
|
|
155
160
|
if not self.mapping:
|
|
156
161
|
self._build_mapping()
|
|
162
|
+
assert self.mapping is not None
|
|
157
163
|
|
|
158
164
|
codeloc = CodeLocation(state.scratch.bbl_addr, state.scratch.stmt_idx, ins_addr=state.scratch.ins_addr)
|
|
159
165
|
if codeloc in self.mapping:
|
|
@@ -250,7 +256,7 @@ class JumpTableProcessorState:
|
|
|
250
256
|
self._stack = {}
|
|
251
257
|
self._tmpvar_source = {} # a mapping from temporary variables to their origins
|
|
252
258
|
|
|
253
|
-
self.is_jumptable = None # is the current slice representing a jump table?
|
|
259
|
+
self.is_jumptable: bool | None = None # is the current slice representing a jump table?
|
|
254
260
|
self.stmts_to_instrument = [] # Store/Put statements that we should instrument
|
|
255
261
|
self.regs_to_initialize = [] # registers that we should initialize
|
|
256
262
|
|
|
@@ -274,9 +280,12 @@ class RegOffsetAnnotation(claripy.Annotation):
|
|
|
274
280
|
return False
|
|
275
281
|
|
|
276
282
|
|
|
283
|
+
binop_handler = SimEngineNostmtVEX[JumpTableProcessorState, claripy.ast.BV, JumpTableProcessorState].binop_handler
|
|
284
|
+
|
|
285
|
+
|
|
277
286
|
class JumpTableProcessor(
|
|
278
|
-
|
|
279
|
-
|
|
287
|
+
SimEngineNostmtVEX[JumpTableProcessorState, claripy.ast.BV, JumpTableProcessorState],
|
|
288
|
+
ClaripyDataVEXEngineMixin[JumpTableProcessorState, claripy.ast.BV, JumpTableProcessorState, None],
|
|
280
289
|
): # pylint:disable=abstract-method
|
|
281
290
|
"""
|
|
282
291
|
Implements a simple and stupid data dependency tracking for stack and register variables.
|
|
@@ -298,20 +307,18 @@ class JumpTableProcessor(
|
|
|
298
307
|
"""
|
|
299
308
|
|
|
300
309
|
def __init__(self, project, indirect_jump_node_pred_addrs: set[int], bp_sp_diff=0x100):
|
|
301
|
-
super().__init__()
|
|
302
|
-
self.project = project
|
|
310
|
+
super().__init__(project)
|
|
303
311
|
self._bp_sp_diff = bp_sp_diff # bp - sp
|
|
304
|
-
self._tsrc
|
|
312
|
+
self._tsrc: set[Literal["const"] | tuple[int, int]] = (
|
|
313
|
+
set()
|
|
314
|
+
) # a scratch variable to store source information for values
|
|
305
315
|
self._indirect_jump_node_pred_addrs = indirect_jump_node_pred_addrs
|
|
306
316
|
|
|
307
317
|
self._SPOFFSET_BASE = claripy.BVS("SpOffset", self.project.arch.bits, explicit_name=True)
|
|
308
318
|
self._REGOFFSET_BASE: dict[int, claripy.ast.BV] = {}
|
|
309
319
|
|
|
310
|
-
def
|
|
311
|
-
return
|
|
312
|
-
|
|
313
|
-
def _is_top(self, expr) -> bool:
|
|
314
|
-
return expr is None
|
|
320
|
+
def _process_block_end(self, stmt_result, whitelist):
|
|
321
|
+
return self.state
|
|
315
322
|
|
|
316
323
|
@staticmethod
|
|
317
324
|
def _is_spoffset(expr) -> bool:
|
|
@@ -321,23 +328,23 @@ class JumpTableProcessor(
|
|
|
321
328
|
return self._SPOFFSET_BASE.annotate(RegOffsetAnnotation(sp_offset))
|
|
322
329
|
|
|
323
330
|
@staticmethod
|
|
324
|
-
def _extract_spoffset_from_expr(expr: claripy.ast.Base) ->
|
|
331
|
+
def _extract_spoffset_from_expr(expr: claripy.ast.Base) -> RegisterOffset | None:
|
|
325
332
|
if expr.op == "BVS":
|
|
326
333
|
for anno in expr.annotations:
|
|
327
334
|
if isinstance(anno, RegOffsetAnnotation):
|
|
328
335
|
return anno.reg_offset
|
|
329
336
|
elif expr.op == "__add__":
|
|
330
337
|
if len(expr.args) == 1:
|
|
331
|
-
return JumpTableProcessor._extract_spoffset_from_expr(expr.args[0])
|
|
332
|
-
if len(expr.args) == 2 and expr.args[1].op == "BVV":
|
|
333
|
-
sp_offset = JumpTableProcessor._extract_spoffset_from_expr(expr.args[0])
|
|
338
|
+
return JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
339
|
+
if len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
340
|
+
sp_offset = JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
334
341
|
if sp_offset is not None:
|
|
335
|
-
delta = expr.args[1].concrete_value
|
|
342
|
+
delta = cast(claripy.ast.BV, expr.args[1]).concrete_value
|
|
336
343
|
sp_offset += delta
|
|
337
344
|
return sp_offset
|
|
338
|
-
elif expr.op == "__and__" and len(expr.args) == 2 and expr.args[1].op == "BVV":
|
|
345
|
+
elif expr.op == "__and__" and len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
339
346
|
# ignore all masking on SpOffsets
|
|
340
|
-
return JumpTableProcessor._extract_spoffset_from_expr(expr.args[0])
|
|
347
|
+
return JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
341
348
|
return None
|
|
342
349
|
|
|
343
350
|
@staticmethod
|
|
@@ -357,33 +364,33 @@ class JumpTableProcessor(
|
|
|
357
364
|
return anno.reg_offset
|
|
358
365
|
elif expr.op == "__add__":
|
|
359
366
|
if len(expr.args) == 1:
|
|
360
|
-
return JumpTableProcessor._extract_regoffset_from_expr(expr.args[0])
|
|
361
|
-
if len(expr.args) == 2 and expr.args[1].op == "BVV":
|
|
362
|
-
reg_offset = JumpTableProcessor._extract_regoffset_from_expr(expr.args[0])
|
|
367
|
+
return JumpTableProcessor._extract_regoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
368
|
+
if len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
369
|
+
reg_offset = JumpTableProcessor._extract_regoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
363
370
|
if reg_offset is not None:
|
|
364
|
-
delta = expr.args[1].concrete_value
|
|
371
|
+
delta = cast(claripy.ast.BV, expr.args[1]).concrete_value
|
|
365
372
|
reg_offset += delta
|
|
366
373
|
return reg_offset
|
|
367
|
-
elif expr.op == "__and__" and len(expr.args) == 2 and expr.args[1].op == "BVV":
|
|
374
|
+
elif expr.op == "__and__" and len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
368
375
|
# ignore all masking on SpOffsets
|
|
369
|
-
return JumpTableProcessor._extract_spoffset_from_expr(expr.args[0])
|
|
376
|
+
return JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
370
377
|
return None
|
|
371
378
|
|
|
372
|
-
def
|
|
379
|
+
def _handle_stmt_WrTmp(self, stmt):
|
|
373
380
|
self._tsrc = set()
|
|
374
|
-
super()._handle_WrTmp(stmt)
|
|
375
381
|
|
|
382
|
+
self.tmps[stmt.tmp] = self._expr(stmt.data)
|
|
376
383
|
if self._tsrc:
|
|
377
384
|
self.state._tmpvar_source[stmt.tmp] = self._tsrc
|
|
378
385
|
|
|
379
|
-
def
|
|
386
|
+
def _handle_stmt_Put(self, stmt):
|
|
380
387
|
self._tsrc = set()
|
|
381
388
|
offset = stmt.offset
|
|
382
389
|
data = self._expr(stmt.data)
|
|
383
390
|
r = (self._tsrc, data) if self._tsrc is not None else ((self.block.addr, self.stmt_idx), data)
|
|
384
391
|
self.state._registers[offset] = r
|
|
385
392
|
|
|
386
|
-
def
|
|
393
|
+
def _handle_stmt_Store(self, stmt):
|
|
387
394
|
self._tsrc = set()
|
|
388
395
|
addr = self._expr(stmt.addr)
|
|
389
396
|
data = self._expr(stmt.data)
|
|
@@ -394,13 +401,16 @@ class JumpTableProcessor(
|
|
|
394
401
|
if isinstance(addr, SpOffset):
|
|
395
402
|
self.state._stack[addr.offset] = ((self.block.addr, self.stmt_idx), data)
|
|
396
403
|
|
|
397
|
-
def
|
|
398
|
-
|
|
404
|
+
def _handle_expr_RdTmp(self, expr):
|
|
405
|
+
try:
|
|
406
|
+
v = self.tmps[expr.tmp]
|
|
407
|
+
except KeyError:
|
|
408
|
+
v = self._top(expr.result_size(self.tyenv))
|
|
399
409
|
if expr.tmp in self.state._tmpvar_source:
|
|
400
410
|
self._tsrc |= set(self.state._tmpvar_source[expr.tmp])
|
|
401
411
|
return v
|
|
402
412
|
|
|
403
|
-
def
|
|
413
|
+
def _handle_expr_Get(self, expr):
|
|
404
414
|
if expr.offset == self.arch.bp_offset:
|
|
405
415
|
v = self._get_spoffset_expr(SpOffset(self.arch.bits, self._bp_sp_diff))
|
|
406
416
|
elif expr.offset == self.arch.sp_offset:
|
|
@@ -433,55 +443,77 @@ class JumpTableProcessor(
|
|
|
433
443
|
def _handle_function(self, expr): # pylint:disable=unused-argument,no-self-use
|
|
434
444
|
return None # This analysis is not interprocedural
|
|
435
445
|
|
|
436
|
-
def
|
|
446
|
+
def _handle_expr_Load(self, expr):
|
|
437
447
|
addr = self._expr(expr.addr)
|
|
438
448
|
size = expr.result_size(self.tyenv) // 8
|
|
439
449
|
return self._do_load(addr, size)
|
|
440
450
|
|
|
441
|
-
def
|
|
442
|
-
|
|
443
|
-
if guard is True:
|
|
444
|
-
return self._do_load(stmt.addr, stmt.addr.result_size(self.tyenv) // 8)
|
|
445
|
-
if guard is False:
|
|
446
|
-
return self._do_load(stmt.alt, stmt.alt.result_size(self.tyenv) // 8)
|
|
447
|
-
return None
|
|
451
|
+
def _handle_stmt_LoadG(self, stmt: pyvex.stmt.LoadG):
|
|
452
|
+
self._tsrc = set()
|
|
448
453
|
|
|
449
|
-
|
|
450
|
-
|
|
454
|
+
guard = self._expr(stmt.guard) != 0
|
|
455
|
+
iftrue = self._do_load(self._expr(stmt.addr), stmt.addr.result_size(self.tyenv) // 8)
|
|
456
|
+
iffalse = self._expr(stmt.alt)
|
|
457
|
+
result = claripy.If(guard, iftrue, iffalse)
|
|
458
|
+
self.tmps[stmt.dst] = result
|
|
459
|
+
if self._tsrc:
|
|
460
|
+
self.state._tmpvar_source[stmt.dst] = self._tsrc
|
|
461
|
+
|
|
462
|
+
def _handle_expr_Const(self, expr):
|
|
463
|
+
v = value(expr.con.type, expr.con.value)
|
|
451
464
|
self._tsrc.add("const")
|
|
465
|
+
if not isinstance(v, claripy.ast.BV):
|
|
466
|
+
return self._top(expr.result_size(self.tyenv))
|
|
452
467
|
return v
|
|
453
468
|
|
|
454
|
-
|
|
455
|
-
|
|
469
|
+
@binop_handler
|
|
470
|
+
def _handle_binop_CmpLE(self, expr):
|
|
471
|
+
return self._handle_Comparison(*expr.args)
|
|
456
472
|
|
|
457
|
-
|
|
458
|
-
|
|
473
|
+
@binop_handler
|
|
474
|
+
def _handle_binop_CmpGE(self, expr):
|
|
475
|
+
return self._handle_Comparison(*expr.args)
|
|
459
476
|
|
|
460
|
-
|
|
461
|
-
|
|
477
|
+
@binop_handler
|
|
478
|
+
def _handle_binop_CmpLT(self, expr):
|
|
479
|
+
return self._handle_Comparison(*expr.args)
|
|
462
480
|
|
|
463
|
-
|
|
464
|
-
|
|
481
|
+
@binop_handler
|
|
482
|
+
def _handle_binop_CmpGT(self, expr):
|
|
483
|
+
return self._handle_Comparison(*expr.args)
|
|
465
484
|
|
|
466
|
-
def
|
|
467
|
-
if
|
|
468
|
-
|
|
469
|
-
cond_type_enum = expr.args[0].con.value
|
|
485
|
+
def _handle_expr_CCall(self, expr):
|
|
486
|
+
if isinstance(expr.args[0], pyvex.IRExpr.Const):
|
|
487
|
+
cond_type_enum = expr.args[0].con.value
|
|
470
488
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
489
|
+
if self.arch.name in {"X86", "AMD64", "AARCH64"}:
|
|
490
|
+
if cond_type_enum in EXPECTED_COND_TYPES[self.arch.name]:
|
|
491
|
+
self._handle_Comparison(expr.args[2], expr.args[3])
|
|
492
|
+
elif is_arm_arch(self.arch):
|
|
493
|
+
if cond_type_enum in EXPECTED_COND_TYPES["ARM"]:
|
|
494
|
+
self._handle_Comparison(expr.args[2], expr.args[3])
|
|
495
|
+
else:
|
|
496
|
+
# other architectures
|
|
497
|
+
l.warning("Please fill in EXPECTED_COND_TYPES for %s.", self.arch.name)
|
|
476
498
|
self._handle_Comparison(expr.args[2], expr.args[3])
|
|
477
|
-
else:
|
|
478
|
-
# other architectures
|
|
479
|
-
l.warning("Please fill in EXPECTED_COND_TYPES for %s.", self.arch.name)
|
|
480
|
-
self._handle_Comparison(expr.args[2], expr.args[3])
|
|
481
499
|
|
|
482
|
-
|
|
500
|
+
return self._top(expr.result_size(self.tyenv))
|
|
501
|
+
|
|
502
|
+
def _handle_expr_VECRET(self, expr):
|
|
503
|
+
return self._top(expr.result_size(self.tyenv))
|
|
504
|
+
|
|
505
|
+
def _handle_expr_GSPTR(self, expr):
|
|
506
|
+
return self._top(expr.result_size(self.tyenv))
|
|
507
|
+
|
|
508
|
+
def _handle_expr_GetI(self, expr):
|
|
509
|
+
return self._top(expr.result_size(self.tyenv))
|
|
510
|
+
|
|
511
|
+
def _handle_expr_ITE(self, expr):
|
|
512
|
+
return self._top(expr.result_size(self.tyenv))
|
|
513
|
+
|
|
514
|
+
def _handle_Comparison(self, arg0: pyvex.expr.IRExpr, arg1: pyvex.expr.IRExpr) -> claripy.ast.BV:
|
|
483
515
|
if self.block.addr not in self._indirect_jump_node_pred_addrs:
|
|
484
|
-
return
|
|
516
|
+
return self._top(1)
|
|
485
517
|
|
|
486
518
|
# found the comparison
|
|
487
519
|
arg0_src, arg1_src = None, None
|
|
@@ -502,10 +534,10 @@ class JumpTableProcessor(
|
|
|
502
534
|
if arg0_src == "const" and arg1_src == "const":
|
|
503
535
|
# comparison of two consts... there is nothing we can do
|
|
504
536
|
self.state.is_jumptable = True
|
|
505
|
-
return
|
|
537
|
+
return self._top(1)
|
|
506
538
|
if arg0_src not in {"const", None} and arg1_src not in {"const", None}:
|
|
507
539
|
# this is probably not a jump table
|
|
508
|
-
return
|
|
540
|
+
return self._top(1)
|
|
509
541
|
if arg1_src == "const":
|
|
510
542
|
# make sure arg0_src is const
|
|
511
543
|
arg0_src, arg1_src = arg1_src, arg0_src
|
|
@@ -515,7 +547,7 @@ class JumpTableProcessor(
|
|
|
515
547
|
if arg0_src != "const":
|
|
516
548
|
# we failed during dependency tracking so arg0_src couldn't be determined
|
|
517
549
|
# but we will still try to resolve it as a jump table as a fall back
|
|
518
|
-
return
|
|
550
|
+
return self._top(1)
|
|
519
551
|
|
|
520
552
|
if isinstance(arg1_src, tuple):
|
|
521
553
|
arg1_src_stmt = self.project.factory.block(arg1_src[0], cross_insn_opt=True).vex.statements[arg1_src[1]]
|
|
@@ -563,23 +595,17 @@ class JumpTableProcessor(
|
|
|
563
595
|
#
|
|
564
596
|
self.state.stmts_to_instrument.append(("reg_write", *arg1_src))
|
|
565
597
|
|
|
566
|
-
|
|
598
|
+
return self._top(1)
|
|
599
|
+
|
|
600
|
+
def _do_load(self, addr: claripy.ast.BV, size: int) -> claripy.ast.BV:
|
|
567
601
|
src = (self.block.addr, self.stmt_idx)
|
|
568
602
|
self._tsrc = {src}
|
|
569
|
-
if addr is None:
|
|
570
|
-
return None
|
|
571
603
|
|
|
572
604
|
if self._is_spoffset(addr):
|
|
573
605
|
spoffset = self._extract_spoffset_from_expr(addr)
|
|
574
606
|
if spoffset is not None and spoffset.offset in self.state._stack:
|
|
575
607
|
self._tsrc = {self.state._stack[spoffset.offset][0]}
|
|
576
608
|
return self.state._stack[spoffset.offset][1]
|
|
577
|
-
elif isinstance(addr, int):
|
|
578
|
-
# Load data from memory if it is mapped
|
|
579
|
-
try:
|
|
580
|
-
return self.project.loader.memory.unpack_word(addr, size=size)
|
|
581
|
-
except KeyError:
|
|
582
|
-
return None
|
|
583
609
|
elif self._is_registeroffset(addr):
|
|
584
610
|
# Load data from a register, but this register hasn't been initialized at this point
|
|
585
611
|
# We will need to initialize this register during slice execution later
|
|
@@ -598,9 +624,7 @@ class JumpTableProcessor(
|
|
|
598
624
|
# function call sub_375c04. Since we do not analyze sub_375c04, we treat r0@11e918 as a constant 0.
|
|
599
625
|
pass
|
|
600
626
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
return None
|
|
627
|
+
return self._top(size)
|
|
604
628
|
|
|
605
629
|
|
|
606
630
|
#
|
|
@@ -658,10 +682,10 @@ class RegisterInitializerHook:
|
|
|
658
682
|
Hook for register init.
|
|
659
683
|
"""
|
|
660
684
|
|
|
661
|
-
def __init__(self, reg_offset, reg_bits,
|
|
685
|
+
def __init__(self, reg_offset, reg_bits, initial_value):
|
|
662
686
|
self.reg_offset = reg_offset
|
|
663
687
|
self.reg_bits = reg_bits
|
|
664
|
-
self.value =
|
|
688
|
+
self.value = initial_value
|
|
665
689
|
|
|
666
690
|
def hook(self, state):
|
|
667
691
|
state.registers.store(self.reg_offset, claripy.BVV(self.value, self.reg_bits))
|
|
@@ -786,7 +810,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
786
810
|
|
|
787
811
|
self._bss_regions = None
|
|
788
812
|
# the maximum number of resolved targets. Will be initialized from CFG.
|
|
789
|
-
self._max_targets =
|
|
813
|
+
self._max_targets = 0
|
|
790
814
|
|
|
791
815
|
# cached memory read addresses that are used to initialize uninitialized registers
|
|
792
816
|
# should be cleared before every symbolic execution run on the slice
|
|
@@ -1044,8 +1068,10 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1044
1068
|
simgr.use_technique(slicecutor)
|
|
1045
1069
|
simgr.use_technique(LocalLoopSeer(bound=1))
|
|
1046
1070
|
if load_stmt is not None:
|
|
1071
|
+
assert load_stmt_loc is not None
|
|
1047
1072
|
explorer = Explorer(find=load_stmt_loc[0])
|
|
1048
1073
|
elif ite_stmt is not None:
|
|
1074
|
+
assert ite_stmt_loc is not None
|
|
1049
1075
|
explorer = Explorer(find=ite_stmt_loc[0])
|
|
1050
1076
|
else:
|
|
1051
1077
|
raise TypeError("Unsupported type of jump table.")
|
|
@@ -1144,7 +1170,14 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1144
1170
|
l.info("Could not resolve indirect jump %#x in function %#x.", addr, func_addr)
|
|
1145
1171
|
return False, None
|
|
1146
1172
|
|
|
1147
|
-
def _find_load_statement(self, b, stmt_loc)
|
|
1173
|
+
def _find_load_statement(self, b, stmt_loc: tuple[int, int]) -> tuple[
|
|
1174
|
+
tuple[int, int] | None,
|
|
1175
|
+
pyvex.stmt.IRStmt | None,
|
|
1176
|
+
int | None,
|
|
1177
|
+
list[tuple[int, int]],
|
|
1178
|
+
list[JumpTargetBaseAddr],
|
|
1179
|
+
OrderedDict[tuple[int, int], AddressTransformation],
|
|
1180
|
+
]:
|
|
1148
1181
|
"""
|
|
1149
1182
|
Find the location of the final Load statement that loads indirect jump targets from the jump table.
|
|
1150
1183
|
"""
|
|
@@ -1306,6 +1339,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1306
1339
|
if isinstance(stmt.data.args[0], pyvex.IRExpr.Const) and isinstance(
|
|
1307
1340
|
stmt.data.args[1], pyvex.IRExpr.RdTmp
|
|
1308
1341
|
):
|
|
1342
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1309
1343
|
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1310
1344
|
AddressTransformationTypes.Add, [stmt.data.args[0].con.value, AddressSingleton]
|
|
1311
1345
|
)
|
|
@@ -1315,6 +1349,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1315
1349
|
elif isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp) and isinstance(
|
|
1316
1350
|
stmt.data.args[1], pyvex.IRExpr.Const
|
|
1317
1351
|
):
|
|
1352
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1318
1353
|
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1319
1354
|
AddressTransformationTypes.Add, [AddressSingleton, stmt.data.args[1].con.value]
|
|
1320
1355
|
)
|
|
@@ -1363,6 +1398,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1363
1398
|
and isinstance(stmt.data.args[1], pyvex.IRExpr.Const)
|
|
1364
1399
|
and stmt.data.args[1].con.value == 1
|
|
1365
1400
|
):
|
|
1401
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1366
1402
|
# great. here it is
|
|
1367
1403
|
stmts_to_remove.append(stmt_loc)
|
|
1368
1404
|
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
@@ -1387,6 +1423,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1387
1423
|
if isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp) and isinstance(
|
|
1388
1424
|
stmt.data.args[1], pyvex.IRExpr.Const
|
|
1389
1425
|
):
|
|
1426
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1390
1427
|
# found it
|
|
1391
1428
|
stmts_to_remove.append(stmt_loc)
|
|
1392
1429
|
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
@@ -1424,6 +1461,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1424
1461
|
and isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp)
|
|
1425
1462
|
and isinstance(stmt.data.args[1], pyvex.IRExpr.Const)
|
|
1426
1463
|
):
|
|
1464
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1427
1465
|
# found it
|
|
1428
1466
|
stmts_to_remove.append(stmt_loc)
|
|
1429
1467
|
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
@@ -1431,6 +1469,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1431
1469
|
)
|
|
1432
1470
|
continue
|
|
1433
1471
|
elif isinstance(stmt.data, pyvex.IRExpr.Load):
|
|
1472
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1434
1473
|
# Got it!
|
|
1435
1474
|
load_stmt, load_stmt_loc, load_size = (
|
|
1436
1475
|
stmt,
|
|
@@ -1558,9 +1597,10 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1558
1597
|
|
|
1559
1598
|
block = self.project.factory.block(block_addr, cross_insn_opt=True, backup_state=self.base_state)
|
|
1560
1599
|
stmt_whitelist = annotatedcfg.get_whitelisted_statements(block_addr)
|
|
1600
|
+
assert isinstance(stmt_whitelist, list)
|
|
1561
1601
|
try:
|
|
1562
1602
|
engine.process(state, block=block, whitelist=stmt_whitelist)
|
|
1563
|
-
except (claripy.
|
|
1603
|
+
except (claripy.ClaripyError, SimError, AngrError):
|
|
1564
1604
|
# anything can happen
|
|
1565
1605
|
break
|
|
1566
1606
|
|
|
@@ -1598,6 +1638,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1598
1638
|
|
|
1599
1639
|
# If we're just reading a constant, don't bother with the rest of this mess!
|
|
1600
1640
|
if isinstance(load_stmt, pyvex.IRStmt.WrTmp):
|
|
1641
|
+
assert isinstance(load_stmt.data, pyvex.IRExpr.Load)
|
|
1601
1642
|
if type(load_stmt.data.addr) is pyvex.IRExpr.Const:
|
|
1602
1643
|
# It's directly loading from a constant address
|
|
1603
1644
|
# e.g.,
|
|
@@ -1717,7 +1758,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1717
1758
|
# full-function data propagation before performing jump table recovery.
|
|
1718
1759
|
l.debug("Multiple statements adding bases, not supported yet") # FIXME: Just check the addresses?
|
|
1719
1760
|
|
|
1720
|
-
if jumptable_addr.has_annotation_type(claripy.
|
|
1761
|
+
if jumptable_addr.has_annotation_type(claripy.RegionAnnotation):
|
|
1721
1762
|
return None
|
|
1722
1763
|
|
|
1723
1764
|
all_targets = []
|
|
@@ -1730,7 +1771,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1730
1771
|
jumptable_si = claripy.backends.vsa.simplify(jumptable_addr)
|
|
1731
1772
|
si_annotation = jumptable_si.get_annotation(claripy.annotation.StridedIntervalAnnotation)
|
|
1732
1773
|
stride = si_annotation.stride if si_annotation is not None else 0
|
|
1733
|
-
except claripy.
|
|
1774
|
+
except claripy.ClaripyError:
|
|
1734
1775
|
return None
|
|
1735
1776
|
|
|
1736
1777
|
# we may resolve a vtable (in C, e.g., the IO_JUMPS_FUNC in libc), but the stride of this load is usually 1
|
|
@@ -1745,6 +1786,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1745
1786
|
total_cases = jumptable_addr.cardinality
|
|
1746
1787
|
sort = "jumptable"
|
|
1747
1788
|
|
|
1789
|
+
assert self._max_targets is not None
|
|
1748
1790
|
if total_cases > self._max_targets:
|
|
1749
1791
|
if (
|
|
1750
1792
|
potential_call_table
|
|
@@ -1755,6 +1797,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
1755
1797
|
# Undetermined table size. Take a guess based on target plausibility.
|
|
1756
1798
|
table_base_addr = None
|
|
1757
1799
|
for arg in jumptable_addr.args:
|
|
1800
|
+
assert isinstance(arg, (claripy.ast.BV, claripy.ast.FP, claripy.ast.Bool))
|
|
1758
1801
|
if arg.concrete:
|
|
1759
1802
|
table_base_addr = state.solver.eval(arg)
|
|
1760
1803
|
break
|
|
@@ -2223,6 +2266,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
2223
2266
|
load_addr_tmp = None
|
|
2224
2267
|
|
|
2225
2268
|
if isinstance(load_stmt, pyvex.IRStmt.WrTmp):
|
|
2269
|
+
assert isinstance(load_stmt.data, pyvex.IRExpr.Load)
|
|
2226
2270
|
if type(load_stmt.data.addr) is pyvex.IRExpr.RdTmp:
|
|
2227
2271
|
load_addr_tmp = load_stmt.data.addr.tmp
|
|
2228
2272
|
elif type(load_stmt.data.addr) is pyvex.IRExpr.Const:
|
|
@@ -2260,6 +2304,7 @@ class JumpTableResolver(IndirectJumpResolver):
|
|
|
2260
2304
|
|
|
2261
2305
|
if isinstance(load_stmt, pyvex.IRStmt.LoadG) and not isinstance(load_stmt.guard, pyvex.IRExpr.Const):
|
|
2262
2306
|
# LoadG comes with a guard. We should apply this guard to the load expression
|
|
2307
|
+
assert isinstance(load_stmt.guard, pyvex.expr.RdTmp)
|
|
2263
2308
|
guard_tmp = load_stmt.guard.tmp
|
|
2264
2309
|
guard = state.scratch.temps[guard_tmp] != 0
|
|
2265
2310
|
try:
|
|
@@ -78,7 +78,7 @@ class X86ElfPicPltResolver(IndirectJumpResolver):
|
|
|
78
78
|
state = cfg._initial_state.copy() if cfg._initial_state is not None else self.project.factory.blank_state()
|
|
79
79
|
state.regs.ebx = got_addr
|
|
80
80
|
|
|
81
|
-
successors = self.project.factory.default_engine.process(state, block, force_addr=addr)
|
|
81
|
+
successors = self.project.factory.default_engine.process(state, block=block, force_addr=addr)
|
|
82
82
|
|
|
83
83
|
if len(successors.flat_successors) != 1:
|
|
84
84
|
return False, []
|