angr 9.2.138__py3-none-manylinux2014_x86_64.whl → 9.2.140__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/calling_convention/calling_convention.py +48 -21
- angr/analyses/calling_convention/fact_collector.py +59 -12
- angr/analyses/calling_convention/utils.py +2 -2
- angr/analyses/cfg/cfg_base.py +13 -0
- angr/analyses/cfg/cfg_fast.py +23 -4
- angr/analyses/decompiler/ail_simplifier.py +79 -53
- angr/analyses/decompiler/block_simplifier.py +0 -2
- angr/analyses/decompiler/callsite_maker.py +80 -14
- angr/analyses/decompiler/clinic.py +99 -80
- angr/analyses/decompiler/condition_processor.py +2 -2
- angr/analyses/decompiler/decompiler.py +19 -7
- angr/analyses/decompiler/dephication/rewriting_engine.py +16 -7
- angr/analyses/decompiler/expression_narrower.py +1 -1
- angr/analyses/decompiler/optimization_passes/__init__.py +3 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +149 -0
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +12 -3
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +21 -12
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +17 -9
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +7 -10
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +12 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +61 -25
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +50 -1
- angr/analyses/decompiler/presets/fast.py +2 -0
- angr/analyses/decompiler/presets/full.py +2 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +259 -108
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +28 -9
- angr/analyses/decompiler/ssailification/rewriting_engine.py +20 -2
- angr/analyses/decompiler/ssailification/traversal_engine.py +4 -3
- angr/analyses/decompiler/structured_codegen/c.py +10 -3
- angr/analyses/decompiler/structuring/dream.py +28 -19
- angr/analyses/decompiler/structuring/phoenix.py +253 -89
- angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
- angr/analyses/decompiler/structuring/structurer_base.py +121 -46
- angr/analyses/decompiler/structuring/structurer_nodes.py +6 -1
- angr/analyses/decompiler/utils.py +60 -1
- angr/analyses/deobfuscator/api_obf_finder.py +13 -5
- angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
- angr/analyses/deobfuscator/string_obf_finder.py +105 -18
- angr/analyses/forward_analysis/forward_analysis.py +1 -1
- angr/analyses/propagator/top_checker_mixin.py +6 -6
- angr/analyses/reaching_definitions/__init__.py +2 -1
- angr/analyses/reaching_definitions/dep_graph.py +1 -12
- angr/analyses/reaching_definitions/engine_vex.py +36 -31
- angr/analyses/reaching_definitions/function_handler.py +15 -2
- angr/analyses/reaching_definitions/rd_state.py +1 -37
- angr/analyses/reaching_definitions/reaching_definitions.py +13 -24
- angr/analyses/s_propagator.py +129 -87
- angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
- angr/analyses/s_reaching_definitions/s_rda_view.py +2 -2
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -1
- angr/analyses/stack_pointer_tracker.py +36 -22
- angr/analyses/typehoon/simple_solver.py +45 -7
- angr/analyses/typehoon/typeconsts.py +18 -5
- angr/analyses/variable_recovery/engine_ail.py +1 -1
- angr/analyses/variable_recovery/engine_base.py +62 -67
- angr/analyses/variable_recovery/engine_vex.py +1 -1
- angr/analyses/variable_recovery/irsb_scanner.py +2 -2
- angr/block.py +69 -107
- angr/callable.py +14 -7
- angr/calling_conventions.py +81 -10
- angr/distributed/__init__.py +1 -1
- angr/engines/__init__.py +7 -8
- angr/engines/engine.py +3 -138
- angr/engines/failure.py +2 -2
- angr/engines/hook.py +2 -2
- angr/engines/light/engine.py +5 -10
- angr/engines/pcode/emulate.py +2 -2
- angr/engines/pcode/engine.py +2 -14
- angr/engines/pcode/lifter.py +2 -2
- angr/engines/procedure.py +2 -2
- angr/engines/soot/engine.py +2 -2
- angr/engines/soot/statements/switch.py +1 -1
- angr/engines/successors.py +123 -17
- angr/engines/syscall.py +2 -2
- angr/engines/unicorn.py +3 -3
- angr/engines/vex/heavy/heavy.py +3 -15
- angr/engines/vex/lifter.py +2 -2
- angr/engines/vex/light/light.py +2 -2
- angr/factory.py +4 -19
- angr/knowledge_plugins/cfg/cfg_model.py +3 -2
- angr/knowledge_plugins/key_definitions/atoms.py +8 -4
- angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
- angr/knowledge_plugins/labels.py +2 -2
- angr/knowledge_plugins/obfuscations.py +1 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +4 -0
- angr/sim_type.py +19 -17
- angr/state_plugins/plugin.py +19 -4
- angr/storage/memory_mixins/memory_mixin.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +10 -5
- angr/utils/ssa/__init__.py +119 -4
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/METADATA +6 -6
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/RECORD +100 -98
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/LICENSE +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/WHEEL +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/entry_points.txt +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/top_level.txt +0 -0
angr/engines/failure.py
CHANGED
|
@@ -3,13 +3,13 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
from angr.errors import AngrExitError
|
|
6
|
-
from .
|
|
6
|
+
from .successors import SuccessorsEngine
|
|
7
7
|
from .procedure import ProcedureMixin
|
|
8
8
|
|
|
9
9
|
l = logging.getLogger(name=__name__)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class SimEngineFailure(
|
|
12
|
+
class SimEngineFailure(SuccessorsEngine, ProcedureMixin):
|
|
13
13
|
def process_successors(self, successors, **kwargs):
|
|
14
14
|
state = self.state
|
|
15
15
|
jumpkind = state.history.parent.jumpkind if state.history and state.history.parent else None
|
angr/engines/hook.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
|
-
from .
|
|
4
|
+
from .successors import SuccessorsEngine
|
|
5
5
|
from .procedure import ProcedureMixin
|
|
6
6
|
from archinfo.arch_soot import SootAddressDescriptor
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ l = logging.getLogger(name=__name__)
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
# pylint: disable=abstract-method,unused-argument,arguments-differ
|
|
12
|
-
class HooksMixin(
|
|
12
|
+
class HooksMixin(SuccessorsEngine, ProcedureMixin):
|
|
13
13
|
"""
|
|
14
14
|
A SimEngine mixin which adds a SimSuccessors handler which will look into the project's hooks and run the hook at
|
|
15
15
|
the current address.
|
angr/engines/light/engine.py
CHANGED
|
@@ -64,13 +64,8 @@ class SimEngineLight(Generic[StateType, DataType_co, BlockType, ResultType], Sim
|
|
|
64
64
|
self.l = logger or logging.getLogger(self.__module__ + "." + self.__class__.__name__)
|
|
65
65
|
super().__init__(project)
|
|
66
66
|
|
|
67
|
-
# there's two of these to support the mixin pattern - mixins can override process while there must be some base
|
|
68
|
-
# class that provides _process
|
|
69
|
-
def process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType:
|
|
70
|
-
return self._process(state, block=block, **kwargs)
|
|
71
|
-
|
|
72
67
|
@abstractmethod
|
|
73
|
-
def
|
|
68
|
+
def process(self, state: StateType, *, block: BlockType | None = None, **kwargs) -> ResultType: ...
|
|
74
69
|
|
|
75
70
|
def lift(self, state: StateType) -> BlockType:
|
|
76
71
|
raise TypeError(f"{type(self)} requires `block` to be passed to `process`")
|
|
@@ -164,7 +159,7 @@ class SimEngineLightVEX(
|
|
|
164
159
|
|
|
165
160
|
@staticmethod
|
|
166
161
|
def binopv_handler(
|
|
167
|
-
f: Callable[[T, int, int, pyvex.expr.Binop], DataType_co]
|
|
162
|
+
f: Callable[[T, int, int, pyvex.expr.Binop], DataType_co],
|
|
168
163
|
) -> Callable[[T, int, int, pyvex.expr.Binop], DataType_co]:
|
|
169
164
|
f.binopv_handler = True
|
|
170
165
|
return f
|
|
@@ -186,7 +181,7 @@ class SimEngineLightVEX(
|
|
|
186
181
|
|
|
187
182
|
@staticmethod
|
|
188
183
|
def dirty_handler(
|
|
189
|
-
f: Callable[[T, pyvex.stmt.Dirty], StmtDataType]
|
|
184
|
+
f: Callable[[T, pyvex.stmt.Dirty], StmtDataType],
|
|
190
185
|
) -> Callable[[T, pyvex.stmt.Dirty], StmtDataType]:
|
|
191
186
|
f.dirty_handler = True
|
|
192
187
|
return f
|
|
@@ -267,7 +262,7 @@ class SimEngineLightVEX(
|
|
|
267
262
|
if name.startswith("_handle_dirty_")
|
|
268
263
|
}
|
|
269
264
|
|
|
270
|
-
def
|
|
265
|
+
def process(
|
|
271
266
|
self, state: StateType, *, block: Block | None = None, whitelist: set[int] | None = None, **kwargs
|
|
272
267
|
) -> ResultType:
|
|
273
268
|
# initialize local variables
|
|
@@ -640,7 +635,7 @@ class SimEngineLightAIL(
|
|
|
640
635
|
}
|
|
641
636
|
super().__init__(*args, **kwargs)
|
|
642
637
|
|
|
643
|
-
def
|
|
638
|
+
def process(
|
|
644
639
|
self, state: StateType, *, block: ailment.Block | None = None, whitelist: set[int] | None = None, **kwargs
|
|
645
640
|
) -> ResultType:
|
|
646
641
|
self.tmps = {}
|
angr/engines/pcode/emulate.py
CHANGED
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
import claripy
|
|
5
5
|
from claripy.ast.bv import BV
|
|
6
6
|
|
|
7
|
-
from angr.engines.engine import
|
|
7
|
+
from angr.engines.engine import SimEngine
|
|
8
8
|
from angr.utils.constants import DEFAULT_STATEMENT
|
|
9
9
|
from .lifter import IRSB
|
|
10
10
|
from .behavior import OpBehavior
|
|
@@ -19,7 +19,7 @@ with contextlib.suppress(ImportError):
|
|
|
19
19
|
l = logging.getLogger(__name__)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class PcodeEmulatorMixin(
|
|
22
|
+
class PcodeEmulatorMixin(SimEngine):
|
|
23
23
|
"""
|
|
24
24
|
Mixin for p-code execution.
|
|
25
25
|
"""
|
angr/engines/pcode/engine.py
CHANGED
|
@@ -5,7 +5,7 @@ import claripy
|
|
|
5
5
|
import logging
|
|
6
6
|
|
|
7
7
|
from angr.calling_conventions import DEFAULT_CC, default_cc, SimRegArg
|
|
8
|
-
from angr.engines.
|
|
8
|
+
from angr.engines.successors import SuccessorsEngine, SimSuccessors
|
|
9
9
|
from angr.misc.ux import once
|
|
10
10
|
from angr.utils.constants import DEFAULT_STATEMENT
|
|
11
11
|
from angr import sim_options as o
|
|
@@ -19,7 +19,7 @@ l = logging.getLogger(__name__)
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class HeavyPcodeMixin(
|
|
22
|
-
|
|
22
|
+
SuccessorsEngine,
|
|
23
23
|
PcodeLifterEngineMixin,
|
|
24
24
|
PcodeEmulatorMixin,
|
|
25
25
|
):
|
|
@@ -52,7 +52,6 @@ class HeavyPcodeMixin(
|
|
|
52
52
|
self,
|
|
53
53
|
successors: SimSuccessors,
|
|
54
54
|
irsb: IRSB | None = None,
|
|
55
|
-
insn_text: str | None = None,
|
|
56
55
|
insn_bytes: bytes | None = None,
|
|
57
56
|
thumb: bool = False,
|
|
58
57
|
size: int | None = None,
|
|
@@ -67,21 +66,10 @@ class HeavyPcodeMixin(
|
|
|
67
66
|
extra_stop_points=extra_stop_points,
|
|
68
67
|
num_inst=num_inst,
|
|
69
68
|
size=size,
|
|
70
|
-
insn_text=insn_text,
|
|
71
69
|
insn_bytes=insn_bytes,
|
|
72
70
|
**kwargs,
|
|
73
71
|
)
|
|
74
72
|
|
|
75
|
-
if insn_text is not None:
|
|
76
|
-
if insn_bytes is not None:
|
|
77
|
-
raise errors.SimEngineError("You cannot provide both 'insn_bytes' and 'insn_text'!")
|
|
78
|
-
|
|
79
|
-
insn_bytes = self.project.arch.asm(insn_text, addr=successors.addr, thumb=thumb)
|
|
80
|
-
if insn_bytes is None:
|
|
81
|
-
raise errors.AngrAssemblyError(
|
|
82
|
-
"Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
|
|
83
|
-
)
|
|
84
|
-
|
|
85
73
|
successors.sort = "IRSB"
|
|
86
74
|
successors.description = "IRSB"
|
|
87
75
|
self.state.history.recent_block_count = 1
|
angr/engines/pcode/lifter.py
CHANGED
|
@@ -20,7 +20,7 @@ from cachetools import LRUCache
|
|
|
20
20
|
from pyvex.errors import PyVEXError, SkipStatementsError, LiftingException
|
|
21
21
|
|
|
22
22
|
from .behavior import BehaviorFactory
|
|
23
|
-
from angr.engines.engine import
|
|
23
|
+
from angr.engines.engine import SimEngine
|
|
24
24
|
from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
|
|
25
25
|
from angr.sim_state import SimState
|
|
26
26
|
from angr.misc.ux import once
|
|
@@ -981,7 +981,7 @@ class PcodeLifter(Lifter):
|
|
|
981
981
|
raise LiftingException(f"pypcode: could not decode any instructions @ 0x{self.addr:x}")
|
|
982
982
|
|
|
983
983
|
|
|
984
|
-
class PcodeLifterEngineMixin(
|
|
984
|
+
class PcodeLifterEngineMixin(SimEngine):
|
|
985
985
|
"""
|
|
986
986
|
Lifter mixin to lift from machine code to P-Code.
|
|
987
987
|
"""
|
angr/engines/procedure.py
CHANGED
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from angr import sim_options as o
|
|
5
5
|
from angr import errors
|
|
6
6
|
from angr.state_plugins.inspect import BP_BEFORE, BP_AFTER
|
|
7
|
-
from .
|
|
7
|
+
from .successors import SuccessorsEngine
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
l = logging.getLogger(name=__name__)
|
|
@@ -58,7 +58,7 @@ class ProcedureMixin:
|
|
|
58
58
|
successors.processed = True
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
class ProcedureEngine(ProcedureMixin,
|
|
61
|
+
class ProcedureEngine(ProcedureMixin, SuccessorsEngine):
|
|
62
62
|
"""
|
|
63
63
|
A SimEngine that you may use if you only care about processing SimProcedures. *Requires* the procedure
|
|
64
64
|
kwarg to be passed to process.
|
angr/engines/soot/engine.py
CHANGED
|
@@ -15,7 +15,7 @@ from angr.errors import SimEngineError, SimTranslationError
|
|
|
15
15
|
from cle import CLEError
|
|
16
16
|
from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
|
|
17
17
|
from angr.sim_type import SimTypeFunction, parse_type
|
|
18
|
-
from angr.engines.
|
|
18
|
+
from angr.engines.successors import SuccessorsEngine
|
|
19
19
|
from angr.engines.procedure import ProcedureMixin
|
|
20
20
|
from .exceptions import BlockTerminationNotice, IncorrectLocationException
|
|
21
21
|
from .statements import SimSootStmt_Return, SimSootStmt_ReturnVoid, translate_stmt
|
|
@@ -26,7 +26,7 @@ l = logging.getLogger("angr.engines.soot.engine")
|
|
|
26
26
|
# pylint: disable=arguments-differ
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class SootMixin(
|
|
29
|
+
class SootMixin(SuccessorsEngine, ProcedureMixin):
|
|
30
30
|
"""
|
|
31
31
|
Execution engine based on Soot.
|
|
32
32
|
"""
|
|
@@ -25,7 +25,7 @@ class SwitchBase(SimSootStmt):
|
|
|
25
25
|
jmp_condition = lookup_value == key_val
|
|
26
26
|
self._add_jmp_target(jmp_target, jmp_condition)
|
|
27
27
|
# add condition for the default target
|
|
28
|
-
default_jmp_conditions += [
|
|
28
|
+
default_jmp_conditions += [lookup_value != key_val]
|
|
29
29
|
|
|
30
30
|
# add default target
|
|
31
31
|
default_jmp_target = self._get_bb_addr_from_instr(self.stmt.default_target)
|
angr/engines/successors.py
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
import claripy
|
|
6
|
-
|
|
7
6
|
from archinfo.arch_soot import ArchSoot, SootAddressDescriptor
|
|
8
7
|
|
|
8
|
+
import angr
|
|
9
9
|
from angr import sim_options as o
|
|
10
|
-
from angr.
|
|
11
|
-
from angr.
|
|
12
|
-
from angr.
|
|
10
|
+
from angr.calling_conventions import SYSCALL_CC
|
|
11
|
+
from angr.engines.engine import SimEngine
|
|
12
|
+
from angr.errors import (
|
|
13
|
+
AngrSyscallError,
|
|
14
|
+
AngrUnsupportedSyscallError,
|
|
15
|
+
SimException,
|
|
16
|
+
SimSolverModeError,
|
|
17
|
+
SimUnsatError,
|
|
18
|
+
SimValueError,
|
|
19
|
+
)
|
|
20
|
+
from angr.sim_state import SimState
|
|
13
21
|
from angr.state_plugins.callstack import CallStack
|
|
22
|
+
from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
|
|
14
23
|
from angr.state_plugins.sim_action_object import _raw_ast
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if TYPE_CHECKING:
|
|
18
|
-
from angr import SimState
|
|
19
|
-
from angr.engines.engine import HeavyState
|
|
24
|
+
from angr.storage import DUMMY_SYMBOLIC_READ_VALUE
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
l = logging.getLogger(name=__name__)
|
|
@@ -66,10 +71,6 @@ class SimSuccessors:
|
|
|
66
71
|
self.sort: str | None = None
|
|
67
72
|
self.artifacts = {}
|
|
68
73
|
|
|
69
|
-
@classmethod
|
|
70
|
-
def failure(cls):
|
|
71
|
-
return cls(None, None)
|
|
72
|
-
|
|
73
74
|
def __repr__(self):
|
|
74
75
|
if self.processed:
|
|
75
76
|
successor_strings = []
|
|
@@ -303,7 +304,7 @@ class SimSuccessors:
|
|
|
303
304
|
else:
|
|
304
305
|
# The architecture doesn't have an ip_at_syscall register.
|
|
305
306
|
# Nothing to do but hope vigorously.
|
|
306
|
-
l.warning(
|
|
307
|
+
l.warning("Handling syscall on arch %s without ip_at_syscall register", state.arch.name)
|
|
307
308
|
|
|
308
309
|
try:
|
|
309
310
|
symbolic_syscall_num, concrete_syscall_nums = self._resolve_syscall(state)
|
|
@@ -544,5 +545,110 @@ class SimSuccessors:
|
|
|
544
545
|
return [(ip == addr, addr) for addr in addrs]
|
|
545
546
|
|
|
546
547
|
|
|
547
|
-
|
|
548
|
-
|
|
548
|
+
HeavyState = SimState[int | SootAddressDescriptor, claripy.ast.BV | SootAddressDescriptor]
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
class SuccessorsEngine(SimEngine[HeavyState, SimSuccessors]):
|
|
552
|
+
"""
|
|
553
|
+
A mixin for SimEngine which implements ``process`` to perform common operations related to symbolic execution
|
|
554
|
+
and dispatches to a ``process_successors`` method to fill a SimSuccessors object with the results.
|
|
555
|
+
"""
|
|
556
|
+
|
|
557
|
+
def __init__(self, project: angr.Project):
|
|
558
|
+
super().__init__(project)
|
|
559
|
+
|
|
560
|
+
self.successors: SimSuccessors | None = None
|
|
561
|
+
|
|
562
|
+
def process(self, state: HeavyState, **kwargs) -> SimSuccessors: # pylint:disable=unused-argument
|
|
563
|
+
"""
|
|
564
|
+
Perform execution with a state.
|
|
565
|
+
|
|
566
|
+
You should only override this method in a subclass in order to provide the correct method signature and
|
|
567
|
+
docstring. You should override the ``_process`` method to do your actual execution.
|
|
568
|
+
|
|
569
|
+
:param state: The state with which to execute. This state will be copied before
|
|
570
|
+
modification.
|
|
571
|
+
:param inline: This is an inline execution. Do not bother copying the state.
|
|
572
|
+
:param force_addr: Force execution to pretend that we're working at this concrete address
|
|
573
|
+
:returns: A SimSuccessors object categorizing the execution's successor states
|
|
574
|
+
"""
|
|
575
|
+
inline = kwargs.pop("inline", False)
|
|
576
|
+
force_addr = kwargs.pop("force_addr", None)
|
|
577
|
+
|
|
578
|
+
ip = state._ip
|
|
579
|
+
addr = (
|
|
580
|
+
(ip if isinstance(ip, SootAddressDescriptor) else state.solver.eval(ip))
|
|
581
|
+
if force_addr is None
|
|
582
|
+
else force_addr
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
# make a copy of the initial state for actual processing, if needed
|
|
586
|
+
new_state = state.copy() if not inline and o.COPY_STATES in state.options else state
|
|
587
|
+
# enforce this distinction
|
|
588
|
+
old_state = state
|
|
589
|
+
del state
|
|
590
|
+
self.state = new_state
|
|
591
|
+
|
|
592
|
+
# we have now officially begun the stepping process! now is where we "cycle" a state's
|
|
593
|
+
# data - move the "present" into the "past" by pushing an entry on the history stack.
|
|
594
|
+
# nuance: make sure to copy from the PREVIOUS state to the CURRENT one
|
|
595
|
+
# to avoid creating a dead link in the history, messing up the statehierarchy
|
|
596
|
+
new_state.register_plugin("history", old_state.history.make_child())
|
|
597
|
+
new_state.history.recent_bbl_addrs.append(addr)
|
|
598
|
+
if new_state.arch.unicorn_support:
|
|
599
|
+
assert isinstance(addr, int)
|
|
600
|
+
new_state.scratch.executed_pages_set = {addr & ~0xFFF}
|
|
601
|
+
|
|
602
|
+
self.successors = SimSuccessors(addr, old_state)
|
|
603
|
+
|
|
604
|
+
new_state._inspect(
|
|
605
|
+
"engine_process", when=BP_BEFORE, sim_engine=self, sim_successors=self.successors, address=addr
|
|
606
|
+
)
|
|
607
|
+
self.successors = new_state._inspect_getattr("sim_successors", self.successors)
|
|
608
|
+
try:
|
|
609
|
+
self.process_successors(self.successors, **kwargs)
|
|
610
|
+
except SimException as e:
|
|
611
|
+
if o.EXCEPTION_HANDLING not in old_state.options:
|
|
612
|
+
raise
|
|
613
|
+
assert old_state.project is not None
|
|
614
|
+
old_state.project.simos.handle_exception(self.successors, self, e)
|
|
615
|
+
|
|
616
|
+
new_state._inspect("engine_process", when=BP_AFTER, sim_successors=self.successors, address=addr)
|
|
617
|
+
self.successors = new_state._inspect_getattr("sim_successors", self.successors)
|
|
618
|
+
assert self.successors is not None
|
|
619
|
+
|
|
620
|
+
# downsizing
|
|
621
|
+
if new_state.supports_inspect:
|
|
622
|
+
new_state.inspect.downsize()
|
|
623
|
+
# if not TRACK, clear actions on OLD state
|
|
624
|
+
# if o.TRACK_ACTION_HISTORY not in old_state.options:
|
|
625
|
+
# old_state.history.recent_events = []
|
|
626
|
+
|
|
627
|
+
# fix up the descriptions...
|
|
628
|
+
description = str(self.successors)
|
|
629
|
+
l.info("Ticked state: %s", description)
|
|
630
|
+
for succ in self.successors.all_successors:
|
|
631
|
+
succ.history.recent_description = description
|
|
632
|
+
for succ in self.successors.flat_successors:
|
|
633
|
+
succ.history.recent_description = description
|
|
634
|
+
|
|
635
|
+
return self.successors
|
|
636
|
+
|
|
637
|
+
def process_successors(self, successors, **kwargs): # pylint:disable=unused-argument,no-self-use
|
|
638
|
+
"""
|
|
639
|
+
Implement this function to fill out the SimSuccessors object with the results of stepping state.
|
|
640
|
+
|
|
641
|
+
In order to implement a model where multiple mixins can potentially handle a request, a mixin may implement
|
|
642
|
+
this method and then perform a super() call if it wants to pass on handling to the next mixin.
|
|
643
|
+
|
|
644
|
+
Keep in mind python's method resolution order when composing multiple classes implementing this method.
|
|
645
|
+
In short: left-to-right, depth-first, but deferring any base classes which are shared by multiple subclasses
|
|
646
|
+
(the merge point of a diamond pattern in the inheritance graph) until the last point where they would be
|
|
647
|
+
encountered in this depth-first search. For example, if you have classes A, B(A), C(B), D(A), E(C, D), then the
|
|
648
|
+
method resolution order will be E, C, B, D, A.
|
|
649
|
+
|
|
650
|
+
:param state: The state to manipulate
|
|
651
|
+
:param successors: The successors object to fill out
|
|
652
|
+
:param kwargs: Any extra arguments. Do not fail if you are passed unexpected arguments.
|
|
653
|
+
"""
|
|
654
|
+
successors.processed = False # mark failure
|
angr/engines/syscall.py
CHANGED
|
@@ -3,14 +3,14 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
import angr
|
|
5
5
|
from angr.errors import AngrUnsupportedSyscallError
|
|
6
|
-
from .
|
|
6
|
+
from .successors import SuccessorsEngine
|
|
7
7
|
from .procedure import ProcedureMixin
|
|
8
8
|
|
|
9
9
|
l = logging.getLogger(name=__name__)
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
# pylint:disable=abstract-method,arguments-differ
|
|
13
|
-
class SimEngineSyscall(
|
|
13
|
+
class SimEngineSyscall(SuccessorsEngine, ProcedureMixin):
|
|
14
14
|
"""
|
|
15
15
|
A SimEngine mixin which adds a successors handling step that checks if a syscall was just requested and if so
|
|
16
16
|
handles it as a step.
|
angr/engines/unicorn.py
CHANGED
|
@@ -8,7 +8,7 @@ import claripy
|
|
|
8
8
|
|
|
9
9
|
import angr
|
|
10
10
|
from angr.errors import SimIRSBError, SimIRSBNoDecodeError, SimValueError
|
|
11
|
-
from .
|
|
11
|
+
from .successors import SuccessorsEngine
|
|
12
12
|
from .vex.heavy.heavy import VEXEarlyExit
|
|
13
13
|
from angr import sim_options as o
|
|
14
14
|
from angr.misc.ux import once
|
|
@@ -21,7 +21,7 @@ from angr.utils.constants import DEFAULT_STATEMENT
|
|
|
21
21
|
l = logging.getLogger(name=__name__)
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class SimEngineUnicorn(
|
|
24
|
+
class SimEngineUnicorn(SuccessorsEngine):
|
|
25
25
|
"""
|
|
26
26
|
Concrete execution in the Unicorn Engine, a fork of qemu.
|
|
27
27
|
|
|
@@ -281,7 +281,7 @@ class SimEngineUnicorn(SuccessorsMixin):
|
|
|
281
281
|
def _get_vex_block_details(self, block_addr, block_size):
|
|
282
282
|
# Mostly based on the lifting code in HeavyVEXMixin
|
|
283
283
|
# pylint:disable=no-member
|
|
284
|
-
irsb =
|
|
284
|
+
irsb = self.project.factory.block(addr=block_addr, backup_state=self.state, size=block_size).vex
|
|
285
285
|
if irsb.size == 0:
|
|
286
286
|
if irsb.jumpkind == "Ijk_NoDecode":
|
|
287
287
|
if not self.state.project.is_hooked(irsb.addr):
|
angr/engines/vex/heavy/heavy.py
CHANGED
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
import claripy
|
|
4
4
|
import pyvex
|
|
5
5
|
|
|
6
|
-
from angr.engines.
|
|
6
|
+
from angr.engines.successors import SuccessorsEngine
|
|
7
7
|
from angr.engines.vex.light import VEXMixin
|
|
8
8
|
from angr.engines.vex.lifter import VEXLifter
|
|
9
9
|
from angr.engines.vex.claripy.datalayer import ClaripyDataMixin, symbol
|
|
@@ -57,7 +57,7 @@ class SimStateStorageMixin(VEXMixin):
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
# pylint:disable=arguments-differ
|
|
60
|
-
class HeavyVEXMixin(
|
|
60
|
+
class HeavyVEXMixin(SuccessorsEngine, ClaripyDataMixin, SimStateStorageMixin, VEXMixin, VEXLifter):
|
|
61
61
|
"""
|
|
62
62
|
Execution engine based on VEX, Valgrind's IR.
|
|
63
63
|
|
|
@@ -83,7 +83,6 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
|
|
|
83
83
|
self,
|
|
84
84
|
successors,
|
|
85
85
|
irsb=None,
|
|
86
|
-
insn_text=None,
|
|
87
86
|
insn_bytes=None,
|
|
88
87
|
thumb=False,
|
|
89
88
|
size=None,
|
|
@@ -99,21 +98,10 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
|
|
|
99
98
|
extra_stop_points=extra_stop_points,
|
|
100
99
|
num_inst=num_inst,
|
|
101
100
|
size=size,
|
|
102
|
-
insn_text=insn_text,
|
|
103
101
|
insn_bytes=insn_bytes,
|
|
104
102
|
**kwargs,
|
|
105
103
|
)
|
|
106
104
|
|
|
107
|
-
if insn_text is not None:
|
|
108
|
-
if insn_bytes is not None:
|
|
109
|
-
raise errors.SimEngineError("You cannot provide both 'insn_bytes' and 'insn_text'!")
|
|
110
|
-
|
|
111
|
-
insn_bytes = self.project.arch.asm(insn_text, addr=successors.addr, thumb=thumb)
|
|
112
|
-
if insn_bytes is None:
|
|
113
|
-
raise errors.AngrAssemblyError(
|
|
114
|
-
"Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
|
|
115
|
-
)
|
|
116
|
-
|
|
117
105
|
successors.sort = "IRSB"
|
|
118
106
|
successors.description = "IRSB"
|
|
119
107
|
self.state.history.recent_block_count = 1
|
|
@@ -137,9 +125,9 @@ class HeavyVEXMixin(SuccessorsMixin, ClaripyDataMixin, SimStateStorageMixin, VEX
|
|
|
137
125
|
|
|
138
126
|
if irsb is None:
|
|
139
127
|
irsb = self.lift_vex(
|
|
128
|
+
insn_bytes=insn_bytes,
|
|
140
129
|
addr=addr,
|
|
141
130
|
state=self.state,
|
|
142
|
-
insn_bytes=insn_bytes,
|
|
143
131
|
thumb=thumb,
|
|
144
132
|
size=size,
|
|
145
133
|
num_inst=num_inst,
|
angr/engines/vex/lifter.py
CHANGED
|
@@ -8,7 +8,7 @@ import cle
|
|
|
8
8
|
from archinfo import ArchARM
|
|
9
9
|
import claripy
|
|
10
10
|
|
|
11
|
-
from angr.engines.engine import
|
|
11
|
+
from angr.engines.engine import SimEngine
|
|
12
12
|
from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE, NO_OVERRIDE
|
|
13
13
|
from angr.misc.ux import once
|
|
14
14
|
from angr.errors import SimEngineError, SimTranslationError, SimError
|
|
@@ -20,7 +20,7 @@ VEX_IRSB_MAX_SIZE = 400
|
|
|
20
20
|
VEX_IRSB_MAX_INST = 99
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class VEXLifter(
|
|
23
|
+
class VEXLifter(SimEngine):
|
|
24
24
|
"""
|
|
25
25
|
Implements the VEX lifter engine mixin.
|
|
26
26
|
"""
|
angr/engines/vex/light/light.py
CHANGED
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
import pyvex
|
|
5
5
|
|
|
6
|
-
from angr.engines.engine import
|
|
6
|
+
from angr.engines.engine import SimEngine
|
|
7
7
|
from angr.utils.constants import DEFAULT_STATEMENT
|
|
8
8
|
|
|
9
9
|
l = logging.getLogger(name=__name__)
|
|
@@ -11,7 +11,7 @@ l = logging.getLogger(name=__name__)
|
|
|
11
11
|
# pylint:disable=arguments-differ,unused-argument,no-self-use
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class VEXMixin(
|
|
14
|
+
class VEXMixin(SimEngine):
|
|
15
15
|
def __init__(self, project, **kwargs):
|
|
16
16
|
super().__init__(project, **kwargs)
|
|
17
17
|
self._vex_expr_handlers = []
|
angr/factory.py
CHANGED
|
@@ -10,7 +10,7 @@ from archinfo.arch_soot import ArchSoot, SootAddressDescriptor
|
|
|
10
10
|
from .sim_state import SimState
|
|
11
11
|
from .calling_conventions import default_cc, SimRegArg, SimStackArg, PointerWrapper, SimCCUnknown
|
|
12
12
|
from .callable import Callable
|
|
13
|
-
from .errors import
|
|
13
|
+
from .errors import AngrError
|
|
14
14
|
from .engines import UberEngine, ProcedureEngine
|
|
15
15
|
from .sim_type import SimTypeFunction, SimTypeInt
|
|
16
16
|
from .codenode import HookNode, SyscallNode
|
|
@@ -245,6 +245,7 @@ class AngrObjectFactory:
|
|
|
245
245
|
cc=None,
|
|
246
246
|
add_options=None,
|
|
247
247
|
remove_options=None,
|
|
248
|
+
step_limit: int | None = None,
|
|
248
249
|
):
|
|
249
250
|
"""
|
|
250
251
|
A Callable is a representation of a function in the binary that can be interacted with like a native python
|
|
@@ -257,6 +258,7 @@ class AngrObjectFactory:
|
|
|
257
258
|
:param base_state: The state from which to do these runs
|
|
258
259
|
:param toc: The address of the table of contents for ppc64
|
|
259
260
|
:param cc: The SimCC to use for a calling convention
|
|
261
|
+
:param step_limit: The maximum number of blocks that Callable will execute before pruning the path.
|
|
260
262
|
:returns: A Callable object that can be used as a interface for executing guest code like a
|
|
261
263
|
python function.
|
|
262
264
|
:rtype: angr.callable.Callable
|
|
@@ -272,6 +274,7 @@ class AngrObjectFactory:
|
|
|
272
274
|
cc=cc,
|
|
273
275
|
add_options=add_options,
|
|
274
276
|
remove_options=remove_options,
|
|
277
|
+
step_limit=step_limit,
|
|
275
278
|
)
|
|
276
279
|
|
|
277
280
|
def cc(self):
|
|
@@ -300,7 +303,6 @@ class AngrObjectFactory:
|
|
|
300
303
|
size=None,
|
|
301
304
|
max_size=None,
|
|
302
305
|
byte_string=None,
|
|
303
|
-
vex=None,
|
|
304
306
|
thumb=False,
|
|
305
307
|
backup_state=None,
|
|
306
308
|
extra_stop_points=None,
|
|
@@ -308,7 +310,6 @@ class AngrObjectFactory:
|
|
|
308
310
|
num_inst=None,
|
|
309
311
|
traceflags=0,
|
|
310
312
|
insn_bytes=None,
|
|
311
|
-
insn_text=None, # backward compatibility
|
|
312
313
|
strict_block_end=None,
|
|
313
314
|
collect_data_refs=False,
|
|
314
315
|
cross_insn_opt=True,
|
|
@@ -326,7 +327,6 @@ class AngrObjectFactory:
|
|
|
326
327
|
size=None,
|
|
327
328
|
max_size=None,
|
|
328
329
|
byte_string=None,
|
|
329
|
-
vex=None,
|
|
330
330
|
thumb=False,
|
|
331
331
|
backup_state=None,
|
|
332
332
|
extra_stop_points=None,
|
|
@@ -334,7 +334,6 @@ class AngrObjectFactory:
|
|
|
334
334
|
num_inst=None,
|
|
335
335
|
traceflags=0,
|
|
336
336
|
insn_bytes=None,
|
|
337
|
-
insn_text=None, # backward compatibility
|
|
338
337
|
strict_block_end=None,
|
|
339
338
|
collect_data_refs=False,
|
|
340
339
|
load_from_ro_regions=False,
|
|
@@ -349,7 +348,6 @@ class AngrObjectFactory:
|
|
|
349
348
|
size=None,
|
|
350
349
|
max_size=None,
|
|
351
350
|
byte_string=None,
|
|
352
|
-
vex=None,
|
|
353
351
|
thumb=False,
|
|
354
352
|
backup_state=None,
|
|
355
353
|
extra_stop_points=None,
|
|
@@ -357,7 +355,6 @@ class AngrObjectFactory:
|
|
|
357
355
|
num_inst=None,
|
|
358
356
|
traceflags=0,
|
|
359
357
|
insn_bytes=None,
|
|
360
|
-
insn_text=None, # backward compatibility
|
|
361
358
|
strict_block_end=None,
|
|
362
359
|
collect_data_refs=False,
|
|
363
360
|
cross_insn_opt=True,
|
|
@@ -369,27 +366,15 @@ class AngrObjectFactory:
|
|
|
369
366
|
if isinstance(self.project.arch, ArchSoot) and isinstance(addr, SootAddressDescriptor):
|
|
370
367
|
return SootBlock(addr, arch=self.project.arch, project=self.project)
|
|
371
368
|
|
|
372
|
-
if insn_bytes is not None and insn_text is not None:
|
|
373
|
-
raise AngrError("You cannot provide both 'insn_bytes' and 'insn_text'!")
|
|
374
|
-
|
|
375
369
|
if insn_bytes is not None:
|
|
376
370
|
byte_string = insn_bytes
|
|
377
371
|
|
|
378
|
-
if insn_text is not None:
|
|
379
|
-
byte_string = self.project.arch.asm(insn_text, addr=addr, as_bytes=True, thumb=thumb)
|
|
380
|
-
if byte_string is None:
|
|
381
|
-
# assembly failed
|
|
382
|
-
raise AngrAssemblyError(
|
|
383
|
-
"Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
|
|
384
|
-
)
|
|
385
|
-
|
|
386
372
|
return Block(
|
|
387
373
|
addr,
|
|
388
374
|
project=self.project,
|
|
389
375
|
size=size,
|
|
390
376
|
max_size=max_size,
|
|
391
377
|
byte_string=byte_string,
|
|
392
|
-
vex=vex,
|
|
393
378
|
extra_stop_points=extra_stop_points,
|
|
394
379
|
thumb=thumb,
|
|
395
380
|
backup_state=backup_state,
|
|
@@ -631,8 +631,9 @@ class CFGModel(Serializable):
|
|
|
631
631
|
|
|
632
632
|
if boundary is not None:
|
|
633
633
|
data.max_size = boundary - data_addr
|
|
634
|
-
|
|
635
|
-
|
|
634
|
+
else:
|
|
635
|
+
# boundary does not exist, which means the data address is not mapped at all
|
|
636
|
+
data.max_size = 0
|
|
636
637
|
|
|
637
638
|
keys = sorted(self.memory_data.keys())
|
|
638
639
|
|