angr 9.2.95__py3-none-manylinux2014_x86_64.whl → 9.2.97__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 (55) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/cfg/cfg_fast.py +9 -6
  3. angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +6 -1
  4. angr/analyses/complete_calling_conventions.py +27 -11
  5. angr/analyses/decompiler/ail_simplifier.py +30 -8
  6. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +20 -7
  7. angr/analyses/decompiler/clinic.py +21 -5
  8. angr/analyses/decompiler/condition_processor.py +11 -0
  9. angr/analyses/decompiler/decompiler.py +58 -46
  10. angr/analyses/decompiler/optimization_passes/__init__.py +11 -5
  11. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +13 -7
  12. angr/analyses/decompiler/optimization_passes/optimization_pass.py +31 -11
  13. angr/analyses/decompiler/optimization_passes/{return_duplicator.py → return_duplicator_base.py} +54 -102
  14. angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +57 -0
  15. angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +121 -0
  16. angr/analyses/decompiler/region_identifier.py +13 -0
  17. angr/analyses/decompiler/seq_to_blocks.py +19 -0
  18. angr/analyses/decompiler/structured_codegen/c.py +21 -0
  19. angr/analyses/decompiler/structuring/phoenix.py +28 -4
  20. angr/analyses/decompiler/structuring/recursive_structurer.py +35 -1
  21. angr/analyses/decompiler/structuring/structurer_base.py +3 -0
  22. angr/analyses/decompiler/utils.py +41 -6
  23. angr/analyses/disassembly.py +4 -1
  24. angr/analyses/find_objects_static.py +15 -10
  25. angr/analyses/forward_analysis/forward_analysis.py +15 -1
  26. angr/analyses/propagator/engine_ail.py +40 -0
  27. angr/analyses/propagator/propagator.py +6 -3
  28. angr/analyses/reaching_definitions/engine_ail.py +16 -24
  29. angr/analyses/reaching_definitions/rd_state.py +14 -1
  30. angr/analyses/reaching_definitions/reaching_definitions.py +19 -2
  31. angr/analyses/variable_recovery/engine_ail.py +6 -6
  32. angr/analyses/variable_recovery/engine_base.py +22 -4
  33. angr/analyses/variable_recovery/variable_recovery_base.py +4 -1
  34. angr/engines/light/engine.py +8 -1
  35. angr/knowledge_plugins/key_definitions/atoms.py +4 -2
  36. angr/knowledge_plugins/key_definitions/environment.py +11 -0
  37. angr/knowledge_plugins/key_definitions/live_definitions.py +41 -8
  38. angr/knowledge_plugins/key_definitions/uses.py +18 -4
  39. angr/knowledge_plugins/propagations/states.py +22 -3
  40. angr/knowledge_plugins/types.py +6 -0
  41. angr/knowledge_plugins/variables/variable_manager.py +54 -5
  42. angr/simos/simos.py +2 -0
  43. angr/storage/memory_mixins/__init__.py +3 -0
  44. angr/storage/memory_mixins/multi_value_merger_mixin.py +22 -11
  45. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +20 -2
  46. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +81 -44
  47. angr/utils/cowdict.py +4 -2
  48. angr/utils/funcid.py +6 -0
  49. angr/utils/mp.py +1 -1
  50. {angr-9.2.95.dist-info → angr-9.2.97.dist-info}/METADATA +6 -6
  51. {angr-9.2.95.dist-info → angr-9.2.97.dist-info}/RECORD +55 -52
  52. {angr-9.2.95.dist-info → angr-9.2.97.dist-info}/LICENSE +0 -0
  53. {angr-9.2.95.dist-info → angr-9.2.97.dist-info}/WHEEL +0 -0
  54. {angr-9.2.95.dist-info → angr-9.2.97.dist-info}/entry_points.txt +0 -0
  55. {angr-9.2.95.dist-info → angr-9.2.97.dist-info}/top_level.txt +0 -0
@@ -294,6 +294,24 @@ class PagedMemoryMixin(MemoryMixin):
294
294
 
295
295
  return bool(merged_bytes)
296
296
 
297
+ def compare(self, other: "PagedMemoryMixin") -> bool:
298
+ changed_pages_and_offsets: Dict[int, Optional[Set[int]]] = dict(self.changed_pages(other))
299
+
300
+ for page_no in sorted(changed_pages_and_offsets):
301
+ page = self._get_page(page_no, False)
302
+ page_addr = page_no * self.page_size
303
+ if page_no in other._pages:
304
+ r = page.compare(
305
+ other._pages[page_no],
306
+ page_addr=page_addr,
307
+ memory=self,
308
+ changed_offsets=changed_pages_and_offsets[page_no],
309
+ )
310
+ if r is False:
311
+ return False
312
+
313
+ return True
314
+
297
315
  def permissions(self, addr, permissions=None, **kwargs):
298
316
  if type(addr) is not int:
299
317
  raise TypeError("addr must be an int in paged memory")
@@ -643,10 +661,10 @@ class LabeledPagesMixin(PagedMemoryMixin):
643
661
  if endness is None:
644
662
  endness = self.endness
645
663
 
