angr 9.2.134__py3-none-win_amd64.whl → 9.2.136__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 +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/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/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 +169 -165
- {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,20 +1,21 @@
|
|
|
1
|
+
# pylint:disable=too-many-boolean-expressions
|
|
1
2
|
from __future__ import annotations
|
|
2
3
|
import os
|
|
3
4
|
import logging
|
|
4
|
-
import networkx
|
|
5
5
|
import itertools
|
|
6
6
|
from collections import defaultdict
|
|
7
7
|
from collections.abc import Iterable
|
|
8
|
+
import contextlib
|
|
9
|
+
from typing import overload
|
|
8
10
|
|
|
11
|
+
import networkx
|
|
9
12
|
from itanium_demangler import parse
|
|
10
13
|
|
|
11
14
|
from cle.backends.symbol import Symbol
|
|
12
15
|
from archinfo.arch_arm import get_real_address_if_arm
|
|
13
16
|
import claripy
|
|
14
17
|
|
|
15
|
-
from angr.block import Block
|
|
16
18
|
from angr.knowledge_plugins.cfg.memory_data import MemoryDataSort
|
|
17
|
-
|
|
18
19
|
from angr.codenode import CodeNode, BlockNode, HookNode, SyscallNode
|
|
19
20
|
from angr.serializable import Serializable
|
|
20
21
|
from angr.errors import AngrValueError, SimEngineError, SimMemoryError
|
|
@@ -23,14 +24,12 @@ from angr.procedures.definitions import SimSyscallLibrary
|
|
|
23
24
|
from angr.protos import function_pb2
|
|
24
25
|
from angr.calling_conventions import DEFAULT_CC, default_cc
|
|
25
26
|
from angr.misc.ux import deprecated
|
|
26
|
-
from .function_parser import FunctionParser
|
|
27
|
-
|
|
28
|
-
l = logging.getLogger(name=__name__)
|
|
29
|
-
|
|
30
27
|
from angr.sim_type import SimTypeFunction, parse_defns
|
|
31
28
|
from angr.calling_conventions import SimCC
|
|
32
29
|
from angr.project import Project
|
|
33
|
-
import
|
|
30
|
+
from .function_parser import FunctionParser
|
|
31
|
+
|
|
32
|
+
l = logging.getLogger(name=__name__)
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
class Function(Serializable):
|
|
@@ -42,7 +41,6 @@ class Function(Serializable):
|
|
|
42
41
|
"_addr_to_block_node",
|
|
43
42
|
"_argument_registers",
|
|
44
43
|
"_argument_stack_variables",
|
|
45
|
-
"_block_cache",
|
|
46
44
|
"_block_sizes",
|
|
47
45
|
"_call_sites",
|
|
48
46
|
"_callout_sites",
|
|
@@ -159,7 +157,6 @@ class Function(Serializable):
|
|
|
159
157
|
# function, it may not be removed from _addr_to_block_node. if you want to list
|
|
160
158
|
# all blocks of a function, access .blocks.
|
|
161
159
|
self._block_sizes = {} # map addresses to block sizes
|
|
162
|
-
self._block_cache = {} # a cache of real, hard data Block objects
|
|
163
160
|
self._local_blocks = {} # a dict of all blocks inside the function
|
|
164
161
|
self._local_block_addrs = set() # a set of addresses of all blocks inside the function
|
|
165
162
|
|
|
@@ -375,13 +372,6 @@ class Function(Serializable):
|
|
|
375
372
|
:param byte_string:
|
|
376
373
|
:return:
|
|
377
374
|
"""
|
|
378
|
-
if addr in self._block_cache:
|
|
379
|
-
b = self._block_cache[addr]
|
|
380
|
-
if size is None or b.size == size:
|
|
381
|
-
return b
|
|
382
|
-
# size seems to be updated. remove this cached entry from the block cache
|
|
383
|
-
del self._block_cache[addr]
|
|
384
|
-
|
|
385
375
|
if size is None and addr in self.block_addrs:
|
|
386
376
|
# we know the size
|
|
387
377
|
size = self._block_sizes[addr]
|
|
@@ -390,7 +380,6 @@ class Function(Serializable):
|
|
|
390
380
|
if size is None:
|
|
391
381
|
# update block_size dict
|
|
392
382
|
self._block_sizes[addr] = block.size
|
|
393
|
-
self._block_cache[addr] = block
|
|
394
383
|
return block
|
|
395
384
|
|
|
396
385
|
# compatibility
|
|
@@ -403,7 +392,7 @@ class Function(Serializable):
|
|
|
403
392
|
def nodes(self) -> Iterable[CodeNode]:
|
|
404
393
|
return self.transition_graph.nodes()
|
|
405
394
|
|
|
406
|
-
def get_node(self, addr) ->
|
|
395
|
+
def get_node(self, addr) -> BlockNode | None:
|
|
407
396
|
return self._addr_to_block_node.get(addr, None)
|
|
408
397
|
|
|
409
398
|
@property
|
|
@@ -441,7 +430,7 @@ class Function(Serializable):
|
|
|
441
430
|
|
|
442
431
|
@classmethod
|
|
443
432
|
def _get_cmsg(cls):
|
|
444
|
-
return function_pb2.Function()
|
|
433
|
+
return function_pb2.Function() # pylint:disable=no-member
|
|
445
434
|
|
|
446
435
|
def serialize_to_cmessage(self):
|
|
447
436
|
return FunctionParser.serialize(self)
|
|
@@ -614,7 +603,6 @@ class Function(Serializable):
|
|
|
614
603
|
d["_local_transition_graph"] = None
|
|
615
604
|
d["_project"] = None
|
|
616
605
|
d["_function_manager"] = None
|
|
617
|
-
d["_block_cache"] = {}
|
|
618
606
|
return d
|
|
619
607
|
|
|
620
608
|
@property
|
|
@@ -643,7 +631,7 @@ class Function(Serializable):
|
|
|
643
631
|
|
|
644
632
|
@property
|
|
645
633
|
def size(self):
|
|
646
|
-
return sum(
|
|
634
|
+
return sum(b.size for b in self.blocks)
|
|
647
635
|
|
|
648
636
|
@property
|
|
649
637
|
def binary(self):
|
|
@@ -676,7 +664,7 @@ class Function(Serializable):
|
|
|
676
664
|
dec = self.project.analyses.Decompiler(self, cfg=self._function_manager._kb.cfgs.get_most_accurate())
|
|
677
665
|
return dec.codegen.text
|
|
678
666
|
|
|
679
|
-
def add_jumpout_site(self, node):
|
|
667
|
+
def add_jumpout_site(self, node: CodeNode):
|
|
680
668
|
"""
|
|
681
669
|
Add a custom jumpout site.
|
|
682
670
|
|
|
@@ -684,11 +672,11 @@ class Function(Serializable):
|
|
|
684
672
|
:return: None
|
|
685
673
|
"""
|
|
686
674
|
|
|
687
|
-
self.
|
|
675
|
+
node = self._register_node(True, node)
|
|
688
676
|
self._jumpout_sites.add(node)
|
|
689
677
|
self._add_endpoint(node, "transition")
|
|
690
678
|
|
|
691
|
-
def add_retout_site(self, node):
|
|
679
|
+
def add_retout_site(self, node: CodeNode):
|
|
692
680
|
"""
|
|
693
681
|
Add a custom retout site.
|
|
694
682
|
|
|
@@ -704,7 +692,7 @@ class Function(Serializable):
|
|
|
704
692
|
:return: None
|
|
705
693
|
"""
|
|
706
694
|
|
|
707
|
-
self.
|
|
695
|
+
node = self._register_node(True, node)
|
|
708
696
|
self._retout_sites.add(node)
|
|
709
697
|
self._add_endpoint(node, "return")
|
|
710
698
|
|
|
@@ -786,7 +774,6 @@ class Function(Serializable):
|
|
|
786
774
|
return None
|
|
787
775
|
|
|
788
776
|
def _clear_transition_graph(self):
|
|
789
|
-
self._block_cache = {}
|
|
790
777
|
self._block_sizes = {}
|
|
791
778
|
self._addr_to_block_node = {}
|
|
792
779
|
self._local_blocks = {}
|
|
@@ -813,11 +800,13 @@ class Function(Serializable):
|
|
|
813
800
|
|
|
814
801
|
# it's confirmed. register the node if needed
|
|
815
802
|
if "outside" not in data or data["outside"] is False:
|
|
816
|
-
self.
|
|
803
|
+
dst = self._register_node(True, dst)
|
|
817
804
|
|
|
818
805
|
self.transition_graph[src][dst]["confirmed"] = True
|
|
819
806
|
|
|
820
|
-
def _transit_to(
|
|
807
|
+
def _transit_to(
|
|
808
|
+
self, from_node: CodeNode, to_node, outside=False, ins_addr=None, stmt_idx=None, is_exception=False
|
|
809
|
+
):
|
|
821
810
|
"""
|
|
822
811
|
Registers an edge between basic blocks in this function's transition graph.
|
|
823
812
|
Arguments are CodeNode objects.
|
|
@@ -831,16 +820,15 @@ class Function(Serializable):
|
|
|
831
820
|
"""
|
|
832
821
|
|
|
833
822
|
if outside:
|
|
834
|
-
self.
|
|
823
|
+
from_node = self._register_node(True, from_node)
|
|
835
824
|
if to_node is not None:
|
|
836
|
-
self.
|
|
825
|
+
to_node = self._register_node(False, to_node)
|
|
837
826
|
|
|
838
827
|
self._jumpout_sites.add(from_node)
|
|
839
828
|
else:
|
|
829
|
+
from_node = self._register_node(True, from_node)
|
|
840
830
|
if to_node is not None:
|
|
841
|
-
self.
|
|
842
|
-
else:
|
|
843
|
-
self._register_nodes(True, from_node)
|
|
831
|
+
to_node = self._register_node(True, to_node)
|
|
844
832
|
|
|
845
833
|
type_ = "transition" if not is_exception else "exception"
|
|
846
834
|
if to_node is not None:
|
|
@@ -872,19 +860,22 @@ class Function(Serializable):
|
|
|
872
860
|
:type ins_addr: int or None
|
|
873
861
|
"""
|
|
874
862
|
|
|
875
|
-
self.
|
|
863
|
+
from_node = self._register_node(True, from_node)
|
|
876
864
|
|
|
877
865
|
if to_func.is_syscall:
|
|
878
866
|
self.transition_graph.add_edge(from_node, to_func, type="syscall", stmt_idx=stmt_idx, ins_addr=ins_addr)
|
|
879
867
|
else:
|
|
880
868
|
self.transition_graph.add_edge(from_node, to_func, type="call", stmt_idx=stmt_idx, ins_addr=ins_addr)
|
|
881
869
|
if ret_node is not None:
|
|
870
|
+
ret_node = self._register_node(return_to_outside is False, ret_node)
|
|
882
871
|
self._fakeret_to(from_node, ret_node, to_outside=return_to_outside)
|
|
883
872
|
|
|
884
873
|
self._local_transition_graph = None
|
|
885
874
|
|
|
886
875
|
def _fakeret_to(self, from_node, to_node, confirmed=None, to_outside=False):
|
|
887
|
-
self.
|
|
876
|
+
from_node = self._register_node(True, from_node)
|
|
877
|
+
if confirmed:
|
|
878
|
+
to_node = self._register_node(not to_outside, to_node)
|
|
888
879
|
|
|
889
880
|
if confirmed is None:
|
|
890
881
|
self.transition_graph.add_edge(from_node, to_node, type="fake_return", outside=to_outside)
|
|
@@ -892,8 +883,6 @@ class Function(Serializable):
|
|
|
892
883
|
self.transition_graph.add_edge(
|
|
893
884
|
from_node, to_node, type="fake_return", confirmed=confirmed, outside=to_outside
|
|
894
885
|
)
|
|
895
|
-
if confirmed:
|
|
896
|
-
self._register_nodes(not to_outside, to_node)
|
|
897
886
|
|
|
898
887
|
self._local_transition_graph = None
|
|
899
888
|
|
|
@@ -911,45 +900,56 @@ class Function(Serializable):
|
|
|
911
900
|
self._local_transition_graph = None
|
|
912
901
|
|
|
913
902
|
def _update_local_blocks(self, node: CodeNode):
|
|
914
|
-
self._local_blocks[node.addr]
|
|
915
|
-
|
|
903
|
+
if node.addr not in self._local_blocks or self._local_blocks[node.addr] != node:
|
|
904
|
+
self._local_blocks[node.addr] = node
|
|
905
|
+
self._local_block_addrs.add(node.addr)
|
|
916
906
|
|
|
917
907
|
def _update_addr_to_block_cache(self, node: BlockNode):
|
|
918
908
|
if node.addr not in self._addr_to_block_node:
|
|
919
909
|
self._addr_to_block_node[node.addr] = node
|
|
920
910
|
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
911
|
+
@overload
|
|
912
|
+
def _register_node(self, is_local: bool, node: CodeNode) -> CodeNode: ...
|
|
913
|
+
|
|
914
|
+
@overload
|
|
915
|
+
def _register_node(self, is_local: bool, node: Function) -> Function: ...
|
|
916
|
+
|
|
917
|
+
def _register_node(self, is_local: bool, node: CodeNode | Function) -> CodeNode | Function:
|
|
918
|
+
# if the node already exists and is the same, we reuse the existing node
|
|
919
|
+
if is_local and self._local_blocks.get(node.addr, None) == node:
|
|
920
|
+
return self._local_blocks[node.addr]
|
|
921
|
+
|
|
922
|
+
if node.addr not in self and node not in self.transition_graph:
|
|
923
|
+
# only add each node to the graph once
|
|
924
|
+
self.transition_graph.add_node(node)
|
|
925
|
+
|
|
926
|
+
if not isinstance(node, CodeNode):
|
|
927
|
+
# function and other things bail here
|
|
928
|
+
return node
|
|
929
|
+
|
|
930
|
+
# this is either a new node or a different node at the same address
|
|
931
|
+
node._graph = self.transition_graph
|
|
932
|
+
if self._block_sizes.get(node.addr, 0) == 0:
|
|
933
|
+
self._block_sizes[node.addr] = node.size
|
|
934
|
+
if node.addr == self.addr and (self.startpoint is None or not self.startpoint.is_hook):
|
|
935
|
+
self.startpoint = node
|
|
936
|
+
if is_local and node.addr not in self._local_blocks:
|
|
937
|
+
self._update_local_blocks(node)
|
|
938
|
+
# add BlockNodes to the addr_to_block_node cache if not already there
|
|
939
|
+
if isinstance(node, BlockNode):
|
|
940
|
+
self._update_addr_to_block_cache(node)
|
|
941
|
+
# else:
|
|
942
|
+
# # checks that we don't have multiple block nodes at a single address
|
|
943
|
+
# assert node == self._addr_to_block_node[node.addr]
|
|
944
|
+
return node
|
|
945
|
+
|
|
946
|
+
def _add_return_site(self, return_site: CodeNode):
|
|
947
947
|
"""
|
|
948
948
|
Registers a basic block as a site for control flow to return from this function.
|
|
949
949
|
|
|
950
|
-
:param
|
|
950
|
+
:param return_site: The block node that ends with a return.
|
|
951
951
|
"""
|
|
952
|
-
self.
|
|
952
|
+
return_site = self._register_node(True, return_site)
|
|
953
953
|
|
|
954
954
|
self._ret_sites.add(return_site)
|
|
955
955
|
# A return site must be an endpoint of the function - you cannot continue execution of the current function
|
|
@@ -1036,8 +1036,9 @@ class Function(Serializable):
|
|
|
1036
1036
|
if function.returning is False:
|
|
1037
1037
|
# the target function does not return
|
|
1038
1038
|
the_node = self.get_node(src.addr)
|
|
1039
|
-
|
|
1040
|
-
|
|
1039
|
+
if the_node is not None:
|
|
1040
|
+
self._callout_sites.add(the_node)
|
|
1041
|
+
self._add_endpoint(the_node, "call")
|
|
1041
1042
|
|
|
1042
1043
|
def get_call_sites(self) -> Iterable[int]:
|
|
1043
1044
|
"""
|
|
@@ -1285,8 +1286,8 @@ class Function(Serializable):
|
|
|
1285
1286
|
"""
|
|
1286
1287
|
Draw the graph and save it to a PNG file.
|
|
1287
1288
|
"""
|
|
1288
|
-
import matplotlib.pyplot as pyplot # pylint: disable=import-error
|
|
1289
|
-
from networkx.drawing.nx_agraph import graphviz_layout # pylint: disable=import-error
|
|
1289
|
+
import matplotlib.pyplot as pyplot # pylint: disable=import-error,import-outside-toplevel
|
|
1290
|
+
from networkx.drawing.nx_agraph import graphviz_layout # pylint: disable=import-error,import-outside-toplevel
|
|
1290
1291
|
|
|
1291
1292
|
tmp_graph = networkx.classes.digraph.DiGraph()
|
|
1292
1293
|
for from_block, to_block in self.transition_graph.edges():
|
|
@@ -1416,11 +1417,8 @@ class Function(Serializable):
|
|
|
1416
1417
|
self._local_blocks[n.addr] = new_node
|
|
1417
1418
|
|
|
1418
1419
|
# update block_cache and block_sizes
|
|
1419
|
-
if
|
|
1420
|
-
n.addr in self._block_sizes and self._block_sizes[n.addr] != new_node.size
|
|
1421
|
-
):
|
|
1420
|
+
if n.addr in self._block_sizes and self._block_sizes[n.addr] != new_node.size:
|
|
1422
1421
|
# the cache needs updating
|
|
1423
|
-
self._block_cache.pop(n.addr, None)
|
|
1424
1422
|
self._block_sizes[n.addr] = new_node.size
|
|
1425
1423
|
|
|
1426
1424
|
for p, _, data in original_predecessors:
|
|
@@ -1680,7 +1678,6 @@ class Function(Serializable):
|
|
|
1680
1678
|
func.startpoint = self.startpoint
|
|
1681
1679
|
func._addr_to_block_node = self._addr_to_block_node.copy()
|
|
1682
1680
|
func._block_sizes = self._block_sizes.copy()
|
|
1683
|
-
func._block_cache = self._block_cache.copy()
|
|
1684
1681
|
func._local_blocks = self._local_blocks.copy()
|
|
1685
1682
|
func._local_block_addrs = self._local_block_addrs.copy()
|
|
1686
1683
|
func.info = self.info.copy()
|
|
@@ -6,6 +6,7 @@ from collections.abc import Generator
|
|
|
6
6
|
import logging
|
|
7
7
|
import collections.abc
|
|
8
8
|
import re
|
|
9
|
+
import weakref
|
|
9
10
|
from sortedcontainers import SortedDict
|
|
10
11
|
|
|
11
12
|
import networkx
|
|
@@ -31,7 +32,7 @@ class FunctionDict(SortedDict):
|
|
|
31
32
|
"""
|
|
32
33
|
|
|
33
34
|
def __init__(self, backref, *args, **kwargs):
|
|
34
|
-
self._backref = backref
|
|
35
|
+
self._backref = weakref.proxy(backref) if backref is not None else None
|
|
35
36
|
self._key_types = kwargs.pop("key_types", int)
|
|
36
37
|
super().__init__(*args, **kwargs)
|
|
37
38
|
|
|
@@ -39,7 +40,7 @@ class FunctionDict(SortedDict):
|
|
|
39
40
|
try:
|
|
40
41
|
return super().__getitem__(addr)
|
|
41
42
|
except KeyError as ex:
|
|
42
|
-
if not isinstance(addr, self._key_types):
|
|
43
|
+
if isinstance(addr, bool) or not isinstance(addr, self._key_types):
|
|
43
44
|
raise TypeError(f"FunctionDict only supports {self._key_types} as key type") from ex
|
|
44
45
|
|
|
45
46
|
if isinstance(addr, SootMethodDescriptor):
|
|
@@ -148,7 +149,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
148
149
|
dst_func = self._function_map[function_addr]
|
|
149
150
|
if syscall in (True, False):
|
|
150
151
|
dst_func.is_syscall = syscall
|
|
151
|
-
dst_func.
|
|
152
|
+
dst_func._register_node(True, node)
|
|
152
153
|
self.block_map[node.addr] = node
|
|
153
154
|
|
|
154
155
|
def _add_call_to(
|
|
@@ -160,7 +161,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
160
161
|
syscall=None,
|
|
161
162
|
stmt_idx=None,
|
|
162
163
|
ins_addr=None,
|
|
163
|
-
return_to_outside=False,
|
|
164
|
+
return_to_outside: bool = False,
|
|
164
165
|
):
|
|
165
166
|
"""
|
|
166
167
|
Add a call to a function.
|
|
@@ -172,7 +173,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
172
173
|
:param bool syscall: If this is a call to a syscall or not.
|
|
173
174
|
:param int stmt_idx: ID of the statement where this call happens.
|
|
174
175
|
:param int ins_addr: Address of the instruction where this call happens.
|
|
175
|
-
:param
|
|
176
|
+
:param return_to_outside: True if the return of the call is considered going to outside of the current
|
|
176
177
|
function.
|
|
177
178
|
:return: None
|
|
178
179
|
"""
|
|
@@ -306,7 +307,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
306
307
|
try:
|
|
307
308
|
_ = self[item]
|
|
308
309
|
return True
|
|
309
|
-
except KeyError:
|
|
310
|
+
except (KeyError, TypeError):
|
|
310
311
|
return False
|
|
311
312
|
|
|
312
313
|
def __getitem__(self, k) -> Function:
|
|
@@ -406,7 +407,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
406
407
|
|
|
407
408
|
try:
|
|
408
409
|
prev_addr = self._function_map.floor_addr(addr)
|
|
409
|
-
return self._function_map
|
|
410
|
+
return self._function_map.get(prev_addr)
|
|
410
411
|
|
|
411
412
|
except KeyError:
|
|
412
413
|
return None
|
|
@@ -460,6 +461,12 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
460
461
|
:rtype: Function or None
|
|
461
462
|
"""
|
|
462
463
|
if name is not None and name.startswith("sub_"):
|
|
464
|
+
# first check if a function with the specified name exists
|
|
465
|
+
for func in self.get_by_name(name, check_previous_names=check_previous_names):
|
|
466
|
+
if plt is None or func.is_plt == plt:
|
|
467
|
+
return func
|
|
468
|
+
|
|
469
|
+
# then enter the syntactic sugar mode
|
|
463
470
|
try:
|
|
464
471
|
addr = int(name.split("_")[-1], 16)
|
|
465
472
|
name = None
|
|
@@ -108,24 +108,24 @@ class SootFunction(Function):
|
|
|
108
108
|
# The Shimple CFG is already normalized.
|
|
109
109
|
pass
|
|
110
110
|
|
|
111
|
-
def
|
|
112
|
-
if
|
|
113
|
-
|
|
111
|
+
def _register_node(self, is_local: bool, node):
|
|
112
|
+
if is_local and self._local_blocks.get(node.addr) == node:
|
|
113
|
+
return self._local_blocks[node.addr]
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
if node not in self.transition_graph:
|
|
116
116
|
self.transition_graph.add_node(node)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
node._graph = self.transition_graph
|
|
118
|
+
if node.addr not in self or self._block_sizes[node.addr] == 0:
|
|
119
|
+
self._block_sizes[node.addr] = node.size
|
|
120
|
+
if node.addr == self.addr.addr and (self.startpoint is None or not self.startpoint.is_hook):
|
|
121
|
+
self.startpoint = node
|
|
122
|
+
if is_local:
|
|
123
|
+
self._local_blocks[node.addr] = node
|
|
124
|
+
self._local_block_addrs.add(node.addr)
|
|
125
|
+
# add BlockNodes to the addr_to_block_node cache if not already there
|
|
126
|
+
if isinstance(node, BlockNode) and node.addr not in self._addr_to_block_node:
|
|
127
|
+
self._addr_to_block_node[node.addr] = node
|
|
128
|
+
return node
|
|
128
129
|
|
|
129
130
|
|
|
130
131
|
from angr.codenode import BlockNode
|
|
131
|
-
from angr.errors import AngrValueError
|
|
@@ -6,7 +6,7 @@ import claripy
|
|
|
6
6
|
import ailment
|
|
7
7
|
from angr.serializable import Serializable
|
|
8
8
|
from angr.knowledge_plugins.functions.function import Function
|
|
9
|
-
from .states import PropagatorVEXState,
|
|
9
|
+
from .states import PropagatorVEXState, PropagatorState
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class PropagationModel(Serializable):
|
|
@@ -65,10 +65,9 @@ class PropagationModel(Serializable):
|
|
|
65
65
|
preds = [self.states[pnode.addr] for pnode in self._function.graph.predecessors(node)]
|
|
66
66
|
if not preds:
|
|
67
67
|
if isinstance(node, ailment.Block):
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
state.store_register(state.arch.ip_offset, state.arch.bytes, claripy.BVV(block_addr, state.arch.bits))
|
|
68
|
+
raise NotImplementedError
|
|
69
|
+
state = PropagatorVEXState.initial_state(self._function.project, func_addr=self._function.addr)
|
|
70
|
+
state.store_register(state.arch.ip_offset, state.arch.bytes, claripy.BVV(block_addr, state.arch.bits))
|
|
72
71
|
else:
|
|
73
72
|
state, _ = preds[0].merge(*preds[1:])
|
|
74
73
|
return state
|