angr 9.2.148__py3-none-win_amd64.whl → 9.2.150__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.

Files changed (62) hide show
  1. angr/__init__.py +1 -1
  2. angr/__main__.py +100 -37
  3. angr/analyses/calling_convention/calling_convention.py +42 -2
  4. angr/analyses/cfg/cfg_emulated.py +5 -2
  5. angr/analyses/cfg/cfg_fast.py +48 -46
  6. angr/analyses/decompiler/ail_simplifier.py +65 -32
  7. angr/analyses/decompiler/block_simplifier.py +20 -6
  8. angr/analyses/decompiler/clinic.py +80 -13
  9. angr/analyses/decompiler/dephication/rewriting_engine.py +24 -2
  10. angr/analyses/decompiler/optimization_passes/__init__.py +5 -0
  11. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +15 -13
  12. angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
  13. angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +165 -0
  14. angr/analyses/decompiler/optimization_passes/engine_base.py +11 -2
  15. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -1
  16. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +17 -2
  17. angr/analyses/decompiler/optimization_passes/optimization_pass.py +10 -6
  18. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +99 -30
  19. angr/analyses/decompiler/peephole_optimizations/__init__.py +6 -0
  20. angr/analyses/decompiler/peephole_optimizations/base.py +43 -3
  21. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +1 -1
  22. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +3 -0
  23. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +4 -1
  24. angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
  25. angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +69 -2
  26. angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
  27. angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
  28. angr/analyses/decompiler/presets/fast.py +2 -0
  29. angr/analyses/decompiler/presets/full.py +2 -0
  30. angr/analyses/decompiler/ssailification/rewriting_engine.py +51 -4
  31. angr/analyses/decompiler/ssailification/ssailification.py +23 -3
  32. angr/analyses/decompiler/ssailification/traversal_engine.py +15 -1
  33. angr/analyses/decompiler/structured_codegen/c.py +141 -10
  34. angr/analyses/decompiler/utils.py +23 -1
  35. angr/analyses/disassembly.py +2 -1
  36. angr/analyses/patchfinder.py +1 -1
  37. angr/analyses/s_reaching_definitions/s_rda_view.py +1 -0
  38. angr/analyses/typehoon/lifter.py +20 -0
  39. angr/analyses/typehoon/simple_solver.py +42 -9
  40. angr/analyses/typehoon/translator.py +4 -1
  41. angr/analyses/typehoon/typeconsts.py +17 -6
  42. angr/analyses/typehoon/typehoon.py +25 -6
  43. angr/analyses/variable_recovery/engine_ail.py +44 -5
  44. angr/analyses/variable_recovery/engine_base.py +35 -12
  45. angr/analyses/variable_recovery/variable_recovery_fast.py +33 -2
  46. angr/calling_conventions.py +23 -5
  47. angr/engines/light/engine.py +7 -0
  48. angr/engines/pcode/lifter.py +7 -0
  49. angr/knowledge_plugins/functions/function.py +68 -0
  50. angr/knowledge_plugins/propagations/states.py +5 -2
  51. angr/knowledge_plugins/variables/variable_manager.py +3 -3
  52. angr/lib/angr_native.dll +0 -0
  53. angr/procedures/definitions/__init__.py +1 -1
  54. angr/procedures/definitions/types_stl.py +22 -0
  55. angr/sim_type.py +251 -130
  56. angr/utils/graph.py +51 -27
  57. {angr-9.2.148.dist-info → angr-9.2.150.dist-info}/METADATA +7 -7
  58. {angr-9.2.148.dist-info → angr-9.2.150.dist-info}/RECORD +62 -56
  59. {angr-9.2.148.dist-info → angr-9.2.150.dist-info}/WHEEL +1 -1
  60. {angr-9.2.148.dist-info → angr-9.2.150.dist-info}/licenses/LICENSE +3 -0
  61. {angr-9.2.148.dist-info → angr-9.2.150.dist-info}/entry_points.txt +0 -0
  62. {angr-9.2.148.dist-info → angr-9.2.150.dist-info}/top_level.txt +0 -0
