angr 9.2.135__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.

Files changed (165) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/__init__.py +3 -7
  3. angr/analyses/analysis.py +4 -0
  4. angr/analyses/backward_slice.py +1 -2
  5. angr/analyses/binary_optimizer.py +3 -4
  6. angr/analyses/bindiff.py +4 -6
  7. angr/analyses/boyscout.py +1 -3
  8. angr/analyses/callee_cleanup_finder.py +4 -4
  9. angr/analyses/calling_convention/calling_convention.py +4 -3
  10. angr/analyses/calling_convention/fact_collector.py +0 -1
  11. angr/analyses/cdg.py +1 -2
  12. angr/analyses/cfg/cfb.py +1 -3
  13. angr/analyses/cfg/cfg.py +2 -2
  14. angr/analyses/cfg/cfg_base.py +37 -35
  15. angr/analyses/cfg/cfg_emulated.py +1 -1
  16. angr/analyses/cfg/cfg_fast.py +62 -15
  17. angr/analyses/cfg/cfg_fast_soot.py +1 -1
  18. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +2 -0
  19. angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +46 -10
  20. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +5 -1
  21. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +50 -14
  22. angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
  23. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +24 -5
  24. angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +2 -5
  25. angr/analyses/congruency_check.py +2 -3
  26. angr/analyses/data_dep/data_dependency_analysis.py +2 -2
  27. angr/analyses/ddg.py +1 -4
  28. angr/analyses/decompiler/ail_simplifier.py +3 -4
  29. angr/analyses/decompiler/clinic.py +42 -7
  30. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +2 -2
  31. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +2 -2
  32. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +1 -1
  33. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
  34. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +1 -1
  35. angr/analyses/decompiler/structuring/phoenix.py +1 -1
  36. angr/analyses/disassembly.py +5 -5
  37. angr/analyses/fcp/__init__.py +4 -0
  38. angr/analyses/fcp/fcp.py +429 -0
  39. angr/analyses/identifier/identify.py +1 -3
  40. angr/analyses/loopfinder.py +4 -3
  41. angr/analyses/patchfinder.py +1 -1
  42. angr/analyses/propagator/engine_base.py +4 -3
  43. angr/analyses/propagator/propagator.py +14 -53
  44. angr/analyses/reassembler.py +1 -2
  45. angr/analyses/s_propagator.py +1 -3
  46. angr/analyses/soot_class_hierarchy.py +1 -2
  47. angr/analyses/stack_pointer_tracker.py +18 -2
  48. angr/analyses/static_hooker.py +1 -2
  49. angr/analyses/typehoon/simple_solver.py +2 -2
  50. angr/analyses/variable_recovery/variable_recovery_fast.py +1 -2
  51. angr/analyses/veritesting.py +4 -7
  52. angr/analyses/vfg.py +1 -1
  53. angr/analyses/vsa_ddg.py +1 -2
  54. angr/block.py +3 -2
  55. angr/callable.py +1 -3
  56. angr/calling_conventions.py +3 -3
  57. angr/codenode.py +5 -1
  58. angr/concretization_strategies/__init__.py +1 -83
  59. angr/concretization_strategies/any.py +2 -1
  60. angr/concretization_strategies/any_named.py +1 -1
  61. angr/concretization_strategies/base.py +81 -0
  62. angr/concretization_strategies/controlled_data.py +2 -1
  63. angr/concretization_strategies/eval.py +2 -1
  64. angr/concretization_strategies/logging.py +3 -1
  65. angr/concretization_strategies/max.py +2 -1
  66. angr/concretization_strategies/nonzero.py +2 -1
  67. angr/concretization_strategies/nonzero_range.py +2 -1
  68. angr/concretization_strategies/norepeats.py +2 -1
  69. angr/concretization_strategies/norepeats_range.py +2 -1
  70. angr/concretization_strategies/range.py +2 -1
  71. angr/concretization_strategies/signed_add.py +2 -1
  72. angr/concretization_strategies/single.py +2 -1
  73. angr/concretization_strategies/solutions.py +2 -1
  74. angr/concretization_strategies/unlimited_range.py +2 -1
  75. angr/engines/__init__.py +8 -5
  76. angr/engines/engine.py +3 -5
  77. angr/engines/failure.py +4 -5
  78. angr/engines/procedure.py +5 -7
  79. angr/engines/soot/expressions/__init__.py +22 -23
  80. angr/engines/soot/expressions/base.py +4 -4
  81. angr/engines/soot/expressions/invoke.py +1 -2
  82. angr/engines/soot/statements/__init__.py +9 -10
  83. angr/engines/soot/values/__init__.py +9 -10
  84. angr/engines/soot/values/arrayref.py +3 -3
  85. angr/engines/soot/values/instancefieldref.py +3 -2
  86. angr/engines/successors.py +7 -6
  87. angr/engines/syscall.py +4 -6
  88. angr/engines/unicorn.py +3 -2
  89. angr/engines/vex/claripy/ccall.py +8 -10
  90. angr/engines/vex/claripy/datalayer.py +4 -5
  91. angr/exploration_techniques/__init__.py +0 -2
  92. angr/exploration_techniques/spiller.py +1 -3
  93. angr/exploration_techniques/stochastic.py +2 -3
  94. angr/factory.py +3 -9
  95. angr/knowledge_plugins/cfg/cfg_model.py +20 -17
  96. angr/knowledge_plugins/functions/function.py +70 -73
  97. angr/knowledge_plugins/functions/function_manager.py +8 -7
  98. angr/knowledge_plugins/functions/function_parser.py +1 -1
  99. angr/knowledge_plugins/functions/soot_function.py +16 -16
  100. angr/knowledge_plugins/propagations/propagation_model.py +4 -5
  101. angr/knowledge_plugins/propagations/states.py +0 -511
  102. angr/procedures/libc/memcpy.py +4 -4
  103. angr/procedures/procedure_dict.py +3 -2
  104. angr/protos/__init__.py +2 -5
  105. angr/protos/cfg_pb2.py +21 -18
  106. angr/protos/function_pb2.py +17 -14
  107. angr/protos/primitives_pb2.py +44 -39
  108. angr/protos/variables_pb2.py +36 -31
  109. angr/protos/xrefs_pb2.py +15 -12
  110. angr/sim_procedure.py +15 -16
  111. angr/sim_variable.py +13 -1
  112. angr/simos/__init__.py +2 -0
  113. angr/simos/javavm.py +4 -6
  114. angr/simos/xbox.py +32 -0
  115. angr/state_plugins/__init__.py +0 -2
  116. angr/state_plugins/callstack.py +4 -4
  117. angr/state_plugins/cgc.py +3 -2
  118. angr/state_plugins/gdb.py +6 -5
  119. angr/state_plugins/globals.py +1 -2
  120. angr/state_plugins/heap/heap_brk.py +1 -2
  121. angr/state_plugins/history.py +10 -12
  122. angr/state_plugins/inspect.py +3 -5
  123. angr/state_plugins/libc.py +2 -2
  124. angr/state_plugins/log.py +8 -10
  125. angr/state_plugins/loop_data.py +1 -2
  126. angr/state_plugins/posix.py +7 -7
  127. angr/state_plugins/preconstrainer.py +2 -3
  128. angr/state_plugins/scratch.py +5 -8
  129. angr/state_plugins/sim_action.py +3 -3
  130. angr/state_plugins/solver.py +8 -3
  131. angr/state_plugins/symbolizer.py +5 -4
  132. angr/state_plugins/uc_manager.py +3 -3
  133. angr/state_plugins/unicorn_engine.py +5 -1
  134. angr/state_plugins/view.py +3 -5
  135. angr/storage/file.py +3 -5
  136. angr/storage/memory_mixins/address_concretization_mixin.py +2 -2
  137. angr/storage/memory_mixins/bvv_conversion_mixin.py +3 -3
  138. angr/storage/memory_mixins/clouseau_mixin.py +1 -3
  139. angr/storage/memory_mixins/name_resolution_mixin.py +1 -3
  140. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +13 -15
  141. angr/storage/memory_mixins/paged_memory/pages/__init__.py +1 -22
  142. angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
  143. angr/storage/memory_mixins/paged_memory/pages/list_page.py +1 -1
  144. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +1 -1
  145. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +2 -4
  146. angr/storage/memory_mixins/paged_memory/privileged_mixin.py +3 -4
  147. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +4 -2
  148. angr/storage/memory_mixins/smart_find_mixin.py +1 -1
  149. angr/storage/memory_mixins/underconstrained_mixin.py +1 -1
  150. angr/storage/memory_mixins/unwrapper_mixin.py +1 -3
  151. angr/utils/enums_conv.py +28 -12
  152. angr/utils/segment_list.py +25 -22
  153. angr/utils/timing.py +18 -1
  154. angr/vaults.py +5 -6
  155. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/METADATA +6 -6
  156. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/RECORD +160 -159
  157. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/WHEEL +1 -1
  158. angr/analyses/propagator/outdated_definition_walker.py +0 -159
  159. angr/analyses/propagator/tmpvar_finder.py +0 -18
  160. angr/engines/concrete.py +0 -180
  161. angr/exploration_techniques/symbion.py +0 -80
  162. angr/state_plugins/concrete.py +0 -295
  163. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/LICENSE +0 -0
  164. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/entry_points.txt +0 -0
  165. {angr-9.2.135.dist-info → angr-9.2.136.dist-info}/top_level.txt +0 -0
