angr 9.2.139__py3-none-manylinux2014_aarch64.whl → 9.2.141__py3-none-manylinux2014_aarch64.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 (87) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/calling_convention/calling_convention.py +136 -53
  3. angr/analyses/calling_convention/fact_collector.py +44 -18
  4. angr/analyses/calling_convention/utils.py +3 -1
  5. angr/analyses/cfg/cfg_base.py +13 -0
  6. angr/analyses/cfg/cfg_fast.py +11 -0
  7. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +9 -8
  8. angr/analyses/decompiler/ail_simplifier.py +115 -72
  9. angr/analyses/decompiler/callsite_maker.py +24 -11
  10. angr/analyses/decompiler/clinic.py +78 -43
  11. angr/analyses/decompiler/decompiler.py +18 -7
  12. angr/analyses/decompiler/expression_narrower.py +1 -1
  13. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
  14. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +3 -1
  15. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +21 -2
  16. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
  17. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +84 -15
  18. angr/analyses/decompiler/optimization_passes/optimization_pass.py +92 -11
  19. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +53 -9
  20. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +44 -7
  21. angr/analyses/decompiler/region_identifier.py +6 -4
  22. angr/analyses/decompiler/region_simplifiers/expr_folding.py +287 -122
  23. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +31 -13
  24. angr/analyses/decompiler/ssailification/rewriting.py +23 -15
  25. angr/analyses/decompiler/ssailification/rewriting_engine.py +105 -24
  26. angr/analyses/decompiler/ssailification/ssailification.py +22 -14
  27. angr/analyses/decompiler/structured_codegen/c.py +73 -137
  28. angr/analyses/decompiler/structuring/dream.py +22 -18
  29. angr/analyses/decompiler/structuring/phoenix.py +158 -41
  30. angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
  31. angr/analyses/decompiler/structuring/structurer_base.py +37 -10
  32. angr/analyses/decompiler/structuring/structurer_nodes.py +4 -1
  33. angr/analyses/decompiler/utils.py +106 -21
  34. angr/analyses/deobfuscator/api_obf_finder.py +8 -5
  35. angr/analyses/deobfuscator/api_obf_type2_finder.py +18 -10
  36. angr/analyses/deobfuscator/string_obf_finder.py +105 -18
  37. angr/analyses/forward_analysis/forward_analysis.py +1 -1
  38. angr/analyses/propagator/top_checker_mixin.py +6 -6
  39. angr/analyses/reaching_definitions/__init__.py +2 -1
  40. angr/analyses/reaching_definitions/dep_graph.py +1 -12
  41. angr/analyses/reaching_definitions/engine_vex.py +36 -31
  42. angr/analyses/reaching_definitions/function_handler.py +15 -2
  43. angr/analyses/reaching_definitions/rd_state.py +1 -37
  44. angr/analyses/reaching_definitions/reaching_definitions.py +13 -24
  45. angr/analyses/s_propagator.py +6 -41
  46. angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
  47. angr/analyses/s_reaching_definitions/s_rda_view.py +43 -25
  48. angr/analyses/stack_pointer_tracker.py +36 -22
  49. angr/analyses/typehoon/simple_solver.py +45 -7
  50. angr/analyses/typehoon/typeconsts.py +18 -5
  51. angr/analyses/variable_recovery/engine_ail.py +1 -1
  52. angr/analyses/variable_recovery/engine_base.py +7 -5
  53. angr/analyses/variable_recovery/engine_vex.py +20 -4
  54. angr/block.py +69 -107
  55. angr/callable.py +14 -7
  56. angr/calling_conventions.py +30 -11
  57. angr/distributed/__init__.py +1 -1
  58. angr/engines/__init__.py +7 -8
  59. angr/engines/engine.py +1 -120
  60. angr/engines/failure.py +2 -2
  61. angr/engines/hook.py +2 -2
  62. angr/engines/light/engine.py +2 -2
  63. angr/engines/pcode/engine.py +2 -14
  64. angr/engines/procedure.py +2 -2
  65. angr/engines/soot/engine.py +2 -2
  66. angr/engines/soot/statements/switch.py +1 -1
  67. angr/engines/successors.py +124 -11
  68. angr/engines/syscall.py +2 -2
  69. angr/engines/unicorn.py +3 -3
  70. angr/engines/vex/heavy/heavy.py +3 -15
  71. angr/factory.py +12 -22
  72. angr/knowledge_plugins/key_definitions/atoms.py +8 -4
  73. angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
  74. angr/knowledge_plugins/variables/variable_manager.py +7 -5
  75. angr/sim_type.py +19 -17
  76. angr/simos/simos.py +3 -1
  77. angr/state_plugins/plugin.py +19 -4
  78. angr/storage/memory_mixins/memory_mixin.py +1 -1
  79. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +10 -5
  80. angr/utils/ssa/__init__.py +119 -4
  81. angr/utils/types.py +48 -0
  82. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/METADATA +6 -6
  83. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/RECORD +87 -86
  84. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/LICENSE +0 -0
  85. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/WHEEL +0 -0
  86. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/entry_points.txt +0 -0
  87. {angr-9.2.139.dist-info → angr-9.2.141.dist-info}/top_level.txt +0 -0