@@ -1196,7 +1196,7 @@ class SimCC:
1196
1196
 
1197
1197
  @staticmethod
1198
1198
  def find_cc(
1199
- arch: archinfo.Arch, args: list[SimRegArg | SimStackArg], sp_delta: int, platform: str = "Linux"
1199
+ arch: archinfo.Arch, args: list[SimRegArg | SimStackArg], sp_delta: int, platform: str | None = "Linux"
1200
1200
  ) -> SimCC | None:
1201
1201
  """
1202
1202
  Pinpoint the best-fit calling convention and return the corresponding SimCC instance, or None if no fit is
@@ -1335,6 +1335,21 @@ class SimCCMicrosoftCdecl(SimCCCdecl):
1335
1335
  STRUCT_RETURN_THRESHOLD = 64
1336
1336
 
1337
1337
 
1338
+ class SimCCMicrosoftThiscall(SimCCCdecl):
1339
+ CALLEE_CLEANUP = True
1340
+ ARG_REGS = ["ecx"]
1341
+ CALLER_SAVED_REGS = ["eax", "ecx", "edx"]
1342
+ STRUCT_RETURN_THRESHOLD = 64
1343
+
1344
+ def arg_locs(self, prototype) -> list[SimFunctionArgument]:
1345
+ if prototype._arch is None:
1346
+ prototype = prototype.with_arch(self.arch)
1347
+ session = self.arg_session(prototype.returnty)
1348
+ if not prototype.args:
1349
+ return []
1350
+ return [SimRegArg("ecx", self.arch.bytes)] + [self.next_arg(session, arg_ty) for arg_ty in prototype.args[1:]]
1351
+
1352
+
1338
1353
  class SimCCStdcall(SimCCMicrosoftCdecl):
1339
1354
  CALLEE_CLEANUP = True
1340
1355
 
@@ -1469,7 +1484,7 @@ class SimCCSyscall(SimCC):
1469
1484
  self.ERROR_REG.set_value(state, error_reg_val)
1470
1485
  return expr
1471
1486
 
1472
- def set_return_val(self, state, val, ty, **kwargs): # pylint:disable=arguments-differ
1487
+ def set_return_val(self, state, val, ty, **kwargs): # type:ignore # pylint:disable=arguments-differ
1473
1488
  if self.ERROR_REG is not None:
1474
1489
  val = self.linux_syscall_update_error_reg(state, val)
1475
1490
  super().set_return_val(state, val, ty, **kwargs)
@@ -1607,6 +1622,7 @@ class SimCCSystemVAMD64(SimCC):
1607
1622
  classification = self._classify(ty)
1608
1623
  if any(cls == "MEMORY" for cls in classification):
1609
1624
  assert all(cls == "MEMORY" for cls in classification)
1625
+ assert ty.size is not None
1610
1626
  byte_size = ty.size // self.arch.byte_width
1611
1627
  referenced_locs = [SimStackArg(offset, self.arch.bytes) for offset in range(0, byte_size, self.arch.bytes)]
1612
1628
  referenced_loc = refine_locs_with_struct_type(self.arch, referenced_locs, ty)
@@ -1645,6 +1661,7 @@ class SimCCSystemVAMD64(SimCC):
1645
1661
  if isinstance(ty, (SimTypeFloat,)):
1646
1662
  return ["SSE"] + ["SSEUP"] * (nchunks - 1)
1647
1663
  if isinstance(ty, (SimStruct, SimTypeFixedSizeArray, SimUnion)):
1664
+ assert ty.size is not None
1648
1665
  if ty.size > 512:
1649
1666
  return ["MEMORY"] * nchunks
1650
1667
  flattened = self._flatten(ty)
@@ -1723,7 +1740,7 @@ class SimCCAMD64LinuxSyscall(SimCCSyscall):
1723
1740
  CALLER_SAVED_REGS = ["rax", "rcx", "r11"]
1724
1741
 
1725
1742
  @staticmethod
1726
- def _match(arch, args, sp_delta): # pylint: disable=unused-argument
1743
+ def _match(arch, args, sp_delta): # type:ignore # pylint: disable=unused-argument
1727
1744
  # doesn't appear anywhere but syscalls
1728
1745
  return False
1729
1746
 
@@ -1855,6 +1872,7 @@ class SimCCARM(SimCC):
1855
1872
  for suboffset, subsubty_list in subresult.items():
1856
1873
  result[offset + suboffset] += subsubty_list
1857
1874
  elif isinstance(ty, SimTypeFixedSizeArray):
1875
+ assert ty.elem_type.size is not None
1858
1876
  subresult = self._flatten(ty.elem_type)
1859
1877
  if subresult is None:
1860
1878
  return None
@@ -2273,7 +2291,7 @@ class SimCCUnknown(SimCC):
2273
2291
  """