angr/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # pylint: disable=wrong-import-position
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "9.2.135"
5
+ __version__ = "9.2.136"
6
6
 
7
7
  if bytes is str:
8
8
  raise Exception(
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
@@ -409,3 +409,7 @@ class Analysis:
409
409
 
410
410
  default_analyses = VendorPreset()
411
411
  AnalysesHub.register_preset("default", default_analyses)
412
+
413
+
414
+ def register_analysis(cls, name):
415
+ AnalysesHub.register_default(name, cls)
@@ -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, dst, data in function.transition_graph.edges(data=True):
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, data in data_graph.edges(data=True):
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 typing import TYPE_CHECKING
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)
@@ -923,9 +923,10 @@ class CallingConventionAnalysis(Analysis):
923
923
  if not set(spilled_regs).issubset(set(allowed_spilled_regs)):
924
924
  return False, None
925
925
 
926
- for i, reg in enumerate(allowed_spilled_regs):
927
- if reg in spilled_regs:
928
- break
926
+ i = next(
927
+ (i for i, reg in enumerate(allowed_spilled_regs) if reg in spilled_regs),
928
+ len(allowed_spilled_regs),
929
+ )
929
930
 
930
931
  return True, i
931
932
 
@@ -297,7 +297,6 @@ class FactCollector(Analysis):
297
297
  try:
