angr 9.2.83__py3-none-win_amd64.whl → 9.2.85__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/analyses/cfg/cfg_base.py +6 -1
  3. angr/analyses/cfg/cfg_fast.py +32 -10
  4. angr/analyses/decompiler/clinic.py +204 -4
  5. angr/analyses/decompiler/condition_processor.py +8 -2
  6. angr/analyses/decompiler/decompilation_options.py +10 -0
  7. angr/analyses/decompiler/decompiler.py +19 -17
  8. angr/analyses/decompiler/goto_manager.py +34 -51
  9. angr/analyses/decompiler/optimization_passes/__init__.py +5 -5
  10. angr/analyses/decompiler/optimization_passes/div_simplifier.py +2 -0
  11. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
  12. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +2 -0
  13. angr/analyses/decompiler/optimization_passes/multi_simplifier.py +2 -0
  14. angr/analyses/decompiler/optimization_passes/optimization_pass.py +131 -3
  15. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +3 -3
  16. angr/analyses/decompiler/optimization_passes/return_duplicator.py +519 -0
  17. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +14 -2
  18. angr/analyses/decompiler/region_identifier.py +8 -2
  19. angr/analyses/decompiler/region_simplifiers/goto.py +5 -4
  20. angr/analyses/decompiler/structured_codegen/c.py +66 -5
  21. angr/analyses/decompiler/structuring/phoenix.py +3 -1
  22. angr/analyses/decompiler/structuring/structurer_nodes.py +11 -5
  23. angr/analyses/decompiler/utils.py +50 -0
  24. angr/analyses/disassembly.py +10 -3
  25. angr/analyses/propagator/engine_ail.py +125 -0
  26. angr/analyses/reaching_definitions/engine_ail.py +36 -2
  27. angr/analyses/reaching_definitions/rd_initializer.py +15 -1
  28. angr/analyses/reaching_definitions/rd_state.py +9 -4
  29. angr/analyses/stack_pointer_tracker.py +10 -17
  30. angr/analyses/variable_recovery/engine_ail.py +27 -1
  31. angr/angrdb/serializers/loader.py +10 -3
  32. angr/calling_conventions.py +2 -0
  33. angr/engines/pcode/behavior.py +7 -2
  34. angr/engines/pcode/cc.py +1 -0
  35. angr/engines/pcode/emulate.py +144 -104
  36. angr/engines/pcode/lifter.py +135 -79
  37. angr/knowledge_plugins/functions/function.py +28 -0
  38. angr/knowledge_plugins/functions/function_manager.py +48 -5
  39. angr/knowledge_plugins/propagations/states.py +14 -0
  40. angr/lib/angr_native.dll +0 -0
  41. angr/procedures/cgc/deallocate.py +5 -2
  42. angr/procedures/posix/gethostbyname.py +23 -8
  43. angr/project.py +4 -0
  44. angr/simos/__init__.py +2 -0
  45. angr/simos/simos.py +1 -0
  46. angr/simos/snimmuc_nxp.py +152 -0
  47. angr/state_plugins/history.py +3 -1
  48. angr/utils/graph.py +20 -18
  49. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/METADATA +9 -8
  50. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/RECORD +61 -59
  51. tests/analyses/cfg/test_cfg_rust_got_resolution.py +2 -1
  52. tests/analyses/cfg/test_jumptables.py +2 -1
  53. tests/analyses/decompiler/test_decompiler.py +155 -103
  54. tests/engines/pcode/test_emulate.py +607 -0
  55. tests/engines/test_java.py +609 -663
  56. tests/knowledge_plugins/functions/test_function_manager.py +13 -0
  57. tests/serialization/test_db.py +30 -0
  58. angr/analyses/decompiler/optimization_passes/eager_returns.py +0 -285
  59. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/LICENSE +0 -0
  60. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/WHEEL +0 -0
  61. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/entry_points.txt +0 -0
  62. {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,152 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from io import BytesIO
4
+
5
+ from cle.backends import Blob
6
+
7
+ from angr.knowledge_base import KnowledgeBase
8
+ from .simos import SimOS
9
+
10
+ if TYPE_CHECKING:
11
+ from angr import Project
12
+
13
+
14
+ class SimSnimmucNxp(SimOS):
15
+ """
16
+ This class implements the "OS" for a bare-metal firmware used at an imaginary company.
17
+ """
18
+
19
+ def __init__(self, project: "Project", name=None, **kwargs): # pylint:disable=unused-argument
20
+ super().__init__(project, name=name)
21
+
22
+ def configure_project(self):
23
+ # pattern match the entry point to figure out if we support parsing this binary
24
+ entry_bytes = self.project.loader.memory.load(self.project.entry, 3 * 4)
25
+ if not entry_bytes == (
26
+ b"\x94\x21\xff\xf0" # stwu r1, -10(r1)
27
+ b"\x7c\x08\x02\xa6" # mfspr r0, lr
28
+ b"\x90\x01\x00\x14" # stw r0, 4(r1)
29
+ ):
30
+ return
31
+
32
+ entry_block = self.project.factory.block(self.project.entry)
33
+ try:
34
+ first_sync = next(
35
+ iter(
36
+ [
37
+ idx
38
+ for idx, insn in enumerate(entry_block.disassembly.insns)
39
+ if insn.mnemonic in {"sync", "isync"}
40
+ ]
41
+ )
42
+ )
43
+ except StopIteration:
44
+ return
45
+
46
+ # run this block and acquire initial registers for each function
47
+ state = self.project.factory.blank_state(addr=self.project.entry)
48
+ # set garbage value to key registers
49
+ key_registers = ["r13", "r2", "r14", "r15", "r16"]
50
+ GARBAGE = 0xDEADBEEF
51
+ for key_reg in key_registers:
52
+ setattr(state.regs, "_" + key_reg, GARBAGE)
53
+ simgr = self.project.factory.simgr(state)
54
+ simgr.step(num_inst=first_sync)
55
+ if simgr.active and len(simgr.active) == 1:
56
+ stepped_state = simgr.one_active
57
+ else:
58
+ return
59
+
60
+ reg_values = {}
61
+ for key_reg in key_registers:
62
+ reg_values[key_reg] = getattr(stepped_state.regs, "_" + key_reg).concrete_value
63
+ if reg_values[key_reg] in {None, GARBAGE}:
64
+ # umm the register is not initialized. unsupported?
65
+ return
66
+
67
+ # TODO: Make them part of the ABI
68
+ self.function_initial_registers = reg_values
69
+
70
+ # load SDATA, SDATA2, and a few other regions
71
+ mappings = {}
72
+
73
+ # this is just CRAZY...
74
+ # TODO: Better resilience
75
+ tmp_kb = KnowledgeBase(self.project)
76
+ self.project.analyses.CFG(
77
+ regions=[(self.project.entry, self.project.entry + 180)], data_references=False, kb=tmp_kb
78
+ )
79
+ # take the last function
80
+ func = tmp_kb.functions[self.project.entry]
81
+ second_to_last_block = sorted(func.blocks, key=lambda x: x.addr)[-2]
82
+ if second_to_last_block.vex.jumpkind != "Ijk_Call":
83
+ return
84
+ init_func_addr = second_to_last_block.vex.next
85
+ if not isinstance(init_func_addr, int):
86
+ return
87
+
88
+ # lift one block
89
+ init_func_block = self.project.factory.block(init_func_addr)
90
+ if init_func_block.vex.jumpkind != "Ijk_Call":
91
+ return
92
+
93
+ section_init_func_addr = init_func_block.vex.next
94
+ if not isinstance(section_init_func_addr, int):
95
+ return
96
+
97
+ self.project.analyses.CFG(
98
+ regions=[(section_init_func_addr, section_init_func_addr + 0x324)], data_references=False, kb=tmp_kb
99
+ )
100
+ section_init_func = tmp_kb.functions[section_init_func_addr]
101
+
102
+ sorted_blocks = sorted(section_init_func.blocks, key=lambda x: x.addr)
103
+ sdata_section_init_call = sorted_blocks[25]
104
+ if sdata_section_init_call.vex.jumpkind != "Ijk_Call":
105
+ return
106
+ sdata_section_init_func = sdata_section_init_call.vex.next
107
+ if not isinstance(sdata_section_init_func, int):
108
+ return
109
+
110
+ # more pattern matching
111
+ state = self.project.factory.blank_state(addr=sdata_section_init_func)
112
+ for key_reg in ["r28", "r29", "r30"]:
113
+ setattr(state.regs, "_" + key_reg, GARBAGE)
114
+ simgr = self.project.factory.simgr(state)
115
+ simgr.step()
116
+ if simgr.active and len(simgr.active) == 1:
117
+ stepped_state = simgr.one_active
118
+ else:
119
+ return
120
+
121
+ sdata_reg_values = {}
122
+ for key_reg in ["r28", "r29", "r30"]:
123
+ sdata_reg_values[key_reg] = getattr(stepped_state.regs, "_" + key_reg).concrete_value
124
+ if sdata_reg_values[key_reg] in {None, GARBAGE}:
125
+ # umm the register is not initialized. unsupported?
126
+ return
127
+
128
+ mappings[sdata_reg_values["r30"]] = (sdata_reg_values["r29"], sdata_reg_values["r28"] - sdata_reg_values["r29"])
129
+
130
+ # TODO: Implement support for SDATA2 and other sections
131
+ # mappings = {
132
+ # 0x60005850: (0x30A734, 0x60008D30 - 0x60005850),
133
+ # 0x60011DA0: (0x3165EC, 0x60014580 - 0x60011DA0),
134
+ # 0x60014580: (0x32AC48, 0x60061638 - 0x60014580),
135
+ # }
136
+
137
+ for mem_base, (source_addr, size) in mappings.items():
138
+ backing = BytesIO()
139
+ backing.write(self.project.loader.memory.load(source_addr, size))
140
+ backing.seek(0)
141
+
142
+ blob = Blob(
143
+ binary=None,
144
+ binary_stream=backing,
145
+ base_addr=mem_base,
146
+ offset=0,
147
+ arch=self.project.arch,
148
+ )
149
+ self.project.loader.dynamic_load(blob)
150
+
151
+ # FIXME: Use ret_offset from the calling convention
152
+ self.project.arch.ret_offset = self.project.arch.registers["r3"][0]
@@ -111,8 +111,10 @@ class SimStateHistory(SimStatePlugin):
111
111
  addr = self.addr
112
112
  if addr is None:
113
113
  addr_str = "Unknown"
114
- else:
114
+ elif isinstance(addr, int):
115
115
  addr_str = "%#x" % addr
116
+ else:
117
+ addr_str = repr(addr)
116
118
 
117
119
  return "<StateHistory @ %s>" % addr_str
118
120
 
angr/utils/graph.py CHANGED
@@ -85,31 +85,33 @@ def to_acyclic_graph(
85
85
 
86
86
  def dfs_back_edges(graph, start_node):
87
87
  """
88
- Do a DFS traversal of the graph, and return with the back edges.
89
-
90
- Note: This is just a naive recursive implementation, feel free to replace it.
91
- I couldn't find anything in networkx to do this functionality. Although the
92
- name suggest it, but `dfs_labeled_edges` is doing something different.
88
+ Perform an iterative DFS traversal of the graph, returning back edges.
93
89
 
94
90
  :param graph: The graph to traverse.
95
- :param start_node: The node where to start the traversal
96
- :returns: An iterator of 'backward' edges
91
+ :param start_node: The node where to start the traversal.
92
+ :returns: An iterator of 'backward' edges.
97
93
  """
94
+ if start_node not in graph:
95
+ return # Ensures that the start node is in the graph
98
96
 
99
- visited = set()
100
- finished = set()
97
+ visited = set() # Tracks visited nodes
98
+ finished = set() # Tracks nodes whose descendants are fully explored
99
+ stack = [(start_node, iter(graph[start_node]))]
101
100
 
102
- def _dfs_back_edges_core(node):
101
+ while stack:
102
+ node, children = stack[-1]
103
103
  visited.add(node)
104
- for child in iter(graph[node]):
105
- if child not in finished:
106
- if child in visited:
107
- yield node, child
108
- else:
109
- yield from _dfs_back_edges_core(child)
110
- finished.add(node)
111
104
 
112
- yield from _dfs_back_edges_core(start_node)
105
+ try:
106
+ child = next(children)
107
+ if child in visited:
108
+ if child not in finished:
109
+ yield node, child # Found a back edge
110
+ elif child not in finished: # Check if the child has not been finished
111
+ stack.append((child, iter(graph[child])))
112
+ except StopIteration:
113
+ stack.pop() # Done with this node's children
114
+ finished.add(node) # Mark this node as finished
113
115
 
114
116
 
115
117
  def subgraph_between_nodes(graph, source, frontier, include_frontier=False):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: angr
3
- Version: 9.2.83
3
+ Version: 9.2.85
4
4
  Summary: A multi-architecture binary analysis toolkit, with the ability to perform dynamic symbolic execution and various static analyses on binaries
5
5
  Home-page: https://github.com/angr/angr
6
6
  License: BSD-2-Clause
@@ -17,13 +17,13 @@ Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: CppHeaderParser
19
19
  Requires-Dist: GitPython
20
- Requires-Dist: ailment ==9.2.83
21
- Requires-Dist: archinfo ==9.2.83
20
+ Requires-Dist: ailment ==9.2.85
21
+ Requires-Dist: archinfo ==9.2.85
22
22
  Requires-Dist: cachetools
23
23
  Requires-Dist: capstone ==5.0.0.post1
24
24
  Requires-Dist: cffi >=1.14.0
25
- Requires-Dist: claripy ==9.2.83
26
- Requires-Dist: cle ==9.2.83
25
+ Requires-Dist: claripy ==9.2.85
26
+ Requires-Dist: cle ==9.2.85
27
27
  Requires-Dist: dpkt
28
28
  Requires-Dist: itanium-demangler
29
29
  Requires-Dist: mulpyplexer
@@ -32,12 +32,13 @@ Requires-Dist: networkx !=2.8.1,>=2.0
32
32
  Requires-Dist: protobuf >=3.19.0
33
33
  Requires-Dist: psutil
34
34
  Requires-Dist: pycparser >=2.18
35
- Requires-Dist: pyvex ==9.2.83
35
+ Requires-Dist: pyvex ==9.2.85
36
36
  Requires-Dist: rich >=13.1.0
37
37
  Requires-Dist: rpyc
38
38
  Requires-Dist: sortedcontainers
39
39
  Requires-Dist: sympy
40
40
  Requires-Dist: unicorn ==2.0.1.post1
41
+ Requires-Dist: unique-log-filter
41
42
  Requires-Dist: colorama ; platform_system == "Windows"
42
43
  Provides-Extra: angrdb
43
44
  Requires-Dist: sqlalchemy ; extra == 'angrdb'
@@ -47,10 +48,10 @@ Requires-Dist: myst-parser ; extra == 'docs'
47
48
  Requires-Dist: sphinx ; extra == 'docs'
48
49
  Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
49
50
  Provides-Extra: pcode
50
- Requires-Dist: pypcode >=1.1 ; extra == 'pcode'
51
+ Requires-Dist: pypcode ~=2.0 ; extra == 'pcode'
51
52
  Provides-Extra: testing
52
53
  Requires-Dist: keystone-engine ; extra == 'testing'
53
- Requires-Dist: pypcode >=1.1 ; extra == 'testing'
54
+ Requires-Dist: pypcode ~=2.0 ; extra == 'testing'
54
55
  Requires-Dist: pytest ; extra == 'testing'
55
56
  Requires-Dist: pytest-split ; extra == 'testing'
56
57
  Requires-Dist: pytest-xdist ; extra == 'testing'