646
- if type(size) is not int:
664
+ if not isinstance(size, int):
647
665
  raise TypeError("Need size to be resolved to an int by this point")
648
666
 
649
- if type(addr) is not int:
667
+ if not isinstance(addr, int):
650
668
  raise TypeError("Need addr to be resolved to an int by this point")
651
669
 
652
670
  pageno, pageoff = self._divide_addr(addr)
@@ -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
- memory_objects = []
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
- # all memories that don't have those bytes
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.append((mo, fv))
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 memory_objects:
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
- mos = {mo for mo, _ in memory_objects}
188
- mo_bases = {mo.base for mo, _ in memory_objects}
189
- mo_lengths = {mo.length for mo, _ in memory_objects}
190
- endnesses = {mo.endness for mo in mos}
191
-
192
- if not unconstrained_in and not (mos - merged_objects): # pylint:disable=superfluous-parens
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 = [(mo.object, fv) for mo, fv in memory_objects]
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 = memory_objects[0][0].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,18 @@ 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
- first_value = True
216
- for v in merged_val:
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
- # the size of all memory objects and unallocated spaces.
231
- min_size = min(
232
- [mo.length - (b + page_addr - mo.base) for mo, _ in memory_objects] + [len(self.content) - b]
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
+ for mo_set in mo_sets:
243
+ for mo in mo_set:
244
+ min_size = min(min_size, mo.length - (b + page_addr - mo.base))
234
245
  for um, _ in unconstrained_in:
235
246
  for i in range(0, min_size):
236
247
  if um._contains(b + i, page_addr):
@@ -241,9 +252,11 @@ class MVListPage(
241
252
 
242
253
  # Now, we have the minimum size. We'll extract/create expressions of that
243
254
  # size and merge them
244
- extracted = (
245
- [(mo.bytes_at(page_addr + b, min_size), fv) for mo, fv in memory_objects] if min_size != 0 else []
246
- )
255
+ extracted = []
256
+ if min_size != 0:
257
+ for mo_set, fv in memory_object_sets:
258
+ for mo in mo_set:
259
+ extracted.append((mo.bytes_at(page_addr + b, min_size), fv))
247
260
  if not memory.skip_missing_values_during_merging:
248
261
  created = [
249
262
  (self._default_value(None, min_size, name=f"merge_uc_{uc.id}_{b:x}", memory=memory), fv)
@@ -257,22 +270,46 @@ class MVListPage(
257
270
  if merged_val is None:
258
271
  continue
259
272
 
260
- first_value = True
261
- for v in merged_val:
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
273
+ new_mos = {SimMemoryObject(v, page_addr + b, endness="Iend_BE") for v in merged_val}
274
+ self.store(b, new_mos, size=min_size, cooperate=True, weak=False)
271
275
  merged_offsets.add(b)
272
276
 
273
277
  self.stored_offset |= merged_offsets
274
278
  return merged_offsets
275
279
 
280
+ def compare(
281
+ self, other: "MVListPage", page_addr: int = None, memory=None, changed_offsets=None
282
+ ) -> bool: # pylint: disable=unused-argument
283
+ compared_to = None
284
+ for b in sorted(changed_offsets):
285
+ if compared_to is not None and not b >= compared_to:
286
+ continue
287
+
288
+ unconstrained_in = []
289
+ self_has_memory_object_set = False
290
+ memory_object_sets: Set[FrozenSet[SimMemoryObject]] = set()
291
+ for sm in [self, other]:
292
+ if sm._contains(b, page_addr):
293
+ memory_objects = set()
294
+ for mo in sm.content_gen(b):
295
+ if mo.includes(page_addr + b):
296
+ memory_objects.add(mo)
297
+ memory_object_sets.add(frozenset(memory_objects))
298
+ if sm is self:
299
+ self_has_memory_object_set = True
300
+ else:
301
+ unconstrained_in.append(sm)
302
+
303
+ if not memory_object_sets:
304
+ continue
305
+ if self_has_memory_object_set and len(memory_object_sets) == 1:
306
+ continue
307
+
308
+ # TODO: compare_values even more?
309
+ return False
310
+
311
+ return True
312
+
276
313
  def changed_bytes(self, other: "MVListPage", page_addr: int = None):
277
314
  candidates: Set[int] = super().changed_bytes(other)
278
315
  if candidates is not 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, default_factory, *args, collapse_threshold=None):
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(collapsed, collapse_threshold=self.collapse_threshold)
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 initalizer to the same state as this initalizer, then calls each initalizer
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.95
3
+ Version: 9.2.97
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.95
21
- Requires-Dist: archinfo ==9.2.95
20
+ Requires-Dist: ailment ==9.2.97
21
+ Requires-Dist: archinfo ==9.2.97
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.95
26
- Requires-Dist: cle ==9.2.95
25
+ Requires-Dist: claripy ==9.2.97
26
+ Requires-Dist: cle ==9.2.97
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.95
36
+ Requires-Dist: pyvex ==9.2.97
37
37
  Requires-Dist: rich >=13.1.0
38
38
  Requires-Dist: rpyc
39
39
  Requires-Dist: sortedcontainers