@@ -9,11 +9,11 @@ import networkx
9
9
 
10
10
  import claripy
11
11
 
12
- from angr import sim_options
13
12
  from angr.analyses import Analysis, AnalysesHub
14
- from angr.errors import SimMemoryMissingError, AngrCallableMultistateError, AngrCallableError
13
+ from angr.errors import SimMemoryMissingError, AngrCallableMultistateError, AngrCallableError, AngrAnalysisError
15
14
  from angr.calling_conventions import SimRegArg, default_cc
16
15
  from angr.state_plugins.sim_action import SimActionData
16
+ from angr.sim_options import ZERO_FILL_UNCONSTRAINED_REGISTERS, ZERO_FILL_UNCONSTRAINED_MEMORY, TRACK_MEMORY_ACTIONS
17
17
  from angr.sim_type import SimTypeFunction, SimTypeBottom, SimTypePointer
18
18
  from angr.analyses.reaching_definitions import ObservationPointType
19
19
  from angr.utils.graph import GraphUtils
@@ -23,12 +23,23 @@ from .irsb_reg_collector import IRSBRegisterCollector
23
23
  _l = logging.getLogger(__name__)
24
24
 
25
25
 
26
+ STEP_LIMIT_FIND = 500
27
+ STEP_LIMIT_ANALYSIS = 5000
28
+
29
+
26
30
  class StringDeobFuncDescriptor:
31
+ """
32
+ Describes a string deobfuscation function.
33
+ """
34
+
35
+ string_input_arg_idx: int
36
+ string_output_arg_idx: int
37
+ string_length_arg_idx: int | None
38
+ string_null_terminating: bool | None
39
+
27
40
  def __init__(self):
28
- self.string_input_arg_idx = None
29
- self.string_output_arg_idx = None
30
41
  self.string_length_arg_idx = None
31
- self.string_null_terminating: bool | None = None
42
+ self.string_null_terminating = None
32
43
 
33
44
 
34
45
  class StringObfuscationFinder(Analysis):
@@ -89,6 +100,9 @@ class StringObfuscationFinder(Analysis):
89
100
  # Type 1 string deobfuscation functions will decrypt each string once and for good.
90
101
 
91
102
  cfg = self.kb.cfgs.get_most_accurate()
103
+ if cfg is None:
104
+ raise AngrAnalysisError("StringObfuscationFinder needs a CFG for the analysis")
105
+
92
106
  arch = self.project.arch
93
107
 
94
108
  type1_candidates: list[tuple[int, StringDeobFuncDescriptor]] = []
@@ -100,6 +114,10 @@ class StringObfuscationFinder(Analysis):
100
114
  if func.prototype is None or len(func.prototype.args) < 1:
101
115
  continue
102
116
 
117
+ if len(func.arguments) != len(func.prototype.args):
118
+ # function argument locations and function prototype arguments do not match
119
+ continue
120
+
103
121
  if self.project.kb.functions.callgraph.out_degree[func.addr] != 0:
104
122
  continue
105
123
 
@@ -123,14 +141,22 @@ class StringObfuscationFinder(Analysis):
123
141
  dec = self.project.analyses.Decompiler(func, cfg=cfg)
124
142
  except Exception: # pylint:disable=broad-exception-caught
125
143
  continue
126
- if dec.codegen is None or not self._like_type1_deobfuscation_function(dec.codegen.text):
144
+ if (
145
+ dec.codegen is None
146
+ or not dec.codegen.text
147
+ or not self._like_type1_deobfuscation_function(dec.codegen.text)
148
+ ):
149
+ continue
150
+
151
+ func_node = cfg.get_any_node(func.addr)
152
+ if func_node is None:
127
153
  continue
128
154
 
129
155
  args_list = []
130
156
  for caller in callers:
131
157
  callsite_nodes = [
132
158
  pred
133
- for pred in cfg.get_predecessors(cfg.get_any_node(func.addr))
159
+ for pred in cfg.get_predecessors(func_node)
134
160
  if pred.function_address == caller and pred.instruction_addrs
135
161
  ]
136
162
  observation_points = []
@@ -148,15 +174,21 @@ class StringObfuscationFinder(Analysis):
148
174
  callsite_node.instruction_addrs[-1],
149
175
  ObservationPointType.OP_BEFORE,
150
176
  )
177
+ if observ is None:
178
+ continue
151
179
  # load values for each function argument
152
180
  args: list[tuple[int, Any]] = []
153
181
  for arg_idx, func_arg in enumerate(func.arguments):
154
182
  # FIXME: We are ignoring all non-register function arguments until we see a test case where
155
183
  # FIXME: stack-passing arguments are used
184
+ real_arg = func.prototype.args[arg_idx]
156
185
  if isinstance(func_arg, SimRegArg):
157
186
  reg_offset, reg_size = arch.registers[func_arg.reg_name]