298
298
  arg_locs = func.calling_convention.arg_locs(func.prototype)
299
299
  except (TypeError, ValueError):
300
- func.prototype = None
301
300
  return
302
301
 
303
302
  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)
@@ -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.copy()
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.clear()
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
- self.kb.functions._add_call_to(
2358
- src_function.addr,
2359
- src_snippet,
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
- to_outside = blockaddr_to_function[returning_target] is not src_function
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
- if returning_snippet is not None:
2388
- self.kb.functions._add_fakeret_to(
2389
- src_function.addr, src_snippet, returning_snippet, confirmed=True, to_outside=to_outside
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:
@@ -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)._register_nodes(True, dst_codenode)
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)
@@ -135,9 +135,9 @@ class PendingJobs:
135
135
  A collection of pending jobs during CFG recovery.
136
136
  """
137
137
 
138
- def __init__(self, functions, deregister_job_callback):
138
+ def __init__(self, kb, deregister_job_callback):
139
139
  self._jobs = OrderedDict() # A mapping between function addresses and lists of pending jobs
140
- self._functions = functions
140
+ self._kb = kb
141
141
  self._deregister_job_callback = deregister_job_callback
142
142
 
143
143
  self._returning_functions = set()
@@ -145,6 +145,10 @@ class PendingJobs:
145
145
  # consecutive calls to cleanup().
146
146
  self._job_count = 0
147
147
 
148
+ @property
149
+ def _functions(self):
150
+ return self._kb.functions
151
+
148
152
  def __len__(self):
149
153
  return self._job_count
150
154
 
@@ -1316,7 +1320,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1316
1320
  self._known_thunks = self._find_thunks()
1317
1321
 
1318
1322
  # Initialize variables used during analysis
1319
- self._pending_jobs: PendingJobs = PendingJobs(self.functions, self._deregister_analysis_job)
1323
+ self._pending_jobs: PendingJobs = PendingJobs(self.kb, self._deregister_analysis_job)
1320
1324
  self._traced_addresses: set[int] = {a for a, n in self._nodes_by_addr.items() if n}
1321
1325
  self._function_returns = defaultdict(set)
1322
1326
 
@@ -1498,6 +1502,18 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1498
1502
  pass
1499
1503
 
1500
1504
  def _function_completed(self, func_addr: int):
1505
+ if self.project.arch.name == "AMD64":
1506
+ # determine if the function is __rust_probestack
1507
+ func = self.kb.functions.get_by_addr(func_addr) if self.kb.functions.contains_addr(func_addr) else None
1508
+ if func is not None and len(func.block_addrs_set) == 3:
1509
+ block_bytes = {func.get_block(block_addr).bytes for block_addr in func.block_addrs_set}
1510
+ if block_bytes == {
1511
+ b"UH\x89\xe5I\x89\xc3I\x81\xfb\x00\x10\x00\x00v\x1c",
1512
+ b"H\x81\xec\x00\x10\x00\x00H\x85d$\x08I\x81\xeb\x00\x10\x00\x00I\x81\xfb\x00\x10\x00\x00w\xe4",
1513
+ b"L)\xdcH\x85d$\x08H\x01\xc4\xc9\xc3",
1514
+ }:
1515
+ func.info["is_rust_probestack"] = True
1516
+
1501
1517
  if self._collect_data_ref and self.project is not None and ":" in self.project.arch.name:
1502
1518
  # this is a pcode arch - use Clinic to recover data references
1503
1519
 
@@ -1744,6 +1760,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1744
1760
  # Clean up
1745
1761
  self._traced_addresses = None
1746
1762
  self._lifter_deregister_readonly_regions()
1763
+ self._function_returns = None
1747
1764
 
1748
1765
  self._finish_progress()
1749
1766
 
@@ -1825,19 +1842,18 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
1825
1842
  break
1826
1843
 
1827
1844
  # special handling: some binaries do not have SecurityCookie set, but still contain _security_init_cookie
1828
- if security_init_cookie_found is False:
1845
+ if security_init_cookie_found is False and self.functions.contains_addr(self.project.entry):
1829
1846
  start_func = self.functions.get_by_addr(self.project.entry)
1830
- if start_func is not None:
1831
- for callee in start_func.transition_graph:
1832
- if (
1833
- isinstance(callee, Function)
1834
- and not security_init_cookie_found
1835
- and is_function_likely_security_init_cookie(callee)
1836
- ):
1837
- security_init_cookie_found = True
1838
- callee.is_default_name = False
1839
- callee.name = "_security_init_cookie"
1840
- break
1847
+ for callee in start_func.transition_graph:
1848
+ if (
1849
+ isinstance(callee, Function)
1850
+ and not security_init_cookie_found
1851
+ and is_function_likely_security_init_cookie(callee)
1852
+ ):
1853
+ security_init_cookie_found = True
1854
+ callee.is_default_name = False
1855
+ callee.name = "_security_init_cookie"
1856
+ break
1841
1857
 
1842
1858
  def _post_process_string_references(self) -> None:
1843
1859
  """
