angr 9.2.139__py3-none-manylinux2014_x86_64.whl → 9.2.140__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.
- angr/__init__.py +1 -1
- angr/analyses/calling_convention/calling_convention.py +48 -21
- angr/analyses/cfg/cfg_base.py +13 -0
- angr/analyses/cfg/cfg_fast.py +11 -0
- angr/analyses/decompiler/ail_simplifier.py +67 -52
- angr/analyses/decompiler/clinic.py +68 -43
- angr/analyses/decompiler/decompiler.py +17 -7
- angr/analyses/decompiler/expression_narrower.py +1 -1
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +16 -10
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +2 -2
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +259 -108
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +27 -12
- angr/analyses/decompiler/structuring/dream.py +21 -17
- angr/analyses/decompiler/structuring/phoenix.py +152 -40
- angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
- angr/analyses/decompiler/structuring/structurer_base.py +36 -10
- angr/analyses/decompiler/structuring/structurer_nodes.py +4 -1
- angr/analyses/decompiler/utils.py +60 -1
- angr/analyses/deobfuscator/api_obf_finder.py +8 -5
- angr/analyses/deobfuscator/api_obf_type2_finder.py +18 -10
- angr/analyses/deobfuscator/string_obf_finder.py +105 -18
- angr/analyses/forward_analysis/forward_analysis.py +1 -1
- angr/analyses/propagator/top_checker_mixin.py +6 -6
- angr/analyses/reaching_definitions/__init__.py +2 -1
- angr/analyses/reaching_definitions/dep_graph.py +1 -12
- angr/analyses/reaching_definitions/engine_vex.py +36 -31
- angr/analyses/reaching_definitions/function_handler.py +15 -2
- angr/analyses/reaching_definitions/rd_state.py +1 -37
- angr/analyses/reaching_definitions/reaching_definitions.py +13 -24
- angr/analyses/s_propagator.py +6 -41
- angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
- angr/analyses/stack_pointer_tracker.py +36 -22
- angr/analyses/typehoon/simple_solver.py +45 -7
- angr/analyses/typehoon/typeconsts.py +18 -5
- angr/analyses/variable_recovery/engine_base.py +7 -5
- angr/block.py +69 -107
- angr/callable.py +14 -7
- angr/calling_conventions.py +15 -1
- angr/distributed/__init__.py +1 -1
- angr/engines/__init__.py +7 -8
- angr/engines/engine.py +1 -120
- angr/engines/failure.py +2 -2
- angr/engines/hook.py +2 -2
- angr/engines/light/engine.py +2 -2
- angr/engines/pcode/engine.py +2 -14
- angr/engines/procedure.py +2 -2
- angr/engines/soot/engine.py +2 -2
- angr/engines/soot/statements/switch.py +1 -1
- angr/engines/successors.py +124 -11
- angr/engines/syscall.py +2 -2
- angr/engines/unicorn.py +3 -3
- angr/engines/vex/heavy/heavy.py +3 -15
- angr/factory.py +4 -19
- angr/knowledge_plugins/key_definitions/atoms.py +8 -4
- angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
- angr/sim_type.py +19 -17
- angr/state_plugins/plugin.py +19 -4
- angr/storage/memory_mixins/memory_mixin.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +10 -5
- angr/utils/ssa/__init__.py +119 -4
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/METADATA +6 -6
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/RECORD +68 -68
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/LICENSE +0 -0
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/WHEEL +0 -0
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/entry_points.txt +0 -0
- {angr-9.2.139.dist-info → angr-9.2.140.dist-info}/top_level.txt +0 -0
angr/factory.py
CHANGED
|
@@ -10,7 +10,7 @@ from archinfo.arch_soot import ArchSoot, SootAddressDescriptor
|
|
|
10
10
|
from .sim_state import SimState
|
|
11
11
|
from .calling_conventions import default_cc, SimRegArg, SimStackArg, PointerWrapper, SimCCUnknown
|
|
12
12
|
from .callable import Callable
|
|
13
|
-
from .errors import
|
|
13
|
+
from .errors import AngrError
|
|
14
14
|
from .engines import UberEngine, ProcedureEngine
|
|
15
15
|
from .sim_type import SimTypeFunction, SimTypeInt
|
|
16
16
|
from .codenode import HookNode, SyscallNode
|
|
@@ -245,6 +245,7 @@ class AngrObjectFactory:
|
|
|
245
245
|
cc=None,
|
|
246
246
|
add_options=None,
|
|
247
247
|
remove_options=None,
|
|
248
|
+
step_limit: int | None = None,
|
|
248
249
|
):
|
|
249
250
|
"""
|
|
250
251
|
A Callable is a representation of a function in the binary that can be interacted with like a native python
|
|
@@ -257,6 +258,7 @@ class AngrObjectFactory:
|
|
|
257
258
|
:param base_state: The state from which to do these runs
|
|
258
259
|
:param toc: The address of the table of contents for ppc64
|
|
259
260
|
:param cc: The SimCC to use for a calling convention
|
|
261
|
+
:param step_limit: The maximum number of blocks that Callable will execute before pruning the path.
|
|
260
262
|
:returns: A Callable object that can be used as a interface for executing guest code like a
|
|
261
263
|
python function.
|
|
262
264
|
:rtype: angr.callable.Callable
|
|
@@ -272,6 +274,7 @@ class AngrObjectFactory:
|
|
|
272
274
|
cc=cc,
|
|
273
275
|
add_options=add_options,
|
|
274
276
|
remove_options=remove_options,
|
|
277
|
+
step_limit=step_limit,
|
|
275
278
|
)
|
|
276
279
|
|
|
277
280
|
def cc(self):
|
|
@@ -300,7 +303,6 @@ class AngrObjectFactory:
|
|
|
300
303
|
size=None,
|
|
301
304
|
max_size=None,
|
|
302
305
|
byte_string=None,
|
|
303
|
-
vex=None,
|
|
304
306
|
thumb=False,
|
|
305
307
|
backup_state=None,
|
|
306
308
|
extra_stop_points=None,
|
|
@@ -308,7 +310,6 @@ class AngrObjectFactory:
|
|
|
308
310
|
num_inst=None,
|
|
309
311
|
traceflags=0,
|
|
310
312
|
insn_bytes=None,
|
|
311
|
-
insn_text=None, # backward compatibility
|
|
312
313
|
strict_block_end=None,
|
|
313
314
|
collect_data_refs=False,
|
|
314
315
|
cross_insn_opt=True,
|
|
@@ -326,7 +327,6 @@ class AngrObjectFactory:
|
|
|
326
327
|
size=None,
|
|
327
328
|
max_size=None,
|
|
328
329
|
byte_string=None,
|
|
329
|
-
vex=None,
|
|
330
330
|
thumb=False,
|
|
331
331
|
backup_state=None,
|
|
332
332
|
extra_stop_points=None,
|
|
@@ -334,7 +334,6 @@ class AngrObjectFactory:
|
|
|
334
334
|
num_inst=None,
|
|
335
335
|
traceflags=0,
|
|
336
336
|
insn_bytes=None,
|
|
337
|
-
insn_text=None, # backward compatibility
|
|
338
337
|
strict_block_end=None,
|
|
339
338
|
collect_data_refs=False,
|
|
340
339
|
load_from_ro_regions=False,
|
|
@@ -349,7 +348,6 @@ class AngrObjectFactory:
|
|
|
349
348
|
size=None,
|
|
350
349
|
max_size=None,
|
|
351
350
|
byte_string=None,
|
|
352
|
-
vex=None,
|
|
353
351
|
thumb=False,
|
|
354
352
|
backup_state=None,
|
|
355
353
|
extra_stop_points=None,
|
|
@@ -357,7 +355,6 @@ class AngrObjectFactory:
|
|
|
357
355
|
num_inst=None,
|
|
358
356
|
traceflags=0,
|
|
359
357
|
insn_bytes=None,
|
|
360
|
-
insn_text=None, # backward compatibility
|
|
361
358
|
strict_block_end=None,
|
|
362
359
|
collect_data_refs=False,
|
|
363
360
|
cross_insn_opt=True,
|
|
@@ -369,27 +366,15 @@ class AngrObjectFactory:
|
|
|
369
366
|
if isinstance(self.project.arch, ArchSoot) and isinstance(addr, SootAddressDescriptor):
|
|
370
367
|
return SootBlock(addr, arch=self.project.arch, project=self.project)
|
|
371
368
|
|
|
372
|
-
if insn_bytes is not None and insn_text is not None:
|
|
373
|
-
raise AngrError("You cannot provide both 'insn_bytes' and 'insn_text'!")
|
|
374
|
-
|
|
375
369
|
if insn_bytes is not None:
|
|
376
370
|
byte_string = insn_bytes
|
|
377
371
|
|
|
378
|
-
if insn_text is not None:
|
|
379
|
-
byte_string = self.project.arch.asm(insn_text, addr=addr, as_bytes=True, thumb=thumb)
|
|
380
|
-
if byte_string is None:
|
|
381
|
-
# assembly failed
|
|
382
|
-
raise AngrAssemblyError(
|
|
383
|
-
"Assembling failed. Please make sure keystone is installed, and the assembly string is correct."
|
|
384
|
-
)
|
|
385
|
-
|
|
386
372
|
return Block(
|
|
387
373
|
addr,
|
|
388
374
|
project=self.project,
|
|
389
375
|
size=size,
|
|
390
376
|
max_size=max_size,
|
|
391
377
|
byte_string=byte_string,
|
|
392
|
-
vex=vex,
|
|
393
378
|
extra_stop_points=extra_stop_points,
|
|
394
379
|
thumb=thumb,
|
|
395
380
|
backup_state=backup_state,
|
|
@@ -3,7 +3,7 @@ from enum import Enum, auto
|
|
|
3
3
|
|
|
4
4
|
import claripy
|
|
5
5
|
import ailment
|
|
6
|
-
from archinfo import Arch, RegisterOffset
|
|
6
|
+
from archinfo import Arch, Endness, RegisterOffset
|
|
7
7
|
|
|
8
8
|
from angr.calling_conventions import SimFunctionArgument, SimRegArg, SimStackArg
|
|
9
9
|
from angr.engines.light import SpOffset
|
|
@@ -123,7 +123,7 @@ class Atom:
|
|
|
123
123
|
register = reg
|
|
124
124
|
|
|
125
125
|
@staticmethod
|
|
126
|
-
def mem(addr: SpOffset | HeapAddress | int, size: int, endness:
|
|
126
|
+
def mem(addr: SpOffset | HeapAddress | int, size: int, endness: Endness | None = None) -> MemoryLocation:
|
|
127
127
|
"""
|
|
128
128
|
Create a MemoryLocation atom,
|
|
129
129
|
|
|
@@ -251,7 +251,11 @@ class VirtualVariable(Atom):
|
|
|
251
251
|
)
|
|
252
252
|
|
|
253
253
|
def __init__(
|
|
254
|
-
self,
|
|
254
|
+
self,
|
|
255
|
+
varid: int,
|
|
256
|
+
size: int,
|
|
257
|
+
category: ailment.Expr.VirtualVariableCategory,
|
|
258
|
+
oident: str | int | tuple | None = None,
|
|
255
259
|
):
|
|
256
260
|
super().__init__(size)
|
|
257
261
|
|
|
@@ -310,7 +314,7 @@ class MemoryLocation(Atom):
|
|
|
310
314
|
"endness",
|
|
311
315
|
)
|
|
312
316
|
|
|
313
|
-
def __init__(self, addr: SpOffset | HeapAddress | int, size: int, endness:
|
|
317
|
+
def __init__(self, addr: SpOffset | HeapAddress | int, size: int, endness: Endness | None = None):
|
|
314
318
|
"""
|
|
315
319
|
:param int addr: The address of the beginning memory location slice.
|
|
316
320
|
:param int size: The size of the represented memory location, in bytes.
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
from typing import Any, TYPE_CHECKING, cast, overload
|
|
3
|
+
from collections import defaultdict
|
|
3
4
|
from collections.abc import Iterable, Generator
|
|
5
|
+
from enum import Enum, auto
|
|
4
6
|
import weakref
|
|
5
7
|
import logging
|
|
6
|
-
from enum import Enum, auto
|
|
7
|
-
|
|
8
|
-
from collections import defaultdict
|
|
9
8
|
|
|
10
9
|
import claripy
|
|
11
10
|
from claripy.annotation import Annotation
|
|
12
11
|
import archinfo
|
|
13
12
|
|
|
14
|
-
from angr.misc.ux import deprecated
|
|
15
13
|
from angr.errors import SimMemoryMissingError, SimMemoryError
|
|
16
14
|
from angr.storage.memory_mixins import MultiValuedMemory
|
|
17
15
|
from angr.storage.memory_mixins.paged_memory.pages.multi_values import MVType, MultiValues
|
|
18
16
|
from angr.knowledge_plugins.key_definitions.definition import A
|
|
19
17
|
from angr.engines.light import SpOffset
|
|
20
18
|
from angr.code_location import CodeLocation, ExternalCodeLocation
|
|
19
|
+
from angr.utils.constants import is_alignment_mask
|
|
21
20
|
from .atoms import Atom, Register, MemoryLocation, Tmp, ConstantSrc
|
|
22
21
|
from .definition import Definition, Tag
|
|
23
22
|
from .heap_address import HeapAddress
|
|
23
|
+
from .undefined import Undefined
|
|
24
24
|
from .uses import Uses
|
|
25
25
|
|
|
26
26
|
if TYPE_CHECKING:
|
|
@@ -207,26 +207,6 @@ class LiveDefinitions:
|
|
|
207
207
|
|
|
208
208
|
self.uses_by_codeloc: dict[CodeLocation, set[Definition]] = defaultdict(set)
|
|
209
209
|
|
|
210
|
-
@property
|
|
211
|
-
@deprecated("registers")
|
|
212
|
-
def register_definitions(self) -> MultiValuedMemory:
|
|
213
|
-
return self.registers
|
|
214
|
-
|
|
215
|
-
@property
|
|
216
|
-
@deprecated("stack")
|
|
217
|
-
def stack_definitions(self) -> MultiValuedMemory:
|
|
218
|
-
return self.stack
|
|
219
|
-
|
|
220
|
-
@property
|
|
221
|
-
@deprecated("memory")
|
|
222
|
-
def memory_definitions(self) -> MultiValuedMemory:
|
|
223
|
-
return self.memory
|
|
224
|
-
|
|
225
|
-
@property
|
|
226
|
-
@deprecated("heap")
|
|
227
|
-
def heap_definitions(self) -> MultiValuedMemory:
|
|
228
|
-
return self.heap
|
|
229
|
-
|
|
230
210
|
def __repr__(self):
|
|
231
211
|
ctnt = "LiveDefs"
|
|
232
212
|
if self.tmps:
|
|
@@ -359,6 +339,19 @@ class LiveDefinitions:
|
|
|
359
339
|
return off0 - off1
|
|
360
340
|
return None
|
|
361
341
|
|
|
342
|
+
@staticmethod
|
|
343
|
+
def _simplify_sp_alignment(data: MultiValues) -> MultiValues:
|
|
344
|
+
"""
|
|
345
|
+
Eliminate trivial stack pointer alignment, e.g.: {sp & ~0xf} -> {sp}
|
|
346
|
+
"""
|
|
347
|
+
value = data.one_value()
|
|
348
|
+
if value is not None and "stack_base" in value.variables and value.op == "__and__" and len(value.args) == 2:
|
|
349
|
+
if value.args[1].concrete and is_alignment_mask(value.args[1].concrete_value):
|
|
350
|
+
return MultiValues(value.args[0])
|
|
351
|
+
if value.args[0].concrete and is_alignment_mask(value.args[0].concrete_value):
|
|
352
|
+
return MultiValues(value.args[1])
|
|
353
|
+
return data
|
|
354
|
+
|
|
362
355
|
@staticmethod
|
|
363
356
|
def annotate_with_def(symvar: MVType, definition: Definition) -> MVType:
|
|
364
357
|
"""
|
|
@@ -521,7 +514,8 @@ class LiveDefinitions:
|
|
|
521
514
|
else:
|
|
522
515
|
l.warning("Skip stack storing since the stack offset is None.")
|
|
523
516
|
elif isinstance(atom.addr, HeapAddress):
|
|
524
|
-
|
|
517
|
+
if not isinstance(atom.addr.value, Undefined):
|
|
518
|
+
self.heap.erase(atom.addr.value, size=atom.size)
|
|
525
519
|
elif isinstance(atom.addr, int):
|
|
526
520
|
self.memory.erase(atom.addr, size=atom.size)
|
|
527
521
|
elif isinstance(atom.addr, claripy.ast.Base):
|
|
@@ -571,6 +565,11 @@ class LiveDefinitions:
|
|
|
571
565
|
|
|
572
566
|
# set_object() replaces kill (not implemented) and add (add) in one step
|
|
573
567
|
if isinstance(atom, Register):
|
|
568
|
+
|
|
569
|
+
# Tolerate simple stack pointer alignments
|
|
570
|
+
if atom.reg_offset == self.arch.sp_offset:
|
|
571
|
+
d = self._simplify_sp_alignment(d)
|
|
572
|
+
|
|
574
573
|
try:
|
|
575
574
|
self.registers.store(
|
|
576
575
|
atom.reg_offset,
|
|
@@ -611,7 +610,7 @@ class LiveDefinitions:
|
|
|
611
610
|
return None
|
|
612
611
|
elif isinstance(atom, Tmp):
|
|
613
612
|
if self.track_tmps:
|
|
614
|
-
self.tmps[atom.tmp_idx] = {
|
|
613
|
+
self.tmps[atom.tmp_idx] = {Definition(atom, code_loc, dummy=dummy, tags=tags)}
|
|
615
614
|
else:
|
|
616
615
|
self.tmps[atom.tmp_idx] = self.uses_by_codeloc[code_loc]
|
|
617
616
|
return None
|
|
@@ -686,6 +685,8 @@ class LiveDefinitions:
|
|
|
686
685
|
if isinstance(thing.addr, SpOffset):
|
|
687
686
|
return self.get_stack_definitions(thing.addr.offset, thing.size)
|
|
688
687
|
if isinstance(thing.addr, HeapAddress):
|
|
688
|
+
if isinstance(thing.addr.value, Undefined):
|
|
689
|
+
return set()
|
|
689
690
|
return self.get_heap_definitions(thing.addr.value, size=thing.size)
|
|
690
691
|
if isinstance(thing.addr, int):
|
|
691
692
|
return self.get_memory_definitions(thing.addr, thing.size)
|
|
@@ -747,72 +748,9 @@ class LiveDefinitions:
|
|
|
747
748
|
|
|
748
749
|
return LiveDefinitions.extract_defs_from_annotations(annotations)
|
|
749
750
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
for atom in atoms:
|
|
754
|
-
result |= self.get_definitions(atom)
|
|
755
|
-
return result
|
|
756
|
-
|
|
757
|
-
@deprecated("get_values")
|
|
758
|
-
def get_value_from_definition(self, definition: Definition) -> MultiValues | None:
|
|
759
|
-
return self.get_value_from_atom(definition.atom)
|
|
760
|
-
|
|
761
|
-
@deprecated("get_one_value")
|
|
762
|
-
def get_one_value_from_definition(self, definition: Definition) -> claripy.ast.bv.BV | None:
|
|
763
|
-
return self.get_one_value_from_atom(definition.atom)
|
|
764
|
-
|
|
765
|
-
@deprecated("get_concrete_value")
|
|
766
|
-
def get_concrete_value_from_definition(self, definition: Definition) -> int | None:
|
|
767
|
-
return self.get_concrete_value_from_atom(definition.atom)
|
|
768
|
-
|
|
769
|
-
@deprecated("get_values")
|
|
770
|
-
def get_value_from_atom(self, atom: Atom) -> MultiValues | None:
|
|
771
|
-
if isinstance(atom, Register):
|
|
772
|
-
try:
|
|
773
|
-
return self.registers.load(atom.reg_offset, size=atom.size)
|
|
774
|
-
except SimMemoryMissingError:
|
|
775
|
-
return None
|
|
776
|
-
elif isinstance(atom, MemoryLocation):
|
|
777
|
-
if isinstance(atom.addr, SpOffset):
|
|
778
|
-
stack_addr = self.stack_offset_to_stack_addr(atom.addr.offset)
|
|
779
|
-
try:
|
|
780
|
-
return self.stack.load(stack_addr, size=atom.size, endness=atom.endness)
|
|
781
|
-
except SimMemoryMissingError:
|
|
782
|
-
return None
|
|
783
|
-
elif isinstance(atom.addr, HeapAddress):
|
|
784
|
-
try:
|
|
785
|
-
return self.heap.load(atom.addr.value, size=atom.size, endness=atom.endness)
|
|
786
|
-
except SimMemoryMissingError:
|
|
787
|
-
return None
|
|
788
|
-
elif isinstance(atom.addr, int):
|
|
789
|
-
try:
|
|
790
|
-
return self.memory.load(atom.addr, size=atom.size, endness=atom.endness)
|
|
791
|
-
except SimMemoryMissingError:
|
|
792
|
-
return None
|
|
793
|
-
else:
|
|
794
|
-
# ignore RegisterOffset
|
|
795
|
-
return None
|
|
796
|
-
else:
|
|
797
|
-
return None
|
|
798
|
-
|
|
799
|
-
@deprecated("get_one_value")
|
|
800
|
-
def get_one_value_from_atom(self, atom: Atom) -> claripy.ast.bv.BV | None:
|
|
801
|
-
r = self.get_value_from_atom(atom)
|
|
802
|
-
if r is None:
|
|
803
|
-
return None
|
|
804
|
-
return r.one_value()
|
|
805
|
-
|
|
806
|
-
@deprecated("get_concrete_value")
|
|
807
|
-
def get_concrete_value_from_atom(self, atom: Atom) -> int | None:
|
|
808
|
-
r = self.get_one_value_from_atom(atom)
|
|
809
|
-
if r is None:
|
|
810
|
-
return None
|
|
811
|
-
if r.symbolic:
|
|
812
|
-
return None
|
|
813
|
-
return r.concrete_value
|
|
814
|
-
|
|
815
|
-
def get_values(self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]]) -> MultiValues | None:
|
|
751
|
+
def get_values(
|
|
752
|
+
self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], endness: archinfo.Endness | None = None
|
|
753
|
+
) -> MultiValues | None:
|
|
816
754
|
if isinstance(spec, Definition):
|
|
817
755
|
atom = spec.atom
|
|
818
756
|
elif isinstance(spec, Atom):
|
|
@@ -820,7 +758,7 @@ class LiveDefinitions:
|
|
|
820
758
|
else:
|
|
821
759
|
result = None
|
|
822
760
|
for atom in spec:
|
|
823
|
-
r = self.get_values(atom)
|
|
761
|
+
r = self.get_values(atom, endness)
|
|
824
762
|
if r is None:
|
|
825
763
|
continue
|
|
826
764
|
result = r if result is None else result.merge(r)
|
|
@@ -831,27 +769,29 @@ class LiveDefinitions:
|
|
|
831
769
|
return self.registers.load(atom.reg_offset, size=atom.size)
|
|
832
770
|
except SimMemoryMissingError:
|
|
833
771
|
return None
|
|
834
|
-
|
|
772
|
+
|
|
773
|
+
if isinstance(atom, MemoryLocation):
|
|
774
|
+
endness = endness or atom.endness
|
|
835
775
|
if isinstance(atom.addr, SpOffset):
|
|
836
776
|
stack_addr = self.stack_offset_to_stack_addr(atom.addr.offset)
|
|
837
777
|
try:
|
|
838
|
-
return self.stack.load(stack_addr, size=atom.size, endness=
|
|
778
|
+
return self.stack.load(stack_addr, size=atom.size, endness=endness)
|
|
839
779
|
except SimMemoryMissingError:
|
|
840
780
|
return None
|
|
841
781
|
elif isinstance(atom.addr, HeapAddress):
|
|
842
782
|
try:
|
|
843
|
-
return self.heap.load(atom.addr.value, size=atom.size, endness=
|
|
783
|
+
return self.heap.load(atom.addr.value, size=atom.size, endness=endness)
|
|
844
784
|
except SimMemoryMissingError:
|
|
845
785
|
return None
|
|
846
786
|
elif isinstance(atom.addr, int):
|
|
847
787
|
try:
|
|
848
|
-
return self.memory.load(atom.addr, size=atom.size, endness=
|
|
788
|
+
return self.memory.load(atom.addr, size=atom.size, endness=endness)
|
|
849
789
|
except SimMemoryMissingError:
|
|
850
790
|
pass
|
|
851
791
|
if self.project is not None:
|
|
852
792
|
try:
|
|
853
793
|
bytestring = self.project.loader.memory.load(atom.addr, atom.size)
|
|
854
|
-
if
|
|
794
|
+
if endness == archinfo.Endness.LE:
|
|
855
795
|
bytestring = bytes(reversed(bytestring))
|
|
856
796
|
return MultiValues(
|
|
857
797
|
self.annotate_with_def(claripy.BVV(bytestring), Definition(atom, ExternalCodeLocation()))
|
|
@@ -877,14 +817,12 @@ class LiveDefinitions:
|
|
|
877
817
|
|
|
878
818
|
@overload
|
|
879
819
|
def get_concrete_value(
|
|
880
|
-
self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], cast_to: type[int]
|
|
820
|
+
self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], cast_to: type[int]
|
|
881
821
|
) -> int | None: ...
|
|
882
822
|
|
|
883
823
|
@overload
|
|
884
824
|
def get_concrete_value(
|
|
885
|
-
self,
|
|
886
|
-
spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]],
|
|
887
|
-
cast_to: type[bytes] = ...,
|
|
825
|
+
self, spec: A | Definition[A] | Iterable[A] | Iterable[Definition[A]], cast_to: type[bytes]
|
|
888
826
|
) -> bytes | None: ...
|
|
889
827
|
|
|
890
828
|
def get_concrete_value(
|
|
@@ -991,7 +929,7 @@ class LiveDefinitions:
|
|
|
991
929
|
|
|
992
930
|
def deref(self, pointer, size, endness=archinfo.Endness.BE):
|
|
993
931
|
if isinstance(pointer, (Atom, Definition)):
|
|
994
|
-
pointer = self.get_values(pointer)
|
|
932
|
+
pointer = self.get_values(pointer, self.arch.memory_endness)
|
|
995
933
|
if pointer is None:
|
|
996
934
|
return set()
|
|
997
935
|
|
angr/sim_type.py
CHANGED
|
@@ -20,10 +20,8 @@ from .misc.ux import deprecated
|
|
|
20
20
|
|
|
21
21
|
if TYPE_CHECKING:
|
|
22
22
|
from angr.procedures.definitions import SimTypeCollection
|
|
23
|
-
from angr.storage.memory_mixins import _Coerce
|
|
24
|
-
|
|
25
|
-
StoreType = _Coerce
|
|
26
23
|
|
|
24
|
+
StoreType = int | claripy.ast.BV
|
|
27
25
|
|
|
28
26
|
l = logging.getLogger(name=__name__)
|
|
29
27
|
|
|
@@ -318,6 +316,8 @@ class SimTypeReg(SimType):
|
|
|
318
316
|
return f"reg{self.size}_t"
|
|
319
317
|
|
|
320
318
|
def store(self, state, addr, value: StoreType):
|
|
319
|
+
if self.size is None:
|
|
320
|
+
raise TypeError("Need a size to store")
|
|
321
321
|
store_endness = state.arch.memory_endness
|
|
322
322
|
with contextlib.suppress(AttributeError):
|
|
323
323
|
value = value.ast # type: ignore
|
|
@@ -366,7 +366,7 @@ class SimTypeNum(SimType):
|
|
|
366
366
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
367
367
|
|
|
368
368
|
@overload
|
|
369
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
369
|
+
def extract(self, state, addr, concrete: Literal[True]) -> int: ...
|
|
370
370
|
|
|
371
371
|
def extract(self, state, addr, concrete=False):
|
|
372
372
|
out = state.memory.load(addr, self.size // state.arch.byte_width, endness=state.arch.memory_endness)
|
|
@@ -445,7 +445,7 @@ class SimTypeInt(SimTypeReg):
|
|
|
445
445
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
446
446
|
|
|
447
447
|
@overload
|
|
448
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
448
|
+
def extract(self, state, addr, concrete: Literal[True]) -> int: ...
|
|
449
449
|
|
|
450
450
|
def extract(self, state, addr, concrete=False):
|
|
451
451
|
out = state.memory.load(addr, self.size // state.arch.byte_width, endness=state.arch.memory_endness)
|
|
@@ -575,7 +575,7 @@ class SimTypeChar(SimTypeReg):
|
|
|
575
575
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
576
576
|
|
|
577
577
|
@overload
|
|
578
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
578
|
+
def extract(self, state, addr, concrete: Literal[True]) -> bytes: ...
|
|
579
579
|
|
|
580
580
|
def extract(self, state, addr, concrete: bool = False) -> claripy.ast.BV | bytes:
|
|
581
581
|
# FIXME: This is a hack.
|
|
@@ -665,7 +665,7 @@ class SimTypeBool(SimTypeReg):
|
|
|
665
665
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.Bool: ...
|
|
666
666
|
|
|
667
667
|
@overload
|
|
668
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
668
|
+
def extract(self, state, addr, concrete: Literal[True]) -> bool: ...
|
|
669
669
|
|
|
670
670
|
def extract(self, state, addr, concrete=False):
|
|
671
671
|
ver = super().extract(state, addr, concrete)
|
|
@@ -715,7 +715,7 @@ class SimTypeFd(SimTypeReg):
|
|
|
715
715
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
716
716
|
|
|
717
717
|
@overload
|
|
718
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
718
|
+
def extract(self, state, addr, concrete: Literal[True]) -> int: ...
|
|
719
719
|
|
|
720
720
|
def extract(self, state, addr, concrete=False):
|
|
721
721
|
# TODO: EDG says this looks dangerously closed-minded. Just in case...
|
|
@@ -788,7 +788,7 @@ class SimTypePointer(SimTypeReg):
|
|
|
788
788
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
789
789
|
|
|
790
790
|
@overload
|
|
791
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
791
|
+
def extract(self, state, addr, concrete: Literal[True]) -> int: ...
|
|
792
792
|
|
|
793
793
|
def extract(self, state, addr, concrete=False):
|
|
794
794
|
# TODO: EDG says this looks dangerously closed-minded. Just in case...
|
|
@@ -848,7 +848,7 @@ class SimTypeReference(SimTypeReg):
|
|
|
848
848
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
849
849
|
|
|
850
850
|
@overload
|
|
851
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
851
|
+
def extract(self, state, addr, concrete: Literal[True]) -> int: ...
|
|
852
852
|
|
|
853
853
|
def extract(self, state, addr, concrete=False):
|
|
854
854
|
# TODO: EDG says this looks dangerously closed-minded. Just in case...
|
|
@@ -984,7 +984,7 @@ class SimTypeString(NamedTypeMixin, SimType):
|
|
|
984
984
|
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
985
985
|
|
|
986
986
|
@overload
|
|
987
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
987
|
+
def extract(self, state, addr, concrete: Literal[True]) -> bytes: ...
|
|
988
988
|
|
|
989
989
|
def extract(self, state: SimState, addr, concrete=False):
|
|
990
990
|
if self.length is None:
|
|
@@ -1585,7 +1585,7 @@ class SimStructValue:
|
|
|
1585
1585
|
for name in self._struct.fields:
|
|
1586
1586
|
value = self._values[name]
|
|
1587
1587
|
try:
|
|
1588
|
-
f = value.__indented_repr__
|
|
1588
|
+
f = value.__indented_repr__ # type: ignore[reportAttributeAccessIssue]
|
|
1589
1589
|
s = f(indent=indent + 2)
|
|
1590
1590
|
except AttributeError:
|
|
1591
1591
|
s = repr(value)
|
|
@@ -1620,7 +1620,7 @@ class SimStructValue:
|
|
|
1620
1620
|
class SimUnion(NamedTypeMixin, SimType):
|
|
1621
1621
|
fields = ("members", "name")
|
|
1622
1622
|
|
|
1623
|
-
def __init__(self, members, name=None, label=None):
|
|
1623
|
+
def __init__(self, members: dict[str, SimType], name=None, label=None):
|
|
1624
1624
|
"""
|
|
1625
1625
|
:param members: The members of the union, as a mapping name -> type
|
|
1626
1626
|
:param name: The name of the union
|
|
@@ -1630,6 +1630,8 @@ class SimUnion(NamedTypeMixin, SimType):
|
|
|
1630
1630
|
|
|
1631
1631
|
@property
|
|
1632
1632
|
def size(self):
|
|
1633
|
+
if self._arch is None:
|
|
1634
|
+
raise ValueError("Can't tell my size without an arch!")
|
|
1633
1635
|
member_sizes = [ty.size for ty in self.members.values() if not isinstance(ty, SimTypeBottom)]
|
|
1634
1636
|
# fall back to word size in case all members are SimTypeBottom
|
|
1635
1637
|
return max(member_sizes) if member_sizes else self._arch.bytes
|
|
@@ -1722,7 +1724,7 @@ class SimUnionValue:
|
|
|
1722
1724
|
fields = []
|
|
1723
1725
|
for name, value in self._values.items():
|
|
1724
1726
|
try:
|
|
1725
|
-
f = value.__indented_repr__
|
|
1727
|
+
f = value.__indented_repr__ # type: ignore[reportAttributeAccessIssue]
|
|
1726
1728
|
s = f(indent=indent + 2)
|
|
1727
1729
|
except AttributeError:
|
|
1728
1730
|
s = repr(value)
|
|
@@ -1820,7 +1822,7 @@ class SimCppClassValue(SimStructValue):
|
|
|
1820
1822
|
for name in self._class.fields:
|
|
1821
1823
|
value = self._values[name]
|
|
1822
1824
|
try:
|
|
1823
|
-
f = value.__indented_repr__
|
|
1825
|
+
f = value.__indented_repr__ # type: ignore[reportAttributeAccessIssue]
|
|
1824
1826
|
s = f(indent=indent + 2)
|
|
1825
1827
|
except AttributeError:
|
|
1826
1828
|
s = repr(value)
|
|
@@ -1864,10 +1866,10 @@ class SimTypeNumOffset(SimTypeNum):
|
|
|
1864
1866
|
self.offset = offset
|
|
1865
1867
|
|
|
1866
1868
|
@overload
|
|
1867
|
-
def extract(self, state, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
1869
|
+
def extract(self, state: SimState, addr, concrete: Literal[False] = ...) -> claripy.ast.BV: ...
|
|
1868
1870
|
|
|
1869
1871
|
@overload
|
|
1870
|
-
def extract(self, state, addr, concrete: Literal[True]
|
|
1872
|
+
def extract(self, state: SimState, addr, concrete: Literal[True]) -> int: ...
|
|
1871
1873
|
|
|
1872
1874
|
def extract(self, state: SimState, addr, concrete=False):
|
|
1873
1875
|
if state.arch.memory_endness != Endness.LE:
|
angr/state_plugins/plugin.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import cast
|
|
3
|
+
from typing import Any, Generic, cast, TypeVar, Protocol
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
|
|
5
6
|
import logging
|
|
6
7
|
|
|
@@ -9,6 +10,18 @@ from angr.misc.ux import once
|
|
|
9
10
|
|
|
10
11
|
l = logging.getLogger(name=__name__)
|
|
11
12
|
|
|
13
|
+
T = TypeVar("T")
|
|
14
|
+
S_co = TypeVar("S_co", covariant=True)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _CopyFunc(Protocol, Generic[S_co]):
|
|
18
|
+
"""
|
|
19
|
+
Function wrapping copy method for memo tracking.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def __call__(memo: dict[int, Any] | None = None) -> S_co: ...
|
|
24
|
+
|
|
12
25
|
|
|
13
26
|
class SimStatePlugin:
|
|
14
27
|
"""
|
|
@@ -55,12 +68,12 @@ class SimStatePlugin:
|
|
|
55
68
|
return o
|
|
56
69
|
|
|
57
70
|
@staticmethod
|
|
58
|
-
def memo(f):
|
|
71
|
+
def memo(f: Callable[[T, dict[int, Any]], S_co]) -> _CopyFunc[S_co]:
|
|
59
72
|
"""
|
|
60
73
|
A decorator function you should apply to ``copy``
|
|
61
74
|
"""
|
|
62
75
|
|
|
63
|
-
def inner(self, memo=None, **kwargs):
|
|
76
|
+
def inner(self, memo: dict[int, Any] | None = None, **kwargs: Any) -> S_co:
|
|
64
77
|
if memo is None:
|
|
65
78
|
memo = {}
|
|
66
79
|
if id(self) in memo:
|
|
@@ -69,7 +82,9 @@ class SimStatePlugin:
|
|
|
69
82
|
memo[id(self)] = c
|
|
70
83
|
return c
|
|
71
84
|
|
|
72
|
-
|
|
85
|
+
# Type-checking fails here because we can't express the `self` partial-application with a Protocol
|
|
86
|
+
# and we can't express the optional `memo` parameter without a Protocol
|
|
87
|
+
return inner # type: ignore
|
|
73
88
|
|
|
74
89
|
def merge(self, others, merge_conditions, common_ancestor=None): # pylint:disable=unused-argument
|
|
75
90
|
"""
|
|
@@ -80,7 +80,7 @@ class MemoryMixin(Generic[InData, OutData, Addr], SimStatePlugin):
|
|
|
80
80
|
def store(self, addr: Addr, data: InData, size: InData | None = None, **kwargs) -> None: ...
|
|
81
81
|
|
|
82
82
|
def merge(
|
|
83
|
-
self, others: list[Self], merge_conditions: list[claripy.ast.Bool], common_ancestor: Self | None = None
|
|
83
|
+
self, others: list[Self], merge_conditions: list[claripy.ast.Bool] | None, common_ancestor: Self | None = None
|
|
84
84
|
) -> bool: ...
|
|
85
85
|
|
|
86
86
|
def compare(self, other: Self) -> bool: ...
|
|
@@ -5,7 +5,6 @@ import archinfo
|
|
|
5
5
|
|
|
6
6
|
import claripy
|
|
7
7
|
|
|
8
|
-
from angr.errors import AngrTypeError
|
|
9
8
|
from angr.storage.memory_object import bv_slice
|
|
10
9
|
|
|
11
10
|
MVType = TypeVar("MVType", bound=claripy.ast.BV | claripy.ast.FP)
|
|
@@ -91,8 +90,10 @@ class MultiValues(Generic[MVType]):
|
|
|
91
90
|
value_end = offset + value.size() // 8
|
|
92
91
|
if value_end > succ_offset:
|
|
93
92
|
if isinstance(value, claripy.ast.FP):
|
|
94
|
-
|
|
93
|
+
# no precise floating point support; it directly goes to TOP
|
|
94
|
+
value = cast(MVType, claripy.BVS("top", value.size()))
|
|
95
95
|
# value is too long. we need to break value into two
|
|
96
|
+
assert isinstance(value, claripy.ast.BV)
|
|
96
97
|
mid_value_size = succ_offset - offset
|
|
97
98
|
remaining_value = cast(MVType, value[value.size() - mid_value_size * 8 - 1 : 0])
|
|
98
99
|
# update value
|
|
@@ -107,7 +108,8 @@ class MultiValues(Generic[MVType]):
|
|
|
107
108
|
remaining_values = set()
|
|
108
109
|
for v in self._values[offset]:
|
|
109
110
|
if isinstance(v, claripy.ast.FP):
|
|
110
|
-
|
|
111
|
+
# no precise floating point support; it directly goes to TOP
|
|
112
|
+
v = claripy.BVS("top", v.size())
|
|
111
113
|
|
|
112
114
|
new_curr_values.add(v[v.size() - 1 : v.size() - value.size()])
|
|
113
115
|
remaining_values.add(v[v.size() - value.size() - 1 : 0])
|
|
@@ -116,9 +118,11 @@ class MultiValues(Generic[MVType]):
|
|
|
116
118
|
self.add_value(offset + value.size() // 8, v)
|
|
117
119
|
elif curr_value_size < value.size() // 8:
|
|
118
120
|
if isinstance(value, claripy.ast.FP):
|
|
119
|
-
|
|
121
|
+
# no precise floating point support; it directly goes to TOP
|
|
122
|
+
value = cast(MVType, claripy.BVS("top", value.size()))
|
|
120
123
|
|
|
121
124
|
# value is too long. we need to break value into two
|
|
125
|
+
assert isinstance(value, claripy.ast.BV)
|
|
122
126
|
remaining_value = cast(MVType, value[value.size() - curr_value_size * 8 - 1 : 0])
|
|
123
127
|
# update value
|
|
124
128
|
value = cast(MVType, value[value.size() - 1 : value.size() - curr_value_size * 8])
|
|
@@ -137,7 +141,8 @@ class MultiValues(Generic[MVType]):
|
|
|
137
141
|
remaining_values = set()
|
|
138
142
|
for v in pre_values:
|
|
139
143
|
if isinstance(v, claripy.ast.FP):
|
|
140
|
-
|
|
144
|
+
# no precise floating point support; it directly goes to TOP
|
|
145
|
+
v = claripy.BVS("top", v.size())
|
|
141
146
|
new_pre_values.add(v[v.size() - 1 : v.size() - new_pre_value_size * 8])
|
|
142
147
|
remaining_values.add(v[v.size() - new_pre_value_size * 8 - 1 : 0])
|
|
143
148
|
self._values[pre_offset] = new_pre_values
|