187
+ arg_size = (
188
+ real_arg.size if real_arg.size is not None else reg_size
189
+ ) // self.project.arch.byte_width
158
190
  try:
159
- mv = observ.registers.load(reg_offset, size=reg_size)
191
+ mv = observ.registers.load(reg_offset, size=arg_size)
160
192
  except SimMemoryMissingError:
161
193
  args.append((arg_idx, claripy.BVV(0xDEADBEEF, self.project.arch.bits)))
162
194
  continue
@@ -185,7 +217,15 @@ class StringObfuscationFinder(Analysis):
185
217
  # now that we have good arguments, let's test the function!
186
218
  for args in args_list:
187
219
  func_call = self.project.factory.callable(
188
- func.addr, concrete_only=True, cc=func.calling_convention, prototype=func.prototype
220
+ func.addr,
221
+ concrete_only=True,
222
+ cc=func.calling_convention,
223
+ prototype=func.prototype,
224
+ add_options={
225
+ ZERO_FILL_UNCONSTRAINED_MEMORY,
226
+ ZERO_FILL_UNCONSTRAINED_REGISTERS,
227
+ },
228
+ step_limit=STEP_LIMIT_FIND,
189
229
  )
190
230
 
191
231
  # before calling the function, let's record the crime scene
@@ -202,6 +242,9 @@ class StringObfuscationFinder(Analysis):
202
242
  except (AngrCallableMultistateError, AngrCallableError):
203
243
  continue
204
244
 
245
+ if func_call.result_state is None:
246
+ continue
247
+
205
248
  # let's see what this amazing function has done
206
249
  # TODO: Support cases where input and output are using different function arguments
207
250
  for arg_idx, addr, old_value in values:
@@ -240,6 +283,9 @@ class StringObfuscationFinder(Analysis):
240
283
 
241
284
  arch = self.project.arch
242
285
  cfg = self.kb.cfgs.get_most_accurate()
286
+ if cfg is None:
287
+ raise AngrAnalysisError("StringObfuscationFinder needs a CFG for the analysis")
288
+
243
289
  func = self.kb.functions.get_by_addr(func_addr)
244
290
  func_node = cfg.get_any_node(func_addr)
245
291
  assert func_node is not None
@@ -260,14 +306,20 @@ class StringObfuscationFinder(Analysis):
260
306
  callsite_node.instruction_addrs[-1],
261
307
  ObservationPointType.OP_BEFORE,
262
308
  )
309
+ if observ is None:
310
+ continue
263
311
  args = []
264
- for func_arg in func.arguments:
312
+ assert func.prototype is not None and len(func.arguments) == len(func.prototype.args)
313
+ for func_arg, real_arg in zip(func.arguments, func.prototype.args):
265
314
  # FIXME: We are ignoring all non-register function arguments until we see a test case where
266
315
  # FIXME: stack-passing arguments are used
267
316
  if isinstance(func_arg, SimRegArg):
268
317
  reg_offset, reg_size = arch.registers[func_arg.reg_name]
318
+ arg_size = (
319
+ real_arg.size if real_arg.size is not None else reg_size
320
+ ) // self.project.arch.byte_width
269
321
  try:
270
- mv = observ.registers.load(reg_offset, size=reg_size)
322
+ mv = observ.registers.load(reg_offset, size=arg_size)
271
323
  except SimMemoryMissingError:
272
324
  args.append(claripy.BVV(0xDEADBEEF, self.project.arch.bits))
273
325
  continue
@@ -286,7 +338,12 @@ class StringObfuscationFinder(Analysis):
286
338
 
287
339
  # call the function
288
340
  func_call = self.project.factory.callable(
289
- func.addr, concrete_only=True, cc=func.calling_convention, prototype=func.prototype
341
+ func.addr,
342
+ concrete_only=True,
343
+ cc=func.calling_convention,
344
+ prototype=func.prototype,
345
+ add_options={ZERO_FILL_UNCONSTRAINED_MEMORY, ZERO_FILL_UNCONSTRAINED_REGISTERS},
346
+ step_limit=STEP_LIMIT_ANALYSIS,
290
347
  )
291
348
  try:
292
349
  func_call(*args)
@@ -303,6 +360,9 @@ class StringObfuscationFinder(Analysis):
303
360
  )
304
361
  continue
305
362
 
363
+ if func_call.result_state is None:
364
+ continue
365
+
306
366
  # dump the decrypted string!
307
367
  output_addr = args[desc.string_output_arg_idx]
308
368
  length = args[desc.string_length_arg_idx].concrete_value if desc.string_length_arg_idx is not None else 256
@@ -322,6 +382,8 @@ class StringObfuscationFinder(Analysis):
322
382
  xref_set = xrefs.get_xrefs_by_dst(str_addr)
323
383
  block_addrs = {xref.block_addr for xref in xref_set}
324
384
  for block_addr in block_addrs:
385
+ if block_addr is None:
386
+ continue
325
387
  node = cfg.get_any_node(block_addr)
326
388
  if node is not None:
327
389
  callees = list(self.kb.functions.callgraph.successors(node.function_address))
