angr 9.2.138__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/calling_convention/fact_collector.py +59 -12
- angr/analyses/calling_convention/utils.py +2 -2
- angr/analyses/cfg/cfg_base.py +13 -0
- angr/analyses/cfg/cfg_fast.py +23 -4
- angr/analyses/decompiler/ail_simplifier.py +79 -53
- angr/analyses/decompiler/block_simplifier.py +0 -2
- angr/analyses/decompiler/callsite_maker.py +80 -14
- angr/analyses/decompiler/clinic.py +99 -80
- angr/analyses/decompiler/condition_processor.py +2 -2
- angr/analyses/decompiler/decompiler.py +19 -7
- angr/analyses/decompiler/dephication/rewriting_engine.py +16 -7
- angr/analyses/decompiler/expression_narrower.py +1 -1
- angr/analyses/decompiler/optimization_passes/__init__.py +3 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +149 -0
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +12 -3
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +21 -12
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +17 -9
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +7 -10
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +12 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +61 -25
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +50 -1
- angr/analyses/decompiler/presets/fast.py +2 -0
- angr/analyses/decompiler/presets/full.py +2 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +259 -108
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +28 -9
- angr/analyses/decompiler/ssailification/rewriting_engine.py +20 -2
- angr/analyses/decompiler/ssailification/traversal_engine.py +4 -3
- angr/analyses/decompiler/structured_codegen/c.py +10 -3
- angr/analyses/decompiler/structuring/dream.py +28 -19
- angr/analyses/decompiler/structuring/phoenix.py +253 -89
- angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
- angr/analyses/decompiler/structuring/structurer_base.py +121 -46
- angr/analyses/decompiler/structuring/structurer_nodes.py +6 -1
- angr/analyses/decompiler/utils.py +60 -1
- angr/analyses/deobfuscator/api_obf_finder.py +13 -5
- angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
- 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 +129 -87
- angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
- angr/analyses/s_reaching_definitions/s_rda_view.py +2 -2
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -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_ail.py +1 -1
- angr/analyses/variable_recovery/engine_base.py +62 -67
- angr/analyses/variable_recovery/engine_vex.py +1 -1
- angr/analyses/variable_recovery/irsb_scanner.py +2 -2
- angr/block.py +69 -107
- angr/callable.py +14 -7
- angr/calling_conventions.py +81 -10
- angr/distributed/__init__.py +1 -1
- angr/engines/__init__.py +7 -8
- angr/engines/engine.py +3 -138
- angr/engines/failure.py +2 -2
- angr/engines/hook.py +2 -2
- angr/engines/light/engine.py +5 -10
- angr/engines/pcode/emulate.py +2 -2
- angr/engines/pcode/engine.py +2 -14
- angr/engines/pcode/lifter.py +2 -2
- 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 +123 -17
- angr/engines/syscall.py +2 -2
- angr/engines/unicorn.py +3 -3
- angr/engines/vex/heavy/heavy.py +3 -15
- angr/engines/vex/lifter.py +2 -2
- angr/engines/vex/light/light.py +2 -2
- angr/factory.py +4 -19
- angr/knowledge_plugins/cfg/cfg_model.py +3 -2
- angr/knowledge_plugins/key_definitions/atoms.py +8 -4
- angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
- angr/knowledge_plugins/labels.py +2 -2
- angr/knowledge_plugins/obfuscations.py +1 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +4 -0
- 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.138.dist-info → angr-9.2.140.dist-info}/METADATA +6 -6
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/RECORD +100 -98
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/LICENSE +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/WHEEL +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/entry_points.txt +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/top_level.txt +0 -0
angr/block.py
CHANGED
|
@@ -130,19 +130,23 @@ class Block(Serializable):
|
|
|
130
130
|
BLOCK_MAX_SIZE = 4096
|
|
131
131
|
|
|
132
132
|
__slots__ = [
|
|
133
|
+
"_backup_state",
|
|
133
134
|
"_bytes",
|
|
134
135
|
"_capstone",
|
|
135
136
|
"_collect_data_refs",
|
|
136
137
|
"_const_prop",
|
|
137
138
|
"_cross_insn_opt",
|
|
138
139
|
"_disassembly",
|
|
140
|
+
"_extra_stop_points",
|
|
139
141
|
"_initial_regs",
|
|
140
142
|
"_instruction_addrs",
|
|
141
143
|
"_instructions",
|
|
142
144
|
"_load_from_ro_regions",
|
|
145
|
+
"_max_size",
|
|
143
146
|
"_opt_level",
|
|
144
147
|
"_project",
|
|
145
148
|
"_strict_block_end",
|
|
149
|
+
"_traceflags",
|
|
146
150
|
"_vex",
|
|
147
151
|
"_vex_nostmt",
|
|
148
152
|
"addr",
|
|
@@ -155,11 +159,10 @@ class Block(Serializable):
|
|
|
155
159
|
self,
|
|
156
160
|
addr,
|
|
157
161
|
project=None,
|
|
158
|
-
arch: Arch = None,
|
|
162
|
+
arch: Arch | None = None,
|
|
159
163
|
size=None,
|
|
160
164
|
max_size=None,
|
|
161
165
|
byte_string=None,
|
|
162
|
-
vex=None,
|
|
163
166
|
thumb=False,
|
|
164
167
|
backup_state=None,
|
|
165
168
|
extra_stop_points=None,
|
|
@@ -174,14 +177,11 @@ class Block(Serializable):
|
|
|
174
177
|
initial_regs=None,
|
|
175
178
|
skip_stmts=False,
|
|
176
179
|
):
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
+
if arch is not None:
|
|
181
|
+
self.arch = arch
|
|
182
|
+
elif project is not None:
|
|
180
183
|
self.arch = project.arch
|
|
181
184
|
else:
|
|
182
|
-
self.arch = arch
|
|
183
|
-
|
|
184
|
-
if self.arch is None:
|
|
185
185
|
raise ValueError('Either "project" or "arch" has to be specified.')
|
|
186
186
|
|
|
187
187
|
if project is not None and backup_state is None and project.kb.patches.values():
|
|
@@ -195,63 +195,23 @@ class Block(Serializable):
|
|
|
195
195
|
else:
|
|
196
196
|
thumb = False
|
|
197
197
|
|
|
198
|
-
self._project
|
|
199
|
-
self.thumb = thumb
|
|
198
|
+
self._project = project
|
|
200
199
|
self.addr = addr
|
|
200
|
+
self._backup_state = backup_state
|
|
201
|
+
self.thumb = thumb
|
|
201
202
|
self._opt_level = opt_level
|
|
202
|
-
self._initial_regs
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
self._initial_regs = initial_regs if (collect_data_refs or const_prop) else None
|
|
204
|
+
self._traceflags = traceflags
|
|
205
|
+
self._extra_stop_points = extra_stop_points
|
|
206
|
+
self._max_size = max_size if max_size is not None else self.BLOCK_MAX_SIZE
|
|
205
207
|
|
|
206
208
|
if self._project is None and byte_string is None:
|
|
207
209
|
raise ValueError('"byte_string" has to be specified if "project" is not provided.')
|
|
208
210
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
size = len(byte_string)
|
|
212
|
-
elif vex is not None:
|
|
213
|
-
size = vex.size
|
|
214
|
-
else:
|
|
215
|
-
if self._initial_regs:
|
|
216
|
-
self.set_initial_regs()
|
|
217
|
-
clemory = None
|
|
218
|
-
if project is not None:
|
|
219
|
-
clemory = (
|
|
220
|
-
project.loader.memory_ro_view
|
|
221
|
-
if project.loader.memory_ro_view is not None
|
|
222
|
-
else project.loader.memory
|
|
223
|
-
)
|
|
224
|
-
vex = self._vex_engine.lift_vex(
|
|
225
|
-
clemory=clemory,
|
|
226
|
-
state=backup_state,
|
|
227
|
-
insn_bytes=byte_string,
|
|
228
|
-
addr=addr,
|
|
229
|
-
size=max_size,
|
|
230
|
-
thumb=thumb,
|
|
231
|
-
extra_stop_points=extra_stop_points,
|
|
232
|
-
opt_level=opt_level,
|
|
233
|
-
num_inst=num_inst,
|
|
234
|
-
traceflags=traceflags,
|
|
235
|
-
strict_block_end=strict_block_end,
|
|
236
|
-
collect_data_refs=collect_data_refs,
|
|
237
|
-
load_from_ro_regions=load_from_ro_regions,
|
|
238
|
-
const_prop=const_prop,
|
|
239
|
-
cross_insn_opt=cross_insn_opt,
|
|
240
|
-
skip_stmts=skip_stmts,
|
|
241
|
-
)
|
|
242
|
-
if self._initial_regs:
|
|
243
|
-
self.reset_initial_regs()
|
|
244
|
-
size = vex.size
|
|
245
|
-
|
|
246
|
-
if skip_stmts:
|
|
247
|
-
self._vex = None
|
|
248
|
-
self._vex_nostmt = vex
|
|
249
|
-
else:
|
|
250
|
-
self._vex = vex
|
|
251
|
-
self._vex_nostmt = None
|
|
211
|
+
self._vex = None
|
|
212
|
+
self._vex_nostmt = None
|
|
252
213
|
self._disassembly = None
|
|
253
214
|
self._capstone = None
|
|
254
|
-
self.size = size
|
|
255
215
|
self._collect_data_refs = collect_data_refs
|
|
256
216
|
self._strict_block_end = strict_block_end
|
|
257
217
|
self._cross_insn_opt = cross_insn_opt
|
|
@@ -261,6 +221,23 @@ class Block(Serializable):
|
|
|
261
221
|
self._instructions: int | None = num_inst
|
|
262
222
|
self._instruction_addrs: list[int] = []
|
|
263
223
|
|
|
224
|
+
self._bytes = byte_string
|
|
225
|
+
self.size = size
|
|
226
|
+
|
|
227
|
+
if size is None:
|
|
228
|
+
if byte_string is not None:
|
|
229
|
+
size = len(byte_string)
|
|
230
|
+
else:
|
|
231
|
+
vex = self._lift_nocache(skip_stmts)
|
|
232
|
+
size = vex.size
|
|
233
|
+
|
|
234
|
+
if skip_stmts:
|
|
235
|
+
self._vex_nostmt = vex
|
|
236
|
+
else:
|
|
237
|
+
self._vex = vex
|
|
238
|
+
|
|
239
|
+
self.size = size
|
|
240
|
+
|
|
264
241
|
if skip_stmts:
|
|
265
242
|
self._parse_vex_info(self._vex_nostmt)
|
|
266
243
|
else:
|
|
@@ -343,50 +320,7 @@ class Block(Serializable):
|
|
|
343
320
|
raise ValueError("Project is not set")
|
|
344
321
|
return self._project.factory.default_engine # type:ignore
|
|
345
322
|
|
|
346
|
-
|
|
347
|
-
def vex(self) -> IRSB | PcodeIRSB:
|
|
348
|
-
if not self._vex:
|
|
349
|
-
if self._initial_regs:
|
|
350
|
-
self.set_initial_regs()
|
|
351
|
-
clemory = None
|
|
352
|
-
if self._project is not None:
|
|
353
|
-
clemory = (
|
|
354
|
-
self._project.loader.memory_ro_view
|
|
355
|
-
if self._project.loader.memory_ro_view is not None
|
|
356
|
-
else self._project.loader.memory
|
|
357
|
-
)
|
|
358
|
-
self._vex = self._vex_engine.lift_vex(
|
|
359
|
-
clemory=clemory,
|
|
360
|
-
insn_bytes=self._bytes,
|
|
361
|
-
addr=self.addr,
|
|
362
|
-
thumb=self.thumb,
|
|
363
|
-
size=self.size,
|
|
364
|
-
num_inst=self._instructions,
|
|
365
|
-
opt_level=self._opt_level,
|
|
366
|
-
arch=self.arch,
|
|
367
|
-
collect_data_refs=self._collect_data_refs,
|
|
368
|
-
strict_block_end=self._strict_block_end,
|
|
369
|
-
cross_insn_opt=self._cross_insn_opt,
|
|
370
|
-
load_from_ro_regions=self._load_from_ro_regions,
|
|
371
|
-
const_prop=self._const_prop,
|
|
372
|
-
)
|
|
373
|
-
if self._initial_regs:
|
|
374
|
-
self.reset_initial_regs()
|
|
375
|
-
self._parse_vex_info(self._vex)
|
|
376
|
-
|
|
377
|
-
assert self._vex is not None
|
|
378
|
-
return self._vex
|
|
379
|
-
|
|
380
|
-
@property
|
|
381
|
-
def vex_nostmt(self):
|
|
382
|
-
if self._vex_nostmt:
|
|
383
|
-
return self._vex_nostmt
|
|
384
|
-
|
|
385
|
-
if self._vex:
|
|
386
|
-
return self._vex
|
|
387
|
-
|
|
388
|
-
if self._initial_regs:
|
|
389
|
-
self.set_initial_regs()
|
|
323
|
+
def _lift_nocache(self, skip_stmts: bool) -> IRSB | PcodeIRSB:
|
|
390
324
|
clemory = None
|
|
391
325
|
if self._project is not None:
|
|
392
326
|
clemory = (
|
|
@@ -394,25 +328,53 @@ class Block(Serializable):
|
|
|
394
328
|
if self._project.loader.memory_ro_view is not None
|
|
395
329
|
else self._project.loader.memory
|
|
396
330
|
)
|
|
397
|
-
|
|
331
|
+
|
|
332
|
+
if self._initial_regs:
|
|
333
|
+
self.set_initial_regs()
|
|
334
|
+
|
|
335
|
+
vex = self._vex_engine.lift_vex(
|
|
336
|
+
addr=self.addr,
|
|
337
|
+
state=self._backup_state,
|
|
398
338
|
clemory=clemory,
|
|
399
339
|
insn_bytes=self._bytes,
|
|
400
|
-
|
|
401
|
-
thumb=self.thumb,
|
|
340
|
+
arch=self.arch,
|
|
402
341
|
size=self.size,
|
|
403
342
|
num_inst=self._instructions,
|
|
343
|
+
traceflags=self._traceflags,
|
|
344
|
+
thumb=self.thumb,
|
|
345
|
+
extra_stop_points=self._extra_stop_points,
|
|
404
346
|
opt_level=self._opt_level,
|
|
405
|
-
arch=self.arch,
|
|
406
|
-
skip_stmts=True,
|
|
407
|
-
collect_data_refs=self._collect_data_refs,
|
|
408
347
|
strict_block_end=self._strict_block_end,
|
|
348
|
+
skip_stmts=skip_stmts,
|
|
349
|
+
collect_data_refs=self._collect_data_refs,
|
|
409
350
|
cross_insn_opt=self._cross_insn_opt,
|
|
410
351
|
load_from_ro_regions=self._load_from_ro_regions,
|
|
411
352
|
const_prop=self._const_prop,
|
|
412
353
|
)
|
|
354
|
+
|
|
413
355
|
if self._initial_regs:
|
|
414
356
|
self.reset_initial_regs()
|
|
357
|
+
|
|
358
|
+
return vex
|
|
359
|
+
|
|
360
|
+
@property
|
|
361
|
+
def vex(self) -> IRSB | PcodeIRSB:
|
|
362
|
+
if not self._vex:
|
|
363
|
+
self._vex = self._lift_nocache(False)
|
|
364
|
+
self._parse_vex_info(self._vex)
|
|
365
|
+
|
|
366
|
+
return self._vex
|
|
367
|
+
|
|
368
|
+
@property
|
|
369
|
+
def vex_nostmt(self):
|
|
370
|
+
if self._vex_nostmt:
|
|
371
|
+
return self._vex_nostmt
|
|
372
|
+
if self._vex:
|
|
373
|
+
return self._vex
|
|
374
|
+
|
|
375
|
+
self._vex_nostmt = self._lift_nocache(True)
|
|
415
376
|
self._parse_vex_info(self._vex_nostmt)
|
|
377
|
+
|
|
416
378
|
return self._vex_nostmt
|
|
417
379
|
|
|
418
380
|
@property
|
angr/callable.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
import pycparser
|
|
3
3
|
|
|
4
|
+
from .sim_manager import SimulationManager
|
|
4
5
|
from .errors import AngrCallableError, AngrCallableMultistateError
|
|
5
6
|
from .calling_conventions import default_cc, SimCC
|
|
6
7
|
|
|
@@ -28,6 +29,7 @@ class Callable:
|
|
|
28
29
|
cc=None,
|
|
29
30
|
add_options=None,
|
|
30
31
|
remove_options=None,
|
|
32
|
+
step_limit: int | None = None,
|
|
31
33
|
):
|
|
32
34
|
"""
|
|
33
35
|
:param project: The project to operate on
|
|
@@ -60,6 +62,7 @@ class Callable:
|
|
|
60
62
|
self._func_ty = prototype
|
|
61
63
|
self._add_options = add_options if add_options else set()
|
|
62
64
|
self._remove_options = remove_options if remove_options else set()
|
|
65
|
+
self._step_limit = step_limit
|
|
63
66
|
|
|
64
67
|
self.result_path_group = None
|
|
65
68
|
self.result_state = None
|
|
@@ -95,16 +98,12 @@ class Callable:
|
|
|
95
98
|
remove_options=self._remove_options,
|
|
96
99
|
)
|
|
97
100
|
|
|
98
|
-
def step_func(pg):
|
|
99
|
-
pg2 = pg.prune()
|
|
100
|
-
if len(pg2.active) > 1:
|
|
101
|
-
raise AngrCallableMultistateError("Execution split on symbolic condition!")
|
|
102
|
-
return pg2
|
|
103
|
-
|
|
104
101
|
caller = self._project.factory.simulation_manager(state)
|
|
105
|
-
caller.run(step_func=
|
|
102
|
+
caller.run(step_func=self._step_func).unstash(from_stash="deadended")
|
|
106
103
|
caller.prune(filter_func=lambda pt: pt.addr == self._deadend_addr)
|
|
107
104
|
|
|
105
|
+
if "step_limited" in caller.stashes:
|
|
106
|
+
caller.stash(from_stash="step_limited", to_stash="active")
|
|
108
107
|
if len(caller.active) == 0:
|
|
109
108
|
raise AngrCallableError("No paths returned from function")
|
|
110
109
|
|
|
@@ -159,3 +158,11 @@ class Callable:
|
|
|
159
158
|
raise AngrCallableError(f"Unsupported expression type {type(expr)}.")
|
|
160
159
|
|
|
161
160
|
return self.__call__(*args)
|
|
161
|
+
|
|
162
|
+
def _step_func(self, pg: SimulationManager):
|
|
163
|
+
pg2 = pg.prune()
|
|
164
|
+
if self._concrete_only and len(pg2.active) > 1:
|
|
165
|
+
raise AngrCallableMultistateError("Execution split on symbolic condition!")
|
|
166
|
+
if self._step_limit:
|
|
167
|
+
pg2.stash(filter_func=lambda p: p.history.depth >= self._step_limit, to_stash="step_limited")
|
|
168
|
+
return pg2
|
angr/calling_conventions.py
CHANGED
|
@@ -11,6 +11,7 @@ import archinfo
|
|
|
11
11
|
from archinfo import RegisterName
|
|
12
12
|
from unique_log_filter import UniqueLogFilter
|
|
13
13
|
|
|
14
|
+
import angr
|
|
14
15
|
from .errors import AngrTypeError
|
|
15
16
|
from .sim_type import (
|
|
16
17
|
SimType,
|
|
@@ -33,7 +34,6 @@ from .sim_type import (
|
|
|
33
34
|
SimTypeReference,
|
|
34
35
|
)
|
|
35
36
|
from .state_plugins.sim_action_object import SimActionObject
|
|
36
|
-
from .engines.soot.engine import SootMixin
|
|
37
37
|
|
|
38
38
|
l = logging.getLogger(name=__name__)
|
|
39
39
|
l.addFilter(UniqueLogFilter())
|
|
@@ -307,7 +307,7 @@ class SimRegArg(SimFunctionArgument):
|
|
|
307
307
|
def __hash__(self):
|
|
308
308
|
return hash((self.size, self.reg_name, self.reg_offset))
|
|
309
309
|
|
|
310
|
-
def check_offset(self, arch):
|
|
310
|
+
def check_offset(self, arch) -> int:
|
|
311
311
|
return arch.registers[self.reg_name][0] + self.reg_offset
|
|
312
312
|
|
|
313
313
|
def set_value(self, state, value, **kwargs): # pylint: disable=unused-argument,arguments-differ
|
|
@@ -582,7 +582,12 @@ class SimCC:
|
|
|
582
582
|
FP_RETURN_VAL: SimFunctionArgument | None = (
|
|
583
583
|
None # The location where floating-point argument return values are stored
|
|
584
584
|
)
|
|
585
|
-
ARCH
|
|
585
|
+
ARCH: type[archinfo.Arch] | None = (
|
|
586
|
+
None # The archinfo.Arch class for which this CC is most likely relevant, if related
|
|
587
|
+
)
|
|
588
|
+
# archinfo.Arch classes for which this CC is relevant, in addition to self.ARCH.
|
|
589
|
+
# you should access cls.arches() to get a list of all arches for which this CC is relevant
|
|
590
|
+
EXTRA_ARCHES: tuple[type[archinfo.Arch], ...] = ()
|
|
586
591
|
CALLEE_CLEANUP = False # Whether the callee has to deallocate the stack space for the arguments
|
|
587
592
|
|
|
588
593
|
STACK_ALIGNMENT = 1 # the alignment requirement of the stack pointer at function start BEFORE call
|
|
@@ -682,7 +687,7 @@ class SimCC:
|
|
|
682
687
|
ty = ty.with_arch(self.arch)
|
|
683
688
|
if isinstance(ty, (SimStruct, SimUnion, SimTypeFixedSizeArray)):
|
|
684
689
|
raise AngrTypeError(
|
|
685
|
-
f"{self} doesn't know how to return aggregate types. Consider overriding return_val to "
|
|
690
|
+
f"{self} doesn't know how to return aggregate types ({type(ty)}). Consider overriding return_val to "
|
|
686
691
|
"implement its ABI logic"
|
|
687
692
|
)
|
|
688
693
|
if self.return_in_implicit_outparam(ty):
|
|
@@ -1082,8 +1087,8 @@ class SimCC:
|
|
|
1082
1087
|
|
|
1083
1088
|
@classmethod
|
|
1084
1089
|
def _match(cls, arch, args: list, sp_delta):
|
|
1085
|
-
if
|
|
1086
|
-
arch, cls.
|
|
1090
|
+
if (
|
|
1091
|
+
cls.arches() is not None and ":" not in arch.name and not isinstance(arch, cls.arches())
|
|
1087
1092
|
): # pylint:disable=isinstance-second-argument-not-valid-type
|
|
1088
1093
|
return False
|
|
1089
1094
|
if sp_delta != cls.STACKARG_SP_DIFF:
|
|
@@ -1149,6 +1154,12 @@ class SimCC:
|
|
|
1149
1154
|
return cc_cls(arch)
|
|
1150
1155
|
return None
|
|
1151
1156
|
|
|
1157
|
+
@classmethod
|
|
1158
|
+
def arches(cls) -> tuple[type[archinfo.Arch], ...]:
|
|
1159
|
+
if cls.ARCH is not None:
|
|
1160
|
+
return (cls.ARCH, *cls.EXTRA_ARCHES)
|
|
1161
|
+
return cls.EXTRA_ARCHES
|
|
1162
|
+
|
|
1152
1163
|
def get_arg_info(self, state, prototype):
|
|
1153
1164
|
"""
|
|
1154
1165
|
This is just a simple wrapper that collects the information from various locations
|
|
@@ -1323,6 +1334,20 @@ class SimCCMicrosoftAMD64(SimCC):
|
|
|
1323
1334
|
def return_val(self, ty, perspective_returned=False):
|
|
1324
1335
|
if ty._arch is None:
|
|
1325
1336
|
ty = ty.with_arch(self.arch)
|
|
1337
|
+
|
|
1338
|
+
# Unions are allocated according to the layout of the largest member
|
|
1339
|
+
if isinstance(ty, SimUnion):
|
|
1340
|
+
chosen = None
|
|
1341
|
+
size = None
|
|
1342
|
+
for subty in ty.members.values():
|
|
1343
|
+
if subty.size is not None and (size is None or size < subty.size):
|
|
1344
|
+
chosen = subty
|
|
1345
|
+
size = subty.size
|
|
1346
|
+
if chosen is None:
|
|
1347
|
+
# fallback to void*
|
|
1348
|
+
chosen = SimTypePointer(SimTypeBottom())
|
|
1349
|
+
return self.return_val(chosen, perspective_returned=perspective_returned)
|
|
1350
|
+
|
|
1326
1351
|
if not isinstance(ty, SimStruct):
|
|
1327
1352
|
return super().return_val(ty, perspective_returned)
|
|
1328
1353
|
|
|
@@ -1444,7 +1469,7 @@ class SimCCSystemVAMD64(SimCC):
|
|
|
1444
1469
|
|
|
1445
1470
|
@classmethod
|
|
1446
1471
|
def _match(cls, arch, args, sp_delta):
|
|
1447
|
-
if cls.ARCH is not None and not isinstance(arch, cls.ARCH):
|
|
1472
|
+
if cls.ARCH is not None and ":" not in arch.name and not isinstance(arch, cls.ARCH):
|
|
1448
1473
|
return False
|
|
1449
1474
|
# if sp_delta != cls.STACKARG_SP_DIFF:
|
|
1450
1475
|
# return False
|
|
@@ -1789,8 +1814,54 @@ class SimCCARMHF(SimCCARM):
|
|
|
1789
1814
|
FP_RETURN_VAL = SimRegArg("s0", 32)
|
|
1790
1815
|
CALLER_SAVED_REGS = []
|
|
1791
1816
|
RETURN_ADDR = SimRegArg("lr", 4)
|
|
1792
|
-
RETURN_VAL = SimRegArg("r0", 4)
|
|
1817
|
+
RETURN_VAL = SimRegArg("r0", 4)
|
|
1818
|
+
OVERFLOW_RETURN_VAL = SimRegArg("r1", 4)
|
|
1793
1819
|
ARCH = archinfo.ArchARMHF
|
|
1820
|
+
EXTRA_ARCHES = (archinfo.ArchARMCortexM,)
|
|
1821
|
+
|
|
1822
|
+
def next_arg(self, session, arg_type):
|
|
1823
|
+
if isinstance(arg_type, (SimTypeArray, SimTypeFixedSizeArray)): # hack
|
|
1824
|
+
arg_type = SimTypePointer(arg_type.elem_type).with_arch(self.arch)
|
|
1825
|
+
state = session.getstate()
|
|
1826
|
+
classification = self._classify(arg_type)
|
|
1827
|
+
try:
|
|
1828
|
+
mapped_classes = []
|
|
1829
|
+
for cls in classification:
|
|
1830
|
+
if cls == "DOUBLEP":
|
|
1831
|
+
if session.getstate()[1] % 2 == 1: # doubles must start on an even register
|
|
1832
|
+
next(session.int_iter)
|
|
1833
|
+
|
|
1834
|
+
if session.getstate()[1] == len(self.ARG_REGS) - 2:
|
|
1835
|
+
mapped_classes.append(next(session.int_iter))
|
|
1836
|
+
mapped_classes.append(next(session.both_iter))
|
|
1837
|
+
else:
|
|
1838
|
+
try:
|
|
1839
|
+
mapped_classes.append(next(session.int_iter))
|
|
1840
|
+
mapped_classes.append(next(session.int_iter))
|
|
1841
|
+
except StopIteration:
|
|
1842
|
+
mapped_classes.append(next(session.both_iter))
|
|
1843
|
+
mapped_classes.append(next(session.both_iter))
|
|
1844
|
+
elif cls == "NO_CLASS":
|
|
1845
|
+
raise NotImplementedError("Bug. Report to @rhelmot")
|
|
1846
|
+
elif cls == "MEMORY":
|
|
1847
|
+
mapped_classes.append(next(session.both_iter))
|
|
1848
|
+
elif cls == "INTEGER":
|
|
1849
|
+
try:
|
|
1850
|
+
mapped_classes.append(next(session.int_iter))
|
|
1851
|
+
except StopIteration:
|
|
1852
|
+
mapped_classes.append(next(session.both_iter))
|
|
1853
|
+
elif cls == "SINGLEP":
|
|
1854
|
+
try:
|
|
1855
|
+
mapped_classes.append(next(session.fp_iter))
|
|
1856
|
+
except StopIteration:
|
|
1857
|
+
mapped_classes.append(next(session.both_iter))
|
|
1858
|
+
else:
|
|
1859
|
+
raise NotImplementedError("Bug. Report to @rhelmot")
|
|
1860
|
+
except StopIteration:
|
|
1861
|
+
session.setstate(state)
|
|
1862
|
+
mapped_classes = [next(session.both_iter) for _ in classification]
|
|
1863
|
+
|
|
1864
|
+
return refine_locs_with_struct_type(self.arch, mapped_classes, arg_type)
|
|
1794
1865
|
|
|
1795
1866
|
|
|
1796
1867
|
class SimCCARMLinuxSyscall(SimCCSyscall):
|
|
@@ -2122,7 +2193,7 @@ class SimCCSoot(SimCC):
|
|
|
2122
2193
|
ARG_REGS = []
|
|
2123
2194
|
|
|
2124
2195
|
def setup_callsite(self, state, ret_addr, args, prototype, stack_base=None, alloc_base=None, grow_like_stack=True):
|
|
2125
|
-
SootMixin.setup_callsite(state, args, ret_addr)
|
|
2196
|
+
angr.engines.SootMixin.setup_callsite(state, args, ret_addr)
|
|
2126
2197
|
|
|
2127
2198
|
@staticmethod
|
|
2128
2199
|
def guess_prototype(args, prototype=None):
|
|
@@ -2226,7 +2297,7 @@ DEFAULT_CC: dict[str, dict[str, type[SimCC]]] = {
|
|
|
2226
2297
|
"X86": {"Linux": SimCCCdecl, "CGC": SimCCCdecl, "Win32": SimCCMicrosoftCdecl},
|
|
2227
2298
|
"ARMEL": {"Linux": SimCCARM},
|
|
2228
2299
|
"ARMHF": {"Linux": SimCCARMHF},
|
|
2229
|
-
"ARMCortexM": {"Linux":
|
|
2300
|
+
"ARMCortexM": {"Linux": SimCCARMHF},
|
|
2230
2301
|
"MIPS32": {"Linux": SimCCO32},
|
|
2231
2302
|
"MIPS64": {"Linux": SimCCN64},
|
|
2232
2303
|
"PPC32": {"Linux": SimCCPowerPC},
|
angr/distributed/__init__.py
CHANGED
angr/engines/__init__.py
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from .
|
|
4
|
-
from .engine import SimEngine, SuccessorsMixin
|
|
5
|
-
|
|
6
|
-
from .vex import HeavyVEXMixin, TrackActionsMixin, SimInspectMixin, HeavyResilienceMixin, SuperFastpathMixin
|
|
7
|
-
from .procedure import ProcedureMixin, ProcedureEngine
|
|
8
|
-
from .unicorn import SimEngineUnicorn
|
|
3
|
+
from .engine import SimEngine
|
|
9
4
|
from .failure import SimEngineFailure
|
|
10
|
-
from .syscall import SimEngineSyscall
|
|
11
5
|
from .hook import HooksMixin
|
|
6
|
+
from .procedure import ProcedureEngine, ProcedureMixin
|
|
12
7
|
from .soot import SootMixin
|
|
8
|
+
from .successors import SimSuccessors, SuccessorsEngine
|
|
9
|
+
from .syscall import SimEngineSyscall
|
|
10
|
+
from .unicorn import SimEngineUnicorn
|
|
11
|
+
from .vex import HeavyResilienceMixin, HeavyVEXMixin, SimInspectMixin, SuperFastpathMixin, TrackActionsMixin
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
class UberEngine(
|
|
@@ -47,7 +46,7 @@ __all__ = [
|
|
|
47
46
|
"SimInspectMixin",
|
|
48
47
|
"SimSuccessors",
|
|
49
48
|
"SootMixin",
|
|
50
|
-
"
|
|
49
|
+
"SuccessorsEngine",
|
|
51
50
|
"SuperFastpathMixin",
|
|
52
51
|
"TrackActionsMixin",
|
|
53
52
|
"UberEngine",
|
angr/engines/engine.py
CHANGED
|
@@ -1,33 +1,19 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Generic, TypeVar
|
|
4
3
|
import abc
|
|
5
|
-
import
|
|
4
|
+
from typing import Generic, TypeVar
|
|
6
5
|
|
|
7
|
-
import claripy
|
|
8
|
-
from archinfo.arch_soot import SootAddressDescriptor
|
|
9
6
|
|
|
10
7
|
import angr
|
|
11
|
-
from angr.sim_state import SimState
|
|
12
|
-
from angr import sim_options as o
|
|
13
|
-
from angr.errors import SimException
|
|
14
|
-
from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
|
|
15
|
-
from .successors import SimSuccessors
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
l = logging.getLogger(name=__name__)
|
|
19
|
-
|
|
20
8
|
|
|
21
9
|
StateType = TypeVar("StateType")
|
|
22
10
|
ResultType = TypeVar("ResultType")
|
|
23
11
|
DataType_co = TypeVar("DataType_co", covariant=True)
|
|
24
|
-
HeavyState = SimState[int | SootAddressDescriptor, claripy.ast.BV | SootAddressDescriptor]
|
|
25
12
|
|
|
26
13
|
|
|
27
|
-
class
|
|
14
|
+
class SimEngine(Generic[StateType, ResultType], metaclass=abc.ABCMeta):
|
|
28
15
|
"""
|
|
29
|
-
|
|
30
|
-
which having method `process` (contained in `SimEngine`) doesn't make sense
|
|
16
|
+
A SimEngine is a type which understands how to perform execution on a state.
|
|
31
17
|
"""
|
|
32
18
|
|
|
33
19
|
state: StateType
|
|
@@ -41,124 +27,3 @@ class SimEngineBase(Generic[StateType]):
|
|
|
41
27
|
|
|
42
28
|
def __setstate__(self, state):
|
|
43
29
|
self.project = state[0]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class SimEngine(Generic[StateType, ResultType], SimEngineBase[StateType], metaclass=abc.ABCMeta):
|
|
47
|
-
"""
|
|
48
|
-
A SimEngine is a class which understands how to perform execution on a state. This is a base class.
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
@abc.abstractmethod
|
|
52
|
-
def process(self, state: StateType, **kwargs) -> ResultType:
|
|
53
|
-
"""
|
|
54
|
-
The main entry point for an engine. Should take a state and return a result.
|
|
55
|
-
|
|
56
|
-
:param state: The state to proceed from
|
|
57
|
-
:return: The result. Whatever you want ;)
|
|
58
|
-
"""
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class SuccessorsMixin(SimEngine[HeavyState, SimSuccessors]):
|
|
62
|
-
"""
|
|
63
|
-
A mixin for SimEngine which implements ``process`` to perform common operations related to symbolic execution
|
|
64
|
-
and dispatches to a ``process_successors`` method to fill a SimSuccessors object with the results.
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
def __init__(self, project: angr.Project):
|
|
68
|
-
super().__init__(project)
|
|
69
|
-
|
|
70
|
-
self.successors: SimSuccessors | None = None
|
|
71
|
-
|
|
72
|
-
def process(self, state: HeavyState, **kwargs) -> SimSuccessors: # pylint:disable=unused-argument
|
|
73
|
-
"""
|
|
74
|
-
Perform execution with a state.
|
|
75
|
-
|
|
76
|
-
You should only override this method in a subclass in order to provide the correct method signature and
|
|
77
|
-
docstring. You should override the ``_process`` method to do your actual execution.
|
|
78
|
-
|
|
79
|
-
:param state: The state with which to execute. This state will be copied before
|
|
80
|
-
modification.
|
|
81
|
-
:param inline: This is an inline execution. Do not bother copying the state.
|
|
82
|
-
:param force_addr: Force execution to pretend that we're working at this concrete address
|
|
83
|
-
:returns: A SimSuccessors object categorizing the execution's successor states
|
|
84
|
-
"""
|
|
85
|
-
inline = kwargs.pop("inline", False)
|
|
86
|
-
force_addr = kwargs.pop("force_addr", None)
|
|
87
|
-
|
|
88
|
-
ip = state._ip
|
|
89
|
-
addr = (
|
|
90
|
-
(ip if isinstance(ip, SootAddressDescriptor) else state.solver.eval(ip))
|
|
91
|
-
if force_addr is None
|
|
92
|
-
else force_addr
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
# make a copy of the initial state for actual processing, if needed
|
|
96
|
-
new_state = state.copy() if not inline and o.COPY_STATES in state.options else state
|
|
97
|
-
# enforce this distinction
|
|
98
|
-
old_state = state
|
|
99
|
-
del state
|
|
100
|
-
self.state = new_state
|
|
101
|
-
|
|
102
|
-
# we have now officially begun the stepping process! now is where we "cycle" a state's
|
|
103
|
-
# data - move the "present" into the "past" by pushing an entry on the history stack.
|
|
104
|
-
# nuance: make sure to copy from the PREVIOUS state to the CURRENT one
|
|
105
|
-
# to avoid creating a dead link in the history, messing up the statehierarchy
|
|
106
|
-
new_state.register_plugin("history", old_state.history.make_child())
|
|
107
|
-
new_state.history.recent_bbl_addrs.append(addr)
|
|
108
|
-
if new_state.arch.unicorn_support:
|
|
109
|
-
assert isinstance(addr, int)
|
|
110
|
-
new_state.scratch.executed_pages_set = {addr & ~0xFFF}
|
|
111
|
-
|
|
112
|
-
self.successors = SimSuccessors(addr, old_state)
|
|
113
|
-
|
|
114
|
-
new_state._inspect(
|
|
115
|
-
"engine_process", when=BP_BEFORE, sim_engine=self, sim_successors=self.successors, address=addr
|
|
116
|
-
)
|
|
117
|
-
self.successors = new_state._inspect_getattr("sim_successors", self.successors)
|
|
118
|
-
try:
|
|
119
|
-
self.process_successors(self.successors, **kwargs)
|
|
120
|
-
except SimException as e:
|
|
121
|
-
if o.EXCEPTION_HANDLING not in old_state.options:
|
|
122
|
-
raise
|
|
123
|
-
assert old_state.project is not None
|
|
124
|
-
old_state.project.simos.handle_exception(self.successors, self, e)
|
|
125
|
-
|
|
126
|
-
new_state._inspect("engine_process", when=BP_AFTER, sim_successors=self.successors, address=addr)
|
|
127
|
-
self.successors = new_state._inspect_getattr("sim_successors", self.successors)
|
|
128
|
-
assert self.successors is not None
|
|
129
|
-
|
|
130
|
-
# downsizing
|
|
131
|
-
if new_state.supports_inspect:
|
|
132
|
-
new_state.inspect.downsize()
|
|
133
|
-
# if not TRACK, clear actions on OLD state
|
|
134
|
-
# if o.TRACK_ACTION_HISTORY not in old_state.options:
|
|
135
|
-
# old_state.history.recent_events = []
|
|
136
|
-
|
|
137
|
-
# fix up the descriptions...
|
|
138
|
-
description = str(self.successors)
|
|
139
|
-
l.info("Ticked state: %s", description)
|
|
140
|
-
for succ in self.successors.all_successors:
|
|
141
|
-
succ.history.recent_description = description
|
|
142
|
-
for succ in self.successors.flat_successors:
|
|
143
|
-
succ.history.recent_description = description
|
|
144
|
-
|
|
145
|
-
return self.successors
|
|
146
|
-
|
|
147
|
-
def process_successors(self, successors, **kwargs): # pylint:disable=unused-argument,no-self-use
|
|
148
|
-
"""
|
|
149
|
-
Implement this function to fill out the SimSuccessors object with the results of stepping state.
|
|
150
|
-
|
|
151
|
-
In order to implement a model where multiple mixins can potentially handle a request, a mixin may implement
|
|
152
|
-
this method and then perform a super() call if it wants to pass on handling to the next mixin.
|
|
153
|
-
|
|
154
|
-
Keep in mind python's method resolution order when composing multiple classes implementing this method.
|
|
155
|
-
In short: left-to-right, depth-first, but deferring any base classes which are shared by multiple subclasses
|
|
156
|
-
(the merge point of a diamond pattern in the inheritance graph) until the last point where they would be
|
|
157
|
-
encountered in this depth-first search. For example, if you have classes A, B(A), C(B), D(A), E(C, D), then the
|
|
158
|
-
method resolution order will be E, C, B, D, A.
|
|
159
|
-
|
|
160
|
-
:param state: The state to manipulate
|
|
161
|
-
:param successors: The successors object to fill out
|
|
162
|
-
:param kwargs: Any extra arguments. Do not fail if you are passed unexpected arguments.
|
|
163
|
-
"""
|
|
164
|
-
successors.processed = False # mark failure
|