angr 9.2.92__py3-none-manylinux2014_x86_64.whl → 9.2.94__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 (45) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/cfg/cfg_base.py +20 -10
  3. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +1 -1
  4. angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +89 -32
  5. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +276 -133
  6. angr/analyses/complete_calling_conventions.py +1 -1
  7. angr/analyses/decompiler/ail_simplifier.py +20 -0
  8. angr/analyses/decompiler/block_io_finder.py +293 -0
  9. angr/analyses/decompiler/block_similarity.py +190 -0
  10. angr/analyses/decompiler/callsite_maker.py +5 -0
  11. angr/analyses/decompiler/clinic.py +103 -1
  12. angr/analyses/decompiler/decompilation_cache.py +2 -0
  13. angr/analyses/decompiler/decompiler.py +21 -4
  14. angr/analyses/decompiler/optimization_passes/__init__.py +6 -0
  15. angr/analyses/decompiler/optimization_passes/code_motion.py +361 -0
  16. angr/analyses/decompiler/optimization_passes/optimization_pass.py +1 -0
  17. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +30 -18
  18. angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +110 -0
  19. angr/analyses/decompiler/peephole_optimizations/bswap.py +53 -2
  20. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +20 -1
  21. angr/analyses/decompiler/structured_codegen/c.py +76 -41
  22. angr/analyses/decompiler/structuring/phoenix.py +41 -9
  23. angr/analyses/decompiler/utils.py +13 -4
  24. angr/analyses/propagator/engine_ail.py +3 -0
  25. angr/analyses/reaching_definitions/engine_ail.py +3 -0
  26. angr/analyses/reaching_definitions/reaching_definitions.py +7 -0
  27. angr/analyses/stack_pointer_tracker.py +60 -10
  28. angr/analyses/typehoon/simple_solver.py +95 -24
  29. angr/analyses/typehoon/typeconsts.py +1 -1
  30. angr/calling_conventions.py +0 -3
  31. angr/engines/pcode/cc.py +1 -1
  32. angr/engines/successors.py +6 -0
  33. angr/knowledge_plugins/propagations/states.py +2 -1
  34. angr/procedures/definitions/glibc.py +3 -1
  35. angr/procedures/definitions/parse_win32json.py +2135 -383
  36. angr/procedures/definitions/wdk_ntoskrnl.py +956 -0
  37. angr/sim_type.py +53 -13
  38. angr/utils/library.py +2 -2
  39. {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/METADATA +6 -6
  40. {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/RECORD +44 -41
  41. {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/WHEEL +1 -1
  42. angr/procedures/definitions/wdk_ntdll.py +0 -994
  43. {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/LICENSE +0 -0
  44. {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/entry_points.txt +0 -0
  45. {angr-9.2.92.dist-info → angr-9.2.94.dist-info}/top_level.txt +0 -0
@@ -224,7 +224,8 @@ class Sketch:
224
224
  @staticmethod
225
225
  def flatten_typevar(
226
226
  derived_typevar: Union[TypeVariable, TypeConstant, DerivedTypeVariable]
227
- ) -> Union[DerivedTypeVariable, TypeVariable, TypeConstant]: # pylint:disable=too-many-boolean-expressions
227
+ ) -> Union[DerivedTypeVariable, TypeVariable, TypeConstant]:
228
+ # pylint:disable=too-many-boolean-expressions
228
229
  if (
229
230
  isinstance(derived_typevar, DerivedTypeVariable)
230
231
  and isinstance(derived_typevar.type_var, Pointer)
@@ -419,15 +420,45 @@ class SimpleSolver:
419
420
  for tv in typevars:
420
421
  if tv in self._constraints:
421
422
  constraints |= self._constraints[tv]
423
+
424
+ # collect typevars used in the constraint set
425
+ constrained_typevars = set()
426
+ for constraint in constraints:
427
+ if isinstance(constraint, Subtype):
428
+ for t in (constraint.sub_type, constraint.super_type):
429
+ if isinstance(t, DerivedTypeVariable):
430
+ if t.type_var in typevars:
431
+ constrained_typevars.add(t.type_var)
432
+ elif isinstance(t, TypeVariable):
433
+ if t in typevars:
434
+ constrained_typevars.add(t)
435
+
422
436
  equivalence_classes, sketches = self.infer_shapes(typevars, constraints)
423
437
  # TODO: Handle global variables
424
438
 
425
439
  type_schemes = constraints
426
440
 
427
- for tv in typevars:
428
- primitive_constraints = self._generate_primitive_constraints(type_schemes, {tv})
429
- for primitive_constraint in primitive_constraints:
430
- sketches[tv].add_constraint(primitive_constraint)
441
+ constraintset2tvs = defaultdict(set)
442
+ for idx, tv in enumerate(constrained_typevars):
443
+ _l.debug("Collecting constraints for type variable %r (%d/%d)", tv, idx + 1, len(constrained_typevars))
444
+ # build a sub constraint set for the type variable
445
+ constraint_subset = frozenset(self._generate_constraint_subset(constraints, {tv}))
446
+ constraintset2tvs[constraint_subset].add(tv)
447
+
448
+ for idx, (constraint_subset, tvs) in enumerate(constraintset2tvs.items()):
449
+ _l.debug(
450
+ "Solving %d constraints for type variables %r (%d/%d)",
451
+ len(constraint_subset),
452
+ tvs,
453
+ idx + 1,
454
+ len(constraintset2tvs),
455
+ )
456
+ base_constraint_graph = self._generate_constraint_graph(constraint_subset, tvs | PRIMITIVE_TYPES)
457
+ for idx_0, tv in enumerate(tvs):
458
+ _l.debug("Solving for type variable %r (%d/%d)", tv, idx_0 + 1, len(tvs))
459
+ primitive_constraints = self._generate_primitive_constraints({tv}, base_constraint_graph)
460
+ for primitive_constraint in primitive_constraints:
461
+ sketches[tv].add_constraint(primitive_constraint)
431
462
 
432
463
  return equivalence_classes, sketches, type_schemes
433
464
 
@@ -515,10 +546,11 @@ class SimpleSolver:
515
546
  return equivalence_classes, out_graph
516
547
 
517
548
  def _generate_primitive_constraints(
518
- self, constraints: Set[TypeConstraint], non_primitive_endpoints: Set[Union[TypeVariable, DerivedTypeVariable]]
549
+ self,
550
+ non_primitive_endpoints: Set[Union[TypeVariable, DerivedTypeVariable]],
551
+ constraint_graph,
519
552
  ) -> Set[TypeConstraint]:
520
553
  # FIXME: Extract interesting variables
521
- constraint_graph = self._generate_constraint_graph(constraints, non_primitive_endpoints | PRIMITIVE_TYPES)
522
554
  constraints_0 = self._solve_constraints_between(constraint_graph, non_primitive_endpoints, PRIMITIVE_TYPES)
523
555
  constraints_1 = self._solve_constraints_between(constraint_graph, PRIMITIVE_TYPES, non_primitive_endpoints)
524
556
  return constraints_0 | constraints_1
@@ -702,6 +734,41 @@ class SimpleSolver:
702
734
  # Constraint graph
703
735
  #
704
736
 
737
+ @staticmethod
738
+ def _generate_constraint_subset(
739
+ constraints: Set[TypeConstraint], typevars: Set[TypeVariable]
740
+ ) -> Set[TypeConstraint]:
741
+ subset = set()
742
+ related_typevars = set(typevars)
743
+ while True:
744
+ new = set()
745
+ for constraint in constraints:
746
+ if constraint in subset:
747
+ continue
748
+ if isinstance(constraint, Subtype):
749
+ if isinstance(constraint.sub_type, DerivedTypeVariable):
750
+ subt = constraint.sub_type.type_var
751
+ elif isinstance(constraint.sub_type, TypeVariable):
752
+ subt = constraint.sub_type
753
+ else:
754
+ subt = None
755
+ if isinstance(constraint.super_type, DerivedTypeVariable):
756
+ supert = constraint.super_type.type_var
757
+ elif isinstance(constraint.super_type, TypeVariable):
758
+ supert = constraint.super_type
759
+ else:
760
+ supert = None
761
+ if subt in related_typevars or supert in related_typevars:
762
+ new.add(constraint)
763
+ if subt is not None:
764
+ related_typevars.add(subt)
765
+ if supert is not None:
766
+ related_typevars.add(supert)
767
+ if not new:
768
+ break
769
+ subset |= new
770
+ return subset
771
+
705
772
  def _generate_constraint_graph(
706
773
  self, constraints: Set[TypeConstraint], interesting_variables: Set[DerivedTypeVariable]
707
774
  ) -> networkx.DiGraph:
@@ -946,7 +1013,8 @@ class SimpleSolver:
946
1013
  return t1
947
1014
  return Top_
948
1015
 
949
- def abstract(self, t: Union[TypeConstant, TypeVariable]) -> Union[TypeConstant, TypeVariable]:
1016
+ @staticmethod
1017
+ def abstract(t: Union[TypeConstant, TypeVariable]) -> Union[TypeConstant, TypeVariable]:
950
1018
  if isinstance(t, Pointer32):
951
1019
  return Pointer32()
952
1020
  elif isinstance(t, Pointer64):
@@ -1011,6 +1079,8 @@ class SimpleSolver:
1011
1079
  last_labels.append(labels[-1])
1012
1080
 
1013
1081
  # now, what is this variable?
1082
+ result = None
1083
+
1014
1084
  if last_labels and all(isinstance(label, (FuncIn, FuncOut)) for label in last_labels):
1015
1085
  # create a dummy result and dump it to the cache
1016
1086
  func_type = Function([], [])
@@ -1049,22 +1119,8 @@ class SimpleSolver:
1049
1119
  for node in nodes:
1050
1120
  solution[node.typevar] = result
1051
1121
 
1052
- elif not path_and_successors:
1053
- # this is a primitive variable
1054
- lower_bound = Bottom_
1055
- upper_bound = Top_
1056
-
1057
- for node in nodes:
1058
- lower_bound = self.join(lower_bound, node.lower_bound)
1059
- upper_bound = self.meet(upper_bound, node.upper_bound)
1060
- # TODO: Support variables that are accessed via differently sized pointers
1061
-
1062
- result = lower_bound if not isinstance(lower_bound, BottomType) else upper_bound
1063
- for node in nodes:
1064
- solution[node.typevar] = result
1065
- self._solution_cache[node.typevar] = result
1066
-
1067
- else:
1122
+ elif path_and_successors:
1123
+ # maybe this is a pointer to a struct?
1068
1124
  if len(nodes) == 1:
1069
1125
  the_node = next(iter(nodes))
1070
1126
  if (
@@ -1136,6 +1192,21 @@ class SimpleSolver:
1136
1192
  for node in nodes:
1137
1193
  solution[node.typevar] = result
1138
1194
 
1195
+ if not path_and_successors or result in {Top_, None}:
1196
+ # this is probably a primitive variable
1197
+ lower_bound = Bottom_
1198
+ upper_bound = Top_
1199
+
1200
+ for node in nodes:
1201
+ lower_bound = self.join(lower_bound, node.lower_bound)
1202
+ upper_bound = self.meet(upper_bound, node.upper_bound)
1203
+ # TODO: Support variables that are accessed via differently sized pointers
1204
+
1205
+ result = lower_bound if not isinstance(lower_bound, BottomType) else upper_bound
1206
+ for node in nodes:
1207
+ solution[node.typevar] = result
1208
+ self._solution_cache[node.typevar] = result
1209
+
1139
1210
  # import pprint
1140
1211
 
1141
1212
  # print("Solution")
@@ -208,7 +208,7 @@ class Struct(TypeConstant):
208
208
 
209
209
  def _hash_fields(self, visited: Set[int]):
210
210
  keys = sorted(self.fields.keys())
211
- tpl = tuple((k, self.fields[k]._hash(visited)) for k in keys)
211
+ tpl = tuple((k, self.fields[k]._hash(visited) if self.fields[k] is not None else None) for k in keys)
212
212
  return hash(tpl)
213
213
 
214
214
  @memoize
@@ -1774,9 +1774,6 @@ class SimCCARMHF(SimCCARM):
1774
1774
  RETURN_VAL = SimRegArg("r0", 4) # TODO Return val can also include reg r1
1775
1775
  ARCH = archinfo.ArchARMHF
1776
1776
 
1777
- def next_arg(self, session, arg_type):
1778
- return SimCC.next_arg(self, session, arg_type)
1779
-
1780
1777
 
1781
1778
  class SimCCARMLinuxSyscall(SimCCSyscall):
1782
1779
  # TODO: Make sure all the information is correct
angr/engines/pcode/cc.py CHANGED
@@ -43,7 +43,7 @@ class SimCCSPARC(SimCC):
43
43
  Default CC for SPARC
44
44
  """
45
45
 
46
- ARG_REGS = ["o0", "o1"]
46
+ ARG_REGS = ["o0", "o1", "o2", "o3", "o4", "o5"]
47
47
  RETURN_VAL = SimRegArg("o0", 8)
48
48
  RETURN_ADDR = SimRegArg("o7", 8)
49
49
 
@@ -271,6 +271,12 @@ class SimSuccessors:
271
271
  self.unsat_successors.append(state)
272
272
  elif o.NO_SYMBOLIC_JUMP_RESOLUTION in state.options and state.solver.symbolic(target):
273
273
  self.unconstrained_successors.append(state)
274
+ elif o.CALLLESS in state.options and state.history.jumpkind == "Ijk_Call" and state.solver.symbolic(target):
275
+ # If CALLESS is set, even a symbolic call target is allowed, because we don't want to resolve the target
276
+ # anyway
277
+ # The actual state will be fixed up later during `VEXMixin.process_successors`
278
+ self.successors.append(state)
279
+ self.flat_successors.append(state)
274
280
  elif not state.solver.symbolic(target) and not state.history.jumpkind.startswith("Ijk_Sys"):
275
281
  # a successor with a concrete IP, and it's not a syscall
276
282
  self.successors.append(state)
@@ -899,7 +899,8 @@ class PropagatorAILState(PropagatorState):
899
899
  def_ = next(iter(defs))
900
900
  if def_ is not None:
901
901
  self._expr_used_locs[def_].append(codeloc)
902
- prop_count = len(self._expr_used_locs[def_])
902
+ # we must consider known future uses of this definition as well
903
+ prop_count = max(len(self._expr_used_locs[def_]), len(self.rda.all_uses.get_uses(def_)))
903
904
  else:
904
905
  # multiple definitions or no definitions - do not propagate
905
906
  return False
@@ -43,7 +43,6 @@ libc.set_non_returning(
43
43
  "__longjmp_chk",
44
44
  "__siglongjmp_chk",
45
45
  )
46
- libc.add_alias("exit", "_exit", "_Exit")
47
46
 
48
47
 
49
48
  #
@@ -6849,6 +6848,9 @@ libc.add_alias("getc", "_IO_getc")
6849
6848
  libc.add_alias("putc", "_IO_putc")
6850
6849
  libc.add_alias("gets", "_IO_gets")
6851
6850
  libc.add_alias("puts", "_IO_puts")
6851
+ libc.add_alias("exit", "_exit", "_Exit")
6852
+ libc.add_alias("sprintf", "siprintf")
6853
+ libc.add_alias("snprintf", "sniprintf")
6852
6854
 
6853
6855
 
6854
6856
  #