@@ -340,6 +402,8 @@ class StringObfuscationFinder(Analysis):
340
402
  # Type 2 string deobfuscation functions will decrypt each string once and for good.
341
403
 
342
404
  cfg = self.kb.cfgs.get_most_accurate()
405
+ if cfg is None:
406
+ raise AngrAnalysisError("StringObfuscationFinder needs a CFG for the analysis")
343
407
 
344
408
  type2_candidates: list[tuple[int, StringDeobFuncDescriptor, list[tuple[int, int, bytes]]]] = []
345
409
 
@@ -374,7 +438,11 @@ class StringObfuscationFinder(Analysis):
374
438
  dec = self.project.analyses.Decompiler(func, cfg=cfg, expr_collapse_depth=64)
375
439
  except Exception: # pylint:disable=broad-exception-caught
376
440
  continue
377
- if dec.codegen is None or not self._like_type2_deobfuscation_function(dec.codegen.text):
441
+ if (
442
+ dec.codegen is None
443
+ or not dec.codegen.text
444
+ or not self._like_type2_deobfuscation_function(dec.codegen.text)
445
+ ):
378
446
  continue
379
447
 
380
448
  desc = StringDeobFuncDescriptor()
@@ -384,7 +452,8 @@ class StringObfuscationFinder(Analysis):
384
452
  concrete_only=True,
385
453
  cc=func.calling_convention,
386
454
  prototype=func.prototype,
387
- add_options={sim_options.TRACK_MEMORY_ACTIONS},
455
+ add_options={TRACK_MEMORY_ACTIONS, ZERO_FILL_UNCONSTRAINED_MEMORY, ZERO_FILL_UNCONSTRAINED_REGISTERS},
456
+ step_limit=STEP_LIMIT_FIND,
388
457
  )
389
458
 
390
459
  try:
@@ -392,6 +461,9 @@ class StringObfuscationFinder(Analysis):
392
461
  except (AngrCallableMultistateError, AngrCallableError):
393
462
  continue
394
463
 
464
+ if func_call.result_state is None:
465
+ continue
466
+
395
467
  # where are the reads and writes?
396
468
  all_global_reads = []
397
469
  all_global_writes = []
@@ -399,7 +471,7 @@ class StringObfuscationFinder(Analysis):
399
471
  if not isinstance(action, SimActionData):
400
472
  continue
401
473
  if not action.actual_addrs:
402
- if not action.addr.ast.concrete:
474
+ if action.addr is None or not action.addr.ast.concrete:
403
475
  continue
404
476
  actual_addrs = [action.addr.ast.concrete_value]
405
477
  else:
@@ -469,6 +541,8 @@ class StringObfuscationFinder(Analysis):
469
541
  """
470
542
 
471
543
  cfg = self.kb.cfgs.get_most_accurate()
544
+ if cfg is None:
545
+ raise AngrAnalysisError("StringObfuscationFinder needs a CFG for the analysis")
472
546
 
473
547
  # for each string table address, we find its string loader function
474
548
  # an obvious candidate function is 0x140001b20
@@ -478,6 +552,8 @@ class StringObfuscationFinder(Analysis):
478
552
  xref_set = xrefs.get_xrefs_by_dst(table_addr)
479
553
  block_addrs = {xref.block_addr for xref in xref_set}
480
554
  for block_addr in block_addrs:
555
+ if block_addr is None:
556
+ continue
481
557
  node = cfg.get_any_node(block_addr)
482
558
  if node is not None:
483
559
  callees = list(self.kb.functions.callgraph.successors(node.function_address))
@@ -496,6 +572,9 @@ class StringObfuscationFinder(Analysis):
496
572
  # not have a SimProcedure for)
497
573
 
498
574
  cfg = self.kb.cfgs.get_most_accurate()
575
+ if cfg is None:
576
+ raise AngrAnalysisError("StringObfuscationFinder needs a CFG for the analysis")
577
+
499
578
  functions = self.kb.functions
500
579
  callgraph_digraph = networkx.DiGraph(functions.callgraph)
501
580
 
@@ -554,7 +633,7 @@ class StringObfuscationFinder(Analysis):
554
633
  except Exception: # pylint:disable=broad-exception-caught
555
634
  # catch all exceptions
556
635
  continue
557
- if dec.codegen is None:
636
+ if dec.codegen is None or not dec.codegen.text:
558
637
  continue
559
638
  if not self._like_type3_deobfuscation_function(dec.codegen.text):
560
639
  continue
@@ -605,6 +684,8 @@ class StringObfuscationFinder(Analysis):
605
684
  """
606
685
 
607
686
  cfg = self.kb.cfgs.get_most_accurate()
687
+ if cfg is None:
688
+ raise AngrAnalysisError("StringObfuscationFinder needs a CFG for the analysis")
608
689
 
609
690
  call_sites = cfg.get_predecessors(cfg.get_any_node(func_addr))
610
691
  callinsn2content = {}
@@ -687,7 +768,7 @@ class StringObfuscationFinder(Analysis):
687
768
  # execute the block at the call site
