angr 9.2.135__py3-none-win_amd64.whl → 9.2.137__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/__init__.py +3 -7
- angr/analyses/analysis.py +4 -0
- angr/analyses/backward_slice.py +1 -2
- angr/analyses/binary_optimizer.py +3 -4
- angr/analyses/bindiff.py +4 -6
- angr/analyses/boyscout.py +1 -3
- angr/analyses/callee_cleanup_finder.py +4 -4
- angr/analyses/calling_convention/calling_convention.py +6 -4
- angr/analyses/calling_convention/fact_collector.py +10 -3
- 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 +40 -68
- angr/analyses/cfg/cfg_emulated.py +1 -104
- angr/analyses/cfg/cfg_fast.py +90 -27
- 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 +65 -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/class_identifier.py +1 -2
- angr/analyses/complete_calling_conventions.py +3 -0
- 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 +15 -5
- angr/analyses/decompiler/block_simplifier.py +2 -2
- angr/analyses/decompiler/ccall_rewriters/__init__.py +2 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +69 -0
- angr/analyses/decompiler/clinic.py +119 -72
- angr/analyses/decompiler/condition_processor.py +2 -0
- angr/analyses/decompiler/decompiler.py +1 -0
- angr/analyses/decompiler/dephication/dephication_base.py +2 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +8 -6
- angr/analyses/decompiler/dephication/seqnode_dephication.py +10 -1
- 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/return_duplicator_base.py +1 -2
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
- angr/analyses/decompiler/sequence_walker.py +6 -2
- angr/analyses/decompiler/ssailification/rewriting.py +11 -1
- angr/analyses/decompiler/ssailification/rewriting_engine.py +56 -19
- angr/analyses/decompiler/ssailification/ssailification.py +13 -3
- angr/analyses/decompiler/ssailification/traversal.py +28 -2
- angr/analyses/decompiler/ssailification/traversal_state.py +6 -1
- angr/analyses/decompiler/structured_codegen/c.py +44 -21
- angr/analyses/decompiler/structuring/phoenix.py +118 -15
- angr/analyses/decompiler/utils.py +113 -8
- 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/reaching_definitions/function_handler.py +1 -1
- angr/analyses/reassembler.py +1 -2
- angr/analyses/s_liveness.py +5 -1
- angr/analyses/s_propagator.py +26 -7
- angr/analyses/s_reaching_definitions/s_rda_model.py +2 -1
- angr/analyses/s_reaching_definitions/s_rda_view.py +20 -1
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +11 -1
- angr/analyses/soot_class_hierarchy.py +1 -2
- angr/analyses/stack_pointer_tracker.py +29 -3
- angr/analyses/static_hooker.py +1 -2
- angr/analyses/typehoon/simple_solver.py +2 -2
- angr/analyses/variable_recovery/engine_ail.py +19 -7
- angr/analyses/variable_recovery/engine_base.py +16 -14
- angr/analyses/variable_recovery/engine_vex.py +2 -2
- angr/analyses/variable_recovery/variable_recovery_fast.py +23 -3
- angr/analyses/veritesting.py +4 -7
- angr/analyses/vfg.py +1 -1
- angr/analyses/vsa_ddg.py +1 -2
- angr/block.py +62 -22
- angr/callable.py +1 -3
- angr/calling_conventions.py +3 -3
- angr/codenode.py +5 -1
- angr/concretization_strategies/__init__.py +1 -83
- angr/concretization_strategies/any.py +2 -1
- angr/concretization_strategies/any_named.py +1 -1
- angr/concretization_strategies/base.py +81 -0
- angr/concretization_strategies/controlled_data.py +2 -1
- angr/concretization_strategies/eval.py +2 -1
- angr/concretization_strategies/logging.py +3 -1
- angr/concretization_strategies/max.py +2 -1
- angr/concretization_strategies/nonzero.py +2 -1
- angr/concretization_strategies/nonzero_range.py +2 -1
- angr/concretization_strategies/norepeats.py +2 -1
- angr/concretization_strategies/norepeats_range.py +2 -1
- angr/concretization_strategies/range.py +2 -1
- angr/concretization_strategies/signed_add.py +2 -1
- angr/concretization_strategies/single.py +2 -1
- angr/concretization_strategies/solutions.py +2 -1
- angr/concretization_strategies/unlimited_range.py +2 -1
- angr/engines/__init__.py +8 -5
- angr/engines/engine.py +3 -5
- angr/engines/failure.py +4 -5
- angr/engines/pcode/emulate.py +1 -1
- angr/engines/pcode/lifter.py +31 -18
- angr/engines/procedure.py +5 -7
- angr/engines/soot/expressions/__init__.py +20 -23
- angr/engines/soot/expressions/base.py +4 -4
- angr/engines/soot/expressions/invoke.py +1 -2
- angr/engines/soot/statements/__init__.py +10 -12
- angr/engines/soot/values/__init__.py +10 -12
- angr/engines/soot/values/arrayref.py +3 -3
- angr/engines/soot/values/instancefieldref.py +3 -2
- angr/engines/successors.py +18 -12
- 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/engines/vex/lifter.py +9 -6
- 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/flirt/build_sig.py +8 -15
- angr/knowledge_plugins/cfg/cfg_model.py +20 -17
- angr/knowledge_plugins/functions/function.py +70 -79
- angr/knowledge_plugins/functions/function_manager.py +8 -7
- angr/knowledge_plugins/functions/function_parser.py +1 -1
- angr/knowledge_plugins/functions/soot_function.py +21 -24
- angr/knowledge_plugins/propagations/propagation_model.py +4 -5
- angr/knowledge_plugins/propagations/states.py +0 -511
- angr/knowledge_plugins/variables/variable_manager.py +16 -10
- angr/lib/angr_native.dll +0 -0
- angr/procedures/libc/memcpy.py +4 -4
- angr/procedures/procedure_dict.py +3 -2
- angr/protos/__init__.py +2 -5
- angr/protos/cfg_pb2.py +21 -18
- angr/protos/function_pb2.py +17 -14
- angr/protos/primitives_pb2.py +44 -39
- angr/protos/variables_pb2.py +36 -31
- angr/protos/xrefs_pb2.py +15 -12
- angr/sim_procedure.py +15 -16
- angr/sim_variable.py +13 -1
- angr/simos/__init__.py +2 -0
- angr/simos/javavm.py +4 -6
- angr/simos/xbox.py +32 -0
- angr/state_plugins/__init__.py +0 -2
- angr/state_plugins/callstack.py +4 -4
- angr/state_plugins/cgc.py +3 -2
- angr/state_plugins/gdb.py +6 -5
- angr/state_plugins/globals.py +1 -2
- angr/state_plugins/heap/heap_brk.py +1 -2
- angr/state_plugins/history.py +10 -12
- angr/state_plugins/inspect.py +3 -5
- angr/state_plugins/libc.py +2 -2
- angr/state_plugins/log.py +8 -10
- angr/state_plugins/loop_data.py +1 -2
- angr/state_plugins/posix.py +7 -7
- angr/state_plugins/preconstrainer.py +2 -3
- angr/state_plugins/scratch.py +5 -8
- angr/state_plugins/sim_action.py +3 -3
- angr/state_plugins/solver.py +8 -3
- angr/state_plugins/symbolizer.py +5 -4
- angr/state_plugins/uc_manager.py +3 -3
- angr/state_plugins/unicorn_engine.py +5 -1
- angr/state_plugins/view.py +3 -5
- angr/storage/file.py +3 -5
- angr/storage/memory_mixins/address_concretization_mixin.py +2 -2
- angr/storage/memory_mixins/bvv_conversion_mixin.py +3 -3
- angr/storage/memory_mixins/clouseau_mixin.py +1 -3
- angr/storage/memory_mixins/name_resolution_mixin.py +1 -3
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +13 -15
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +1 -22
- angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +3 -4
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +4 -2
- angr/storage/memory_mixins/smart_find_mixin.py +1 -1
- angr/storage/memory_mixins/underconstrained_mixin.py +1 -1
- angr/storage/memory_mixins/unwrapper_mixin.py +1 -3
- angr/utils/enums_conv.py +28 -12
- angr/utils/segment_list.py +25 -22
- angr/utils/timing.py +18 -1
- angr/vaults.py +5 -6
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/METADATA +7 -7
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/RECORD +194 -192
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/WHEEL +1 -1
- angr/analyses/propagator/outdated_definition_walker.py +0 -159
- angr/analyses/propagator/tmpvar_finder.py +0 -18
- angr/engines/concrete.py +0 -180
- angr/exploration_techniques/symbion.py +0 -80
- angr/state_plugins/concrete.py +0 -295
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/LICENSE +0 -0
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/entry_points.txt +0 -0
- {angr-9.2.135.dist-info → angr-9.2.137.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/analyses/__init__.py
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
# " pylint:disable=wrong-import-position
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
from .analysis import Analysis, AnalysesHub
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def register_analysis(cls, name):
|
|
8
|
-
AnalysesHub.register_default(name, cls)
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
from .analysis import Analysis, AnalysesHub, register_analysis
|
|
11
5
|
from .forward_analysis import ForwardAnalysis, visitors
|
|
12
6
|
from .propagator import PropagatorAnalysis
|
|
13
7
|
from .cfg import CFGFast, CFGEmulated, CFG, CFGArchOptions, CFGFastSoot
|
|
@@ -54,6 +48,7 @@ from .patchfinder import PatchFinderAnalysis
|
|
|
54
48
|
from .pathfinder import Pathfinder
|
|
55
49
|
from .smc import SelfModifyingCodeAnalysis
|
|
56
50
|
from .unpacker import PackingDetector
|
|
51
|
+
from .fcp import FastConstantPropagation
|
|
57
52
|
from . import deobfuscator
|
|
58
53
|
|
|
59
54
|
|
|
@@ -85,6 +80,7 @@ __all__ = (
|
|
|
85
80
|
"Disassembly",
|
|
86
81
|
"DominanceFrontier",
|
|
87
82
|
"FactCollector",
|
|
83
|
+
"FastConstantPropagation",
|
|
88
84
|
"FlirtAnalysis",
|
|
89
85
|
"ForwardAnalysis",
|
|
90
86
|
"Identifier",
|
angr/analyses/analysis.py
CHANGED
angr/analyses/backward_slice.py
CHANGED
|
@@ -6,6 +6,7 @@ import networkx
|
|
|
6
6
|
import pyvex
|
|
7
7
|
from . import Analysis
|
|
8
8
|
|
|
9
|
+
from angr.analyses import AnalysesHub
|
|
9
10
|
from angr.code_location import CodeLocation
|
|
10
11
|
from angr.annocfg import AnnotatedCFG
|
|
11
12
|
from angr.errors import AngrBackwardSlicingError
|
|
@@ -682,6 +683,4 @@ class BackwardSlice(Analysis):
|
|
|
682
683
|
return cmp_stmt_id, cmp_tmp_id
|
|
683
684
|
|
|
684
685
|
|
|
685
|
-
from angr.analyses import AnalysesHub
|
|
686
|
-
|
|
687
686
|
AnalysesHub.register_default("BackwardSlice", BackwardSlice)
|
|
@@ -4,6 +4,7 @@ import re
|
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
from collections import defaultdict
|
|
6
6
|
|
|
7
|
+
from angr.analyses import AnalysesHub
|
|
7
8
|
from angr.knowledge_base import KnowledgeBase
|
|
8
9
|
from angr.codenode import HookNode
|
|
9
10
|
from angr.sim_variable import SimConstantVariable, SimRegisterVariable, SimMemoryVariable, SimStackVariable
|
|
@@ -430,7 +431,7 @@ class BinaryOptimizer(Analysis):
|
|
|
430
431
|
|
|
431
432
|
# find out all call instructions
|
|
432
433
|
call_insns = set()
|
|
433
|
-
for src,
|
|
434
|
+
for src, _dst, data in function.transition_graph.edges(data=True):
|
|
434
435
|
if "type" in data and data["type"] == "call":
|
|
435
436
|
src_block = function._get_block(src.addr)
|
|
436
437
|
call_insns.add(src_block.instruction_addrs[-1])
|
|
@@ -460,7 +461,7 @@ class BinaryOptimizer(Analysis):
|
|
|
460
461
|
# make sure we never gets the address of those stack variables into any register
|
|
461
462
|
# say, lea edx, [ebp-0x4] is forbidden
|
|
462
463
|
# check all edges in data graph
|
|
463
|
-
for src, dst
|
|
464
|
+
for src, dst in data_graph.edges():
|
|
464
465
|
if (
|
|
465
466
|
isinstance(dst.variable, SimRegisterVariable)
|
|
466
467
|
and dst.variable.reg != ebp_offset
|
|
@@ -666,6 +667,4 @@ class BinaryOptimizer(Analysis):
|
|
|
666
667
|
self.dead_assignments.append(da)
|
|
667
668
|
|
|
668
669
|
|
|
669
|
-
from angr.analyses import AnalysesHub
|
|
670
|
-
|
|
671
670
|
AnalysesHub.register_default("BinaryOptimizer", BinaryOptimizer)
|
angr/analyses/bindiff.py
CHANGED
|
@@ -3,17 +3,17 @@ import logging
|
|
|
3
3
|
import math
|
|
4
4
|
import types
|
|
5
5
|
from collections import deque, defaultdict
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
6
7
|
|
|
7
8
|
import networkx
|
|
8
9
|
|
|
9
|
-
from
|
|
10
|
+
from angr.analyses import AnalysesHub, Analysis, CFGEmulated
|
|
11
|
+
from angr.errors import SimEngineError, SimMemoryError
|
|
12
|
+
|
|
10
13
|
|
|
11
14
|
if TYPE_CHECKING:
|
|
12
15
|
from angr.knowledge_plugins import Function
|
|
13
16
|
|
|
14
|
-
from . import Analysis, CFGEmulated
|
|
15
|
-
|
|
16
|
-
from angr.errors import SimEngineError, SimMemoryError
|
|
17
17
|
|
|
18
18
|
# todo include an explanation of the algorithm
|
|
19
19
|
# todo include a method that detects any change other than constants
|
|
@@ -1234,6 +1234,4 @@ class BinDiff(Analysis):
|
|
|
1234
1234
|
return matches
|
|
1235
1235
|
|
|
1236
1236
|
|
|
1237
|
-
from angr.analyses import AnalysesHub
|
|
1238
|
-
|
|
1239
1237
|
AnalysesHub.register_default("BinDiff", BinDiff)
|
angr/analyses/boyscout.py
CHANGED
|
@@ -6,7 +6,7 @@ from collections import defaultdict
|
|
|
6
6
|
from archinfo import all_arches
|
|
7
7
|
from archinfo.arch_arm import is_arm_arch
|
|
8
8
|
|
|
9
|
-
from . import Analysis
|
|
9
|
+
from angr.analyses import AnalysesHub, Analysis
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
l = logging.getLogger(name=__name__)
|
|
@@ -73,6 +73,4 @@ class BoyScout(Analysis):
|
|
|
73
73
|
l.debug("The architecture should be %s with %s", self.arch, self.endianness)
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
from angr.analyses import AnalysesHub
|
|
77
|
-
|
|
78
76
|
AnalysesHub.register_default("BoyScout", BoyScout)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from . import Analysis
|
|
3
|
-
from angr import SIM_PROCEDURES
|
|
4
2
|
|
|
5
3
|
import logging
|
|
6
4
|
|
|
5
|
+
from angr import SIM_PROCEDURES
|
|
6
|
+
from angr.analyses import AnalysesHub, Analysis
|
|
7
|
+
|
|
8
|
+
|
|
7
9
|
l = logging.getLogger(name=__name__)
|
|
8
10
|
|
|
9
11
|
|
|
@@ -69,6 +71,4 @@ class CalleeCleanupFinder(Analysis):
|
|
|
69
71
|
return None
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
from angr.analyses import AnalysesHub
|
|
73
|
-
|
|
74
74
|
AnalysesHub.register_default("CalleeCleanupFinder", CalleeCleanupFinder)
|
|
@@ -436,7 +436,8 @@ class CallingConventionAnalysis(Analysis):
|
|
|
436
436
|
if caller.is_simprocedure or caller.is_alignment:
|
|
437
437
|
# do not analyze SimProcedures or alignment stubs
|
|
438
438
|
continue
|
|
439
|
-
|
|
439
|
+
if src.instruction_addrs:
|
|
440
|
+
call_sites_by_function[caller].append((src.addr, src.instruction_addrs[-1]))
|
|
440
441
|
|
|
441
442
|
call_sites_by_function_list = sorted(call_sites_by_function.items(), key=lambda x: x[0].addr)[
|
|
442
443
|
:max_analyzing_callsites
|
|
@@ -923,9 +924,10 @@ class CallingConventionAnalysis(Analysis):
|
|
|
923
924
|
if not set(spilled_regs).issubset(set(allowed_spilled_regs)):
|
|
924
925
|
return False, None
|
|
925
926
|
|
|
926
|
-
|
|
927
|
-
if reg in spilled_regs
|
|
928
|
-
|
|
927
|
+
i = next(
|
|
928
|
+
(i for i, reg in enumerate(allowed_spilled_regs) if reg in spilled_regs),
|
|
929
|
+
len(allowed_spilled_regs),
|
|
930
|
+
)
|
|
929
931
|
|
|
930
932
|
return True, i
|
|
931
933
|
|
|
@@ -276,13 +276,21 @@ class FactCollector(Analysis):
|
|
|
276
276
|
call_succ, ret_succ = None, None
|
|
277
277
|
for _, succ, data in func_graph.out_edges(node, data=True):
|
|
278
278
|
edge_type = data.get("type")
|
|
279
|
+
outside = data.get("outside", False)
|
|
279
280
|
if succ not in traversed and depth + 1 <= self._max_depth:
|
|
280
281
|
if edge_type == "fake_return":
|
|
281
282
|
ret_succ = succ
|
|
282
|
-
elif edge_type == "transition":
|
|
283
|
+
elif edge_type == "transition" and not outside:
|
|
283
284
|
successor_added = True
|
|
284
285
|
queue.append((depth + 1, state.copy(), succ, None))
|
|
285
|
-
elif edge_type == "call":
|
|
286
|
+
elif edge_type == "call" or (edge_type == "transition" and outside):
|
|
287
|
+
# a call or a tail-call
|
|
288
|
+
if not isinstance(succ, Function):
|
|
289
|
+
if self.kb.functions.contains_addr(succ.addr):
|
|
290
|
+
succ = self.kb.functions.get_by_addr(succ.addr)
|
|
291
|
+
else:
|
|
292
|
+
# not sure who we are calling
|
|
293
|
+
continue
|
|
286
294
|
call_succ = succ
|
|
287
295
|
if call_succ is not None:
|
|
288
296
|
successor_added = True
|
|
@@ -297,7 +305,6 @@ class FactCollector(Analysis):
|
|
|
297
305
|
try:
|
|
298
306
|
arg_locs = func.calling_convention.arg_locs(func.prototype)
|
|
299
307
|
except (TypeError, ValueError):
|
|
300
|
-
func.prototype = None
|
|
301
308
|
return
|
|
302
309
|
|
|
303
310
|
if None in arg_locs:
|
angr/analyses/cdg.py
CHANGED
|
@@ -3,6 +3,7 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
import networkx
|
|
5
5
|
|
|
6
|
+
from angr.analyses import AnalysesHub
|
|
6
7
|
from angr.utils.graph import compute_dominance_frontier, PostDominators, TemporaryNode
|
|
7
8
|
from . import Analysis
|
|
8
9
|
|
|
@@ -185,6 +186,4 @@ class CDG(Analysis):
|
|
|
185
186
|
_l.debug("%s is not in post dominator dict.", b2)
|
|
186
187
|
|
|
187
188
|
|
|
188
|
-
from angr.analyses import AnalysesHub
|
|
189
|
-
|
|
190
189
|
AnalysesHub.register_default("CDG", CDG)
|
angr/analyses/cfg/cfb.py
CHANGED
|
@@ -6,9 +6,9 @@ from collections.abc import Callable
|
|
|
6
6
|
import cle
|
|
7
7
|
from cle.backends.externs import KernelObject, ExternObject
|
|
8
8
|
from cle.backends.tls.elf_tls import ELFTLSObject
|
|
9
|
-
|
|
10
9
|
from sortedcontainers import SortedDict
|
|
11
10
|
|
|
11
|
+
from angr.analyses import AnalysesHub
|
|
12
12
|
from angr.knowledge_plugins.cfg.memory_data import MemoryDataSort, MemoryData
|
|
13
13
|
from angr.analyses.analysis import Analysis
|
|
14
14
|
|
|
@@ -424,7 +424,5 @@ class CFBlanket(Analysis):
|
|
|
424
424
|
addr = max_addr
|
|
425
425
|
|
|
426
426
|
|
|
427
|
-
from angr.analyses import AnalysesHub
|
|
428
|
-
|
|
429
427
|
AnalysesHub.register_default("CFB", CFBlanket)
|
|
430
428
|
AnalysesHub.register_default("CFBlanket", CFBlanket)
|
angr/analyses/cfg/cfg.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
+
|
|
2
3
|
import sys
|
|
3
4
|
|
|
5
|
+
from angr.analyses import AnalysesHub
|
|
4
6
|
from .cfg_fast import CFGFast
|
|
5
7
|
|
|
6
8
|
|
|
@@ -69,6 +71,4 @@ class CFG(CFGFast): # pylint: disable=abstract-method
|
|
|
69
71
|
CFGFast.__init__(self, **kwargs)
|
|
70
72
|
|
|
71
73
|
|
|
72
|
-
from angr.analyses import AnalysesHub
|
|
73
|
-
|
|
74
74
|
AnalysesHub.register_default("CFG", CFG)
|
angr/analyses/cfg/cfg_base.py
CHANGED
|
@@ -1570,13 +1570,13 @@ class CFGBase(Analysis):
|
|
|
1570
1570
|
# TODO: Is it required that PLT stubs are always aligned by 16? If so, on what architectures and platforms is it
|
|
1571
1571
|
# TODO: enforced?
|
|
1572
1572
|
|
|
1573
|
-
tmp_functions = self.kb.functions
|
|
1573
|
+
tmp_functions = self.kb.functions
|
|
1574
1574
|
|
|
1575
1575
|
for function in tmp_functions.values():
|
|
1576
1576
|
function.mark_nonreturning_calls_endpoints()
|
|
1577
1577
|
if function.returning is False:
|
|
1578
1578
|
# remove all FakeRet edges that are related to this function
|
|
1579
|
-
func_node = self.model.get_any_node(function.addr)
|
|
1579
|
+
func_node = self.model.get_any_node(function.addr, force_fastpath=True)
|
|
1580
1580
|
if func_node is not None:
|
|
1581
1581
|
callsite_nodes = [
|
|
1582
1582
|
src
|
|
@@ -1588,8 +1588,8 @@ class CFGBase(Analysis):
|
|
|
1588
1588
|
if data.get("jumpkind", None) == "Ijk_FakeRet":
|
|
1589
1589
|
self.graph.remove_edge(callsite_node, dst)
|
|
1590
1590
|
|
|
1591
|
-
# Clear old functions dict
|
|
1592
|
-
self.kb.functions.
|
|
1591
|
+
# Clear old functions dict by creating a new function manager
|
|
1592
|
+
self.kb.functions = FunctionManager(self.kb)
|
|
1593
1593
|
|
|
1594
1594
|
blockaddr_to_function = {}
|
|
1595
1595
|
traversed_cfg_nodes = set()
|
|
@@ -1602,7 +1602,7 @@ class CFGBase(Analysis):
|
|
|
1602
1602
|
if jumpkind == "Ijk_Call" or jumpkind.startswith("Ijk_Sys"):
|
|
1603
1603
|
function_nodes.add(dst)
|
|
1604
1604
|
|
|
1605
|
-
entry_node = self.model.get_any_node(self._binary.entry)
|
|
1605
|
+
entry_node = self.model.get_any_node(self._binary.entry, force_fastpath=True)
|
|
1606
1606
|
if entry_node is not None:
|
|
1607
1607
|
function_nodes.add(entry_node)
|
|
1608
1608
|
|
|
@@ -1663,7 +1663,7 @@ class CFGBase(Analysis):
|
|
|
1663
1663
|
secondary_function_nodes = set()
|
|
1664
1664
|
# add all function chunks ("functions" that are not called from anywhere)
|
|
1665
1665
|
for func_addr in tmp_functions:
|
|
1666
|
-
node = self.model.get_any_node(func_addr)
|
|
1666
|
+
node = self.model.get_any_node(func_addr, force_fastpath=True)
|
|
1667
1667
|
if node is None:
|
|
1668
1668
|
continue
|
|
1669
1669
|
if node.addr not in blockaddr_to_function:
|
|
@@ -1992,8 +1992,8 @@ class CFGBase(Analysis):
|
|
|
1992
1992
|
if not transition_found:
|
|
1993
1993
|
continue
|
|
1994
1994
|
|
|
1995
|
-
cfgnode_0 = self.model.get_any_node(block_node.addr)
|
|
1996
|
-
cfgnode_1 = self.model.get_any_node(addr_1)
|
|
1995
|
+
cfgnode_0 = self.model.get_any_node(block_node.addr, force_fastpath=True)
|
|
1996
|
+
cfgnode_1 = self.model.get_any_node(addr_1, force_fastpath=True)
|
|
1997
1997
|
|
|
1998
1998
|
if cfgnode_0 is None or cfgnode_1 is None:
|
|
1999
1999
|
continue
|
|
@@ -2089,7 +2089,7 @@ class CFGBase(Analysis):
|
|
|
2089
2089
|
continue
|
|
2090
2090
|
if func_addr in jumptable_entries:
|
|
2091
2091
|
# is there any call edge pointing to it?
|
|
2092
|
-
func_node = self.get_any_node(func_addr)
|
|
2092
|
+
func_node = self.get_any_node(func_addr, force_fastpath=True)
|
|
2093
2093
|
if func_node is not None:
|
|
2094
2094
|
in_edges = self.graph.in_edges(func_node, data=True)
|
|
2095
2095
|
has_transition_pred = None
|
|
@@ -2128,7 +2128,7 @@ class CFGBase(Analysis):
|
|
|
2128
2128
|
else:
|
|
2129
2129
|
is_syscall = self.project.simos.is_syscall_addr(addr)
|
|
2130
2130
|
|
|
2131
|
-
n = self.model.get_any_node(addr, is_syscall=is_syscall)
|
|
2131
|
+
n = self.model.get_any_node(addr, is_syscall=is_syscall, force_fastpath=True)
|
|
2132
2132
|
node = addr if n is None else self._to_snippet(n)
|
|
2133
2133
|
|
|
2134
2134
|
if isinstance(addr, SootAddressDescriptor):
|
|
@@ -2304,7 +2304,7 @@ class CFGBase(Analysis):
|
|
|
2304
2304
|
src_function = self._addr_to_function(src_addr, blockaddr_to_function, known_functions)
|
|
2305
2305
|
|
|
2306
2306
|
if src_addr not in src_function.block_addrs_set:
|
|
2307
|
-
n = self.model.get_any_node(src_addr)
|
|
2307
|
+
n = self.model.get_any_node(src_addr, force_fastpath=True)
|
|
2308
2308
|
node = src_addr if n is None else self._to_snippet(n)
|
|
2309
2309
|
self.kb.functions._add_node(src_function.addr, node)
|
|
2310
2310
|
|
|
@@ -2315,7 +2315,7 @@ class CFGBase(Analysis):
|
|
|
2315
2315
|
jumpkind = data["jumpkind"]
|
|
2316
2316
|
|
|
2317
2317
|
if jumpkind == "Ijk_Ret":
|
|
2318
|
-
n = self.model.get_any_node(src_addr)
|
|
2318
|
+
n = self.model.get_any_node(src_addr, force_fastpath=True)
|
|
2319
2319
|
from_node = src_addr if n is None else self._to_snippet(n)
|
|
2320
2320
|
self.kb.functions._add_return_from(src_function.addr, from_node, None)
|
|
2321
2321
|
|
|
@@ -2334,7 +2334,7 @@ class CFGBase(Analysis):
|
|
|
2334
2334
|
# It must be calling a function
|
|
2335
2335
|
dst_function = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
|
|
2336
2336
|
|
|
2337
|
-
n = self.model.get_any_node(src_addr)
|
|
2337
|
+
n = self.model.get_any_node(src_addr, force_fastpath=True)
|
|
2338
2338
|
if n is None:
|
|
2339
2339
|
src_snippet = self._to_snippet(addr=src_addr, base_state=self._base_state)
|
|
2340
2340
|
else:
|
|
@@ -2349,21 +2349,12 @@ class CFGBase(Analysis):
|
|
|
2349
2349
|
else:
|
|
2350
2350
|
fakeret_node = self._one_fakeret_node(all_edges)
|
|
2351
2351
|
|
|
2352
|
-
fakeret_snippet = None if fakeret_node is None else self._to_snippet(cfg_node=fakeret_node)
|
|
2353
|
-
|
|
2354
2352
|
if isinstance(dst_addr, SootAddressDescriptor):
|
|
2355
2353
|
dst_addr = dst_addr.method
|
|
2356
2354
|
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
dst_addr,
|
|
2361
|
-
fakeret_snippet,
|
|
2362
|
-
syscall=is_syscall,
|
|
2363
|
-
ins_addr=ins_addr,
|
|
2364
|
-
stmt_idx=stmt_idx,
|
|
2365
|
-
)
|
|
2366
|
-
|
|
2355
|
+
# determining the returning target
|
|
2356
|
+
return_to_outside = False
|
|
2357
|
+
returning_snippet = None
|
|
2367
2358
|
if dst_function.returning and fakeret_node is not None:
|
|
2368
2359
|
returning_target = src.addr + src.size
|
|
2369
2360
|
if returning_target not in blockaddr_to_function:
|
|
@@ -2372,9 +2363,9 @@ class CFGBase(Analysis):
|
|
|
2372
2363
|
else:
|
|
2373
2364
|
self._addr_to_function(returning_target, blockaddr_to_function, known_functions)
|
|
2374
2365
|
|
|
2375
|
-
|
|
2366
|
+
return_to_outside = blockaddr_to_function[returning_target] is not src_function
|
|
2376
2367
|
|
|
2377
|
-
n = self.model.get_any_node(returning_target)
|
|
2368
|
+
n = self.model.get_any_node(returning_target, force_fastpath=True)
|
|
2378
2369
|
if n is None:
|
|
2379
2370
|
try:
|
|
2380
2371
|
returning_snippet = self._to_snippet(addr=returning_target, base_state=self._base_state)
|
|
@@ -2384,17 +2375,28 @@ class CFGBase(Analysis):
|
|
|
2384
2375
|
else:
|
|
2385
2376
|
returning_snippet = self._to_snippet(cfg_node=n)
|
|
2386
2377
|
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2378
|
+
self.kb.functions._add_call_to(
|
|
2379
|
+
src_function.addr,
|
|
2380
|
+
src_snippet,
|
|
2381
|
+
dst_addr,
|
|
2382
|
+
retn_node=returning_snippet,
|
|
2383
|
+
syscall=is_syscall,
|
|
2384
|
+
ins_addr=ins_addr,
|
|
2385
|
+
stmt_idx=stmt_idx,
|
|
2386
|
+
return_to_outside=return_to_outside,
|
|
2387
|
+
)
|
|
2388
|
+
|
|
2389
|
+
if returning_snippet is not None:
|
|
2390
|
+
self.kb.functions._add_fakeret_to(
|
|
2391
|
+
src_function.addr, src_snippet, returning_snippet, confirmed=True, to_outside=return_to_outside
|
|
2392
|
+
)
|
|
2391
2393
|
|
|
2392
2394
|
elif jumpkind in ("Ijk_Boring", "Ijk_InvalICache", "Ijk_Exception"):
|
|
2393
2395
|
# convert src_addr and dst_addr to CodeNodes
|
|
2394
|
-
n = self.model.get_any_node(src_addr)
|
|
2396
|
+
n = self.model.get_any_node(src_addr, force_fastpath=True)
|
|
2395
2397
|
src_node = src_addr if n is None else self._to_snippet(cfg_node=n)
|
|
2396
2398
|
|
|
2397
|
-
n = self.model.get_any_node(dst_addr)
|
|
2399
|
+
n = self.model.get_any_node(dst_addr, force_fastpath=True)
|
|
2398
2400
|
dst_node = dst_addr if n is None else self._to_snippet(cfg_node=n)
|
|
2399
2401
|
|
|
2400
2402
|
if self._skip_unmapped_addrs:
|
|
@@ -2460,10 +2462,10 @@ class CFGBase(Analysis):
|
|
|
2460
2462
|
|
|
2461
2463
|
elif jumpkind == "Ijk_FakeRet":
|
|
2462
2464
|
# convert src_addr and dst_addr to CodeNodes
|
|
2463
|
-
n = self.model.get_any_node(src_addr)
|
|
2465
|
+
n = self.model.get_any_node(src_addr, force_fastpath=True)
|
|
2464
2466
|
src_node = src_addr if n is None else self._to_snippet(n)
|
|
2465
2467
|
|
|
2466
|
-
n = self.model.get_any_node(dst_addr)
|
|
2468
|
+
n = self.model.get_any_node(dst_addr, force_fastpath=True)
|
|
2467
2469
|
dst_node = dst_addr if n is None else self._to_snippet(n)
|
|
2468
2470
|
|
|
2469
2471
|
if dst_addr not in blockaddr_to_function:
|
|
@@ -2518,18 +2520,17 @@ class CFGBase(Analysis):
|
|
|
2518
2520
|
#
|
|
2519
2521
|
|
|
2520
2522
|
@staticmethod
|
|
2521
|
-
def _is_noop_block(arch: archinfo.Arch, block):
|
|
2523
|
+
def _is_noop_block(arch: archinfo.Arch, block) -> bool:
|
|
2522
2524
|
"""
|
|
2523
2525
|
Check if the block is a no-op block by checking VEX statements.
|
|
2524
2526
|
|
|
2525
2527
|
:param arch: An architecture descriptor.
|
|
2526
2528
|
:param block: The VEX block instance.
|
|
2527
2529
|
:return: True if the entire block is a single-byte or multi-byte nop instruction, False otherwise.
|
|
2528
|
-
:rtype: bool
|
|
2529
2530
|
"""
|
|
2530
2531
|
|
|
2531
2532
|
if arch.name == "X86" or arch.name == "AMD64":
|
|
2532
|
-
if set(block.bytes) == {
|
|
2533
|
+
if set(block.bytes) == {0x90}:
|
|
2533
2534
|
return True
|
|
2534
2535
|
elif arch.name == "MIPS32":
|
|
2535
2536
|
if arch.memory_endness == "Iend_BE":
|
|
@@ -2575,36 +2576,7 @@ class CFGBase(Analysis):
|
|
|
2575
2576
|
if THUMB_NOOPS.issuperset(insns):
|
|
2576
2577
|
return True
|
|
2577
2578
|
|
|
2578
|
-
|
|
2579
|
-
# the block is a noop block if it only has IMark statements **and** it jumps to its immediate successor. VEX
|
|
2580
|
-
# will generate such blocks when opt_level==1 and cross_insn_opt is True
|
|
2581
|
-
fallthrough_addr = block.addr + block.size
|
|
2582
|
-
next_ = block.vex.next
|
|
2583
|
-
if (
|
|
2584
|
-
isinstance(next_, pyvex.IRExpr.Const)
|
|
2585
|
-
and next_.con.value == fallthrough_addr
|
|
2586
|
-
and all((type(stmt) is pyvex.IRStmt.IMark) for stmt in block.vex.statements)
|
|
2587
|
-
):
|
|
2588
|
-
return True
|
|
2589
|
-
|
|
2590
|
-
# the block is a noop block if it only has IMark statements and IP-setting statements that set the IP to the
|
|
2591
|
-
# next location. VEX will generate such blocks when opt_level==1 and cross_insn_opt is False
|
|
2592
|
-
ip_offset = arch.ip_offset
|
|
2593
|
-
if (
|
|
2594
|
-
all(
|
|
2595
|
-
(type(stmt) is pyvex.IRStmt.IMark or (type(stmt) is pyvex.IRStmt.Put and stmt.offset == ip_offset))
|
|
2596
|
-
for stmt in block.vex.statements
|
|
2597
|
-
)
|
|
2598
|
-
and block.vex.statements
|
|
2599
|
-
):
|
|
2600
|
-
last_stmt = block.vex.statements[-1]
|
|
2601
|
-
if (
|
|
2602
|
-
isinstance(last_stmt, pyvex.IRStmt.IMark)
|
|
2603
|
-
and isinstance(next_, pyvex.IRExpr.Const)
|
|
2604
|
-
and next_.con.value == fallthrough_addr
|
|
2605
|
-
):
|
|
2606
|
-
return True
|
|
2607
|
-
return False
|
|
2579
|
+
return block.vex_nostmt.is_noop_block
|
|
2608
2580
|
|
|
2609
2581
|
@staticmethod
|
|
2610
2582
|
def _is_noop_insn(insn):
|
|
@@ -2083,7 +2083,7 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
2083
2083
|
if src_node_key is None:
|
|
2084
2084
|
if dst_node is None:
|
|
2085
2085
|
raise ValueError("Either src_node_key or dst_node_key must be specified.")
|
|
2086
|
-
self.kb.functions.function(dst_node.function_address, create=True).
|
|
2086
|
+
self.kb.functions.function(dst_node.function_address, create=True)._register_node(True, dst_codenode)
|
|
2087
2087
|
return
|
|
2088
2088
|
|
|
2089
2089
|
src_node = self._graph_get_node(src_node_key, terminator_for_nonexistent_node=True)
|
|
@@ -3208,109 +3208,6 @@ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
|
|
|
3208
3208
|
# Update loop backedges and graph
|
|
3209
3209
|
self._loop_back_edges = list(itertools.chain.from_iterable(loop.continue_edges for loop in loop_finder.loops))
|
|
3210
3210
|
|
|
3211
|
-
# Private methods - function/procedure/subroutine analysis
|
|
3212
|
-
# Including calling convention, function arguments, etc.
|
|
3213
|
-
|
|
3214
|
-
def _refine_function_arguments(self, func, callsites):
|
|
3215
|
-
"""
|
|
3216
|
-
|
|
3217
|
-
:param func:
|
|
3218
|
-
:param callsites:
|
|
3219
|
-
:return:
|
|
3220
|
-
"""
|
|
3221
|
-
|
|
3222
|
-
for i, c in enumerate(callsites):
|
|
3223
|
-
# Execute one block ahead of the callsite, and execute one basic block after the callsite
|
|
3224
|
-
# In this process, the following tasks are performed:
|
|
3225
|
-
# - Record registers/stack variables that are modified
|
|
3226
|
-
# - Record the change of the stack pointer
|
|
3227
|
-
# - Check if the return value is used immediately
|
|
3228
|
-
# We assume that the stack is balanced before and after the call (you can have caller clean-up of course).
|
|
3229
|
-
# Any abnormal behaviors will be logged.
|
|
3230
|
-
# Hopefully this approach will allow us to have a better understanding of parameters of those function
|
|
3231
|
-
# stubs and function proxies.
|
|
3232
|
-
|
|
3233
|
-
if c.simprocedure_name is not None:
|
|
3234
|
-
# Skip all SimProcedures
|
|
3235
|
-
continue
|
|
3236
|
-
|
|
3237
|
-
l.debug("Refining %s at 0x%x (%d/%d).", repr(func), c.addr, i, len(callsites))
|
|
3238
|
-
|
|
3239
|
-
# Get a basic block ahead of the callsite
|
|
3240
|
-
blocks_ahead = [c]
|
|
3241
|
-
|
|
3242
|
-
# the block after
|
|
3243
|
-
blocks_after = []
|
|
3244
|
-
successors = self.get_successors_and_jumpkind(c, excluding_fakeret=False)
|
|
3245
|
-
for s, jk in successors:
|
|
3246
|
-
if jk == "Ijk_FakeRet":
|
|
3247
|
-
blocks_after = [s]
|
|
3248
|
-
break
|
|
3249
|
-
|
|
3250
|
-
regs_overwritten = set()
|
|
3251
|
-
stack_overwritten = set()
|
|
3252
|
-
regs_read = set()
|
|
3253
|
-
regs_written = set()
|
|
3254
|
-
|
|
3255
|
-
try:
|
|
3256
|
-
# Execute the predecessor
|
|
3257
|
-
path = self.project.factory.path(
|
|
3258
|
-
self.project.factory.blank_state(mode="fastpath", addr=blocks_ahead[0].addr)
|
|
3259
|
-
)
|
|
3260
|
-
path.step()
|
|
3261
|
-
all_successors = path.next_run.successors + path.next_run.unsat_successors
|
|
3262
|
-
if not all_successors:
|
|
3263
|
-
continue
|
|
3264
|
-
|
|
3265
|
-
suc = all_successors[0]
|
|
3266
|
-
se = suc.solver
|
|
3267
|
-
# Examine the path log
|
|
3268
|
-
actions = suc.history.recent_actions
|
|
3269
|
-
sp = se.eval_one(suc.regs.sp, default=0) + self.project.arch.call_sp_fix
|
|
3270
|
-
for ac in actions:
|
|
3271
|
-
if ac.type == "reg" and ac.action == "write":
|
|
3272
|
-
regs_overwritten.add(ac.offset)
|
|
3273
|
-
elif ac.type == "mem" and ac.action == "write":
|
|
3274
|
-
addr = se.eval_one(ac.addr.ast, default=0)
|
|
3275
|
-
if (self.project.arch.call_pushes_ret and addr >= sp + self.project.arch.bytes) or (
|
|
3276
|
-
not self.project.arch.call_pushes_ret and addr >= sp
|
|
3277
|
-
):
|
|
3278
|
-
offset = addr - sp
|
|
3279
|
-
stack_overwritten.add(offset)
|
|
3280
|
-
|
|
3281
|
-
func.prepared_registers.add(tuple(regs_overwritten))
|
|
3282
|
-
func.prepared_stack_variables.add(tuple(stack_overwritten))
|
|
3283
|
-
|
|
3284
|
-
except (SimError, AngrError):
|
|
3285
|
-
pass
|
|
3286
|
-
|
|
3287
|
-
try:
|
|
3288
|
-
if blocks_after:
|
|
3289
|
-
path = self.project.factory.path(
|
|
3290
|
-
self.project.factory.blank_state(mode="fastpath", addr=blocks_after[0].addr)
|
|
3291
|
-
)
|
|
3292
|
-
path.step()
|
|
3293
|
-
all_successors = path.next_run.successors + path.next_run.unsat_successors
|
|
3294
|
-
if not all_successors:
|
|
3295
|
-
continue
|
|
3296
|
-
|
|
3297
|
-
suc = all_successors[0]
|
|
3298
|
-
actions = suc.history.recent_actions
|
|
3299
|
-
for ac in actions:
|
|
3300
|
-
if ac.type == "reg" and ac.action == "read" and ac.offset not in regs_written:
|
|
3301
|
-
regs_read.add(ac.offset)
|
|
3302
|
-
elif ac.type == "reg" and ac.action == "write":
|
|
3303
|
-
regs_written.add(ac.offset)
|
|
3304
|
-
|
|
3305
|
-
# Filter registers, remove unnecessary registers from the set
|
|
3306
|
-
# regs_overwritten = self.project.arch.argument_registers.intersection(regs_overwritten)
|
|
3307
|
-
regs_read = self.project.arch.argument_registers.intersection(regs_read)
|
|
3308
|
-
|
|
3309
|
-
func.registers_read_afterwards.add(tuple(regs_read))
|
|
3310
|
-
|
|
3311
|
-
except (SimError, AngrError):
|
|
3312
|
-
pass
|
|
3313
|
-
|
|
3314
3211
|
# Private methods - dominators and post-dominators
|
|
3315
3212
|
|
|
3316
3213
|
def _immediate_dominators(self, node, target_graph=None, reverse_graph=False):
|