angr 9.2.143__py3-none-win_amd64.whl → 9.2.145__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/calling_convention/calling_convention.py +13 -1
- angr/analyses/calling_convention/fact_collector.py +41 -5
- angr/analyses/cfg/cfg_base.py +7 -2
- angr/analyses/cfg/cfg_emulated.py +13 -4
- angr/analyses/cfg/cfg_fast.py +35 -61
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +2 -0
- angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +2 -1
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2 -101
- angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
- angr/analyses/decompiler/ail_simplifier.py +5 -0
- angr/analyses/decompiler/clinic.py +163 -69
- angr/analyses/decompiler/decompiler.py +4 -4
- angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +5 -5
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +5 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +58 -2
- angr/analyses/decompiler/peephole_optimizations/__init__.py +2 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
- angr/analyses/decompiler/ssailification/rewriting_engine.py +2 -0
- angr/analyses/decompiler/ssailification/ssailification.py +10 -2
- angr/analyses/decompiler/ssailification/traversal_engine.py +17 -2
- angr/analyses/decompiler/structured_codegen/c.py +25 -4
- angr/analyses/disassembly.py +3 -3
- angr/analyses/fcp/fcp.py +1 -4
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +21 -22
- angr/analyses/stack_pointer_tracker.py +61 -25
- angr/analyses/typehoon/dfa.py +13 -3
- angr/analyses/typehoon/typehoon.py +60 -18
- angr/analyses/typehoon/typevars.py +11 -7
- angr/analyses/variable_recovery/engine_ail.py +13 -17
- angr/analyses/variable_recovery/engine_base.py +26 -30
- angr/analyses/variable_recovery/variable_recovery_fast.py +17 -21
- angr/knowledge_plugins/functions/function.py +29 -15
- angr/knowledge_plugins/key_definitions/constants.py +2 -2
- angr/knowledge_plugins/key_definitions/liveness.py +4 -4
- angr/lib/angr_native.dll +0 -0
- angr/state_plugins/unicorn_engine.py +24 -8
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +1 -2
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +2 -2
- angr/utils/funcid.py +27 -2
- angr/utils/graph.py +26 -20
- {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/METADATA +11 -8
- {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/RECORD +49 -46
- {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/WHEEL +1 -1
- {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/LICENSE +0 -0
- {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/entry_points.txt +0 -0
- {angr-9.2.143.dist-info → angr-9.2.145.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
# pylint:disable=bad-builtin
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
|
+
from collections import defaultdict
|
|
4
5
|
|
|
5
6
|
from angr.sim_type import SimStruct, SimTypePointer, SimTypeArray
|
|
6
7
|
from angr.errors import AngrRuntimeError
|
|
7
8
|
from angr.analyses.analysis import Analysis, AnalysesHub
|
|
9
|
+
from angr.sim_variable import SimVariable, SimStackVariable
|
|
8
10
|
from .simple_solver import SimpleSolver
|
|
9
11
|
from .translator import TypeTranslator
|
|
10
12
|
from .typeconsts import Struct, Pointer, TypeConstant, Array, TopType
|
|
11
13
|
from .typevars import Equivalence, Subtype, TypeVariable
|
|
12
14
|
|
|
13
15
|
if TYPE_CHECKING:
|
|
14
|
-
from angr.sim_variable import SimVariable
|
|
15
16
|
from angr.sim_type import SimType
|
|
16
17
|
from .typevars import TypeConstraint
|
|
17
18
|
|
|
@@ -38,6 +39,7 @@ class Typehoon(Analysis):
|
|
|
38
39
|
var_mapping: dict[SimVariable, set[TypeVariable]] | None = None,
|
|
39
40
|
must_struct: set[TypeVariable] | None = None,
|
|
40
41
|
stackvar_max_sizes: dict[TypeVariable, int] | None = None,
|
|
42
|
+
stack_offset_tvs: dict[int, TypeVariable] | None = None,
|
|
41
43
|
):
|
|
42
44
|
"""
|
|
43
45
|
|
|
@@ -54,6 +56,7 @@ class Typehoon(Analysis):
|
|
|
54
56
|
self._var_mapping = var_mapping
|
|
55
57
|
self._must_struct = must_struct
|
|
56
58
|
self._stackvar_max_sizes = stackvar_max_sizes if stackvar_max_sizes is not None else {}
|
|
59
|
+
self._stack_offset_tvs = stack_offset_tvs if stack_offset_tvs is not None else {}
|
|
57
60
|
|
|
58
61
|
self.bits = self.project.arch.bits
|
|
59
62
|
self.solution = None
|
|
@@ -70,25 +73,55 @@ class Typehoon(Analysis):
|
|
|
70
73
|
# Public methods
|
|
71
74
|
#
|
|
72
75
|
|
|
73
|
-
def update_variable_types(
|
|
76
|
+
def update_variable_types(
|
|
77
|
+
self,
|
|
78
|
+
func_addr: int | str,
|
|
79
|
+
var_to_typevars: dict[SimVariable, set[TypeVariable]],
|
|
80
|
+
stack_offset_tvs: dict[int, TypeVariable] | None = None,
|
|
81
|
+
) -> None:
|
|
82
|
+
|
|
83
|
+
if not self.simtypes_solution:
|
|
84
|
+
return
|
|
85
|
+
|
|
74
86
|
for var, typevars in var_to_typevars.items():
|
|
75
|
-
|
|
87
|
+
# if the variable is a stack variable, does the stack offset have any corresponding type variable?
|
|
88
|
+
typevars_list = sorted(typevars, key=lambda tv: tv.idx)
|
|
89
|
+
if stack_offset_tvs and isinstance(var, SimStackVariable) and var.offset in stack_offset_tvs:
|
|
90
|
+
typevars_list.append(stack_offset_tvs[var.offset])
|
|
91
|
+
|
|
92
|
+
type_candidates: list[SimType] = []
|
|
93
|
+
for typevar in typevars_list:
|
|
76
94
|
type_ = self.simtypes_solution.get(typevar, None)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
# print("{} -> {}: {}".format(var, typevar, type_))
|
|
96
|
+
# Hack: if a global address is of a pointer type and it is not an array, we unpack the type
|
|
97
|
+
if (
|
|
98
|
+
func_addr == "global"
|
|
99
|
+
and isinstance(type_, SimTypePointer)
|
|
100
|
+
and not isinstance(type_.pts_to, SimTypeArray)
|
|
101
|
+
):
|
|
102
|
+
type_ = type_.pts_to
|
|
103
|
+
type_candidates.append(type_)
|
|
104
|
+
|
|
105
|
+
# determine the best type - this logic can be made better!
|
|
106
|
+
if not type_candidates:
|
|
107
|
+
continue
|
|
108
|
+
if len(type_candidates) > 1:
|
|
109
|
+
types_by_size: dict[int, list[SimType]] = defaultdict(list)
|
|
110
|
+
for t in type_candidates:
|
|
111
|
+
if t.size is not None:
|
|
112
|
+
types_by_size[t.size].append(t)
|
|
113
|
+
if not types_by_size:
|
|
114
|
+
# we only have BOT and TOP? damn
|
|
115
|
+
the_type = type_candidates[0]
|
|
116
|
+
else:
|
|
117
|
+
max_size = max(types_by_size.keys())
|
|
118
|
+
the_type = types_by_size[max_size][0] # TODO: Sort it
|
|
119
|
+
else:
|
|
120
|
+
the_type = type_candidates[0]
|
|
121
|
+
|
|
122
|
+
self.kb.variables[func_addr].set_variable_type(
|
|
123
|
+
var, the_type, name=the_type.name if isinstance(the_type, SimStruct) else None
|
|
124
|
+
)
|
|
92
125
|
|
|
93
126
|
def pp_constraints(self) -> None:
|
|
94
127
|
"""
|
|
@@ -131,6 +164,8 @@ class Typehoon(Analysis):
|
|
|
131
164
|
sol = self.solution[typevar]
|
|
132
165
|
var_and_typevar = f"{typevar_to_var[typevar]} ({typevar})" if typevar in typevar_to_var else typevar
|
|
133
166
|
print(f" {var_and_typevar} -> {sol}")
|
|
167
|
+
for stack_off, tv in self._stack_offset_tvs.items():
|
|
168
|
+
print(f" stack_{stack_off:#x} ({tv}) -> {self.solution[tv]}")
|
|
134
169
|
print("### end of solutions ###")
|
|
135
170
|
|
|
136
171
|
#
|
|
@@ -157,6 +192,7 @@ class Typehoon(Analysis):
|
|
|
157
192
|
if self._var_mapping:
|
|
158
193
|
for variable_typevars in self._var_mapping.values():
|
|
159
194
|
typevars |= variable_typevars
|
|
195
|
+
typevars |= set(self._stack_offset_tvs.values())
|
|
160
196
|
else:
|
|
161
197
|
# collect type variables from constraints
|
|
162
198
|
for constraint in self._constraints[self.func_var]:
|
|
@@ -175,6 +211,9 @@ class Typehoon(Analysis):
|
|
|
175
211
|
- structs where every element is of the same type will be converted to an array of that element type.
|
|
176
212
|
"""
|
|
177
213
|
|
|
214
|
+
if not self.solution:
|
|
215
|
+
return
|
|
216
|
+
|
|
178
217
|
for tv in list(self.solution.keys()):
|
|
179
218
|
if self._must_struct and tv in self._must_struct:
|
|
180
219
|
continue
|
|
@@ -223,6 +262,9 @@ class Typehoon(Analysis):
|
|
|
223
262
|
Translate solutions in type variables to solutions in SimTypes.
|
|
224
263
|
"""
|
|
225
264
|
|
|
265
|
+
if not self.solution:
|
|
266
|
+
return
|
|
267
|
+
|
|
226
268
|
simtypes_solution = {}
|
|
227
269
|
translator = TypeTranslator(arch=self.project.arch)
|
|
228
270
|
needs_backpatch = set()
|
|
@@ -397,11 +397,13 @@ class DerivedTypeVariable(TypeVariable):
|
|
|
397
397
|
class TypeVariables:
|
|
398
398
|
__slots__ = (
|
|
399
399
|
"_last_typevars",
|
|
400
|
+
"_typevar2var",
|
|
400
401
|
"_typevars",
|
|
401
402
|
)
|
|
402
403
|
|
|
403
404
|
def __init__(self):
|
|
404
405
|
self._typevars: dict[SimVariable, set[TypeVariable]] = {}
|
|
406
|
+
self._typevar2var: dict[TypeVariable, SimVariable] = {}
|
|
405
407
|
self._last_typevars: dict[SimVariable, TypeVariable] = {}
|
|
406
408
|
|
|
407
409
|
def copy(self):
|
|
@@ -418,22 +420,24 @@ class TypeVariables:
|
|
|
418
420
|
# )
|
|
419
421
|
return f"{{TypeVars: {len(self._typevars)} items}}"
|
|
420
422
|
|
|
421
|
-
def add_type_variable(self, var: SimVariable,
|
|
423
|
+
def add_type_variable(self, var: SimVariable, typevar: TypeVariable, latest: bool = True):
|
|
422
424
|
if var not in self._typevars:
|
|
423
425
|
self._typevars[var] = set()
|
|
424
426
|
elif typevar in self._typevars[var]:
|
|
425
427
|
return
|
|
426
428
|
self._typevars[var].add(typevar)
|
|
427
|
-
|
|
429
|
+
if latest:
|
|
430
|
+
self._last_typevars[var] = typevar
|
|
431
|
+
self._typevar2var[typevar] = var
|
|
428
432
|
|
|
429
|
-
def get_type_variable(self, var
|
|
433
|
+
def get_type_variable(self, var): # pylint:disable=unused-argument
|
|
430
434
|
return self._last_typevars[var]
|
|
431
435
|
|
|
432
|
-
def has_type_variable_for(self, var: SimVariable
|
|
436
|
+
def has_type_variable_for(self, var: SimVariable): # pylint:disable=unused-argument
|
|
433
437
|
return var in self._typevars
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
438
|
+
|
|
439
|
+
def typevar_to_variable(self, typevar: TypeVariable) -> SimVariable | None:
|
|
440
|
+
return self._typevar2var.get(typevar, None)
|
|
437
441
|
|
|
438
442
|
def __getitem__(self, var):
|
|
439
443
|
return self._last_typevars[var]
|
|
@@ -9,14 +9,13 @@ from unique_log_filter import UniqueLogFilter
|
|
|
9
9
|
|
|
10
10
|
from angr.engines.light.engine import SimEngineNostmtAIL
|
|
11
11
|
from angr.procedures import SIM_LIBRARIES, SIM_TYPE_COLLECTIONS
|
|
12
|
-
from angr.utils.constants import MAX_POINTSTO_BITS
|
|
13
12
|
from angr.sim_type import SimTypeFunction, dereference_simtype
|
|
14
13
|
from angr.analyses.typehoon import typeconsts, typevars
|
|
15
14
|
from angr.analyses.typehoon.lifter import TypeLifter
|
|
16
15
|
from .engine_base import SimEngineVRBase, RichR
|
|
17
16
|
|
|
18
17
|
if TYPE_CHECKING:
|
|
19
|
-
|
|
18
|
+
from .variable_recovery_fast import VariableRecoveryFastState # noqa: F401
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
l = logging.getLogger(name=__name__)
|
|
@@ -272,6 +271,8 @@ class SimEngineVRAIL(
|
|
|
272
271
|
if arg.typevar is not None:
|
|
273
272
|
arg_type = dereference_simtype(arg_type, type_collections).with_arch(arg_type._arch)
|
|
274
273
|
arg_ty = TypeLifter(self.arch.bits).lift(arg_type)
|
|
274
|
+
if isinstance(arg_ty, typevars.TypeConstraint) and isinstance(arg.typevar, typevars.TypeConstraint):
|
|
275
|
+
continue
|
|
275
276
|
type_constraint = typevars.Subtype(arg.typevar, arg_ty)
|
|
276
277
|
self.state.add_type_constraint(type_constraint)
|
|
277
278
|
|
|
@@ -399,28 +400,23 @@ class SimEngineVRAIL(
|
|
|
399
400
|
return RichR(self.state.top(expr.to_bits), typevar=typevar)
|
|
400
401
|
|
|
401
402
|
def _handle_expr_StackBaseOffset(self, expr: ailment.Expr.StackBaseOffset):
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
if ref_typevar is None:
|
|
403
|
+
refbase_typevar = self.state.stack_offset_typevars.get(expr.offset, None)
|
|
404
|
+
if refbase_typevar is None:
|
|
405
405
|
# allocate a new type variable
|
|
406
|
-
|
|
407
|
-
self.state.stack_offset_typevars[expr.offset] =
|
|
406
|
+
refbase_typevar = typevars.TypeVariable()
|
|
407
|
+
self.state.stack_offset_typevars[expr.offset] = refbase_typevar
|
|
408
|
+
|
|
409
|
+
ref_typevar = typevars.TypeVariable()
|
|
410
|
+
access_derived_typevar = self._create_access_typevar(ref_typevar, False, None, 0)
|
|
411
|
+
load_constraint = typevars.Subtype(refbase_typevar, access_derived_typevar)
|
|
412
|
+
self.state.add_type_constraint(load_constraint)
|
|
408
413
|
|
|
409
414
|
value_v = self.state.stack_address(expr.offset)
|
|
410
415
|
richr = RichR(value_v, typevar=ref_typevar)
|
|
411
416
|
codeloc = self._codeloc()
|
|
412
|
-
|
|
417
|
+
self._ensure_variable_existence(richr, codeloc, src_expr=expr)
|
|
413
418
|
if self._reference_spoffset:
|
|
414
419
|
self._reference(richr, codeloc, src=expr)
|
|
415
|
-
for var, off_in_var in var_and_offsets:
|
|
416
|
-
if self.state.typevars.has_type_variable_for(var, codeloc):
|
|
417
|
-
var_typevar = self.state.typevars.get_type_variable(var, codeloc)
|
|
418
|
-
load_typevar = self._create_access_typevar(
|
|
419
|
-
ref_typevar, False, MAX_POINTSTO_BITS // 8, 0 if off_in_var is None else off_in_var
|
|
420
|
-
)
|
|
421
|
-
type_constraint = typevars.Subtype(var_typevar, load_typevar)
|
|
422
|
-
self.state.add_type_constraint(type_constraint)
|
|
423
|
-
|
|
424
420
|
return richr
|
|
425
421
|
|
|
426
422
|
def _handle_expr_BasePointerOffset(self, expr):
|
|
@@ -15,7 +15,7 @@ from angr.sim_variable import SimVariable, SimStackVariable, SimRegisterVariable
|
|
|
15
15
|
from angr.code_location import CodeLocation
|
|
16
16
|
from angr.analyses.typehoon import typevars, typeconsts
|
|
17
17
|
from angr.analyses.typehoon.typevars import TypeVariable, DerivedTypeVariable, AddN, SubN, Load, Store
|
|
18
|
-
|
|
18
|
+
from angr.utils.constants import MAX_POINTSTO_BITS
|
|
19
19
|
|
|
20
20
|
#
|
|
21
21
|
# The base engine used in VariableRecoveryFast
|
|
@@ -269,9 +269,9 @@ class SimEngineVRBase(
|
|
|
269
269
|
return
|
|
270
270
|
variable, _ = existing_vars[0]
|
|
271
271
|
|
|
272
|
-
if not self.state.typevars.has_type_variable_for(variable
|
|
272
|
+
if not self.state.typevars.has_type_variable_for(variable):
|
|
273
273
|
variable_typevar = typevars.TypeVariable()
|
|
274
|
-
self.state.typevars.add_type_variable(variable,
|
|
274
|
+
self.state.typevars.add_type_variable(variable, variable_typevar)
|
|
275
275
|
# we do not add any type constraint here because we are not sure if the given memory address will ever be
|
|
276
276
|
# accessed or not
|
|
277
277
|
|
|
@@ -350,13 +350,13 @@ class SimEngineVRBase(
|
|
|
350
350
|
self.state.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
|
|
351
351
|
|
|
352
352
|
if richr.typevar is not None:
|
|
353
|
-
if not self.state.typevars.has_type_variable_for(variable
|
|
353
|
+
if not self.state.typevars.has_type_variable_for(variable):
|
|
354
354
|
# assign a new type variable to it
|
|
355
355
|
typevar = typevars.TypeVariable()
|
|
356
|
-
self.state.typevars.add_type_variable(variable,
|
|
356
|
+
self.state.typevars.add_type_variable(variable, typevar)
|
|
357
357
|
# create constraints
|
|
358
358
|
else:
|
|
359
|
-
typevar = self.state.typevars.get_type_variable(variable
|
|
359
|
+
typevar = self.state.typevars.get_type_variable(variable)
|
|
360
360
|
self.state.add_type_constraint(typevars.Subtype(richr.typevar, typevar))
|
|
361
361
|
self.state.add_type_constraint(typevars.Subtype(typevar, typeconsts.int_type(variable.size * 8)))
|
|
362
362
|
|
|
@@ -448,13 +448,13 @@ class SimEngineVRBase(
|
|
|
448
448
|
self.state.variable_manager[self.func_addr].write_to(variable, None, codeloc, atom=dst, overwrite=False)
|
|
449
449
|
|
|
450
450
|
if richr.typevar is not None:
|
|
451
|
-
if not self.state.typevars.has_type_variable_for(variable
|
|
451
|
+
if not self.state.typevars.has_type_variable_for(variable):
|
|
452
452
|
# assign a new type variable to it
|
|
453
453
|
typevar = typevars.TypeVariable()
|
|
454
|
-
self.state.typevars.add_type_variable(variable,
|
|
454
|
+
self.state.typevars.add_type_variable(variable, typevar)
|
|
455
455
|
# create constraints
|
|
456
456
|
else:
|
|
457
|
-
typevar = self.state.typevars.get_type_variable(variable
|
|
457
|
+
typevar = self.state.typevars.get_type_variable(variable)
|
|
458
458
|
self.state.add_type_constraint(typevars.Subtype(richr.typevar, typevar))
|
|
459
459
|
# the constraint below is a default constraint that may conflict with more specific ones with different
|
|
460
460
|
# sizes; we post-process at the very end of VRA to remove conflicting default constraints.
|
|
@@ -564,11 +564,11 @@ class SimEngineVRBase(
|
|
|
564
564
|
|
|
565
565
|
# create type constraints
|
|
566
566
|
if data.typevar is not None:
|
|
567
|
-
if not self.state.typevars.has_type_variable_for(variable
|
|
567
|
+
if not self.state.typevars.has_type_variable_for(variable):
|
|
568
568
|
typevar = typevars.TypeVariable()
|
|
569
|
-
self.state.typevars.add_type_variable(variable,
|
|
569
|
+
self.state.typevars.add_type_variable(variable, typevar)
|
|
570
570
|
else:
|
|
571
|
-
typevar = self.state.typevars.get_type_variable(variable
|
|
571
|
+
typevar = self.state.typevars.get_type_variable(variable)
|
|
572
572
|
if typevar is not None:
|
|
573
573
|
self.state.add_type_constraint(typevars.Subtype(data.typevar, typevar))
|
|
574
574
|
# TODO: Create a tv_sp.store.<bits>@N <: typevar type constraint for the stack pointer
|
|
@@ -640,11 +640,11 @@ class SimEngineVRBase(
|
|
|
640
640
|
variable_manager.write_to(var, var_offset, codeloc, atom=stmt)
|
|
641
641
|
|
|
642
642
|
# create type constraints
|
|
643
|
-
if not self.state.typevars.has_type_variable_for(variable
|
|
643
|
+
if not self.state.typevars.has_type_variable_for(variable):
|
|
644
644
|
typevar = typevars.TypeVariable()
|
|
645
|
-
self.state.typevars.add_type_variable(variable,
|
|
645
|
+
self.state.typevars.add_type_variable(variable, typevar)
|
|
646
646
|
else:
|
|
647
|
-
typevar = self.state.typevars.get_type_variable(variable
|
|
647
|
+
typevar = self.state.typevars.get_type_variable(variable)
|
|
648
648
|
|
|
649
649
|
if offset is not None and elem_size is not None:
|
|
650
650
|
# it's an array!
|
|
@@ -671,9 +671,6 @@ class SimEngineVRBase(
|
|
|
671
671
|
self.state.add_type_constraint(typevars.Subtype(data.typevar, store_typevar))
|
|
672
672
|
|
|
673
673
|
def _store_to_variable(self, richr_addr: RichR[claripy.ast.BV], data: RichR, size: int):
|
|
674
|
-
addr_variable = richr_addr.variable
|
|
675
|
-
codeloc = self._codeloc()
|
|
676
|
-
|
|
677
674
|
# Storing data into a pointer
|
|
678
675
|
if richr_addr.type_constraints:
|
|
679
676
|
for tc in richr_addr.type_constraints:
|
|
@@ -690,8 +687,6 @@ class SimEngineVRBase(
|
|
|
690
687
|
field_offset = 0
|
|
691
688
|
|
|
692
689
|
store_typevar = self._create_access_typevar(base_typevar, True, size, field_offset)
|
|
693
|
-
if addr_variable is not None:
|
|
694
|
-
self.state.typevars.add_type_variable(addr_variable, codeloc, typevar)
|
|
695
690
|
data_typevar = data.typevar if data.typevar is not None else typeconsts.TopType()
|
|
696
691
|
self.state.add_type_constraint(typevars.Subtype(store_typevar, data_typevar))
|
|
697
692
|
|
|
@@ -823,11 +818,11 @@ class SimEngineVRBase(
|
|
|
823
818
|
self.state.delayed_type_constraints.pop(var)
|
|
824
819
|
|
|
825
820
|
# create type constraints
|
|
826
|
-
if not self.state.typevars.has_type_variable_for(var
|
|
821
|
+
if not self.state.typevars.has_type_variable_for(var):
|
|
827
822
|
typevar = typevars.TypeVariable()
|
|
828
|
-
self.state.typevars.add_type_variable(var,
|
|
823
|
+
self.state.typevars.add_type_variable(var, typevar)
|
|
829
824
|
else:
|
|
830
|
-
typevar = self.state.typevars.get_type_variable(var
|
|
825
|
+
typevar = self.state.typevars.get_type_variable(var)
|
|
831
826
|
|
|
832
827
|
else:
|
|
833
828
|
typevar = typevars.TypeVariable()
|
|
@@ -933,11 +928,11 @@ class SimEngineVRBase(
|
|
|
933
928
|
|
|
934
929
|
variable, _ = next(iter(existing_vars))
|
|
935
930
|
# create type constraints
|
|
936
|
-
if not self.state.typevars.has_type_variable_for(variable
|
|
931
|
+
if not self.state.typevars.has_type_variable_for(variable):
|
|
937
932
|
typevar = typevars.TypeVariable()
|
|
938
|
-
self.state.typevars.add_type_variable(variable,
|
|
933
|
+
self.state.typevars.add_type_variable(variable, typevar)
|
|
939
934
|
else:
|
|
940
|
-
typevar = self.state.typevars.get_type_variable(variable
|
|
935
|
+
typevar = self.state.typevars.get_type_variable(variable)
|
|
941
936
|
|
|
942
937
|
if offset is not None and elem_size is not None:
|
|
943
938
|
# it's an array!
|
|
@@ -1024,7 +1019,7 @@ class SimEngineVRBase(
|
|
|
1024
1019
|
|
|
1025
1020
|
if var not in self.state.typevars:
|
|
1026
1021
|
typevar = typevars.TypeVariable()
|
|
1027
|
-
self.state.typevars.add_type_variable(var,
|
|
1022
|
+
self.state.typevars.add_type_variable(var, typevar)
|
|
1028
1023
|
else:
|
|
1029
1024
|
# FIXME: This is an extremely stupid hack. Fix it later.
|
|
1030
1025
|
# | typevar = next(reversed(list(self.state.typevars[var].values())))
|
|
@@ -1125,7 +1120,7 @@ class SimEngineVRBase(
|
|
|
1125
1120
|
|
|
1126
1121
|
if var not in self.state.typevars:
|
|
1127
1122
|
typevar = typevars.TypeVariable()
|
|
1128
|
-
self.state.typevars.add_type_variable(var,
|
|
1123
|
+
self.state.typevars.add_type_variable(var, typevar)
|
|
1129
1124
|
else:
|
|
1130
1125
|
# FIXME: This is an extremely stupid hack. Fix it later.
|
|
1131
1126
|
# | typevar = next(reversed(list(self.state.typevars[var].values())))
|
|
@@ -1140,7 +1135,7 @@ class SimEngineVRBase(
|
|
|
1140
1135
|
self,
|
|
1141
1136
|
typevar: typeconsts.TypeConstant | TypeVariable | DerivedTypeVariable,
|
|
1142
1137
|
is_store: bool,
|
|
1143
|
-
size: int,
|
|
1138
|
+
size: int | None,
|
|
1144
1139
|
offset: int,
|
|
1145
1140
|
) -> DerivedTypeVariable:
|
|
1146
1141
|
if isinstance(typevar, DerivedTypeVariable):
|
|
@@ -1157,8 +1152,9 @@ class SimEngineVRBase(
|
|
|
1157
1152
|
else:
|
|
1158
1153
|
typevar = DerivedTypeVariable(typevar.type_var, None, labels=typevar.labels[:-1])
|
|
1159
1154
|
lbl = Store() if is_store else Load()
|
|
1155
|
+
bits = size * self.project.arch.byte_width if size is not None else MAX_POINTSTO_BITS
|
|
1160
1156
|
return DerivedTypeVariable(
|
|
1161
1157
|
typevar,
|
|
1162
1158
|
None,
|
|
1163
|
-
labels=(lbl, typevars.HasField(
|
|
1159
|
+
labels=(lbl, typevars.HasField(bits, offset)),
|
|
1164
1160
|
)
|
|
@@ -47,6 +47,7 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
|
|
|
47
47
|
analysis,
|
|
48
48
|
arch,
|
|
49
49
|
func,
|
|
50
|
+
project,
|
|
50
51
|
stack_region=None,
|
|
51
52
|
register_region=None,
|
|
52
53
|
global_region=None,
|
|
@@ -55,7 +56,6 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
|
|
|
55
56
|
func_typevar=None,
|
|
56
57
|
delayed_type_constraints=None,
|
|
57
58
|
stack_offset_typevars=None,
|
|
58
|
-
project=None,
|
|
59
59
|
ret_val_size=None,
|
|
60
60
|
):
|
|
61
61
|
super().__init__(
|
|
@@ -63,6 +63,7 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
|
|
|
63
63
|
analysis,
|
|
64
64
|
arch,
|
|
65
65
|
func,
|
|
66
|
+
project,
|
|
66
67
|
stack_region=stack_region,
|
|
67
68
|
register_region=register_region,
|
|
68
69
|
global_region=global_region,
|
|
@@ -71,12 +72,11 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
|
|
|
71
72
|
func_typevar=func_typevar,
|
|
72
73
|
delayed_type_constraints=delayed_type_constraints,
|
|
73
74
|
stack_offset_typevars=stack_offset_typevars,
|
|
74
|
-
project=project,
|
|
75
75
|
)
|
|
76
76
|
self.ret_val_size = ret_val_size
|
|
77
77
|
|
|
78
78
|
def __repr__(self):
|
|
79
|
-
return f"<VRAbstractState@{self.block_addr:#x}
|
|
79
|
+
return f"<VRAbstractState@{self.block_addr:#x}"
|
|
80
80
|
|
|
81
81
|
def __eq__(self, other):
|
|
82
82
|
if type(other) is not VariableRecoveryFastState:
|
|
@@ -96,12 +96,14 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
|
|
|
96
96
|
type_constraints=self.type_constraints,
|
|
97
97
|
func_typevar=self.func_typevar,
|
|
98
98
|
delayed_type_constraints=self.delayed_type_constraints,
|
|
99
|
-
stack_offset_typevars=
|
|
99
|
+
stack_offset_typevars=self.stack_offset_typevars,
|
|
100
100
|
project=self.project,
|
|
101
101
|
ret_val_size=self.ret_val_size,
|
|
102
102
|
)
|
|
103
103
|
|
|
104
|
-
def merge(
|
|
104
|
+
def merge(
|
|
105
|
+
self, others: tuple[VariableRecoveryFastState, ...], successor=None
|
|
106
|
+
) -> tuple[VariableRecoveryFastState, bool]:
|
|
105
107
|
"""
|
|
106
108
|
Merge two abstract states.
|
|
107
109
|
|
|
@@ -135,10 +137,10 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
|
|
|
135
137
|
# add subtype constraints for all replacements
|
|
136
138
|
for v0, v1 in self.phi_variables.items():
|
|
137
139
|
# v0 will be replaced by v1
|
|
138
|
-
if not typevars.has_type_variable_for(v1
|
|
139
|
-
typevars.add_type_variable(v1,
|
|
140
|
-
if not typevars.has_type_variable_for(v0
|
|
141
|
-
typevars.add_type_variable(v0,
|
|
140
|
+
if not typevars.has_type_variable_for(v1):
|
|
141
|
+
typevars.add_type_variable(v1, TypeVariable())
|
|
142
|
+
if not typevars.has_type_variable_for(v0):
|
|
143
|
+
typevars.add_type_variable(v0, TypeVariable())
|
|
142
144
|
# Assuming v2 = phi(v0, v1), then we know that v0_typevar == v1_typevar == v2_typevar
|
|
143
145
|
# However, it's possible that neither v0 nor v1 will ever be used in future blocks, which not only makes
|
|
144
146
|
# this phi function useless, but also leads to the incorrect assumption that v1_typevar == v2_typevar.
|
|
@@ -146,7 +148,7 @@ class VariableRecoveryFastState(VariableRecoveryStateBase):
|
|
|
146
148
|
# when v1 (the new variable that will end up in the state) is ever used in the future.
|
|
147
149
|
|
|
148
150
|
# create an equivalence relationship
|
|
149
|
-
equivalence = Equivalence(typevars.get_type_variable(v1
|
|
151
|
+
equivalence = Equivalence(typevars.get_type_variable(v1), typevars.get_type_variable(v0))
|
|
150
152
|
delayed_typeconstraints[v1].add(equivalence)
|
|
151
153
|
|
|
152
154
|
stack_offset_typevars = {}
|
|
@@ -281,6 +283,7 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
|
|
|
281
283
|
self.func_typevar = TypeVariable(name=func.name)
|
|
282
284
|
self.delayed_type_constraints = None
|
|
283
285
|
self.ret_val_size = None
|
|
286
|
+
self.stack_offset_typevars: dict[int, TypeVariable] = {}
|
|
284
287
|
|
|
285
288
|
self._analyze()
|
|
286
289
|
|
|
@@ -328,6 +331,7 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
|
|
|
328
331
|
type_constraints=self.type_constraints,
|
|
329
332
|
func_typevar=self.func_typevar,
|
|
330
333
|
delayed_type_constraints=self.delayed_type_constraints,
|
|
334
|
+
stack_offset_typevars=self.stack_offset_typevars,
|
|
331
335
|
)
|
|
332
336
|
initial_sp = state.stack_address(self.project.arch.bytes if self.project.arch.call_pushes_ret else 0)
|
|
333
337
|
if self.project.arch.sp_offset is not None:
|
|
@@ -439,20 +443,10 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
|
|
|
439
443
|
block = self.project.factory.block(node.addr, node.size, opt_level=1, cross_insn_opt=False)
|
|
440
444
|
block_key = node.addr
|
|
441
445
|
|
|
442
|
-
# if node.addr in self._instates:
|
|
443
|
-
# prev_state: VariableRecoveryFastState = self._instates[node.addr]
|
|
444
|
-
# if input_state == prev_state:
|
|
445
|
-
# l.debug('Skip node %#x as we have reached a fixed-point', node.addr)
|
|
446
|
-
# return False, input_state
|
|
447
|
-
# else:
|
|
448
|
-
# l.debug('Merging input state of node %#x with the previous state.', node.addr)
|
|
449
|
-
# input_state, _ = prev_state.merge((input_state,), successor=node.addr)
|
|
450
|
-
|
|
451
446
|
state = state.copy()
|
|
452
447
|
state.block_addr = node.addr
|
|
453
448
|
if isinstance(node, ailment.Block):
|
|
454
449
|
state.block_idx = node.idx
|
|
455
|
-
# self._instates[node.addr] = state
|
|
456
450
|
|
|
457
451
|
if self._node_iterations[block_key] >= self._max_iterations:
|
|
458
452
|
l.debug("Skip node %#x as we have iterated %d times on it.", node.addr, self._node_iterations[node.addr])
|
|
@@ -491,10 +485,12 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
|
|
|
491
485
|
self.variable_manager[self.function.addr].unify_variables()
|
|
492
486
|
|
|
493
487
|
# fill in var_to_typevars
|
|
488
|
+
assert self.typevars is not None
|
|
494
489
|
for var, typevar_set in self.typevars._typevars.items():
|
|
495
490
|
self.var_to_typevars[var] = typevar_set
|
|
496
491
|
|
|
497
492
|
# unify type variables for global variables
|
|
493
|
+
assert self.type_constraints is not None
|
|
498
494
|
for var, typevars in self.var_to_typevars.items():
|
|
499
495
|
if len(typevars) > 1 and isinstance(var, SimMemoryVariable) and not isinstance(var, SimStackVariable):
|
|
500
496
|
sorted_typevars = sorted(typevars, key=lambda x: str(x)) # pylint:disable=unnecessary-lambda
|
|
@@ -600,7 +596,7 @@ class VariableRecoveryFast(ForwardAnalysis, VariableRecoveryBase): # pylint:dis
|
|
|
600
596
|
block = self._peephole_optimize(block)
|
|
601
597
|
|
|
602
598
|
processor = self._ail_engine if isinstance(block, ailment.Block) else self._vex_engine
|
|
603
|
-
processor.process(state, block=block, fail_fast=self._fail_fast)
|
|
599
|
+
processor.process(state, block=block, fail_fast=self._fail_fast) # type: ignore
|
|
604
600
|
|
|
605
601
|
if self._track_sp and block.addr in self._node_to_cc:
|
|
606
602
|
# readjusting sp at the end for blocks that end in a call
|
|
@@ -237,21 +237,7 @@ class Function(Serializable):
|
|
|
237
237
|
|
|
238
238
|
self._returning = self._get_initial_returning()
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
# If it is a SimProcedure it might have a CC already defined which can be used
|
|
242
|
-
if self.is_simprocedure and self.project is not None and self.addr in self.project._sim_procedures:
|
|
243
|
-
simproc = self.project._sim_procedures[self.addr]
|
|
244
|
-
cc = simproc.cc
|
|
245
|
-
if cc is None:
|
|
246
|
-
arch = self.project.arch
|
|
247
|
-
if self.project.arch.name in DEFAULT_CC:
|
|
248
|
-
cc = default_cc(
|
|
249
|
-
arch.name, platform=self.project.simos.name if self.project.simos is not None else None
|
|
250
|
-
)(arch)
|
|
251
|
-
|
|
252
|
-
self.calling_convention: SimCC | None = cc
|
|
253
|
-
else:
|
|
254
|
-
self.calling_convention: SimCC | None = None
|
|
240
|
+
self._init_prototype_and_calling_convention()
|
|
255
241
|
|
|
256
242
|
@property
|
|
257
243
|
@deprecated(".is_alignment")
|
|
@@ -768,6 +754,34 @@ class Function(Serializable):
|
|
|
768
754
|
# Cannot determine
|
|
769
755
|
return None
|
|
770
756
|
|
|
757
|
+
def _init_prototype_and_calling_convention(self) -> None:
|
|
758
|
+
"""
|
|
759
|
+
Initialize prototype and calling convention from a SimProcedure, if available.
|
|
760
|
+
"""
|
|
761
|
+
hooker = None
|
|
762
|
+
if self.is_syscall and self.project is not None and self.project.simos.is_syscall_addr(self.addr):
|
|
763
|
+
hooker = self.project.simos.syscall_from_addr(self.addr)
|
|
764
|
+
elif self.is_simprocedure and self.project is not None:
|
|
765
|
+
hooker = self.project.hooked_by(self.addr)
|
|
766
|
+
if hooker is None or hooker.guessed_prototype:
|
|
767
|
+
return
|
|
768
|
+
|
|
769
|
+
if hooker.prototype:
|
|
770
|
+
self.prototype_libname = hooker.library_name
|
|
771
|
+
self.prototype = hooker.prototype
|
|
772
|
+
self.is_prototype_guessed = False
|
|
773
|
+
|
|
774
|
+
cc = hooker.cc
|
|
775
|
+
if cc is None and self.project is not None:
|
|
776
|
+
arch = self.project.arch
|
|
777
|
+
if arch.name in DEFAULT_CC:
|
|
778
|
+
cc_cls = default_cc(
|
|
779
|
+
arch.name, platform=self.project.simos.name if self.project.simos is not None else None
|
|
780
|
+
)
|
|
781
|
+
if cc_cls is not None:
|
|
782
|
+
cc = cc_cls(arch)
|
|
783
|
+
self.calling_convention = cc
|
|
784
|
+
|
|
771
785
|
def _clear_transition_graph(self):
|
|
772
786
|
self._block_sizes = {}
|
|
773
787
|
self._addr_to_block_node = {}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import Literal
|
|
2
|
+
from typing import Literal
|
|
3
3
|
import enum
|
|
4
4
|
|
|
5
5
|
DEBUG = False
|
|
@@ -25,5 +25,5 @@ OP_BEFORE = ObservationPointType.OP_BEFORE
|
|
|
25
25
|
OP_AFTER = ObservationPointType.OP_AFTER
|
|
26
26
|
|
|
27
27
|
ObservationPoint = tuple[
|
|
28
|
-
Literal["insn", "node", "stmt", "exit"],
|
|
28
|
+
Literal["insn", "node", "stmt", "exit"], int | tuple[int, int] | tuple[int, int, int], ObservationPointType
|
|
29
29
|
]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
from itertools import chain
|
|
@@ -14,11 +14,11 @@ if TYPE_CHECKING:
|
|
|
14
14
|
from angr.code_location import CodeLocation
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
LocationType = tuple[int,
|
|
17
|
+
LocationType = tuple[int, int | None, int | None] # block addr, block ID, stmt ID
|
|
18
18
|
LocationWithPosType = tuple[
|
|
19
|
-
int,
|
|
19
|
+
int, int | None, int | None, ObservationPointType
|
|
20
20
|
] # block addr, block ID, stmt ID, before/after
|
|
21
|
-
BlockAddrType = tuple[int,
|
|
21
|
+
BlockAddrType = tuple[int, int | None] # block addr, block ID
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class Liveness:
|
angr/lib/angr_native.dll
CHANGED
|
Binary file
|