angr 9.2.96__py3-none-win_amd64.whl → 9.2.98__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 +14 -1
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +10 -6
- angr/analyses/complete_calling_conventions.py +27 -11
- angr/analyses/decompiler/ail_simplifier.py +20 -8
- angr/analyses/decompiler/condition_processor.py +2 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +2 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +380 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +4 -1
- angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +71 -3
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +162 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +1 -1
- angr/analyses/decompiler/structured_codegen/c.py +72 -99
- angr/analyses/decompiler/utils.py +5 -1
- angr/analyses/find_objects_static.py +15 -10
- angr/analyses/forward_analysis/forward_analysis.py +15 -1
- angr/analyses/propagator/engine_ail.py +2 -0
- angr/analyses/propagator/engine_vex.py +15 -0
- angr/analyses/propagator/propagator.py +6 -3
- angr/analyses/reaching_definitions/engine_vex.py +6 -0
- angr/analyses/reaching_definitions/rd_state.py +14 -1
- angr/analyses/reaching_definitions/reaching_definitions.py +19 -2
- angr/analyses/variable_recovery/engine_ail.py +6 -6
- angr/analyses/variable_recovery/engine_vex.py +6 -0
- angr/analyses/variable_recovery/irsb_scanner.py +12 -0
- angr/analyses/variable_recovery/variable_recovery_base.py +4 -1
- angr/engines/light/engine.py +134 -16
- angr/knowledge_plugins/functions/function.py +4 -0
- angr/knowledge_plugins/key_definitions/environment.py +11 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +41 -8
- angr/knowledge_plugins/key_definitions/uses.py +18 -4
- angr/knowledge_plugins/propagations/states.py +22 -3
- angr/knowledge_plugins/types.py +6 -0
- angr/knowledge_plugins/variables/variable_manager.py +31 -5
- angr/lib/angr_native.dll +0 -0
- angr/simos/simos.py +2 -0
- angr/storage/memory_mixins/__init__.py +3 -0
- angr/storage/memory_mixins/multi_value_merger_mixin.py +22 -11
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +20 -2
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +20 -5
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +82 -44
- angr/storage/memory_mixins/simple_interface_mixin.py +4 -0
- angr/utils/cowdict.py +4 -2
- angr/utils/funcid.py +6 -0
- angr/utils/mp.py +1 -1
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/METADATA +6 -6
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/RECORD +52 -50
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/LICENSE +0 -0
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/WHEEL +0 -0
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/entry_points.txt +0 -0
- {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# pylint:disable=abstract-method,arguments-differ
|
|
1
|
+
# pylint:disable=abstract-method,arguments-differ,assignment-from-no-return
|
|
2
2
|
import logging
|
|
3
|
-
from typing import Optional, List, Set, Tuple, Union, Callable
|
|
3
|
+
from typing import Optional, List, Set, Tuple, Union, Callable, Any, FrozenSet
|
|
4
4
|
|
|
5
5
|
from angr.utils.dynamic_dictlist import DynamicDictList
|
|
6
6
|
from .....storage.memory_object import SimMemoryObject, SimLabeledMemoryObject
|
|
@@ -166,40 +166,58 @@ class MVListPage(
|
|
|
166
166
|
continue
|
|
167
167
|
l.debug("... on byte 0x%x", b)
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
memory_object_sets: Set[Tuple[FrozenSet[SimMemoryObject], Any]] = set()
|
|
170
170
|
unconstrained_in = []
|
|
171
171
|
|
|
172
|
-
# first get a list of all memory objects at that location, and
|
|
173
|
-
|
|
172
|
+
# first get a list of all memory objects at that location, and all memories that don't have those bytes
|
|
173
|
+
self_has_memory_object_set = False
|
|
174
174
|
for sm, fv in zip(all_pages, merge_conditions):
|
|
175
175
|
if sm._contains(b, page_addr):
|
|
176
176
|
l.info("... present in %s", fv)
|
|
177
|
+
memory_objects = set()
|
|
177
178
|
for mo in sm.content_gen(b):
|
|
178
179
|
if mo.includes(page_addr + b):
|
|
179
|
-
memory_objects.
|
|
180
|
+
memory_objects.add(mo)
|
|
181
|
+
memory_object_sets.add((frozenset(memory_objects), fv))
|
|
182
|
+
if sm is self:
|
|
183
|
+
self_has_memory_object_set = True
|
|
180
184
|
else:
|
|
181
185
|
l.info("... not present in %s", fv)
|
|
182
186
|
unconstrained_in.append((sm, fv))
|
|
183
187
|
|
|
184
|
-
if not
|
|
188
|
+
if not memory_object_sets:
|
|
189
|
+
continue
|
|
190
|
+
if self_has_memory_object_set and len(memory_object_sets) == 1:
|
|
185
191
|
continue
|
|
186
192
|
|
|
187
|
-
|
|
188
|
-
mo_bases =
|
|
189
|
-
mo_lengths =
|
|
190
|
-
endnesses =
|
|
191
|
-
|
|
192
|
-
|
|
193
|
+
mo_sets = {mo_set for mo_set, _ in memory_object_sets}
|
|
194
|
+
mo_bases = set()
|
|
195
|
+
mo_lengths = set()
|
|
196
|
+
endnesses = set()
|
|
197
|
+
for mo_set in mo_sets:
|
|
198
|
+
for mo in mo_set:
|
|
199
|
+
mo_bases.add(mo.base)
|
|
200
|
+
mo_lengths.add(mo.length)
|
|
201
|
+
endnesses.add(mo.endness)
|
|
202
|
+
|
|
203
|
+
if not unconstrained_in and not (mo_sets - merged_objects): # pylint:disable=superfluous-parens
|
|
193
204
|
continue
|
|
194
205
|
|
|
195
206
|
# first, optimize the case where we are dealing with the same-sized memory objects
|
|
196
207
|
if len(mo_bases) == 1 and len(mo_lengths) == 1 and not unconstrained_in and len(endnesses) == 1:
|
|
208
|
+
if len(memory_object_sets) == 1:
|
|
209
|
+
# nothing to merge!
|
|
210
|
+
continue
|
|
211
|
+
|
|
197
212
|
the_endness = next(iter(endnesses))
|
|
198
|
-
to_merge = [
|
|
213
|
+
to_merge = []
|
|
214
|
+
for mo_set, fv in memory_object_sets:
|
|
215
|
+
for mo in mo_set:
|
|
216
|
+
to_merge.append((mo.object, fv))
|
|
199
217
|
|
|
200
218
|
# Update `merged_to`
|
|
201
219
|
mo_base = list(mo_bases)[0]
|
|
202
|
-
mo_length =
|
|
220
|
+
mo_length = next(iter(mo_lengths))
|
|
203
221
|
size = min(mo_length - (page_addr + b - mo_base), len(self.content) - b)
|
|
204
222
|
merged_to = b + size
|
|
205
223
|
|
|
@@ -212,25 +230,19 @@ class MVListPage(
|
|
|
212
230
|
# TODO: Implement in-place replacement instead of calling store()
|
|
213
231
|
# new_object = self._replace_memory_object(our_mo, merged_val, page_addr, memory.page_size)
|
|
214
232
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
self.store(
|
|
218
|
-
b,
|
|
219
|
-
{SimMemoryObject(v, mo_base, endness=the_endness)},
|
|
220
|
-
size=size,
|
|
221
|
-
cooperate=True,
|
|
222
|
-
weak=not first_value,
|
|
223
|
-
)
|
|
224
|
-
first_value = False
|
|
233
|
+
new_mos = {SimMemoryObject(v, mo_base, endness=the_endness) for v in merged_val}
|
|
234
|
+
self.store(b, new_mos, size=size, cooperate=True, weak=False)
|
|
225
235
|
|
|
226
236
|
merged_offsets.add(b)
|
|
227
237
|
|
|
228
238
|
else:
|
|
229
|
-
# get the size that we can merge easily. This is the minimum of
|
|
230
|
-
#
|
|
231
|
-
min_size =
|
|
232
|
-
|
|
233
|
-
|
|
239
|
+
# get the size that we can merge easily. This is the minimum of the size of all memory objects and
|
|
240
|
+
# unallocated spaces.
|
|
241
|
+
min_size = len(self.content) - b
|
|
242
|
+
mask = (1 << memory.state.arch.bits) - 1
|
|
243
|
+
for mo_set in mo_sets:
|
|
244
|
+
for mo in mo_set:
|
|
245
|
+
min_size = min(min_size, mo.length - ((b + page_addr - mo.base) & mask))
|
|
234
246
|
for um, _ in unconstrained_in:
|
|
235
247
|
for i in range(0, min_size):
|
|
236
248
|
if um._contains(b + i, page_addr):
|
|
@@ -241,9 +253,11 @@ class MVListPage(
|
|
|
241
253
|
|
|
242
254
|
# Now, we have the minimum size. We'll extract/create expressions of that
|
|
243
255
|
# size and merge them
|
|
244
|
-
extracted =
|
|
245
|
-
|
|
246
|
-
|
|
256
|
+
extracted = []
|
|
257
|
+
if min_size != 0:
|
|
258
|
+
for mo_set, fv in memory_object_sets:
|
|
259
|
+
for mo in mo_set:
|
|
260
|
+
extracted.append((mo.bytes_at(page_addr + b, min_size), fv))
|
|
247
261
|
if not memory.skip_missing_values_during_merging:
|
|
248
262
|
created = [
|
|
249
263
|
(self._default_value(None, min_size, name=f"merge_uc_{uc.id}_{b:x}", memory=memory), fv)
|
|
@@ -257,22 +271,46 @@ class MVListPage(
|
|
|
257
271
|
if merged_val is None:
|
|
258
272
|
continue
|
|
259
273
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
self.store(
|
|
263
|
-
b,
|
|
264
|
-
{SimMemoryObject(v, page_addr + b, endness="Iend_BE")},
|
|
265
|
-
size=min_size,
|
|
266
|
-
endness="Iend_BE",
|
|
267
|
-
cooperate=True,
|
|
268
|
-
weak=not first_value,
|
|
269
|
-
) # do not convert endianness again
|
|
270
|
-
first_value = False
|
|
274
|
+
new_mos = {SimMemoryObject(v, page_addr + b, endness="Iend_BE") for v in merged_val}
|
|
275
|
+
self.store(b, new_mos, size=min_size, cooperate=True, weak=False)
|
|
271
276
|
merged_offsets.add(b)
|
|
272
277
|
|
|
273
278
|
self.stored_offset |= merged_offsets
|
|
274
279
|
return merged_offsets
|
|
275
280
|
|
|
281
|
+
def compare(
|
|
282
|
+
self, other: "MVListPage", page_addr: int = None, memory=None, changed_offsets=None
|
|
283
|
+
) -> bool: # pylint: disable=unused-argument
|
|
284
|
+
compared_to = None
|
|
285
|
+
for b in sorted(changed_offsets):
|
|
286
|
+
if compared_to is not None and not b >= compared_to:
|
|
287
|
+
continue
|
|
288
|
+
|
|
289
|
+
unconstrained_in = []
|
|
290
|
+
self_has_memory_object_set = False
|
|
291
|
+
memory_object_sets: Set[FrozenSet[SimMemoryObject]] = set()
|
|
292
|
+
for sm in [self, other]:
|
|
293
|
+
if sm._contains(b, page_addr):
|
|
294
|
+
memory_objects = set()
|
|
295
|
+
for mo in sm.content_gen(b):
|
|
296
|
+
if mo.includes(page_addr + b):
|
|
297
|
+
memory_objects.add(mo)
|
|
298
|
+
memory_object_sets.add(frozenset(memory_objects))
|
|
299
|
+
if sm is self:
|
|
300
|
+
self_has_memory_object_set = True
|
|
301
|
+
else:
|
|
302
|
+
unconstrained_in.append(sm)
|
|
303
|
+
|
|
304
|
+
if not memory_object_sets:
|
|
305
|
+
continue
|
|
306
|
+
if self_has_memory_object_set and len(memory_object_sets) == 1:
|
|
307
|
+
continue
|
|
308
|
+
|
|
309
|
+
# TODO: compare_values even more?
|
|
310
|
+
return False
|
|
311
|
+
|
|
312
|
+
return True
|
|
313
|
+
|
|
276
314
|
def changed_bytes(self, other: "MVListPage", page_addr: int = None):
|
|
277
315
|
candidates: Set[int] = super().changed_bytes(other)
|
|
278
316
|
if candidates is not None:
|
|
@@ -28,6 +28,8 @@ class SimpleInterfaceMixin(MemoryMixin):
|
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
def _translate_addr(self, a):
|
|
31
|
+
if isinstance(a, int):
|
|
32
|
+
return a
|
|
31
33
|
if isinstance(a, claripy.ast.Base) and not a.singlevalued:
|
|
32
34
|
raise SimMemoryError("address not supported")
|
|
33
35
|
return self.state.solver.eval(a)
|
|
@@ -43,6 +45,8 @@ class SimpleInterfaceMixin(MemoryMixin):
|
|
|
43
45
|
raise SimMemoryError("data not supported")
|
|
44
46
|
|
|
45
47
|
def _translate_size(self, s, data):
|
|
48
|
+
if isinstance(s, int):
|
|
49
|
+
return s
|
|
46
50
|
if isinstance(s, claripy.ast.Base) and not s.singlevalued:
|
|
47
51
|
raise SimMemoryError("size not supported")
|
|
48
52
|
if s is None:
|
angr/utils/cowdict.py
CHANGED
|
@@ -35,7 +35,7 @@ class DefaultChainMapCOW(ChainMapCOW):
|
|
|
35
35
|
Implements a copy-on-write version of ChainMap with default values that supports auto-collapsing.
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
|
-
def __init__(self,
|
|
38
|
+
def __init__(self, *args, default_factory=None, collapse_threshold=None):
|
|
39
39
|
super().__init__(*args, collapse_threshold=collapse_threshold)
|
|
40
40
|
self.default_factory = default_factory
|
|
41
41
|
|
|
@@ -53,7 +53,9 @@ class DefaultChainMapCOW(ChainMapCOW):
|
|
|
53
53
|
collapsed = {}
|
|
54
54
|
for m in reversed(self.maps):
|
|
55
55
|
collapsed.update(m)
|
|
56
|
-
return DefaultChainMapCOW(
|
|
56
|
+
return DefaultChainMapCOW(
|
|
57
|
+
collapsed, default_factory=self.default_factory, collapse_threshold=self.collapse_threshold
|
|
58
|
+
)
|
|
57
59
|
r = self.new_child()
|
|
58
60
|
r.default_factory = self.default_factory
|
|
59
61
|
r.collapse_threshold = self.collapse_threshold
|
angr/utils/funcid.py
CHANGED
|
@@ -13,6 +13,8 @@ def is_function_security_check_cookie(func, project, security_cookie_addr: int)
|
|
|
13
13
|
block = project.factory.block(func.addr)
|
|
14
14
|
if block.instructions != 2:
|
|
15
15
|
return False
|
|
16
|
+
if not block.capstone.insns or len(block.capstone.insns) != 2:
|
|
17
|
+
return False
|
|
16
18
|
ins0 = block.capstone.insns[0]
|
|
17
19
|
if (
|
|
18
20
|
ins0.mnemonic == "cmp"
|
|
@@ -57,6 +59,8 @@ def is_function_security_init_cookie(func: "Function", project, security_cookie_
|
|
|
57
59
|
block = project.factory.block(node_addr, size=node_size)
|
|
58
60
|
if not block.instructions:
|
|
59
61
|
continue
|
|
62
|
+
if not block.capstone.insns:
|
|
63
|
+
continue
|
|
60
64
|
last_insn = block.capstone.insns[-1]
|
|
61
65
|
if (
|
|
62
66
|
last_insn.mnemonic == "mov"
|
|
@@ -78,6 +82,8 @@ def is_function_security_init_cookie_win8(func: "Function", project, security_co
|
|
|
78
82
|
block = project.factory.block(func.addr)
|
|
79
83
|
if block.instructions != 3:
|
|
80
84
|
return False
|
|
85
|
+
if not block.capstone.insns or len(block.capstone.insns) != 3:
|
|
86
|
+
return False
|
|
81
87
|
ins0 = block.capstone.insns[0]
|
|
82
88
|
if (
|
|
83
89
|
ins0.mnemonic == "mov"
|
angr/utils/mp.py
CHANGED
|
@@ -43,7 +43,7 @@ class Initializer:
|
|
|
43
43
|
def initialize(self) -> None:
|
|
44
44
|
"""
|
|
45
45
|
Initialize a multiprocessing.Process
|
|
46
|
-
Set the current global
|
|
46
|
+
Set the current global initializer to the same state as this initializer, then calls each initializer
|
|
47
47
|
"""
|
|
48
48
|
self._single = self
|
|
49
49
|
for i in self.initializers:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: angr
|
|
3
|
-
Version: 9.2.
|
|
3
|
+
Version: 9.2.98
|
|
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.98
|
|
21
|
+
Requires-Dist: archinfo ==9.2.98
|
|
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.98
|
|
26
|
+
Requires-Dist: cle ==9.2.98
|
|
27
27
|
Requires-Dist: dpkt
|
|
28
28
|
Requires-Dist: itanium-demangler
|
|
29
29
|
Requires-Dist: mulpyplexer
|
|
@@ -33,7 +33,7 @@ Requires-Dist: protobuf >=3.19.0
|
|
|
33
33
|
Requires-Dist: psutil
|
|
34
34
|
Requires-Dist: pycparser >=2.18
|
|
35
35
|
Requires-Dist: pyformlang
|
|
36
|
-
Requires-Dist: pyvex ==9.2.
|
|
36
|
+
Requires-Dist: pyvex ==9.2.98
|
|
37
37
|
Requires-Dist: rich >=13.1.0
|
|
38
38
|
Requires-Dist: rpyc
|
|
39
39
|
Requires-Dist: sortedcontainers
|