@@ -4765,6 +4781,37 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
4765
4781
  func = self.kb.functions.get_by_addr(func_addr)
4766
4782
  func.info["get_pc"] = "ebx"
4767
4783
 
4784
+ # determine if the function uses ebp as a general purpose register or not
4785
+ if addr == func_addr or 0 < addr - func_addr <= 0x20:
4786
+ ebp_as_gpr = True
4787
+ cap = self._lift(addr, size=cfg_node.size).capstone
4788
+ for insn in cap.insns:
4789
+ if (
4790
+ insn.mnemonic == "mov"
4791
+ and len(insn.operands) == 2
4792
+ and insn.operands[0].type == capstone.x86.X86_OP_REG
4793
+ and insn.operands[1].type == capstone.x86.X86_OP_REG
4794
+ ):
4795
+ if (
4796
+ insn.operands[0].reg == capstone.x86.X86_REG_EBP
4797
+ and insn.operands[1].reg == capstone.x86.X86_REG_ESP
4798
+ ):
4799
+ ebp_as_gpr = False
4800
+ break
4801
+ elif (
4802
+ insn.mnemonic == "lea"
4803
+ and len(insn.operands) == 2
4804
+ and insn.operands[0].type == capstone.x86.X86_OP_REG
4805
+ and insn.operands[1].type == capstone.x86.X86_OP_MEM
4806
+ ) and (
4807
+ insn.operands[0].reg == capstone.x86.X86_REG_EBP
4808
+ and insn.operands[1].mem.base == capstone.x86.X86_REG_ESP
4809
+ ):
4810
+ ebp_as_gpr = False
4811
+ break
4812
+ func = self.kb.functions.get_by_addr(func_addr)
4813
+ func.info["bp_as_gpr"] = ebp_as_gpr
4814
+
4768
4815
  elif self.project.arch.name == "AMD64":
4769
4816
  # determine if the function uses rbp as a general purpose register or not
4770
4817
  if addr == func_addr or 0 < addr - func_addr <= 0x20:
@@ -50,7 +50,7 @@ class CFGFastSoot(CFGFast):
50
50
  self._initialize_cfg()
51
51
 
52
52
  # Initialize variables used during analysis
53
- self._pending_jobs = PendingJobs(self.functions, self._deregister_analysis_job)
53
+ self._pending_jobs = PendingJobs(self.kb, self._deregister_analysis_job)
54
54
  self._traced_addresses = set()
55
55
  self._changed_functions = set()
56
56
  self._updated_nonreturning_functions = set()
@@ -9,6 +9,7 @@ from .amd64_elf_got import AMD64ElfGotResolver
9
9
  from .arm_elf_fast import ArmElfFastResolver
10
10
  from .const_resolver import ConstantResolver
11
11
  from .amd64_pe_iat import AMD64PeIatResolver
12
+ from .memload_resolver import MemoryLoadResolver
12
13
 
13
14
 
14
15
  __all__ = (
@@ -17,6 +18,7 @@ __all__ = (
17
18
  "ArmElfFastResolver",
18
19
  "ConstantResolver",
19
20
  "JumpTableResolver",
21
+ "MemoryLoadResolver",
20
22
  "MipsElfFastResolver",
21
23
  "MipsElfGotResolver",
22
24
  "X86ElfPicPltResolver",