688
769
  state = self.project.factory.blank_state(
689
770
  addr=call_site_addr,
690
- add_options={sim_options.ZERO_FILL_UNCONSTRAINED_REGISTERS, sim_options.ZERO_FILL_UNCONSTRAINED_MEMORY},
771
+ add_options={ZERO_FILL_UNCONSTRAINED_REGISTERS, ZERO_FILL_UNCONSTRAINED_MEMORY},
691
772
  )
692
773
  # setup sp and bp, just in case
693
774
  state.regs._sp = 0x7FFF0000
@@ -728,7 +809,13 @@ class StringObfuscationFinder(Analysis):
728
809
  self.project.arch
729
810
  )
730
811
  callable_0 = self.project.factory.callable(
731
- func_addr, concrete_only=True, base_state=in_state, cc=cc, prototype=prototype_0
812
+ func_addr,
813
+ concrete_only=True,
814
+ base_state=in_state,
815
+ cc=cc,
816
+ prototype=prototype_0,
817
+ add_options={ZERO_FILL_UNCONSTRAINED_MEMORY, ZERO_FILL_UNCONSTRAINED_REGISTERS},
818
+ step_limit=STEP_LIMIT_ANALYSIS,
732
819
  )
733
820
 
734
821
  try:
@@ -181,7 +181,7 @@ class ForwardAnalysis(Generic[AnalysisState, NodeType, JobType, JobKey]):
181
181
  """
182
182
  return node
183
183
 
184
- def _run_on_node(self, node: NodeType, state: AnalysisState) -> tuple[bool, AnalysisState]:
184
+ def _run_on_node(self, node: NodeType, state: AnalysisState) -> tuple[bool | None, AnalysisState]:
185
185
  """
186
186
  The analysis routine that runs on each node in the graph.
187
187
 
@@ -31,7 +31,7 @@ class ClaripyDataEngineMixin(
31
31
 
32
32
 
33
33
  def _vex_make_comparison(
34
- func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool]
34
+ func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool],
35
35
  ) -> Callable[[ClaripyDataEngineMixin, Binop], claripy.ast.BV]:
36
36
  @SimEngineLightVEX.binop_handler
37
37
  def inner(self, expr):
@@ -44,7 +44,7 @@ def _vex_make_comparison(
44
44
 
45
45
 
46
46
  def _vex_make_vec_comparison(
47
- func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool]
47
+ func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.Bool],
48
48
  ) -> Callable[[ClaripyDataEngineMixin, int, int, Binop], claripy.ast.BV]:
49
49
  @SimEngineLightVEX.binopv_handler
50
50
  def inner(self, size, count, expr):
@@ -56,7 +56,7 @@ def _vex_make_vec_comparison(
56
56
 
57
57
 
58
58
  def _vex_make_operation(
59
- func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]
59
+ func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV],
60
60
  ) -> Callable[[ClaripyDataEngineMixin, Binop], claripy.ast.BV]:
61
61
  @SimEngineLightVEX.binop_handler
62
62
  def inner(self, expr: Binop):
@@ -70,7 +70,7 @@ def _vex_make_operation(
70
70
 
71
71
 
72
72
  def _vex_make_unary_operation(
73
- func: Callable[[claripy.ast.BV], claripy.ast.BV]
73
+ func: Callable[[claripy.ast.BV], claripy.ast.BV],
74
74
  ) -> Callable[[ClaripyDataEngineMixin, Unop], claripy.ast.BV]:
75
75
  @SimEngineLightVEX.unop_handler
76
76
  def inner(self, expr):
@@ -84,7 +84,7 @@ def _vex_make_unary_operation(
84
84
 
85
85
 
86
86
  def _vex_make_shift_operation(
87
- func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]
87
+ func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV],
88
88
  ) -> Callable[[ClaripyDataEngineMixin, Binop], claripy.ast.BV]:
89
89
  @_vex_make_operation
90
90
  def inner(a, b):
@@ -99,7 +99,7 @@ def _vex_make_shift_operation(
99
99
 
100
100
 
101
101
  def _vex_make_vec_operation(
102
- func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV]
102
+ func: Callable[[claripy.ast.BV, claripy.ast.BV], claripy.ast.BV],
103
103
  ) -> Callable[[ClaripyDataEngineMixin, int, int, Binop], claripy.ast.BV]:
104
104
  @SimEngineLightVEX.binopv_handler
105
105
  def inner(self, size, count, expr):
