angr 9.2.134__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 +5 -8
- 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/__init__.py +6 -0
- angr/analyses/{calling_convention.py → calling_convention/calling_convention.py} +32 -64
- angr/analyses/calling_convention/fact_collector.py +502 -0
- angr/analyses/calling_convention/utils.py +57 -0
- 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/complete_calling_conventions.py +32 -3
- 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/register_save_area_simplifier.py +0 -6
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +2 -7
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +0 -6
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +0 -6
- 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/engine_vex.py +5 -0
- 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 +15 -7
- 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 +74 -77
- angr/knowledge_plugins/functions/function_manager.py +14 -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/bits.py +13 -0
- 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.134.dist-info → angr-9.2.136.dist-info}/METADATA +6 -6
- {angr-9.2.134.dist-info → angr-9.2.136.dist-info}/RECORD +168 -164
- {angr-9.2.134.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.134.dist-info → angr-9.2.136.dist-info}/LICENSE +0 -0
- {angr-9.2.134.dist-info → angr-9.2.136.dist-info}/entry_points.txt +0 -0
- {angr-9.2.134.dist-info → angr-9.2.136.dist-info}/top_level.txt +0 -0
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
# pylint:disable=consider-using-in
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
from collections.abc import Callable
|
|
5
|
-
|
|
6
|
-
from ailment import Block, Stmt, Expr, AILBlockWalker
|
|
7
|
-
|
|
8
|
-
from angr.code_location import CodeLocation
|
|
9
|
-
from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE, OP_AFTER
|
|
10
|
-
from angr.knowledge_plugins.key_definitions import atoms
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from archinfo import Arch
|
|
14
|
-
from .propagator import PropagatorAILState
|
|
15
|
-
from angr.analyses.reaching_definitions import ReachingDefinitionsModel
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class OutdatedDefinitionWalker(AILBlockWalker):
|
|
19
|
-
"""
|
|
20
|
-
Walks an AIL expression to find outdated definitions.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(
|
|
24
|
-
self,
|
|
25
|
-
expr,
|
|
26
|
-
expr_defat: CodeLocation,
|
|
27
|
-
current_loc: CodeLocation,
|
|
28
|
-
state: PropagatorAILState,
|
|
29
|
-
arch: Arch,
|
|
30
|
-
avoid: Expr.Expression | None = None,
|
|
31
|
-
extract_offset_to_sp: Callable | None = None,
|
|
32
|
-
rda: ReachingDefinitionsModel = None,
|
|
33
|
-
):
|
|
34
|
-
super().__init__()
|
|
35
|
-
self.expr = expr
|
|
36
|
-
self.expr_defat = expr_defat
|
|
37
|
-
self.current_loc = current_loc
|
|
38
|
-
self.state = state
|
|
39
|
-
self.avoid = avoid
|
|
40
|
-
self.arch = arch
|
|
41
|
-
self.extract_offset_to_sp = extract_offset_to_sp
|
|
42
|
-
self.expr_handlers[Expr.Register] = self._handle_Register
|
|
43
|
-
self.expr_handlers[Expr.Load] = self._handle_Load
|
|
44
|
-
self.expr_handlers[Expr.Tmp] = self._handle_Tmp
|
|
45
|
-
self.expr_handlers[Expr.VEXCCallExpression] = self._handle_VEXCCallExpression
|
|
46
|
-
self.out_dated = False
|
|
47
|
-
self.has_avoid = False
|
|
48
|
-
self.rda = rda
|
|
49
|
-
|
|
50
|
-
# pylint:disable=unused-argument
|
|
51
|
-
def _handle_Tmp(self, expr_idx: int, expr: Expr.Tmp, stmt_idx: int, stmt: Stmt.Assignment, block: Block | None):
|
|
52
|
-
if self.avoid is not None and expr.likes(self.avoid):
|
|
53
|
-
self.has_avoid = True
|
|
54
|
-
|
|
55
|
-
# pylint:disable=unused-argument
|
|
56
|
-
def _handle_Register(
|
|
57
|
-
self, expr_idx: int, expr: Expr.Register, stmt_idx: int, stmt: Stmt.Assignment, block: Block | None
|
|
58
|
-
):
|
|
59
|
-
if (
|
|
60
|
-
self.avoid is not None
|
|
61
|
-
and isinstance(self.avoid, Expr.Register)
|
|
62
|
-
and (expr.likes(self.avoid) or self._reg_overlap(expr, self.avoid))
|
|
63
|
-
):
|
|
64
|
-
self.has_avoid = True
|
|
65
|
-
|
|
66
|
-
# is the used register still alive at this point?
|
|
67
|
-
defs_defat = self.rda.get_defs(atoms.Register(expr.reg_offset, expr.size), self.expr_defat, OP_AFTER)
|
|
68
|
-
defs_currentloc = self.rda.get_defs(atoms.Register(expr.reg_offset, expr.size), self.current_loc, OP_BEFORE)
|
|
69
|
-
|
|
70
|
-
codelocs_defat = {def_.codeloc for def_ in defs_defat}
|
|
71
|
-
codelocs_currentloc = {def_.codeloc for def_ in defs_currentloc}
|
|
72
|
-
if not (codelocs_defat and codelocs_currentloc and codelocs_defat == codelocs_currentloc):
|
|
73
|
-
self.out_dated = True
|
|
74
|
-
|
|
75
|
-
def _handle_Load(self, expr_idx: int, expr: Expr.Load, stmt_idx: int, stmt: Stmt.Statement, block: Block | None):
|
|
76
|
-
if self.avoid is not None and (expr == self.avoid or expr.addr == self.avoid):
|
|
77
|
-
self.has_avoid = True
|
|
78
|
-
|
|
79
|
-
if isinstance(expr.addr, Expr.StackBaseOffset):
|
|
80
|
-
sp_offset = self.extract_offset_to_sp(expr.addr)
|
|
81
|
-
|
|
82
|
-
if sp_offset is not None:
|
|
83
|
-
defs_defat = self.rda.get_defs(
|
|
84
|
-
atoms.MemoryLocation(atoms.SpOffset(expr.bits, sp_offset), expr.size), self.expr_defat, OP_AFTER
|
|
85
|
-
)
|
|
86
|
-
defs_currentloc = self.rda.get_defs(
|
|
87
|
-
atoms.MemoryLocation(atoms.SpOffset(expr.bits, sp_offset), expr.size), self.current_loc, OP_BEFORE
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
codelocs_defat = {def_.codeloc for def_ in defs_defat}
|
|
91
|
-
codelocs_currentloc = {def_.codeloc for def_ in defs_currentloc}
|
|
92
|
-
|
|
93
|
-
if not codelocs_defat and not codelocs_currentloc:
|
|
94
|
-
# fallback
|
|
95
|
-
if not self._check_store_precedes_load(self.expr_defat, self.current_loc):
|
|
96
|
-
self.out_dated = True
|
|
97
|
-
elif not (codelocs_defat and codelocs_currentloc and codelocs_defat == codelocs_currentloc):
|
|
98
|
-
self.out_dated = True
|
|
99
|
-
|
|
100
|
-
else:
|
|
101
|
-
# in cases where expr.addr cannot be resolved to a concrete stack offset, we play safe and assume
|
|
102
|
-
# it's outdated
|
|
103
|
-
self.out_dated = True
|
|
104
|
-
|
|
105
|
-
elif isinstance(expr.addr, Expr.Const):
|
|
106
|
-
mem_addr = expr.addr.value
|
|
107
|
-
|
|
108
|
-
defs_defat = self.rda.get_defs(atoms.MemoryLocation(mem_addr, expr.size), self.expr_defat, OP_AFTER)
|
|
109
|
-
defs_currentloc = self.rda.get_defs(atoms.MemoryLocation(mem_addr, expr.size), self.current_loc, OP_BEFORE)
|
|
110
|
-
|
|
111
|
-
codelocs_defat = {def_.codeloc for def_ in defs_defat}
|
|
112
|
-
codelocs_currentloc = {def_.codeloc for def_ in defs_currentloc}
|
|
113
|
-
|
|
114
|
-
if codelocs_defat != codelocs_currentloc:
|
|
115
|
-
self.out_dated = True
|
|
116
|
-
|
|
117
|
-
else:
|
|
118
|
-
# the address is not concrete - we check the address first
|
|
119
|
-
super()._handle_Load(expr_idx, expr, stmt_idx, stmt, block)
|
|
120
|
-
# then if the address expression is up-to-date, we check the global store
|
|
121
|
-
if not self.out_dated and (
|
|
122
|
-
(
|
|
123
|
-
self.state.global_stores
|
|
124
|
-
and not all(
|
|
125
|
-
self._check_store_precedes_load(CodeLocation(store_block_addr, store_stmt_idx), self.expr_defat)
|
|
126
|
-
for store_block_addr, store_stmt_idx, addr, store in self.state.global_stores
|
|
127
|
-
)
|
|
128
|
-
)
|
|
129
|
-
or (
|
|
130
|
-
self.state.last_stack_store is not None
|
|
131
|
-
and not self._check_store_precedes_load(
|
|
132
|
-
CodeLocation(*self.state.last_stack_store[:2]), self.expr_defat
|
|
133
|
-
)
|
|
134
|
-
)
|
|
135
|
-
):
|
|
136
|
-
self.out_dated = True
|
|
137
|
-
|
|
138
|
-
def _handle_VEXCCallExpression(
|
|
139
|
-
self, expr_idx: int, expr: Expr.VEXCCallExpression, stmt_idx: int, stmt: Stmt.Statement, block: Block | None
|
|
140
|
-
):
|
|
141
|
-
if self.avoid is not None and any(op == self.avoid for op in expr.operands):
|
|
142
|
-
self.has_avoid = True
|
|
143
|
-
|
|
144
|
-
super()._handle_VEXCCallExpression(expr_idx, expr, stmt_idx, stmt, block)
|
|
145
|
-
|
|
146
|
-
@staticmethod
|
|
147
|
-
def _reg_overlap(reg0: Expr.Register, reg1: Expr.Register) -> bool:
|
|
148
|
-
if reg0.reg_offset <= reg1.reg_offset < reg0.reg_offset + reg0.size:
|
|
149
|
-
return True
|
|
150
|
-
return reg1.reg_offset <= reg0.reg_offset < reg1.reg_offset + reg1.size
|
|
151
|
-
|
|
152
|
-
@staticmethod
|
|
153
|
-
def _check_store_precedes_load(store_defat: CodeLocation | None, load_defat: CodeLocation | None) -> bool:
|
|
154
|
-
"""
|
|
155
|
-
Check if store precedes load based on their AIL statement IDs.
|
|
156
|
-
"""
|
|
157
|
-
if store_defat is None or load_defat is None:
|
|
158
|
-
return True
|
|
159
|
-
return store_defat.block_addr == load_defat.block_addr and store_defat.stmt_idx <= load_defat.stmt_idx
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
from ailment.expression import Expression, Tmp
|
|
3
|
-
from ailment import AILBlockWalkerBase
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class TmpvarFinder(AILBlockWalkerBase):
|
|
7
|
-
"""
|
|
8
|
-
Walks an AIL expression to find Tmp expressions.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
def __init__(self, expr: Expression):
|
|
12
|
-
super().__init__()
|
|
13
|
-
self.has_tmp = False
|
|
14
|
-
|
|
15
|
-
self.walk_expression(expr)
|
|
16
|
-
|
|
17
|
-
def _handle_Tmp(self, expr_idx: int, expr: Tmp, stmt_idx: int, stmt, block):
|
|
18
|
-
self.has_tmp = True
|
angr/engines/concrete.py
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
import logging
|
|
3
|
-
import threading
|
|
4
|
-
|
|
5
|
-
import claripy
|
|
6
|
-
|
|
7
|
-
from angr.errors import AngrError
|
|
8
|
-
from .engine import SuccessorsMixin
|
|
9
|
-
from angr.errors import SimConcreteRegisterError
|
|
10
|
-
|
|
11
|
-
l = logging.getLogger("angr.engines.concrete")
|
|
12
|
-
|
|
13
|
-
try:
|
|
14
|
-
from angr_targets.concrete import ConcreteTarget
|
|
15
|
-
except ImportError:
|
|
16
|
-
ConcreteTarget = None
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class SimEngineConcrete(SuccessorsMixin):
|
|
20
|
-
"""
|
|
21
|
-
Concrete execution using a concrete target provided by the user.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, project):
|
|
25
|
-
if not ConcreteTarget:
|
|
26
|
-
l.critical("Error, can't find angr_target project")
|
|
27
|
-
raise AngrError
|
|
28
|
-
|
|
29
|
-
l.info("Initializing SimEngineConcrete with ConcreteTarget provided.")
|
|
30
|
-
super().__init__()
|
|
31
|
-
self.project = project
|
|
32
|
-
if isinstance(self.project.concrete_target, ConcreteTarget) and self.check_concrete_target_methods(
|
|
33
|
-
self.project.concrete_target
|
|
34
|
-
):
|
|
35
|
-
self.target = self.project.concrete_target
|
|
36
|
-
else:
|
|
37
|
-
l.warning("Error, you must provide an instance of a ConcreteTarget to initialize a SimEngineConcrete.")
|
|
38
|
-
self.target = None
|
|
39
|
-
raise NotImplementedError
|
|
40
|
-
|
|
41
|
-
self.segment_registers_already_init = False
|
|
42
|
-
|
|
43
|
-
def process_successors(
|
|
44
|
-
self,
|
|
45
|
-
successors,
|
|
46
|
-
extra_stop_points=None,
|
|
47
|
-
memory_concretize=None,
|
|
48
|
-
register_concretize=None,
|
|
49
|
-
timeout=0,
|
|
50
|
-
*args,
|
|
51
|
-
**kwargs,
|
|
52
|
-
):
|
|
53
|
-
new_state = self.state
|
|
54
|
-
# setup the concrete process and resume the execution
|
|
55
|
-
self.to_engine(new_state, extra_stop_points, memory_concretize, register_concretize, timeout)
|
|
56
|
-
|
|
57
|
-
# sync angr with the current state of the concrete process using
|
|
58
|
-
# the state plugin
|
|
59
|
-
new_state.concrete.sync()
|
|
60
|
-
|
|
61
|
-
successors.engine = "SimEngineConcrete"
|
|
62
|
-
successors.sort = "SimEngineConcrete"
|
|
63
|
-
successors.add_successor(new_state, new_state.ip, claripy.true(), new_state.unicorn.jumpkind)
|
|
64
|
-
successors.description = "Concrete Successors"
|
|
65
|
-
successors.processed = True
|
|
66
|
-
|
|
67
|
-
def to_engine(self, state, extra_stop_points, memory_concretize, register_concretize, timeout):
|
|
68
|
-
"""
|
|
69
|
-
Handle the concrete execution of the process
|
|
70
|
-
This method takes care of:
|
|
71
|
-
1- Set the breakpoints on the addresses provided by the user
|
|
72
|
-
2- Concretize the symbolic variables and perform the write inside the concrete process
|
|
73
|
-
3- Continue the program execution.
|
|
74
|
-
|
|
75
|
-
:param state: The state with which to execute
|
|
76
|
-
:param extra_stop_points: list of a addresses where to stop the concrete execution and return to the
|
|
77
|
-
simulated one
|
|
78
|
-
:param memory_concretize: list of tuples (address, symbolic variable) that are going to be written
|
|
79
|
-
in the concrete process memory.
|
|
80
|
-
:param register_concretize: list of tuples (reg_name, symbolic variable) that are going to be written
|
|
81
|
-
:param timeout: how long we should wait the concrete target to reach the breakpoint
|
|
82
|
-
:return: None
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
state.globals["symbion_timeout"] = False
|
|
86
|
-
extra_stop_points = [] if extra_stop_points is None else extra_stop_points
|
|
87
|
-
|
|
88
|
-
l.debug(
|
|
89
|
-
"Entering in SimEngineConcrete: simulated address %#x concrete address %#x stop points %s",
|
|
90
|
-
state.addr,
|
|
91
|
-
self.target.read_register("pc"),
|
|
92
|
-
map(hex, extra_stop_points),
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
if memory_concretize:
|
|
96
|
-
l.debug("SimEngineConcrete is concretizing memory variables before resuming the concrete process")
|
|
97
|
-
|
|
98
|
-
for sym_var in memory_concretize:
|
|
99
|
-
sym_var_address = state.solver.eval(sym_var[0])
|
|
100
|
-
sym_var_value = state.solver.eval(sym_var[1], cast_to=bytes)
|
|
101
|
-
l.debug("Concretize memory at address %#x with value %s", sym_var_address, str(sym_var_value))
|
|
102
|
-
self.target.write_memory(sym_var_address, sym_var_value, raw=True)
|
|
103
|
-
|
|
104
|
-
if register_concretize:
|
|
105
|
-
l.debug("SimEngineConcrete is concretizing registers variables before resuming the concrete process")
|
|
106
|
-
for reg in register_concretize:
|
|
107
|
-
register_name = reg[0]
|
|
108
|
-
register_value = state.solver.eval(reg[1])
|
|
109
|
-
l.debug("Concretize register %s with value %s", register_name, str(register_value))
|
|
110
|
-
self.target.write_register(register_name, register_value)
|
|
111
|
-
|
|
112
|
-
# Set breakpoint on remote target
|
|
113
|
-
for stop_point in extra_stop_points:
|
|
114
|
-
l.debug("Setting breakpoints at %#x", stop_point)
|
|
115
|
-
self.target.set_breakpoint(stop_point, hardware=True, temporary=True)
|
|
116
|
-
|
|
117
|
-
if timeout > 0:
|
|
118
|
-
l.debug("Found timeout as option, setting it up!")
|
|
119
|
-
|
|
120
|
-
def timeout_handler():
|
|
121
|
-
self.target.stop() # stop the concrete target now!
|
|
122
|
-
state.globals["symbion_timeout"] = True # this will end up in the timeout stash
|
|
123
|
-
|
|
124
|
-
execution_timer = threading.Timer(timeout, timeout_handler)
|
|
125
|
-
execution_timer.start() # start the timer!
|
|
126
|
-
|
|
127
|
-
# resuming of the concrete process, if the target won't reach the
|
|
128
|
-
# breakpoint specified by the user the timeout will abort angr execution.
|
|
129
|
-
l.debug("SimEngineConcrete is resuming the concrete process")
|
|
130
|
-
self.target.run()
|
|
131
|
-
l.debug("SimEngineConcrete has successfully resumed the process")
|
|
132
|
-
|
|
133
|
-
if state.globals["symbion_timeout"]:
|
|
134
|
-
l.critical("Timeout has been reached during resuming of concrete process")
|
|
135
|
-
l.critical(
|
|
136
|
-
"This can be a bad thing ( the ConcreteTarget didn't hit your breakpoint ) or"
|
|
137
|
-
"just it will take a while."
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
# reset the alarm
|
|
141
|
-
if timeout > 0:
|
|
142
|
-
execution_timer.cancel()
|
|
143
|
-
|
|
144
|
-
# removing all breakpoints set by the concrete target
|
|
145
|
-
for stop_point in extra_stop_points:
|
|
146
|
-
self.target.remove_breakpoint(stop_point)
|
|
147
|
-
|
|
148
|
-
# handling the case in which the program stops at a point different than the breakpoints set
|
|
149
|
-
# by the user.
|
|
150
|
-
current_pc = self.target.read_register("pc")
|
|
151
|
-
if current_pc not in extra_stop_points and not state.globals["symbion_timeout"]:
|
|
152
|
-
l.critical("Stopped at unexpected location inside the concrete process: %#x", current_pc)
|
|
153
|
-
raise AngrError
|
|
154
|
-
|
|
155
|
-
@staticmethod
|
|
156
|
-
def check_concrete_target_methods(concrete_target):
|
|
157
|
-
"""
|
|
158
|
-
Check if the concrete target methods return the correct type of data
|
|
159
|
-
:return: True if the concrete target is compliant
|
|
160
|
-
"""
|
|
161
|
-
entry_point = concrete_target.read_register("pc")
|
|
162
|
-
if type(entry_point) is not int:
|
|
163
|
-
l.error("read_register result type is %s, should be <type 'int'>", (type(entry_point)))
|
|
164
|
-
return False
|
|
165
|
-
|
|
166
|
-
mem_read = concrete_target.read_memory(entry_point, 0x4)
|
|
167
|
-
|
|
168
|
-
if type(mem_read) is not bytes:
|
|
169
|
-
l.error("read_memory result type is %s, should be <type 'bytes'>", (type(mem_read)))
|
|
170
|
-
return False
|
|
171
|
-
|
|
172
|
-
try:
|
|
173
|
-
concrete_target.read_register("not_existent_reg")
|
|
174
|
-
l.error("read_register should raise a SimConcreteRegisterError when accessing non existent registers")
|
|
175
|
-
return False
|
|
176
|
-
|
|
177
|
-
except SimConcreteRegisterError:
|
|
178
|
-
l.debug("read_register raise a SimConcreteRegisterError, ok!")
|
|
179
|
-
|
|
180
|
-
return True
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import logging
|
|
4
|
-
|
|
5
|
-
from .base import ExplorationTechnique
|
|
6
|
-
from .common import condition_to_lambda
|
|
7
|
-
|
|
8
|
-
l = logging.getLogger("angr.exploration_techniques.symbion")
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class Symbion(ExplorationTechnique):
|
|
12
|
-
"""
|
|
13
|
-
The Symbion exploration technique uses the SimEngineConcrete available to step a SimState.
|
|
14
|
-
|
|
15
|
-
:param find: address or list of addresses that we want to reach, these will be translated into breakpoints
|
|
16
|
-
inside the concrete process using the ConcreteTarget interface provided by the user
|
|
17
|
-
inside the SimEngineConcrete.
|
|
18
|
-
:param memory_concretize: list of tuples (address, symbolic variable) that are going to be written
|
|
19
|
-
in the concrete process memory.
|
|
20
|
-
:param register_concretize: list of tuples (reg_name, symbolic variable) that are going to be written
|
|
21
|
-
:param timeout: how long we should wait the concrete target to reach the breakpoint
|
|
22
|
-
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(self, find=None, memory_concretize=None, register_concretize=None, timeout=0, find_stash="found"):
|
|
26
|
-
super().__init__()
|
|
27
|
-
|
|
28
|
-
# need to keep the raw list of addresses to
|
|
29
|
-
self.breakpoints = find
|
|
30
|
-
self.find = condition_to_lambda(find)
|
|
31
|
-
self.memory_concretize = memory_concretize
|
|
32
|
-
self.register_concretize = register_concretize
|
|
33
|
-
self.find_stash = find_stash
|
|
34
|
-
self.timeout = timeout
|
|
35
|
-
|
|
36
|
-
def setup(self, simgr):
|
|
37
|
-
# adding the 'found' stash during the setup
|
|
38
|
-
simgr.stashes[self.find_stash] = []
|
|
39
|
-
|
|
40
|
-
def step(self, simgr, stash="active", **kwargs):
|
|
41
|
-
# safe guard
|
|
42
|
-
if not len(simgr.stashes[stash]):
|
|
43
|
-
l.warning("No stashes to step, aborting.")
|
|
44
|
-
return None
|
|
45
|
-
|
|
46
|
-
# check if the stash contains only one SimState and if not warn the user that only the
|
|
47
|
-
# first state in the stash can be stepped in the SimEngineConcrete.
|
|
48
|
-
# This because for now we support only one concrete execution, in future we can think about
|
|
49
|
-
# a snapshot engine and give to each SimState an instance of a concrete process.
|
|
50
|
-
if len(simgr.stashes[stash]) > 1:
|
|
51
|
-
l.warning(
|
|
52
|
-
"You are trying to use the Symbion exploration technique on multiple state, "
|
|
53
|
-
"this is not supported now."
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
return simgr.step(stash=stash, **kwargs)
|
|
57
|
-
|
|
58
|
-
def step_state(self, simgr, *args, **kwargs): # pylint:disable=arguments-differ
|
|
59
|
-
state = args[0]
|
|
60
|
-
ss = self.successors(
|
|
61
|
-
state=state,
|
|
62
|
-
simgr=simgr,
|
|
63
|
-
engine=self.project.factory.concrete_engine,
|
|
64
|
-
extra_stop_points=self.breakpoints,
|
|
65
|
-
memory_concretize=self.memory_concretize,
|
|
66
|
-
register_concretize=self.register_concretize,
|
|
67
|
-
timeout=self.timeout,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
new_state = ss.successors
|
|
71
|
-
|
|
72
|
-
if new_state[0].globals.get("symbion_timeout", None):
|
|
73
|
-
return {"timeout": new_state}
|
|
74
|
-
|
|
75
|
-
return {"found": new_state}
|
|
76
|
-
|
|
77
|
-
def complete(self, simgr):
|
|
78
|
-
# We are done if we have hit at least one breakpoint in
|
|
79
|
-
# the concrete execution
|
|
80
|
-
return len(simgr.stashes[self.find_stash]) >= 1
|