angr 9.2.123__py3-none-macosx_11_0_arm64.whl → 9.2.125__py3-none-macosx_11_0_arm64.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/__init__.py +9 -1
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +11 -8
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +2 -2
- angr/analyses/codecave.py +77 -0
- angr/analyses/decompiler/ail_simplifier.py +16 -19
- angr/analyses/decompiler/callsite_maker.py +8 -7
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +24 -2
- angr/analyses/decompiler/clinic.py +58 -2
- angr/analyses/decompiler/condition_processor.py +10 -3
- angr/analyses/decompiler/decompilation_cache.py +2 -0
- angr/analyses/decompiler/decompiler.py +54 -8
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +10 -2
- angr/analyses/decompiler/dephication/rewriting_engine.py +64 -1
- angr/analyses/decompiler/expression_narrower.py +5 -1
- angr/analyses/decompiler/optimization_passes/__init__.py +3 -0
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +4 -1
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +13 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +23 -4
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +3 -1
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +8 -5
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +10 -5
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +18 -7
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +6 -0
- angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +2 -0
- angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +2 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +2 -2
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +8 -2
- angr/analyses/decompiler/region_identifier.py +36 -0
- angr/analyses/decompiler/region_simplifiers/loop.py +2 -8
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +9 -3
- angr/analyses/decompiler/ssailification/rewriting.py +5 -2
- angr/analyses/decompiler/ssailification/rewriting_engine.py +151 -25
- angr/analyses/decompiler/ssailification/rewriting_state.py +1 -0
- angr/analyses/decompiler/ssailification/ssailification.py +17 -9
- angr/analyses/decompiler/ssailification/traversal.py +3 -1
- angr/analyses/decompiler/ssailification/traversal_engine.py +35 -8
- angr/analyses/decompiler/ssailification/traversal_state.py +1 -0
- angr/analyses/decompiler/structured_codegen/c.py +42 -4
- angr/analyses/decompiler/structuring/phoenix.py +3 -0
- angr/analyses/patchfinder.py +137 -0
- angr/analyses/pathfinder.py +282 -0
- angr/analyses/propagator/engine_ail.py +10 -3
- angr/analyses/reaching_definitions/engine_ail.py +10 -15
- angr/analyses/s_propagator.py +16 -9
- angr/analyses/s_reaching_definitions/s_rda_view.py +127 -63
- angr/analyses/smc.py +159 -0
- angr/analyses/variable_recovery/engine_ail.py +14 -0
- angr/analyses/variable_recovery/engine_base.py +11 -0
- angr/angrdb/models.py +1 -2
- angr/engines/light/engine.py +12 -0
- angr/engines/vex/heavy/heavy.py +2 -0
- angr/exploration_techniques/spiller_db.py +1 -2
- angr/knowledge_plugins/__init__.py +2 -0
- angr/knowledge_plugins/decompilation.py +45 -0
- angr/knowledge_plugins/functions/function.py +4 -0
- angr/knowledge_plugins/functions/function_manager.py +18 -9
- angr/knowledge_plugins/functions/function_parser.py +1 -1
- angr/knowledge_plugins/functions/soot_function.py +1 -0
- angr/knowledge_plugins/key_definitions/atoms.py +8 -0
- angr/lib/angr_native.dylib +0 -0
- angr/misc/ux.py +2 -2
- angr/procedures/definitions/parse_win32json.py +2 -1
- angr/project.py +17 -1
- angr/state_plugins/history.py +6 -4
- angr/storage/memory_mixins/actions_mixin.py +7 -7
- angr/storage/memory_mixins/address_concretization_mixin.py +5 -5
- angr/storage/memory_mixins/bvv_conversion_mixin.py +1 -1
- angr/storage/memory_mixins/clouseau_mixin.py +3 -3
- angr/storage/memory_mixins/conditional_store_mixin.py +3 -3
- angr/storage/memory_mixins/default_filler_mixin.py +3 -3
- angr/storage/memory_mixins/memory_mixin.py +45 -34
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +15 -14
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +27 -16
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +18 -9
- angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +5 -5
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +89 -55
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +16 -25
- angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +11 -9
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +23 -7
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +1 -1
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +9 -7
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +9 -9
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +1 -0
- angr/storage/memory_mixins/simple_interface_mixin.py +2 -2
- angr/storage/memory_mixins/simplification_mixin.py +2 -2
- angr/storage/memory_mixins/size_resolution_mixin.py +1 -1
- angr/storage/memory_mixins/slotted_memory.py +3 -3
- angr/storage/memory_mixins/smart_find_mixin.py +1 -0
- angr/storage/memory_mixins/underconstrained_mixin.py +5 -5
- angr/storage/memory_mixins/unwrapper_mixin.py +4 -4
- angr/storage/memory_object.py +4 -3
- angr/utils/bits.py +4 -0
- angr/utils/constants.py +1 -1
- angr/utils/graph.py +15 -0
- angr/utils/tagged_interval_map.py +112 -0
- angr/vaults.py +2 -2
- {angr-9.2.123.dist-info → angr-9.2.125.dist-info}/METADATA +6 -6
- {angr-9.2.123.dist-info → angr-9.2.125.dist-info}/RECORD +104 -97
- {angr-9.2.123.dist-info → angr-9.2.125.dist-info}/WHEEL +1 -1
- {angr-9.2.123.dist-info → angr-9.2.125.dist-info}/LICENSE +0 -0
- {angr-9.2.123.dist-info → angr-9.2.125.dist-info}/entry_points.txt +0 -0
- {angr-9.2.123.dist-info → angr-9.2.125.dist-info}/top_level.txt +0 -0
|
@@ -56,6 +56,7 @@ class Function(Serializable):
|
|
|
56
56
|
"addr",
|
|
57
57
|
"is_simprocedure",
|
|
58
58
|
"_name",
|
|
59
|
+
"previous_names",
|
|
59
60
|
"is_default_name",
|
|
60
61
|
"from_signature",
|
|
61
62
|
"binary_name",
|
|
@@ -224,6 +225,7 @@ class Function(Serializable):
|
|
|
224
225
|
else:
|
|
225
226
|
self.is_default_name = False
|
|
226
227
|
self._name = name
|
|
228
|
+
self.previous_names = []
|
|
227
229
|
self.from_signature = None
|
|
228
230
|
|
|
229
231
|
# Determine the name the binary where this function is.
|
|
@@ -274,6 +276,7 @@ class Function(Serializable):
|
|
|
274
276
|
|
|
275
277
|
@name.setter
|
|
276
278
|
def name(self, v):
|
|
279
|
+
self.previous_names.append(self._name)
|
|
277
280
|
self._name = v
|
|
278
281
|
self._function_manager._kb.labels[self.addr] = v
|
|
279
282
|
|
|
@@ -1667,6 +1670,7 @@ class Function(Serializable):
|
|
|
1667
1670
|
func._endpoints = self._endpoints.copy()
|
|
1668
1671
|
func._call_sites = self._call_sites.copy()
|
|
1669
1672
|
func._project = self._project
|
|
1673
|
+
func.previous_names = list(self.previous_names)
|
|
1670
1674
|
func.is_plt = self.is_plt
|
|
1671
1675
|
func.is_simprocedure = self.is_simprocedure
|
|
1672
1676
|
func.binary_name = self.binary_name
|
|
@@ -313,7 +313,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
313
313
|
if isinstance(k, self.function_address_types):
|
|
314
314
|
f = self.function(addr=k)
|
|
315
315
|
elif type(k) is str:
|
|
316
|
-
f = self.function(name=k)
|
|
316
|
+
f = self.function(name=k) or self.function(name=k, check_previous_names=True)
|
|
317
317
|
else:
|
|
318
318
|
raise ValueError(f"FunctionManager.__getitem__ does not support keys of type {type(k)}")
|
|
319
319
|
|
|
@@ -350,9 +350,9 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
350
350
|
def get_by_addr(self, addr) -> Function:
|
|
351
351
|
return self._function_map.get(addr)
|
|
352
352
|
|
|
353
|
-
def get_by_name(self, name: str) -> Generator[Function]:
|
|
353
|
+
def get_by_name(self, name: str, check_previous_names: bool = False) -> Generator[Function]:
|
|
354
354
|
for f in self._function_map.values():
|
|
355
|
-
if f.name == name:
|
|
355
|
+
if f.name == name or (check_previous_names and name in f.previous_names):
|
|
356
356
|
yield f
|
|
357
357
|
|
|
358
358
|
def _function_added(self, func: Function):
|
|
@@ -411,7 +411,7 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
411
411
|
except KeyError:
|
|
412
412
|
return None
|
|
413
413
|
|
|
414
|
-
def query(self, query: str) -> Function | None:
|
|
414
|
+
def query(self, query: str, check_previous_names: bool = False) -> Function | None:
|
|
415
415
|
"""
|
|
416
416
|
Query for a function using selectors to disambiguate. Supported variations:
|
|
417
417
|
|
|
@@ -430,19 +430,21 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
430
430
|
addr = int(matches.group(2), 0)
|
|
431
431
|
try:
|
|
432
432
|
func = self._function_map.get(addr)
|
|
433
|
-
if func.name == name:
|
|
433
|
+
if func.name == name or (check_previous_names and name in func.previous_names):
|
|
434
434
|
return func
|
|
435
435
|
except KeyError:
|
|
436
436
|
pass
|
|
437
437
|
|
|
438
438
|
obj_name = selector or self._kb._project.loader.main_object.binary_basename
|
|
439
|
-
for func in self.get_by_name(name):
|
|
439
|
+
for func in self.get_by_name(name, check_previous_names=check_previous_names):
|
|
440
440
|
if func.binary_name == obj_name:
|
|
441
441
|
return func
|
|
442
442
|
|
|
443
443
|
return None
|
|
444
444
|
|
|
445
|
-
def function(
|
|
445
|
+
def function(
|
|
446
|
+
self, addr=None, name=None, check_previous_names=False, create=False, syscall=False, plt=None
|
|
447
|
+
) -> Function | None:
|
|
446
448
|
"""
|
|
447
449
|
Get a function object from the function manager.
|
|
448
450
|
|
|
@@ -457,6 +459,13 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
457
459
|
:return: The Function instance, or None if the function is not found and create is False.
|
|
458
460
|
:rtype: Function or None
|
|
459
461
|
"""
|
|
462
|
+
if name is not None and name.startswith("sub_"):
|
|
463
|
+
try:
|
|
464
|
+
addr = int(name.split("_")[-1], 16)
|
|
465
|
+
name = None
|
|
466
|
+
except ValueError:
|
|
467
|
+
pass
|
|
468
|
+
|
|
460
469
|
if addr is not None:
|
|
461
470
|
try:
|
|
462
471
|
f = self._function_map.get(addr)
|
|
@@ -472,11 +481,11 @@ class FunctionManager(KnowledgeBasePlugin, collections.abc.Mapping):
|
|
|
472
481
|
f.is_syscall = True
|
|
473
482
|
return f
|
|
474
483
|
elif name is not None:
|
|
475
|
-
func = self.query(name)
|
|
484
|
+
func = self.query(name, check_previous_names=check_previous_names)
|
|
476
485
|
if func is not None:
|
|
477
486
|
return func
|
|
478
487
|
|
|
479
|
-
for func in self.get_by_name(name):
|
|
488
|
+
for func in self.get_by_name(name, check_previous_names=check_previous_names):
|
|
480
489
|
if plt is None or func.is_plt == plt:
|
|
481
490
|
return func
|
|
482
491
|
|
|
@@ -33,7 +33,7 @@ class FunctionParser:
|
|
|
33
33
|
obj.is_syscall = function.is_syscall
|
|
34
34
|
obj.is_simprocedure = function.is_simprocedure
|
|
35
35
|
obj.returning = function.returning
|
|
36
|
-
obj.alignment = function.
|
|
36
|
+
obj.alignment = function.is_alignment
|
|
37
37
|
obj.binary_name = function.binary_name or ""
|
|
38
38
|
obj.normalized = function.normalized
|
|
39
39
|
|
|
@@ -34,6 +34,7 @@ class SootFunction(Function):
|
|
|
34
34
|
# block nodes (basic block nodes) at whose ends the function terminates
|
|
35
35
|
# in theory, if everything works fine, endpoints == ret_sites | jumpout_sites | callout_sites
|
|
36
36
|
self._endpoints = defaultdict(set)
|
|
37
|
+
self.previous_names = []
|
|
37
38
|
|
|
38
39
|
self._call_sites = {}
|
|
39
40
|
self.addr = addr
|
|
@@ -277,6 +277,10 @@ class VirtualVariable(Atom):
|
|
|
277
277
|
def was_parameter(self) -> bool:
|
|
278
278
|
return self.category == ailment.Expr.VirtualVariableCategory.PARAMETER
|
|
279
279
|
|
|
280
|
+
@property
|
|
281
|
+
def was_tmp(self) -> bool:
|
|
282
|
+
return self.category == ailment.Expr.VirtualVariableCategory.TMP
|
|
283
|
+
|
|
280
284
|
@property
|
|
281
285
|
def reg_offset(self) -> int | None:
|
|
282
286
|
if self.was_reg:
|
|
@@ -289,6 +293,10 @@ class VirtualVariable(Atom):
|
|
|
289
293
|
return self.oident
|
|
290
294
|
return None
|
|
291
295
|
|
|
296
|
+
@property
|
|
297
|
+
def tmp_idx(self) -> int | None:
|
|
298
|
+
return self.oident if self.was_tmp else None
|
|
299
|
+
|
|
292
300
|
|
|
293
301
|
class MemoryLocation(Atom):
|
|
294
302
|
"""
|
angr/lib/angr_native.dylib
CHANGED
|
Binary file
|
angr/misc/ux.py
CHANGED
|
@@ -20,9 +20,9 @@ def deprecated(replacement=None):
|
|
|
20
20
|
def inner(*args, **kwargs):
|
|
21
21
|
if func not in already_complained:
|
|
22
22
|
if replacement is None:
|
|
23
|
-
warnings.warn(f"Don't use {func.__name__}", DeprecationWarning, stacklevel=
|
|
23
|
+
warnings.warn(f"Don't use {func.__name__}", DeprecationWarning, stacklevel=2)
|
|
24
24
|
else:
|
|
25
|
-
warnings.warn(f"Use {replacement} instead of {func.__name__}", DeprecationWarning, stacklevel=
|
|
25
|
+
warnings.warn(f"Use {replacement} instead of {func.__name__}", DeprecationWarning, stacklevel=2)
|
|
26
26
|
already_complained.add(func)
|
|
27
27
|
return func(*args, **kwargs)
|
|
28
28
|
|
|
@@ -162,7 +162,8 @@ def do_it(in_dir, out_file):
|
|
|
162
162
|
|
|
163
163
|
for file in files:
|
|
164
164
|
logging.info("Found file %s", file)
|
|
165
|
-
|
|
165
|
+
with codecs.open(file, "r", "utf-8-sig") as f:
|
|
166
|
+
api_namespaces[file.stem] = json.load(f)
|
|
166
167
|
|
|
167
168
|
logging.info("Making a bunch of types...")
|
|
168
169
|
missing_types_last_round = set()
|
angr/project.py
CHANGED
|
@@ -236,7 +236,7 @@ class Project:
|
|
|
236
236
|
self._initialize_analyses_hub()
|
|
237
237
|
|
|
238
238
|
# Step 5.3: ...etc
|
|
239
|
-
self.
|
|
239
|
+
self._knowledge_bases = {"default": KnowledgeBase(self, name="global")}
|
|
240
240
|
|
|
241
241
|
self.is_java_project = isinstance(self.arch, ArchSoot)
|
|
242
242
|
self.is_java_jni_project = isinstance(self.arch, ArchSoot) and getattr(
|
|
@@ -257,6 +257,22 @@ class Project:
|
|
|
257
257
|
# Step 7: Run OS-specific configuration
|
|
258
258
|
self.simos.configure_project()
|
|
259
259
|
|
|
260
|
+
@property
|
|
261
|
+
def kb(self):
|
|
262
|
+
return self._knowledge_bases["default"]
|
|
263
|
+
|
|
264
|
+
@kb.setter
|
|
265
|
+
def kb(self, kb):
|
|
266
|
+
self._knowledge_bases["default"] = kb
|
|
267
|
+
|
|
268
|
+
def get_kb(self, name):
|
|
269
|
+
try:
|
|
270
|
+
return self._knowledge_bases[name]
|
|
271
|
+
except KeyError:
|
|
272
|
+
kb = KnowledgeBase(self, name)
|
|
273
|
+
self._knowledge_bases[name] = kb
|
|
274
|
+
return kb
|
|
275
|
+
|
|
260
276
|
@property
|
|
261
277
|
def analyses(self) -> AnalysesHubWithDefault:
|
|
262
278
|
result = self._analyses
|
angr/state_plugins/history.py
CHANGED
|
@@ -63,9 +63,11 @@ class SimStateHistory(SimStatePlugin):
|
|
|
63
63
|
self.successor_ip = None if clone is None else clone.successor_ip
|
|
64
64
|
|
|
65
65
|
self.strongref_state = None if clone is None else clone.strongref_state
|
|
66
|
+
self.arch = None
|
|
66
67
|
|
|
67
68
|
def init_state(self):
|
|
68
69
|
self.successor_ip = self.state._ip
|
|
70
|
+
self.arch = self.state.arch
|
|
69
71
|
|
|
70
72
|
def __getstate__(self):
|
|
71
73
|
# flatten ancestry, otherwise we hit recursion errors trying to get the entire history...
|
|
@@ -217,7 +219,7 @@ class SimStateHistory(SimStatePlugin):
|
|
|
217
219
|
read_offset = None
|
|
218
220
|
elif isinstance(read_from, str):
|
|
219
221
|
read_type = "reg"
|
|
220
|
-
read_offset = self.
|
|
222
|
+
read_offset = self.arch.registers[read_from][0]
|
|
221
223
|
else:
|
|
222
224
|
read_type = "mem"
|
|
223
225
|
read_offset = read_from
|
|
@@ -227,7 +229,7 @@ class SimStateHistory(SimStatePlugin):
|
|
|
227
229
|
write_offset = None
|
|
228
230
|
elif isinstance(write_to, str):
|
|
229
231
|
write_type = "reg"
|
|
230
|
-
write_offset = self.
|
|
232
|
+
write_offset = self.arch.registers[write_to][0]
|
|
231
233
|
else:
|
|
232
234
|
write_type = "mem"
|
|
233
235
|
write_offset = write_to
|
|
@@ -256,7 +258,7 @@ class SimStateHistory(SimStatePlugin):
|
|
|
256
258
|
if isinstance(addr, claripy.ast.Base):
|
|
257
259
|
if addr.symbolic:
|
|
258
260
|
return False
|
|
259
|
-
addr =
|
|
261
|
+
addr = addr.concrete_value
|
|
260
262
|
return addr == read_offset
|
|
261
263
|
|
|
262
264
|
def action_writes(action):
|
|
@@ -272,7 +274,7 @@ class SimStateHistory(SimStatePlugin):
|
|
|
272
274
|
if isinstance(addr, claripy.ast.Base):
|
|
273
275
|
if addr.symbolic:
|
|
274
276
|
return False
|
|
275
|
-
addr =
|
|
277
|
+
addr = addr.concrete_value
|
|
276
278
|
return addr == write_offset
|
|
277
279
|
|
|
278
280
|
return [
|
|
@@ -7,7 +7,7 @@ from angr.storage.memory_mixins.memory_mixin import MemoryMixin
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class ActionsMixinHigh(MemoryMixin):
|
|
10
|
-
def load(self, addr, size=None, condition=None, fallback=None, disable_actions=False, action=None, **kwargs):
|
|
10
|
+
def load(self, addr, size=None, *, condition=None, fallback=None, disable_actions=False, action=None, **kwargs):
|
|
11
11
|
if not disable_actions and o.AUTO_REFS in self.state.options and action is None:
|
|
12
12
|
action = self.__make_action("read", addr, size, None, condition, fallback)
|
|
13
13
|
|
|
@@ -28,7 +28,7 @@ class ActionsMixinHigh(MemoryMixin):
|
|
|
28
28
|
|
|
29
29
|
return r
|
|
30
30
|
|
|
31
|
-
def store(self, addr, data, size=None, disable_actions=False, action=None, condition=None, **kwargs):
|
|
31
|
+
def store(self, addr, data, size=None, *, disable_actions=False, action=None, condition=None, **kwargs):
|
|
32
32
|
if not disable_actions and o.AUTO_REFS in self.state.options and action is None:
|
|
33
33
|
action = self.__make_action("write", addr, size, data, condition, None)
|
|
34
34
|
|
|
@@ -49,24 +49,24 @@ class ActionsMixinHigh(MemoryMixin):
|
|
|
49
49
|
action.added_constraints = claripy.true()
|
|
50
50
|
return action
|
|
51
51
|
|
|
52
|
-
def _add_constraints(self, c, action=None, **kwargs):
|
|
52
|
+
def _add_constraints(self, c, *, action=None, **kwargs):
|
|
53
53
|
if action is not None:
|
|
54
54
|
action.added_constraints = claripy.And(action.added_constraints, c)
|
|
55
55
|
return super()._add_constraints(c, action=action, **kwargs)
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
class ActionsMixinLow(MemoryMixin):
|
|
59
|
-
def load(self, addr, action=None, **kwargs):
|
|
59
|
+
def load(self, addr, size=None, *, action=None, **kwargs):
|
|
60
60
|
if action is not None:
|
|
61
61
|
if action.actual_addrs is None:
|
|
62
62
|
action.actual_addrs = []
|
|
63
63
|
action.actual_addrs.append(addr)
|
|
64
|
-
return super().load(addr, action=action, **kwargs)
|
|
64
|
+
return super().load(addr, size, action=action, **kwargs)
|
|
65
65
|
|
|
66
|
-
def store(self, addr, data, action: SimActionData | None = None, **kwargs):
|
|
66
|
+
def store(self, addr, data, size=None, *, action: SimActionData | None = None, **kwargs):
|
|
67
67
|
if action is not None:
|
|
68
68
|
if action.actual_addrs is None:
|
|
69
69
|
action.actual_addrs = []
|
|
70
70
|
action.actual_addrs.append(addr)
|
|
71
71
|
action.actual_value = action._make_object(data)
|
|
72
|
-
return super().store(addr, data, action=action, **kwargs)
|
|
72
|
+
return super().store(addr, data, size, action=action, **kwargs)
|
|
@@ -230,7 +230,7 @@ class AddressConcretizationMixin(MemoryMixin):
|
|
|
230
230
|
"""
|
|
231
231
|
Take a list of integers and return a new list of integers where front and back integers interleave.
|
|
232
232
|
"""
|
|
233
|
-
lst = [
|
|
233
|
+
lst = [0xFACE] * len(addrs)
|
|
234
234
|
front, back = 0, len(addrs) - 1
|
|
235
235
|
i = 0
|
|
236
236
|
while front <= back:
|
|
@@ -257,7 +257,7 @@ class AddressConcretizationMixin(MemoryMixin):
|
|
|
257
257
|
return sub_value
|
|
258
258
|
return claripy.If(addr == concrete_addr, sub_value, read_value)
|
|
259
259
|
|
|
260
|
-
def load(self, addr, size=None, condition=None, **kwargs):
|
|
260
|
+
def load(self, addr, size=None, *, condition=None, **kwargs):
|
|
261
261
|
if type(size) is not int:
|
|
262
262
|
raise TypeError("Size must have been specified as an int before reaching address concretization")
|
|
263
263
|
|
|
@@ -309,7 +309,7 @@ class AddressConcretizationMixin(MemoryMixin):
|
|
|
309
309
|
sub_condition = condition & sub_condition
|
|
310
310
|
super().store(concrete_addr, data, size=size, condition=sub_condition, **kwargs)
|
|
311
311
|
|
|
312
|
-
def store(self, addr, data, size=None, condition=None, **kwargs):
|
|
312
|
+
def store(self, addr, data, size=None, *, condition=None, **kwargs):
|
|
313
313
|
# Fast path
|
|
314
314
|
if type(addr) is int:
|
|
315
315
|
self._store_one_addr(addr, data, True, addr, condition, size, **kwargs)
|
|
@@ -374,11 +374,11 @@ class AddressConcretizationMixin(MemoryMixin):
|
|
|
374
374
|
raise SimMemoryAddressError("Cannot unmap a region for a symbolic address")
|
|
375
375
|
return super().unmap_region(addr, length, **kwargs)
|
|
376
376
|
|
|
377
|
-
def concrete_load(self, addr, size,
|
|
377
|
+
def concrete_load(self, addr, size, writing=False, **kwargs):
|
|
378
378
|
if type(addr) is int:
|
|
379
379
|
pass
|
|
380
380
|
elif getattr(addr, "op", None) == "BVV":
|
|
381
381
|
addr = addr.args[0]
|
|
382
382
|
else:
|
|
383
383
|
raise SimMemoryAddressError("Cannot unmap a region for a symbolic address")
|
|
384
|
-
return super().concrete_load(addr, size,
|
|
384
|
+
return super().concrete_load(addr, size, writing=writing, **kwargs)
|
|
@@ -26,7 +26,7 @@ class DataNormalizationMixin(MemoryMixin):
|
|
|
26
26
|
|
|
27
27
|
super().store(addr, data_bv, size=size, **kwargs)
|
|
28
28
|
|
|
29
|
-
def load(self, addr, size=None, fallback=None, **kwargs):
|
|
29
|
+
def load(self, addr, size=None, *, fallback=None, **kwargs):
|
|
30
30
|
fallback_bv = self._convert_to_ast(fallback, size, self.state.arch.byte_width) if fallback is not None else None
|
|
31
31
|
return super().load(addr, size=size, fallback=fallback_bv, **kwargs)
|
|
32
32
|
|
|
@@ -4,7 +4,7 @@ from angr.storage.memory_mixins.memory_mixin import MemoryMixin
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class InspectMixinHigh(MemoryMixin):
|
|
7
|
-
def store(self, addr, data, size=None, condition=None, endness=None, inspect=True, **kwargs):
|
|
7
|
+
def store(self, addr, data, size=None, *, condition=None, endness=None, inspect=True, **kwargs):
|
|
8
8
|
if not inspect or not self.state.supports_inspect:
|
|
9
9
|
super().store(addr, data, size=size, condition=condition, endness=endness, inspect=inspect, **kwargs)
|
|
10
10
|
return
|
|
@@ -63,7 +63,7 @@ class InspectMixinHigh(MemoryMixin):
|
|
|
63
63
|
mem_write_endness=endness,
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
-
def load(self, addr, size=None, condition=None, endness=None, inspect=True, **kwargs):
|
|
66
|
+
def load(self, addr, size=None, *, condition=None, endness=None, inspect=True, **kwargs):
|
|
67
67
|
if not inspect or not self.state.supports_inspect:
|
|
68
68
|
return super().load(addr, size=size, condition=condition, endness=endness, inspect=inspect, **kwargs)
|
|
69
69
|
|
|
@@ -122,7 +122,7 @@ class InspectMixinHigh(MemoryMixin):
|
|
|
122
122
|
|
|
123
123
|
return r
|
|
124
124
|
|
|
125
|
-
def _add_constraints(self, c, add_constraints=True, inspect=True, **kwargs):
|
|
125
|
+
def _add_constraints(self, c, *, add_constraints=True, inspect=True, **kwargs):
|
|
126
126
|
if inspect and self.state.supports_inspect:
|
|
127
127
|
# tracer uses address_concretization_add_constraints
|
|
128
128
|
add_constraints = self.state._inspect_getattr("address_concretization_add_constraints", add_constraints)
|
|
@@ -5,13 +5,13 @@ from angr.storage.memory_mixins.memory_mixin import MemoryMixin
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class ConditionalMixin(MemoryMixin):
|
|
8
|
-
def load(self, addr, condition=None, fallback=None, **kwargs):
|
|
9
|
-
res = super().load(addr, condition=condition, **kwargs)
|
|
8
|
+
def load(self, addr, size=None, *, condition=None, fallback=None, **kwargs):
|
|
9
|
+
res = super().load(addr, size, condition=condition, **kwargs)
|
|
10
10
|
if condition is not None and fallback is not None:
|
|
11
11
|
res = claripy.If(condition, res, fallback)
|
|
12
12
|
return res
|
|
13
13
|
|
|
14
|
-
def store(self, addr, data, size=None, condition=None, **kwargs):
|
|
14
|
+
def store(self, addr, data, size=None, *, condition=None, **kwargs):
|
|
15
15
|
condition = self.state._adjust_condition(condition)
|
|
16
16
|
|
|
17
17
|
if condition is None or self.state.solver.is_true(condition):
|
|
@@ -13,7 +13,7 @@ l = logging.getLogger(__name__)
|
|
|
13
13
|
|
|
14
14
|
class DefaultFillerMixin(MemoryMixin):
|
|
15
15
|
def _default_value(
|
|
16
|
-
self, addr, size, name=None, inspect=True, events=True, key=None, fill_missing: bool = True, **kwargs
|
|
16
|
+
self, addr, size, *, name=None, inspect=True, events=True, key=None, fill_missing: bool = True, **kwargs
|
|
17
17
|
):
|
|
18
18
|
if self.state.project and self.state.project.concrete_target:
|
|
19
19
|
mem = self.state.project.concrete_target.read_memory(addr, size)
|
|
@@ -115,7 +115,7 @@ class SpecialFillerMixin(MemoryMixin):
|
|
|
115
115
|
super().__init__(**kwargs)
|
|
116
116
|
self._special_memory_filler = special_memory_filler
|
|
117
117
|
|
|
118
|
-
def _default_value(self, addr, size, name=None, **kwargs):
|
|
118
|
+
def _default_value(self, addr, size, *, name=None, **kwargs):
|
|
119
119
|
if (
|
|
120
120
|
options.SPECIAL_MEMORY_FILL in self.state.options
|
|
121
121
|
and self.state._special_memory_filler is not None
|
|
@@ -135,7 +135,7 @@ class ExplicitFillerMixin(MemoryMixin):
|
|
|
135
135
|
super().__init__(**kwargs)
|
|
136
136
|
self._uninitialized_read_handler = uninitialized_read_handler
|
|
137
137
|
|
|
138
|
-
def _default_value(self, addr, size, inspect=True, events=True, **kwargs):
|
|
138
|
+
def _default_value(self, addr, size, *, inspect=True, events=True, **kwargs):
|
|
139
139
|
if self._uninitialized_read_handler is not None:
|
|
140
140
|
return self._uninitialized_read_handler(addr, size, inspect=inspect, events=events)
|
|
141
141
|
return super()._default_value(addr, size, inspect=inspect, events=events, **kwargs)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from collections.abc import Iterable
|
|
4
|
-
from typing import Any
|
|
4
|
+
from typing import Any, Generic, TypeVar
|
|
5
|
+
from typing_extensions import Self
|
|
5
6
|
|
|
6
7
|
import claripy
|
|
7
8
|
|
|
@@ -9,33 +10,44 @@ from angr.errors import SimMemoryError
|
|
|
9
10
|
from angr.state_plugins.plugin import SimStatePlugin
|
|
10
11
|
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
InData = TypeVar("InData")
|
|
14
|
+
OutData = TypeVar("OutData")
|
|
15
|
+
Addr = TypeVar("Addr")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MemoryMixin(Generic[InData, OutData, Addr], SimStatePlugin):
|
|
13
19
|
"""
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
memory
|
|
20
|
+
MemoryMixin is the base class for the memory model in angr. It provides a
|
|
21
|
+
set of methods that should be implemented by memory models. This is done
|
|
22
|
+
using mixins, where each mixin handles some specific feature of the memory
|
|
23
|
+
model, only overriding methods that it needs to implement its function. The
|
|
24
|
+
memory model class itself then combines a set of mixins using inheritence to
|
|
25
|
+
form the final memory model class.
|
|
17
26
|
"""
|
|
18
27
|
|
|
19
|
-
|
|
28
|
+
# pylint: disable=no-self-use,unused-argument
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
SUPPORTS_CONCRETE_LOAD: bool = False
|
|
31
|
+
|
|
32
|
+
def __init__(self, memory_id: str | None = None, endness: str = "Iend_BE"):
|
|
22
33
|
super().__init__()
|
|
23
34
|
self.id = memory_id
|
|
24
35
|
self.endness = endness
|
|
25
36
|
|
|
26
|
-
def copy(self, memo)
|
|
37
|
+
def copy(self, memo) -> Self:
|
|
27
38
|
o = type(self).__new__(type(self))
|
|
28
39
|
o.id = self.id
|
|
29
40
|
o.endness = self.endness
|
|
30
41
|
return o
|
|
31
42
|
|
|
32
43
|
@property
|
|
33
|
-
def category(self):
|
|
44
|
+
def category(self) -> str:
|
|
34
45
|
"""
|
|
35
46
|
Return the category of this SimMemory instance. It can be one of the three following categories: reg, mem,
|
|
36
47
|
or file.
|
|
37
48
|
"""
|
|
38
49
|
|
|
50
|
+
assert isinstance(self.id, str)
|
|
39
51
|
if self.id in ("reg", "mem"):
|
|
40
52
|
return self.id
|
|
41
53
|
|
|
@@ -48,46 +60,46 @@ class MemoryMixin(SimStatePlugin):
|
|
|
48
60
|
raise SimMemoryError(f'Unknown SimMemory category for memory_id "{self.id}"')
|
|
49
61
|
|
|
50
62
|
@property
|
|
51
|
-
def variable_key_prefix(self):
|
|
63
|
+
def variable_key_prefix(self) -> tuple[Any, ...]:
|
|
52
64
|
s = self.category
|
|
53
65
|
if s == "file":
|
|
54
66
|
return (s, self.id)
|
|
55
67
|
return (s,)
|
|
56
68
|
|
|
57
|
-
def find(
|
|
58
|
-
|
|
69
|
+
def find(
|
|
70
|
+
self, addr: Addr, data: InData, max_search: int, **kwargs
|
|
71
|
+
) -> tuple[Addr, list[claripy.ast.Bool], list[int]]: ...
|
|
59
72
|
|
|
60
|
-
def _add_constraints(self, c, add_constraints=True, condition=None, **kwargs):
|
|
73
|
+
def _add_constraints(self, c, *, add_constraints=True, condition=None, **kwargs):
|
|
61
74
|
if add_constraints:
|
|
62
75
|
to_add = c & condition | ~condition if condition is not None else c
|
|
63
76
|
self.state.add_constraints(to_add)
|
|
64
77
|
|
|
65
|
-
def load(self, addr, size=None, **kwargs):
|
|
66
|
-
pass
|
|
78
|
+
def load(self, addr: Addr, size: InData | None = None, **kwargs) -> OutData: ...
|
|
67
79
|
|
|
68
|
-
def store(self, addr, data, **kwargs):
|
|
69
|
-
pass
|
|
80
|
+
def store(self, addr: Addr, data: InData, size: InData | None = None, **kwargs) -> None: ...
|
|
70
81
|
|
|
71
|
-
def merge(
|
|
72
|
-
|
|
82
|
+
def merge(
|
|
83
|
+
self, others: list[Self], merge_conditions: list[claripy.ast.Bool], common_ancestor: Self | None = None
|
|
84
|
+
) -> bool: ...
|
|
73
85
|
|
|
74
|
-
def compare(self, other) -> bool:
|
|
75
|
-
pass
|
|
86
|
+
def compare(self, other: Self) -> bool: ...
|
|
76
87
|
|
|
77
|
-
def widen(self, others):
|
|
78
|
-
pass
|
|
88
|
+
def widen(self, others: list[Self]) -> bool: ...
|
|
79
89
|
|
|
80
|
-
def permissions(self, addr, permissions=None, **kwargs):
|
|
81
|
-
pass
|
|
90
|
+
def permissions(self, addr: Addr, permissions: int | claripy.ast.BV | None = None, **kwargs) -> claripy.ast.BV: ...
|
|
82
91
|
|
|
83
|
-
def map_region(
|
|
92
|
+
def map_region(
|
|
93
|
+
self, addr: Addr, length: int, permissions: int | claripy.ast.BV, *, init_zero: bool = False, **kwargs
|
|
94
|
+
):
|
|
84
95
|
pass
|
|
85
96
|
|
|
86
|
-
def unmap_region(self, addr, length, **kwargs):
|
|
97
|
+
def unmap_region(self, addr: Addr, length: int, **kwargs):
|
|
87
98
|
pass
|
|
88
99
|
|
|
89
100
|
# Optional interface:
|
|
90
|
-
|
|
101
|
+
# TODO type this correctly. maybe split the bitmap version into another function?
|
|
102
|
+
def concrete_load(self, addr, size, writing=False, **kwargs) -> Any:
|
|
91
103
|
"""
|
|
92
104
|
Set SUPPORTS_CONCRETE_LOAD to True and implement concrete_load if reading concrete bytes is faster in this
|
|
93
105
|
memory model.
|
|
@@ -99,7 +111,7 @@ class MemoryMixin(SimStatePlugin):
|
|
|
99
111
|
"""
|
|
100
112
|
raise NotImplementedError
|
|
101
113
|
|
|
102
|
-
def erase(self, addr, size=None, **kwargs) -> None:
|
|
114
|
+
def erase(self, addr: Addr, size: int | None = None, **kwargs) -> None:
|
|
103
115
|
"""
|
|
104
116
|
Set [addr:addr+size) to uninitialized. In many cases this will be faster than overwriting those locations with
|
|
105
117
|
new values. This is commonly used during static data flow analysis.
|
|
@@ -110,9 +122,7 @@ class MemoryMixin(SimStatePlugin):
|
|
|
110
122
|
"""
|
|
111
123
|
raise NotImplementedError
|
|
112
124
|
|
|
113
|
-
def _default_value(
|
|
114
|
-
self, addr, size, name=None, inspect=True, events=True, key=None, **kwargs
|
|
115
|
-
):
|
|
125
|
+
def _default_value(self, addr, size, *, name=None, inspect=True, events=True, key=None, **kwargs) -> OutData:
|
|
116
126
|
"""
|
|
117
127
|
Override this method to provide default values for a variety of edge cases and base cases.
|
|
118
128
|
|
|
@@ -123,8 +133,9 @@ class MemoryMixin(SimStatePlugin):
|
|
|
123
133
|
|
|
124
134
|
The ``inspect``, ``events``, and ``key`` parameters are for ``state.solver.Unconstrained``, if it is used.
|
|
125
135
|
"""
|
|
136
|
+
raise NotImplementedError
|
|
126
137
|
|
|
127
|
-
def _merge_values(self, values: Iterable[tuple[Any, Any]], merged_size: int, **kwargs) ->
|
|
138
|
+
def _merge_values(self, values: Iterable[tuple[Any, Any]], merged_size: int, **kwargs) -> OutData | None:
|
|
128
139
|
"""
|
|
129
140
|
Override this method to provide value merging support.
|
|
130
141
|
|
|
@@ -149,7 +160,7 @@ class MemoryMixin(SimStatePlugin):
|
|
|
149
160
|
def _replace_all(self, addrs: Iterable[int], old: claripy.ast.BV, new: claripy.ast.BV):
|
|
150
161
|
raise NotImplementedError
|
|
151
162
|
|
|
152
|
-
def copy_contents(self, dst, src, size, condition=None, **kwargs):
|
|
163
|
+
def copy_contents(self, dst: Addr, src: Addr, size: InData, condition: claripy.ast.Bool | None = None, **kwargs):
|
|
153
164
|
"""
|
|
154
165
|
Override this method to provide faster copying of large chunks of data.
|
|
155
166
|
|