@@ -15,7 +15,7 @@ from angr.knowledge_plugins.key_definitions.atoms import (
15
15
  from angr.knowledge_plugins.key_definitions.definition import Definition
16
16
  from angr.analyses import register_analysis
17
17
  from .reaching_definitions import ReachingDefinitionsAnalysis, ReachingDefinitionsModel
18
- from .function_handler import FunctionHandler, FunctionCallData
18
+ from .function_handler import FunctionHandler, FunctionCallData, FunctionCallRelationships
19
19
  from .rd_state import ReachingDefinitionsState
20
20
 
21
21
  if TYPE_CHECKING:
@@ -29,6 +29,7 @@ __all__ = (
29
29
  "ConstantSrc",
30
30
  "Definition",
31
31
  "FunctionCallData",
32
+ "FunctionCallRelationships",
32
33
  "FunctionHandler",
33
34
  "GuardUse",
34
35
  "LiveDefinitions",
@@ -6,7 +6,6 @@ from typing import (
6
6
  Any,
7
7
  )
8
8
  from collections.abc import Iterable, Iterator
9
- from dataclasses import dataclass
10
9
 
11
10
  import networkx
12
11
 
@@ -35,16 +34,6 @@ def _is_definition(node):
35
34
  return isinstance(node, Definition)
36
35
 
37
36
 
38
- @dataclass
39
- class FunctionCallRelationships: # TODO this doesn't belong in this file anymore
40
- callsite: CodeLocation
41
- target: int | None
42
- args_defns: list[set[Definition]]
43
- other_input_defns: set[Definition]
44
- ret_defns: set[Definition]
45
- other_output_defns: set[Definition]
46
-
47
-
48
37
  class DepGraph:
49
38
  """
50
39
  The representation of a dependency graph: a directed graph, where nodes are definitions, and edges represent uses.
@@ -84,7 +73,7 @@ class DepGraph:
84
73
  """
85
74
  self._graph.add_edge(source, destination, **labels)
86
75
 
87
- def nodes(self) -> networkx.classes.reportviews.NodeView[Definition]:
76
+ def nodes(self) -> Iterator[Definition]:
88
77
  return self._graph.nodes()
89
78
 
90
79
  def predecessors(self, node: Definition) -> Iterator[Definition]:
@@ -12,7 +12,8 @@ from angr.engines.light import SimEngineNostmtVEX, SpOffset
12
12
  from angr.engines.vex.claripy.datalayer import value as claripy_value
13
13
  from angr.errors import SimEngineError, SimMemoryMissingError
14
14
  from angr.utils.constants import DEFAULT_STATEMENT
15
- from angr.knowledge_plugins.key_definitions.live_definitions import Definition, LiveDefinitions
15
+ from angr.knowledge_plugins.key_definitions.definition import Definition
16
+ from angr.knowledge_plugins.key_definitions.live_definitions import LiveDefinitions
16
17
  from angr.knowledge_plugins.key_definitions.tag import LocalVariableTag, ParameterTag, Tag
17
18
  from angr.knowledge_plugins.key_definitions.atoms import Atom, Register, MemoryLocation, Tmp
18
19
  from angr.knowledge_plugins.key_definitions.constants import OP_BEFORE, OP_AFTER
@@ -78,11 +79,15 @@ class SimEngineRDVEX(
78
79
  self._set_codeloc()
79
80
  if self.block.vex.jumpkind == "Ijk_Call":
80
81
  # it has to be a function
81
- addr = self._expr_bv(self.block.vex.next)
82
+ block_next = self.block.vex.next
83
+ assert isinstance(block_next, pyvex.expr.IRExpr)
84
+ addr = self._expr_bv(block_next)
82
85
  self._handle_function(addr)
83
86
  elif self.block.vex.jumpkind == "Ijk_Boring":
84
87
  # test if the target addr is a function or not
85
- addr = self._expr_bv(self.block.vex.next)
88
+ block_next = self.block.vex.next
89
+ assert isinstance(block_next, pyvex.expr.IRExpr)
90
+ addr = self._expr_bv(block_next)
86
91
  addr_v = addr.one_value()
87
92
  if addr_v is not None and addr_v.concrete:
88
93
  addr_int = addr_v.concrete_value
@@ -550,7 +555,7 @@ class SimEngineRDVEX(
550
555
  return r
551
556
 
552
557
  @unop_handler
553
- def _handle_unop_Not(self, expr):
558
+ def _handle_unop_Not(self, expr: pyvex.expr.Unop) -> MultiValues:
554
559
  arg0 = expr.args[0]
555
560
  expr_0 = self._expr_bv(arg0)
556
561
  bits = expr.result_size(self.tyenv)
@@ -563,7 +568,7 @@ class SimEngineRDVEX(
563
568
  return MultiValues(self.state.top(bits))
564
569
 
565
570
  @unop_handler
566
- def _handle_unop_Clz(self, expr):
571
+ def _handle_unop_Clz(self, expr: pyvex.expr.Unop) -> MultiValues:
567
572
  arg0 = expr.args[0]
568
573
  _ = self._expr(arg0)
569
574
  bits = expr.result_size(self.tyenv)
@@ -571,7 +576,7 @@ class SimEngineRDVEX(
571
576
  return MultiValues(self.state.top(bits))
572
577
 
573
578
  @unop_handler
574
- def _handle_unop_Ctz(self, expr):
579
+ def _handle_unop_Ctz(self, expr: pyvex.expr.Unop) -> MultiValues:
575
580
  arg0 = expr.args[0]
576
581
  _ = self._expr(arg0)
577
582
  bits = expr.result_size(self.tyenv)
@@ -582,19 +587,19 @@ class SimEngineRDVEX(
582
587
  # Binary operation handlers
583
588
  #
584
589
  @binop_handler
585
- def _handle_binop_ExpCmpNE64(self, expr):
590
+ def _handle_binop_ExpCmpNE64(self, expr: pyvex.expr.Binop) -> MultiValues:
586
591
  _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
587
592
  bits = expr.result_size(self.tyenv)
588
593
  # Need to actually implement this later
589
594
  return MultiValues(self.state.top(bits))
590
595
 
591
596
  @binop_handler
592
- def _handle_binop_16HLto32(self, expr):
597
+ def _handle_binop_16HLto32(self, expr: pyvex.expr.Binop) -> MultiValues:
593
598
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
594
599
  return expr0.concat(expr1)
595
600
 
596
601
  @binop_handler
597
- def _handle_binop_Add(self, expr):
602
+ def _handle_binop_Add(self, expr: pyvex.expr.Binop) -> MultiValues:
598
603
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
599
604
  bits = expr.result_size(self.tyenv)
600
605
 
@@ -625,7 +630,7 @@ class SimEngineRDVEX(
625
630
  return r
626
631
 
627
632
  @binop_handler
628
- def _handle_binop_Sub(self, expr):
633
+ def _handle_binop_Sub(self, expr: pyvex.expr.Binop) -> MultiValues:
629
634
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
630
635
  bits = expr.result_size(self.tyenv)
631
636
 
@@ -656,7 +661,7 @@ class SimEngineRDVEX(
656
661
  return r
657
662
 
658
663
  @binop_handler
659
- def _handle_binop_Mul(self, expr):
664
+ def _handle_binop_Mul(self, expr: pyvex.expr.Binop) -> MultiValues:
660
665
  expr0, expr1 = self._expr_pair(expr.args[0], expr.args[1])
661
666
  bits = expr.result_size(self.tyenv)
662
667
 
@@ -687,13 +692,13 @@ class SimEngineRDVEX(
687
692
  return r
688
693
 
689
694
  @binop_handler
690
- def _handle_binop_Mull(self, expr):
695
+ def _handle_binop_Mull(self, expr: pyvex.expr.Binop) -> MultiValues:
691
696
  _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
692
697
  bits = expr.result_size(self.tyenv)
693
698
  return MultiValues(self.state.top(bits))
694
699
 
695
700
  @binop_handler
696
- def _handle_binop_Div(self, expr):
701
+ def _handle_binop_Div(self, expr: pyvex.expr.Binop) -> MultiValues:
697
702
  expr0, expr1 = self._expr_pair(expr.args[0], expr.args[1])
698
703
  bits = expr.result_size(self.tyenv)
699
704
 
@@ -727,19 +732,20 @@ class SimEngineRDVEX(
727
732
  return r
728
733
 
729
734
  @binop_handler
730
- def _handle_binop_DivMod(self, expr):
735
+ def _handle_binop_DivMod(self, expr: pyvex.expr.Binop) -> MultiValues:
731
736
  _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
732
737
  bits = expr.result_size(self.tyenv)
733
738
 
734
739
  return MultiValues(self.state.top(bits))
735
740
 
736
- def _handle_Mod(self, expr):
741
+ @binop_handler
742
+ def _handle_Mod(self, expr: pyvex.expr.Binop) -> MultiValues:
737
743
  _, _ = self._expr(expr.args[0]), self._expr(expr.args[1])
738
744
  bits = expr.result_size(self.tyenv)
739
745
  return MultiValues(self.state.top(bits))
740
746
 
741
747
  @binop_handler
742
- def _handle_binop_And(self, expr):
748
+ def _handle_binop_And(self, expr: pyvex.expr.Binop) -> MultiValues:
743
749
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
744
750
  bits = expr.result_size(self.tyenv)
745
751
 
@@ -748,9 +754,8 @@ class SimEngineRDVEX(
748
754
  expr1_v = expr1.one_value()
749
755
 
750
756
  if expr0_v is not None and expr1_v is not None:
751
- if expr0_v.concrete and expr1_v.concrete:
752
- # bitwise-and two single values together
753
- r = MultiValues(expr0_v & expr1_v)
757
+ # bitwise-and two single values together
758
+ r = MultiValues(expr0_v & expr1_v)
754
759
  elif expr0_v is None and expr1_v is not None:
755
760
  # bitwise-and a single value with a multivalue
756
761
  if expr0.count() == 1 and 0 in expr0:
@@ -771,7 +776,7 @@ class SimEngineRDVEX(
771
776
  return r
772
777
 
773
778
  @binop_handler
774
- def _handle_binop_Xor(self, expr):
779
+ def _handle_binop_Xor(self, expr: pyvex.expr.Binop) -> MultiValues:
775
780
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
776
781
  bits = expr.result_size(self.tyenv)
777
782
 
@@ -803,7 +808,7 @@ class SimEngineRDVEX(
803
808
  return r
804
809
 
805
810
  @binop_handler
806
- def _handle_binop_Or(self, expr):
811
+ def _handle_binop_Or(self, expr: pyvex.expr.Binop) -> MultiValues:
807
812
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
808
813
  bits = expr.result_size(self.tyenv)
809
814
 
@@ -834,7 +839,7 @@ class SimEngineRDVEX(
834
839
  return r
835
840
 
836
841
  @binop_handler
837
- def _handle_binop_Sar(self, expr):
842
+ def _handle_binop_Sar(self, expr: pyvex.expr.Binop) -> MultiValues:
838
843
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
839
844
  bits = expr.result_size(self.tyenv)
840
845
 
@@ -877,7 +882,7 @@ class SimEngineRDVEX(
877
882
  return r
878
883
 
879
884
  @binop_handler
880
- def _handle_binop_Shr(self, expr):
885
+ def _handle_binop_Shr(self, expr: pyvex.expr.Binop) -> MultiValues:
881
886
  expr0, expr1 = self._expr_bv(expr.args[0]), self._expr_bv(expr.args[1])
882
887
  bits = expr.result_size(self.tyenv)
883
888
 
@@ -918,7 +923,7 @@ class SimEngineRDVEX(
918
923
  return r
919
924
 
920
925
  @binop_handler
921
- def _handle_binop_Shl(self, expr):
926
+ def _handle_binop_Shl(self, expr: pyvex.expr.Binop) -> MultiValues:
922
927
  expr0, expr1 = self._expr(expr.args[0]), self._expr(expr.args[1])
923
928
  bits = expr.result_size(self.tyenv)
924
929
 
@@ -956,7 +961,7 @@ class SimEngineRDVEX(
956
961
  return r
957
962
 
958
963
  @binop_handler
959
- def _handle_binop_CmpEQ(self, expr):
964
+ def _handle_binop_CmpEQ(self, expr: pyvex.expr.Binop) -> MultiValues:
960
965
  arg0, arg1 = expr.args
961
966
  expr_0 = self._expr(arg0)
962
967
  expr_1 = self._expr(arg1)
@@ -974,7 +979,7 @@ class SimEngineRDVEX(
974
979
  return MultiValues(self.state.top(1))
975
980
 
976
981
  @binop_handler
977
- def _handle_binop_CmpNE(self, expr):
982
+ def _handle_binop_CmpNE(self, expr: pyvex.expr.Binop) -> MultiValues:
978
983
  arg0, arg1 = expr.args
979
984
  expr_0 = self._expr(arg0)
980
985
  expr_1 = self._expr(arg1)
@@ -989,7 +994,7 @@ class SimEngineRDVEX(
989
994
  return MultiValues(self.state.top(1))
990
995
 
991
996
  @binop_handler
992
- def _handle_binop_CmpLT(self, expr):
997
+ def _handle_binop_CmpLT(self, expr: pyvex.expr.Binop) -> MultiValues:
993
998
  arg0, arg1 = expr.args
994
999
  expr_0, expr_1 = self._expr_pair(arg0, arg1)
995
1000
 
@@ -1004,7 +1009,7 @@ class SimEngineRDVEX(
1004
1009
  return MultiValues(self.state.top(1))
1005
1010
 
1006
1011
  @binop_handler
1007
- def _handle_binop_CmpLE(self, expr):
1012
+ def _handle_binop_CmpLE(self, expr: pyvex.expr.Binop) -> MultiValues:
1008
1013
  arg0, arg1 = expr.args
1009
1014
  expr_0, expr_1 = self._expr_pair(arg0, arg1)
1010
1015
 
@@ -1019,7 +1024,7 @@ class SimEngineRDVEX(
1019
1024
  return MultiValues(self.state.top(1))
1020
1025
 
1021
1026
  @binop_handler
1022
- def _handle_binop_CmpGT(self, expr):
1027
+ def _handle_binop_CmpGT(self, expr: pyvex.expr.Binop) -> MultiValues:
1023
1028
  arg0, arg1 = expr.args
1024
1029
  expr_0, expr_1 = self._expr_pair(arg0, arg1)
1025
1030
 
@@ -1034,7 +1039,7 @@ class SimEngineRDVEX(
1034
1039
  return MultiValues(self.state.top(1))
1035
1040
 
1036
1041
  @binop_handler
1037
- def _handle_binop_CmpGE(self, expr):
1042
+ def _handle_binop_CmpGE(self, expr: pyvex.expr.Binop) -> MultiValues:
1038
1043
  arg0, arg1 = expr.args
1039
1044
  expr_0, expr_1 = self._expr_pair(arg0, arg1)
1040
1045
 
@@ -1050,7 +1055,7 @@ class SimEngineRDVEX(
1050
1055
 
1051
1056
  # ppc only
1052
1057
  @binop_handler
1053
- def _handle_binop_CmpORD(self, expr):
1058
+ def _handle_binop_CmpORD(self, expr: pyvex.expr.Binop) -> MultiValues:
1054
1059
  arg0, arg1 = expr.args
1055
1060
  expr_0, expr_1 = self._expr_pair(arg0, arg1)
1056
1061