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.

Files changed (52) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/cfg/cfg_base.py +14 -1
  3. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +10 -6
  4. angr/analyses/complete_calling_conventions.py +27 -11
  5. angr/analyses/decompiler/ail_simplifier.py +20 -8
  6. angr/analyses/decompiler/condition_processor.py +2 -0
  7. angr/analyses/decompiler/optimization_passes/__init__.py +2 -0
  8. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +380 -0
  9. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +4 -1
  10. angr/analyses/decompiler/peephole_optimizations/__init__.py +1 -0
  11. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +71 -3
  12. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +162 -0
  13. angr/analyses/decompiler/structured_codegen/__init__.py +1 -1
  14. angr/analyses/decompiler/structured_codegen/c.py +72 -99
  15. angr/analyses/decompiler/utils.py +5 -1
  16. angr/analyses/find_objects_static.py +15 -10
  17. angr/analyses/forward_analysis/forward_analysis.py +15 -1
  18. angr/analyses/propagator/engine_ail.py +2 -0
  19. angr/analyses/propagator/engine_vex.py +15 -0
  20. angr/analyses/propagator/propagator.py +6 -3
  21. angr/analyses/reaching_definitions/engine_vex.py +6 -0
  22. angr/analyses/reaching_definitions/rd_state.py +14 -1
  23. angr/analyses/reaching_definitions/reaching_definitions.py +19 -2
  24. angr/analyses/variable_recovery/engine_ail.py +6 -6
  25. angr/analyses/variable_recovery/engine_vex.py +6 -0
  26. angr/analyses/variable_recovery/irsb_scanner.py +12 -0
  27. angr/analyses/variable_recovery/variable_recovery_base.py +4 -1
  28. angr/engines/light/engine.py +134 -16
  29. angr/knowledge_plugins/functions/function.py +4 -0
  30. angr/knowledge_plugins/key_definitions/environment.py +11 -0
  31. angr/knowledge_plugins/key_definitions/live_definitions.py +41 -8
  32. angr/knowledge_plugins/key_definitions/uses.py +18 -4
  33. angr/knowledge_plugins/propagations/states.py +22 -3
  34. angr/knowledge_plugins/types.py +6 -0
  35. angr/knowledge_plugins/variables/variable_manager.py +31 -5
  36. angr/lib/angr_native.dll +0 -0
  37. angr/simos/simos.py +2 -0
  38. angr/storage/memory_mixins/__init__.py +3 -0
  39. angr/storage/memory_mixins/multi_value_merger_mixin.py +22 -11
  40. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +20 -2
  41. angr/storage/memory_mixins/paged_memory/pages/list_page.py +20 -5
  42. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +82 -44
  43. angr/storage/memory_mixins/simple_interface_mixin.py +4 -0
  44. angr/utils/cowdict.py +4 -2
  45. angr/utils/funcid.py +6 -0
  46. angr/utils/mp.py +1 -1
  47. {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/METADATA +6 -6
  48. {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/RECORD +52 -50
  49. {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/LICENSE +0 -0
  50. {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/WHEEL +0 -0
  51. {angr-9.2.96.dist-info → angr-9.2.98.dist-info}/entry_points.txt +0 -0
  52. {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
- 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,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
- 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
+ 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
- [(mo.bytes_at(page_addr + b, min_size), fv) for mo, fv in memory_objects] if min_size != 0 else []
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
- 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
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, 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.96
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.96
21
- Requires-Dist: archinfo ==9.2.96
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.96
26
- Requires-Dist: cle ==9.2.96
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.96
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