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.
- angr/__init__.py +1 -1
- angr/analyses/cfg/cfg_base.py +6 -1
- angr/analyses/cfg/cfg_fast.py +32 -10
- angr/analyses/decompiler/clinic.py +204 -4
- angr/analyses/decompiler/condition_processor.py +8 -2
- angr/analyses/decompiler/decompilation_options.py +10 -0
- angr/analyses/decompiler/decompiler.py +19 -17
- angr/analyses/decompiler/goto_manager.py +34 -51
- angr/analyses/decompiler/optimization_passes/__init__.py +5 -5
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +131 -3
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +3 -3
- angr/analyses/decompiler/optimization_passes/return_duplicator.py +519 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +14 -2
- angr/analyses/decompiler/region_identifier.py +8 -2
- angr/analyses/decompiler/region_simplifiers/goto.py +5 -4
- angr/analyses/decompiler/structured_codegen/c.py +66 -5
- angr/analyses/decompiler/structuring/phoenix.py +3 -1
- angr/analyses/decompiler/structuring/structurer_nodes.py +11 -5
- angr/analyses/decompiler/utils.py +50 -0
- angr/analyses/disassembly.py +10 -3
- angr/analyses/propagator/engine_ail.py +125 -0
- angr/analyses/reaching_definitions/engine_ail.py +36 -2
- angr/analyses/reaching_definitions/rd_initializer.py +15 -1
- angr/analyses/reaching_definitions/rd_state.py +9 -4
- angr/analyses/stack_pointer_tracker.py +10 -17
- angr/analyses/variable_recovery/engine_ail.py +27 -1
- angr/angrdb/serializers/loader.py +10 -3
- angr/calling_conventions.py +2 -0
- angr/engines/pcode/behavior.py +7 -2
- angr/engines/pcode/cc.py +1 -0
- angr/engines/pcode/emulate.py +144 -104
- angr/engines/pcode/lifter.py +135 -79
- angr/knowledge_plugins/functions/function.py +28 -0
- angr/knowledge_plugins/functions/function_manager.py +48 -5
- angr/knowledge_plugins/propagations/states.py +14 -0
- angr/lib/angr_native.dll +0 -0
- angr/procedures/cgc/deallocate.py +5 -2
- angr/procedures/posix/gethostbyname.py +23 -8
- angr/project.py +4 -0
- angr/simos/__init__.py +2 -0
- angr/simos/simos.py +1 -0
- angr/simos/snimmuc_nxp.py +152 -0
- angr/state_plugins/history.py +3 -1
- angr/utils/graph.py +20 -18
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/METADATA +9 -8
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/RECORD +61 -59
- tests/analyses/cfg/test_cfg_rust_got_resolution.py +2 -1
- tests/analyses/cfg/test_jumptables.py +2 -1
- tests/analyses/decompiler/test_decompiler.py +155 -103
- tests/engines/pcode/test_emulate.py +607 -0
- tests/engines/test_java.py +609 -663
- tests/knowledge_plugins/functions/test_function_manager.py +13 -0
- tests/serialization/test_db.py +30 -0
- angr/analyses/decompiler/optimization_passes/eager_returns.py +0 -285
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/LICENSE +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/WHEEL +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/entry_points.txt +0 -0
- {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]
|
angr/state_plugins/history.py
CHANGED
|
@@ -111,8 +111,10 @@ class SimStateHistory(SimStatePlugin):
|
|
|
111
111
|
addr = self.addr
|
|
112
112
|
if addr is None:
|
|
113
113
|
addr_str = "Unknown"
|
|
114
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
21
|
-
Requires-Dist: archinfo ==9.2.
|
|
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.
|
|
26
|
-
Requires-Dist: cle ==9.2.
|
|
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.
|
|
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
|
|
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
|
|
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'
|