2274
2292
 
2275
2293
  @staticmethod
2276
- def _match(arch, args, sp_delta): # pylint: disable=unused-argument
2294
+ def _match(arch, args, sp_delta): # type:ignore # pylint: disable=unused-argument
2277
2295
  # It always returns True
2278
2296
  return True
2279
2297
 
@@ -2317,7 +2335,7 @@ CC: dict[str, dict[str, list[type[SimCC]]]] = {
2317
2335
  "default": [SimCCCdecl],
2318
2336
  "Linux": [SimCCCdecl],
2319
2337
  "CGC": [SimCCCdecl],
2320
- "Win32": [SimCCMicrosoftCdecl, SimCCMicrosoftFastcall],
2338
+ "Win32": [SimCCMicrosoftCdecl, SimCCMicrosoftFastcall, SimCCMicrosoftThiscall],
2321
2339
  },
2322
2340
  "ARMEL": {
2323
2341
  "default": [SimCCARM],
@@ -533,6 +533,7 @@ class SimEngineLightAIL(
533
533
  def __init__(self, *args, **kwargs):
534
534
  self._stmt_handlers: dict[str, Callable[[Any], StmtDataType]] = {
535
535
  "Assignment": self._handle_stmt_Assignment,
536
+ "WeakAssignment": self._handle_stmt_WeakAssignment,
536
537
  "Store": self._handle_stmt_Store,
537
538
  "Jump": self._handle_stmt_Jump,
538
539
  "ConditionalJump": self._handle_stmt_ConditionalJump,
@@ -697,6 +698,9 @@ class SimEngineLightAIL(
697
698
  @abstractmethod
698
699
  def _handle_stmt_Assignment(self, stmt: ailment.statement.Assignment) -> StmtDataType: ...
699
700
 
701
+ @abstractmethod
702
+ def _handle_stmt_WeakAssignment(self, stmt: ailment.statement.WeakAssignment) -> StmtDataType: ...
703
+
700
704
  @abstractmethod
701
705
  def _handle_stmt_Store(self, stmt: ailment.statement.Store) -> StmtDataType: ...
702
706
 
@@ -1006,6 +1010,9 @@ class SimEngineNostmtAIL(
1006
1010
  def _handle_stmt_Assignment(self, stmt) -> StmtDataType | None:
1007
1011
  pass
1008
1012
 
1013
+ def _handle_stmt_WeakAssignment(self, stmt) -> StmtDataType | None:
1014
+ pass
1015
+
1009
1016
  def _handle_stmt_Store(self, stmt) -> StmtDataType | None:
1010
1017
  pass
1011
1018
 
@@ -427,6 +427,13 @@ class IRSB:
427
427
 
428
428
  return exits
429
429
 
430
+ @property
431
+ def is_noop_block(self) -> bool:
432
+ """
433
+ Returns True if this block is a no-op block (i.e. it has no instructions and no jumps).
434
+ """
435
+ return not any(op.opcode != pypcode.OpCode.IMARK for op in self._ops)
436
+
430
437
  #
431
438
  # private methods
432
439
  #
@@ -26,6 +26,7 @@ from angr.calling_conventions import DEFAULT_CC, default_cc
26
26
  from angr.sim_type import SimTypeFunction, parse_defns
27
27
  from angr.calling_conventions import SimCC
28
28
  from angr.project import Project
29
+ from angr.utils.library import get_cpp_function_name
29
30
  from .function_parser import FunctionParser
30
31
 
31
32
  l = logging.getLogger(name=__name__)
@@ -1582,11 +1583,78 @@ class Function(Serializable):
1582
1583
  # int, long
1583
1584
  return addr
1584
1585
 
1586
+ def is_rust_function(self):
1587
+ ast = pydemumble.demangle(self.name)
1588
+ if ast:
1589
+ nodes = ast.split("::")
1590
+ if len(nodes) >= 2:
1591
+ last_node = nodes[-1]
1592
+ return (
1593
+ len(last_node) == 17
1594
+ and last_node.startswith("h")
1595
+ and all(c in "0123456789abcdef" for c in last_node[1:])
1596
+ )
1597
+ return False
1598
+
1599
+ @staticmethod
1600
+ def _rust_fmt_node(node):
1601
+ result = []
1602
+ rest = node
1603
+ if rest.startswith("_$"):
1604
+ rest = rest[1:]
1605
+ while True:
1606
+ if rest.startswith("."):
1607
+ if len(rest) > 1 and rest[1] == ".":
1608
+ result.append("::")
1609
+ rest = rest[2:]
1610
+ else:
1611
+ result.append(".")
1612
+ rest = rest[1:]
1613
+ elif rest.startswith("$"):
1614
+ if "$" in rest[1:]:
1615
+ escape, rest = rest[1:].split("$", 1)
1616
+ else:
1617
+ break
1618
+
1619
+ unescaped = {"SP": "@", "BP": "*", "RF": "&", "LT": "<", "GT": ">", "LP": "(", "RP": ")", "C": ","}.get(
1620
+ escape
1621
+ )
1622
+
1623
+ if unescaped is None and escape.startswith("u"):
1624
+ digits = escape[1:]
1625
+ if all(c in "0123456789abcdef" for c in digits):
1626
+ c = chr(int(digits, 16))
1627
+ if ord(c) >= 32 and ord(c) != 127:
1628
+ result.append(c)
1629
+ continue
1630
+ if unescaped:
1631
+ result.append(unescaped)
1632
+ else:
1633
+ break
1634
+ else:
1635
+ idx = min((rest.find(c) for c in "$." if c in rest), default=len(rest))
1636
+ result.append(rest[:idx])
1637
+ rest = rest[idx:]
1638
+ if not rest:
1639
+ break
1640
+ return "".join(result)
1641
+
1585
1642
  @property
1586
1643
  def demangled_name(self):
1587
1644
  ast = pydemumble.demangle(self.name)
1645
+ if self.is_rust_function():
1646
+ nodes = ast.split("::")[:-1]
1647
+ ast = "::".join([Function._rust_fmt_node(node) for node in nodes])
1588
1648
  return ast if ast else self.name
1589
1649
 
1650
+ @property
1651
+ def short_name(self):
1652
+ if self.is_rust_function():
1653
+ ast = pydemumble.demangle(self.name)
1654
+ return Function._rust_fmt_node(ast.split("::")[-2])
1655
+ func_name = get_cpp_function_name(self.demangled_name, specialized=False, qualified=True)
1656
+ return func_name.split("::")[-1]
1657
+
1590
1658
  def get_unambiguous_name(self, display_name: str | None = None) -> str:
1591
1659
  """
1592
1660
  Get a disambiguated function name.
@@ -527,12 +527,14 @@ class Equivalence:
527
527
  "atom0",
528
528
  "atom1",
529
529
  "codeloc",
530
+ "is_weakassignment",
530
531
  )
531
532
 
532
- def __init__(self, codeloc, atom0, atom1):
533
+ def __init__(self, codeloc, atom0, atom1, is_weakassignment: bool = False):
533
534
  self.codeloc = codeloc
534
535
  self.atom0 = atom0
535
536
  self.atom1 = atom1
537
+ self.is_weakassignment = is_weakassignment
536
538
 
537
539
  def __repr__(self):
538
540
  return f"<Eq@{self.codeloc!r}: {self.atom0!r}=={self.atom1!r}>"
@@ -543,7 +545,8 @@ class Equivalence:
543
545
  and other.codeloc == self.codeloc
544
546
  and other.atom0 == self.atom0
545
547
  and other.atom1 == self.atom1
548
+ and other.is_weakassignment == self.is_weakassignment
546
549
  )
547
550
 
548
551
  def __hash__(self):
549
- return hash((Equivalence, self.codeloc, self.atom0, self.atom1))
552
+ return hash((Equivalence, self.codeloc, self.atom0, self.atom1, self.is_weakassignment))
@@ -934,7 +934,7 @@ class VariableManagerInternal(Serializable):
934
934
 
935
935
  for var in chain(sorted_stack_variables, sorted_reg_variables, phi_only_vars):
936
936
  idx = next(var_ctr)
937
- if var.name is not None and not reset:
937
+ if var.name is not None and var.name != var.ident and not reset:
938
938
  continue
939
939
  if isinstance(var, (SimStackVariable, SimRegisterVariable)):
940
940
  var.name = f"v{idx}"
@@ -946,7 +946,7 @@ class VariableManagerInternal(Serializable):
946
946
  arg_vars = sorted(arg_vars, key=lambda v: _id_from_varident(v.ident))
947
947
  for var in arg_vars:
948
948
  idx = next(arg_ctr)
949
- if var.name is not None and not reset:
949
+ if var.name is not None and var.name != var.ident and not reset:
950
950
  continue
951
951
  var.name = arg_names[idx] if arg_names else f"a{idx}"
952
952
  var._hash = None
@@ -1040,7 +1040,7 @@ class VariableManagerInternal(Serializable):
1040
1040
  reg_vars: set[SimRegisterVariable] = set()
1041
1041
 
1042
1042
  # unify stack variables based on their locations
1043
- for v in self.get_variables():
1043
+ for v in self.get_variables() + list(self._phi_variables):
1044
1044
  if v in self._variables_to_unified_variables:
1045
1045
  # do not unify twice
1046
1046
  continue
angr/lib/angr_native.dll CHANGED
Binary file
@@ -397,7 +397,7 @@ class SimCppLibrary(SimLibrary):
397
397
  stub = super().get_stub(demangled_name, arch)
398
398
  # try to determine a prototype from the function name if possible
399
399
  if demangled_name != name:
400
- # itanium-mangled function name
400
+ # mangled function name
401
401
  stub.prototype = self._proto_from_demangled_name(demangled_name)
402
402
  if stub.prototype is not None:
403
403
  stub.prototype = stub.prototype.with_arch(arch)
@@ -0,0 +1,22 @@
1
+ # pylint:disable=line-too-long
2
+ from __future__ import annotations
3
+ from collections import OrderedDict
4
+
5
+ from angr.procedures.definitions import SimTypeCollection
6
+ from angr.sim_type import SimCppClass, SimTypePointer, SimTypeChar, SimTypeInt
7
+
8
+ typelib = SimTypeCollection()
9
+ typelib.set_names("cpp::std")
10
+ typelib.types = {
11
+ "class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>": SimCppClass(
12
+ unique_name="class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>>",
13
+ name="std::string",
14
+ members=OrderedDict(
15
+ [
16
+ ("m_data", SimTypePointer(SimTypeChar())),
17
+ ("m_size", SimTypeInt(signed=False)),
18
+ ("m_capacity", SimTypeInt(signed=False)),
19
+ ]
20
+ ),
21
+ ),
22
+ }