angr 9.2.136__py3-none-manylinux2014_aarch64.whl → 9.2.138__py3-none-manylinux2014_aarch64.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 +2 -1
- angr/analyses/calling_convention/fact_collector.py +10 -2
- angr/analyses/cfg/cfg_base.py +3 -33
- angr/analyses/cfg/cfg_emulated.py +0 -103
- angr/analyses/cfg/cfg_fast.py +31 -12
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +15 -0
- angr/analyses/class_identifier.py +1 -2
- angr/analyses/complete_calling_conventions.py +6 -3
- angr/analyses/decompiler/ail_simplifier.py +12 -1
- angr/analyses/decompiler/block_simplifier.py +2 -2
- angr/analyses/decompiler/ccall_rewriters/__init__.py +2 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +1 -1
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +69 -0
- angr/analyses/decompiler/clinic.py +77 -65
- angr/analyses/decompiler/condition_processor.py +2 -0
- angr/analyses/decompiler/decompilation_options.py +10 -0
- angr/analyses/decompiler/decompiler.py +1 -0
- angr/analyses/decompiler/dephication/dephication_base.py +2 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +8 -6
- angr/analyses/decompiler/dephication/seqnode_dephication.py +10 -1
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +2 -2
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +1 -2
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +21 -3
- angr/analyses/decompiler/sequence_walker.py +6 -2
- angr/analyses/decompiler/ssailification/rewriting.py +11 -1
- angr/analyses/decompiler/ssailification/rewriting_engine.py +56 -19
- angr/analyses/decompiler/ssailification/ssailification.py +13 -3
- angr/analyses/decompiler/ssailification/traversal.py +28 -2
- angr/analyses/decompiler/ssailification/traversal_state.py +6 -1
- angr/analyses/decompiler/structured_codegen/c.py +44 -21
- angr/analyses/decompiler/structuring/phoenix.py +117 -14
- angr/analyses/decompiler/utils.py +113 -8
- angr/analyses/reaching_definitions/function_handler.py +1 -1
- angr/analyses/s_liveness.py +5 -1
- angr/analyses/s_propagator.py +127 -28
- angr/analyses/s_reaching_definitions/s_rda_model.py +2 -1
- angr/analyses/s_reaching_definitions/s_rda_view.py +20 -1
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +11 -1
- angr/analyses/stack_pointer_tracker.py +26 -16
- angr/analyses/variable_recovery/engine_ail.py +19 -7
- angr/analyses/variable_recovery/engine_base.py +16 -14
- angr/analyses/variable_recovery/engine_vex.py +2 -2
- angr/analyses/variable_recovery/variable_recovery_fast.py +22 -1
- angr/block.py +59 -20
- angr/engines/pcode/emulate.py +1 -1
- angr/engines/pcode/lifter.py +31 -18
- angr/engines/soot/expressions/__init__.py +2 -4
- angr/engines/soot/statements/__init__.py +1 -2
- angr/engines/soot/values/__init__.py +1 -2
- angr/engines/successors.py +11 -6
- angr/engines/vex/lifter.py +9 -6
- angr/flirt/build_sig.py +8 -15
- angr/knowledge_plugins/functions/function.py +0 -6
- angr/knowledge_plugins/functions/soot_function.py +5 -8
- angr/knowledge_plugins/variables/variable_manager.py +16 -10
- angr/procedures/glibc/__libc_start_main.py +10 -3
- angr/utils/ssa/__init__.py +14 -1
- {angr-9.2.136.dist-info → angr-9.2.138.dist-info}/METADATA +7 -7
- {angr-9.2.136.dist-info → angr-9.2.138.dist-info}/RECORD +64 -63
- {angr-9.2.136.dist-info → angr-9.2.138.dist-info}/WHEEL +1 -1
- {angr-9.2.136.dist-info → angr-9.2.138.dist-info}/LICENSE +0 -0
- {angr-9.2.136.dist-info → angr-9.2.138.dist-info}/entry_points.txt +0 -0
- {angr-9.2.136.dist-info → angr-9.2.138.dist-info}/top_level.txt +0 -0
angr/block.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# pylint:disable=wrong-import-position,arguments-differ
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
import logging
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
import pyvex
|
|
6
7
|
from pyvex import IRSB
|
|
7
|
-
from archinfo import ArchARM
|
|
8
|
+
from archinfo import Arch, ArchARM
|
|
8
9
|
|
|
9
10
|
from .protos import primitives_pb2 as pb2
|
|
10
11
|
from .serializable import Serializable
|
|
@@ -14,6 +15,12 @@ try:
|
|
|
14
15
|
except ImportError:
|
|
15
16
|
pcode = None
|
|
16
17
|
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from angr import Project
|
|
20
|
+
from angr.engines.vex import VEXLifter
|
|
21
|
+
from angr.engines.pcode.lifter import PcodeLifterEngineMixin, IRSB as PcodeIRSB
|
|
22
|
+
from angr.engines.soot.engine import SootMixin
|
|
23
|
+
|
|
17
24
|
|
|
18
25
|
l = logging.getLogger(name=__name__)
|
|
19
26
|
|
|
@@ -148,7 +155,7 @@ class Block(Serializable):
|
|
|
148
155
|
self,
|
|
149
156
|
addr,
|
|
150
157
|
project=None,
|
|
151
|
-
arch=None,
|
|
158
|
+
arch: Arch = None,
|
|
152
159
|
size=None,
|
|
153
160
|
max_size=None,
|
|
154
161
|
byte_string=None,
|
|
@@ -168,6 +175,7 @@ class Block(Serializable):
|
|
|
168
175
|
skip_stmts=False,
|
|
169
176
|
):
|
|
170
177
|
# set up arch
|
|
178
|
+
self.arch: Arch
|
|
171
179
|
if project is not None:
|
|
172
180
|
self.arch = project.arch
|
|
173
181
|
else:
|
|
@@ -187,7 +195,7 @@ class Block(Serializable):
|
|
|
187
195
|
else:
|
|
188
196
|
thumb = False
|
|
189
197
|
|
|
190
|
-
self._project = project
|
|
198
|
+
self._project: Project | None = project
|
|
191
199
|
self.thumb = thumb
|
|
192
200
|
self.addr = addr
|
|
193
201
|
self._opt_level = opt_level
|
|
@@ -206,8 +214,15 @@ class Block(Serializable):
|
|
|
206
214
|
else:
|
|
207
215
|
if self._initial_regs:
|
|
208
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
|
+
)
|
|
209
224
|
vex = self._vex_engine.lift_vex(
|
|
210
|
-
clemory=
|
|
225
|
+
clemory=clemory,
|
|
211
226
|
state=backup_state,
|
|
212
227
|
insn_bytes=byte_string,
|
|
213
228
|
addr=addr,
|
|
@@ -243,7 +258,7 @@ class Block(Serializable):
|
|
|
243
258
|
self._load_from_ro_regions = load_from_ro_regions
|
|
244
259
|
self._const_prop = const_prop
|
|
245
260
|
|
|
246
|
-
self._instructions = num_inst
|
|
261
|
+
self._instructions: int | None = num_inst
|
|
247
262
|
self._instruction_addrs: list[int] = []
|
|
248
263
|
|
|
249
264
|
if skip_stmts:
|
|
@@ -258,7 +273,7 @@ class Block(Serializable):
|
|
|
258
273
|
if type(self._bytes) is memoryview:
|
|
259
274
|
self._bytes = bytes(self._bytes)
|
|
260
275
|
elif type(self._bytes) is not bytes:
|
|
261
|
-
self._bytes = bytes(pyvex.ffi.buffer(self._bytes, size))
|
|
276
|
+
self._bytes = bytes(pyvex.ffi.buffer(self._bytes, size)) # type:ignore
|
|
262
277
|
else:
|
|
263
278
|
self._bytes = None
|
|
264
279
|
elif type(byte_string) is bytes:
|
|
@@ -269,7 +284,7 @@ class Block(Serializable):
|
|
|
269
284
|
else:
|
|
270
285
|
# Convert bytestring to a str
|
|
271
286
|
# size will ALWAYS be known at this point
|
|
272
|
-
self._bytes =
|
|
287
|
+
self._bytes = bytes(pyvex.ffi.buffer(byte_string, self.size)) # type:ignore
|
|
273
288
|
|
|
274
289
|
def _parse_vex_info(self, vex_block):
|
|
275
290
|
if vex_block is not None:
|
|
@@ -323,16 +338,25 @@ class Block(Serializable):
|
|
|
323
338
|
pyvex.pvc.reset_initial_register_values()
|
|
324
339
|
|
|
325
340
|
@property
|
|
326
|
-
def _vex_engine(self):
|
|
327
|
-
|
|
341
|
+
def _vex_engine(self) -> VEXLifter | PcodeLifterEngineMixin:
|
|
342
|
+
if self._project is None:
|
|
343
|
+
raise ValueError("Project is not set")
|
|
344
|
+
return self._project.factory.default_engine # type:ignore
|
|
328
345
|
|
|
329
346
|
@property
|
|
330
|
-
def vex(self) -> IRSB:
|
|
347
|
+
def vex(self) -> IRSB | PcodeIRSB:
|
|
331
348
|
if not self._vex:
|
|
332
349
|
if self._initial_regs:
|
|
333
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
|
+
)
|
|
334
358
|
self._vex = self._vex_engine.lift_vex(
|
|
335
|
-
clemory=
|
|
359
|
+
clemory=clemory,
|
|
336
360
|
insn_bytes=self._bytes,
|
|
337
361
|
addr=self.addr,
|
|
338
362
|
thumb=self.thumb,
|
|
@@ -350,6 +374,7 @@ class Block(Serializable):
|
|
|
350
374
|
self.reset_initial_regs()
|
|
351
375
|
self._parse_vex_info(self._vex)
|
|
352
376
|
|
|
377
|
+
assert self._vex is not None
|
|
353
378
|
return self._vex
|
|
354
379
|
|
|
355
380
|
@property
|
|
@@ -362,8 +387,15 @@ class Block(Serializable):
|
|
|
362
387
|
|
|
363
388
|
if self._initial_regs:
|
|
364
389
|
self.set_initial_regs()
|
|
390
|
+
clemory = None
|
|
391
|
+
if self._project is not None:
|
|
392
|
+
clemory = (
|
|
393
|
+
self._project.loader.memory_ro_view
|
|
394
|
+
if self._project.loader.memory_ro_view is not None
|
|
395
|
+
else self._project.loader.memory
|
|
396
|
+
)
|
|
365
397
|
self._vex_nostmt = self._vex_engine.lift_vex(
|
|
366
|
-
clemory=
|
|
398
|
+
clemory=clemory,
|
|
367
399
|
insn_bytes=self._bytes,
|
|
368
400
|
addr=self.addr,
|
|
369
401
|
thumb=self.thumb,
|
|
@@ -394,17 +426,17 @@ class Block(Serializable):
|
|
|
394
426
|
"""
|
|
395
427
|
if self._disassembly is None:
|
|
396
428
|
if self._using_pcode_engine:
|
|
397
|
-
self._disassembly = self.vex.disassembly
|
|
429
|
+
self._disassembly = self.vex.disassembly # type:ignore
|
|
398
430
|
else:
|
|
399
431
|
self._disassembly = self.capstone
|
|
400
432
|
return self._disassembly
|
|
401
433
|
|
|
402
434
|
@property
|
|
403
|
-
def capstone(self):
|
|
435
|
+
def capstone(self) -> CapstoneBlock:
|
|
404
436
|
if self._capstone:
|
|
405
437
|
return self._capstone
|
|
406
438
|
|
|
407
|
-
cs = self.arch.capstone if not self.thumb else self.arch.capstone_thumb
|
|
439
|
+
cs = self.arch.capstone if not self.thumb else self.arch.capstone_thumb # type:ignore
|
|
408
440
|
|
|
409
441
|
insns = []
|
|
410
442
|
|
|
@@ -423,12 +455,18 @@ class Block(Serializable):
|
|
|
423
455
|
return BlockNode(self.addr, self.size, bytestr=self.bytes, thumb=self.thumb)
|
|
424
456
|
|
|
425
457
|
@property
|
|
426
|
-
def bytes(self) -> bytes:
|
|
458
|
+
def bytes(self) -> bytes | None:
|
|
427
459
|
if self._bytes is None:
|
|
428
460
|
addr = self.addr
|
|
429
461
|
if self.thumb:
|
|
430
462
|
addr = (addr >> 1) << 1
|
|
431
|
-
|
|
463
|
+
if self._project is not None:
|
|
464
|
+
mem = (
|
|
465
|
+
self._project.loader.memory_ro_view
|
|
466
|
+
if self._project.loader.memory_ro_view is not None
|
|
467
|
+
else self._project.loader.memory
|
|
468
|
+
)
|
|
469
|
+
self._bytes = mem.load(addr, self.size)
|
|
432
470
|
return self._bytes
|
|
433
471
|
|
|
434
472
|
@property
|
|
@@ -437,6 +475,7 @@ class Block(Serializable):
|
|
|
437
475
|
# initialize from VEX
|
|
438
476
|
_ = self.vex
|
|
439
477
|
|
|
478
|
+
assert self._instructions is not None
|
|
440
479
|
return self._instructions
|
|
441
480
|
|
|
442
481
|
@property
|
|
@@ -477,17 +516,17 @@ class SootBlock:
|
|
|
477
516
|
Represents a Soot IR basic block.
|
|
478
517
|
"""
|
|
479
518
|
|
|
480
|
-
def __init__(self, addr, project
|
|
519
|
+
def __init__(self, addr, *, project: Project, arch: Arch):
|
|
481
520
|
self.addr = addr
|
|
482
521
|
self.arch = arch
|
|
483
522
|
self._project = project
|
|
484
523
|
self._the_binary = project.loader.main_object
|
|
485
524
|
|
|
486
525
|
@property
|
|
487
|
-
def _soot_engine(self):
|
|
526
|
+
def _soot_engine(self) -> SootMixin:
|
|
488
527
|
if self._project is None:
|
|
489
528
|
assert False, "This should be unreachable"
|
|
490
|
-
return self._project.factory.default_engine
|
|
529
|
+
return self._project.factory.default_engine # type:ignore
|
|
491
530
|
|
|
492
531
|
@property
|
|
493
532
|
def soot(self):
|
angr/engines/pcode/emulate.py
CHANGED
angr/engines/pcode/lifter.py
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
import logging
|
|
10
|
-
from typing import
|
|
10
|
+
from typing import Any, TYPE_CHECKING
|
|
11
11
|
from collections.abc import Iterable, Sequence
|
|
12
12
|
|
|
13
13
|
import archinfo
|
|
@@ -35,6 +35,12 @@ except ImportError:
|
|
|
35
35
|
pypcode = None
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
if TYPE_CHECKING:
|
|
39
|
+
# this is to make pyright happy; otherwise it believes pypcode is None
|
|
40
|
+
import pypcode
|
|
41
|
+
from pypcode import PcodeOp, Context
|
|
42
|
+
|
|
43
|
+
|
|
38
44
|
l = logging.getLogger(__name__)
|
|
39
45
|
|
|
40
46
|
IRSB_MAX_SIZE = 400
|
|
@@ -130,8 +136,8 @@ class IRSB:
|
|
|
130
136
|
|
|
131
137
|
_direct_next: bool | None
|
|
132
138
|
_exit_statements: Sequence[tuple[int, int, ExitStatement]]
|
|
133
|
-
_instruction_addresses:
|
|
134
|
-
_ops:
|
|
139
|
+
_instruction_addresses: list[int] | None
|
|
140
|
+
_ops: list[PcodeOp] # FIXME: Merge into _statements
|
|
135
141
|
_size: int | None
|
|
136
142
|
_statements: Iterable # Note: currently unused
|
|
137
143
|
_disassembly: PcodeDisassemblerBlock | None
|
|
@@ -140,7 +146,7 @@ class IRSB:
|
|
|
140
146
|
behaviors: BehaviorFactory | None
|
|
141
147
|
data_refs: Sequence # Note: currently unused
|
|
142
148
|
const_vals: Sequence # Note: currently unused
|
|
143
|
-
default_exit_target:
|
|
149
|
+
default_exit_target: Any # Note: currently used
|
|
144
150
|
jumpkind: str | None
|
|
145
151
|
next: int | None
|
|
146
152
|
|
|
@@ -199,7 +205,7 @@ class IRSB:
|
|
|
199
205
|
self._direct_next = None
|
|
200
206
|
self._exit_statements = []
|
|
201
207
|
self._instruction_addresses = None
|
|
202
|
-
self._ops = []
|
|
208
|
+
self._ops: list[PcodeOp] = []
|
|
203
209
|
self._size = None
|
|
204
210
|
self._statements = []
|
|
205
211
|
self.addr = mem_addr
|
|
@@ -248,7 +254,7 @@ class IRSB:
|
|
|
248
254
|
|
|
249
255
|
@property
|
|
250
256
|
def has_statements(self) -> bool:
|
|
251
|
-
return self.statements is not None and self.statements
|
|
257
|
+
return bool(self.statements is not None and self.statements)
|
|
252
258
|
|
|
253
259
|
@property
|
|
254
260
|
def exit_statements(self) -> Sequence[tuple[int, int, ExitStatement]]:
|
|
@@ -320,7 +326,7 @@ class IRSB:
|
|
|
320
326
|
return len(self.statements)
|
|
321
327
|
|
|
322
328
|
@property
|
|
323
|
-
def offsIP(self) -> int:
|
|
329
|
+
def offsIP(self) -> int | None:
|
|
324
330
|
return self.arch.ip_offset
|
|
325
331
|
|
|
326
332
|
@property
|
|
@@ -459,10 +465,10 @@ class IRSB:
|
|
|
459
465
|
jumpkind: str | None = None,
|
|
460
466
|
direct_next: bool | None = None,
|
|
461
467
|
size: int | None = None,
|
|
462
|
-
ops:
|
|
463
|
-
instruction_addresses:
|
|
468
|
+
ops: list[PcodeOp] | None = None,
|
|
469
|
+
instruction_addresses: list[int] | None = None,
|
|
464
470
|
exit_statements: Sequence[tuple[int, int, ExitStatement]] | None = None,
|
|
465
|
-
default_exit_target:
|
|
471
|
+
default_exit_target: Any = None,
|
|
466
472
|
) -> None:
|
|
467
473
|
# pylint: disable=unused-argument
|
|
468
474
|
self._statements = statements if statements is not None else []
|
|
@@ -490,7 +496,7 @@ class IRSB:
|
|
|
490
496
|
)
|
|
491
497
|
|
|
492
498
|
@property
|
|
493
|
-
def statements(self) ->
|
|
499
|
+
def statements(self) -> list:
|
|
494
500
|
# FIXME: For compatibility, may want to implement Ist_IMark and
|
|
495
501
|
# pyvex.IRStmt.Exit to ease analyses.
|
|
496
502
|
l.debug("Returning empty statements list!")
|
|
@@ -807,7 +813,7 @@ class PcodeBasicBlockLifter:
|
|
|
807
813
|
Lifts basic blocks to P-code
|
|
808
814
|
"""
|
|
809
815
|
|
|
810
|
-
context:
|
|
816
|
+
context: Context
|
|
811
817
|
behaviors: BehaviorFactory
|
|
812
818
|
|
|
813
819
|
def __init__(self, arch: archinfo.Arch):
|
|
@@ -1032,7 +1038,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1032
1038
|
self,
|
|
1033
1039
|
addr: int | None = None,
|
|
1034
1040
|
state: SimState | None = None,
|
|
1035
|
-
clemory: cle.Clemory | None = None,
|
|
1041
|
+
clemory: cle.Clemory | cle.ClemoryReadOnlyView | None = None,
|
|
1036
1042
|
insn_bytes: bytes | None = None,
|
|
1037
1043
|
arch: archinfo.Arch | None = None,
|
|
1038
1044
|
size: int | None = None,
|
|
@@ -1047,7 +1053,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1047
1053
|
load_from_ro_regions: bool = False,
|
|
1048
1054
|
cross_insn_opt: bool | None = None,
|
|
1049
1055
|
const_prop: bool | None = None,
|
|
1050
|
-
):
|
|
1056
|
+
) -> IRSB:
|
|
1051
1057
|
"""
|
|
1052
1058
|
Temporary compatibility interface for integration with block code.
|
|
1053
1059
|
"""
|
|
@@ -1075,7 +1081,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1075
1081
|
self,
|
|
1076
1082
|
addr: int | None = None,
|
|
1077
1083
|
state: SimState | None = None,
|
|
1078
|
-
clemory: cle.Clemory | None = None,
|
|
1084
|
+
clemory: cle.Clemory | cle.ClemoryReadOnlyView | None = None,
|
|
1079
1085
|
insn_bytes: bytes | None = None,
|
|
1080
1086
|
arch: archinfo.Arch | None = None,
|
|
1081
1087
|
size: int | None = None,
|
|
@@ -1090,7 +1096,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1090
1096
|
load_from_ro_regions: bool = False,
|
|
1091
1097
|
cross_insn_opt: bool | None = None,
|
|
1092
1098
|
const_prop: bool | None = None,
|
|
1093
|
-
):
|
|
1099
|
+
) -> IRSB:
|
|
1094
1100
|
"""
|
|
1095
1101
|
Lift an IRSB.
|
|
1096
1102
|
|
|
@@ -1137,6 +1143,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1137
1143
|
|
|
1138
1144
|
# phase 1: parameter defaults
|
|
1139
1145
|
if addr is None:
|
|
1146
|
+
assert state is not None
|
|
1140
1147
|
addr = state.solver.eval(state._ip)
|
|
1141
1148
|
if size is not None:
|
|
1142
1149
|
size = min(size, IRSB_MAX_SIZE)
|
|
@@ -1158,6 +1165,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1158
1165
|
" disabled."
|
|
1159
1166
|
)
|
|
1160
1167
|
opt_level = 0
|
|
1168
|
+
assert state is not None
|
|
1161
1169
|
if state and o.OPTIMIZE_IR in state.options:
|
|
1162
1170
|
state.options.remove(o.OPTIMIZE_IR)
|
|
1163
1171
|
if skip_stmts is not True:
|
|
@@ -1278,13 +1286,18 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1278
1286
|
)
|
|
1279
1287
|
return irsb
|
|
1280
1288
|
|
|
1289
|
+
raise SimEngineError("Unreachable code reached")
|
|
1281
1290
|
# phase x: error handling
|
|
1282
1291
|
except PyVEXError as e:
|
|
1283
1292
|
l.debug("Translation error at %#x", addr)
|
|
1284
1293
|
raise SimTranslationError("Unable to translate bytecode") from e
|
|
1285
1294
|
|
|
1286
1295
|
def _load_bytes(
|
|
1287
|
-
self,
|
|
1296
|
+
self,
|
|
1297
|
+
addr: int,
|
|
1298
|
+
max_size: int,
|
|
1299
|
+
state: SimState | None = None,
|
|
1300
|
+
clemory: cle.Clemory | cle.ClemoryReadOnlyView | None = None,
|
|
1288
1301
|
) -> tuple[bytes, int, int]:
|
|
1289
1302
|
if clemory is None and state is None:
|
|
1290
1303
|
raise SimEngineError("state and clemory cannot both be None in _load_bytes().")
|
|
@@ -1306,7 +1319,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
|
|
|
1306
1319
|
|
|
1307
1320
|
# Load from the clemory if we can
|
|
1308
1321
|
if not load_from_state or not state:
|
|
1309
|
-
if isinstance(clemory, cle.Clemory):
|
|
1322
|
+
if isinstance(clemory, (cle.Clemory, cle.ClemoryReadOnlyView)):
|
|
1310
1323
|
try:
|
|
1311
1324
|
start, backer = next(clemory.backers(addr))
|
|
1312
1325
|
except StopIteration:
|
|
@@ -39,10 +39,8 @@ l = logging.getLogger("angr.engines.soot.expressions")
|
|
|
39
39
|
|
|
40
40
|
def translate_expr(expr, state):
|
|
41
41
|
expr_name = expr.__class__.__name__.split(".")[-1]
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if expr_name.endswith("Expr"):
|
|
45
|
-
expr_name = expr_name[:-4]
|
|
42
|
+
expr_name = expr_name.removeprefix("Soot")
|
|
43
|
+
expr_name = expr_name.removesuffix("Expr")
|
|
46
44
|
expr_cls_name = "SimSootExpr_" + expr_name
|
|
47
45
|
|
|
48
46
|
g = globals()
|
|
@@ -16,8 +16,7 @@ l = logging.getLogger("angr.engines.soot.statements")
|
|
|
16
16
|
|
|
17
17
|
def translate_stmt(stmt, state):
|
|
18
18
|
stmt_name = stmt.__class__.__name__.split(".")[-1]
|
|
19
|
-
|
|
20
|
-
stmt_name = stmt_name[:-4]
|
|
19
|
+
stmt_name = stmt_name.removesuffix("Stmt")
|
|
21
20
|
|
|
22
21
|
stmt_cls_name = f"SimSootStmt_{stmt_name}"
|
|
23
22
|
if stmt_cls_name in globals():
|
|
@@ -12,8 +12,7 @@ from .strref import SimSootValue_StringRef
|
|
|
12
12
|
|
|
13
13
|
def translate_value(value, state):
|
|
14
14
|
value_name = value.__class__.__name__
|
|
15
|
-
|
|
16
|
-
value_name = value_name[4:]
|
|
15
|
+
value_name = value_name.removeprefix("Soot")
|
|
17
16
|
value_cls_name = "SimSootValue_" + value_name
|
|
18
17
|
|
|
19
18
|
g = globals()
|
angr/engines/successors.py
CHANGED
|
@@ -269,11 +269,11 @@ class SimSuccessors:
|
|
|
269
269
|
# categorize the state
|
|
270
270
|
if o.APPROXIMATE_GUARDS in state.options and state.solver.is_false(state.scratch.guard, exact=False):
|
|
271
271
|
if o.VALIDATE_APPROXIMATIONS in state.options and state.satisfiable():
|
|
272
|
-
raise
|
|
272
|
+
raise AssertionError("WTF")
|
|
273
273
|
self.unsat_successors.append(state)
|
|
274
274
|
elif o.APPROXIMATE_SATISFIABILITY in state.options and not state.solver.satisfiable(exact=False):
|
|
275
275
|
if o.VALIDATE_APPROXIMATIONS in state.options and state.solver.satisfiable():
|
|
276
|
-
raise
|
|
276
|
+
raise AssertionError("WTF")
|
|
277
277
|
self.unsat_successors.append(state)
|
|
278
278
|
elif (not state.scratch.guard.symbolic and state.solver.is_false(state.scratch.guard)) or (
|
|
279
279
|
o.LAZY_SOLVES not in state.options and not state.satisfiable()
|
|
@@ -295,10 +295,15 @@ class SimSuccessors:
|
|
|
295
295
|
# syscall
|
|
296
296
|
self.successors.append(state)
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
298
|
+
if "ip_at_syscall" in state.arch.registers:
|
|
299
|
+
# Misuse the ip_at_syscall register to save the return address for this syscall
|
|
300
|
+
# state.ip *might be* changed to be the real address
|
|
301
|
+
# of syscall SimProcedures by syscall handling code in angr
|
|
302
|
+
state.regs.ip_at_syscall = state.ip
|
|
303
|
+
else:
|
|
304
|
+
# The architecture doesn't have an ip_at_syscall register.
|
|
305
|
+
# Nothing to do but hope vigorously.
|
|
306
|
+
l.warning(f"Handling syscall on arch {state.arch.name:s} without ip_at_syscall register")
|
|
302
307
|
|
|
303
308
|
try:
|
|
304
309
|
symbolic_syscall_num, concrete_syscall_nums = self._resolve_syscall(state)
|
angr/engines/vex/lifter.py
CHANGED
|
@@ -57,7 +57,7 @@ class VEXLifter(SimEngineBase):
|
|
|
57
57
|
self.selfmodifying_code = False
|
|
58
58
|
|
|
59
59
|
# block cache
|
|
60
|
-
self._block_cache = None
|
|
60
|
+
self._block_cache: LRUCache = None
|
|
61
61
|
self._block_cache_hits = 0
|
|
62
62
|
self._block_cache_misses = 0
|
|
63
63
|
|
|
@@ -78,8 +78,8 @@ class VEXLifter(SimEngineBase):
|
|
|
78
78
|
self,
|
|
79
79
|
addr=None,
|
|
80
80
|
state=None,
|
|
81
|
-
clemory=None,
|
|
82
|
-
insn_bytes=None,
|
|
81
|
+
clemory: cle.Clemory | cle.ClemoryReadOnlyView | None = None,
|
|
82
|
+
insn_bytes: bytes | None = None,
|
|
83
83
|
offset=None,
|
|
84
84
|
arch=None,
|
|
85
85
|
size=None,
|
|
@@ -94,7 +94,7 @@ class VEXLifter(SimEngineBase):
|
|
|
94
94
|
cross_insn_opt=None,
|
|
95
95
|
load_from_ro_regions=False,
|
|
96
96
|
const_prop=False,
|
|
97
|
-
):
|
|
97
|
+
) -> pyvex.IRSB:
|
|
98
98
|
"""
|
|
99
99
|
Lift an IRSB.
|
|
100
100
|
|
|
@@ -245,6 +245,7 @@ class VEXLifter(SimEngineBase):
|
|
|
245
245
|
raise SimEngineError(f"No bytes in memory for block starting at {addr:#x}.")
|
|
246
246
|
|
|
247
247
|
# phase 5: call into pyvex
|
|
248
|
+
buff: bytes | claripy.ast.BV
|
|
248
249
|
l.debug("Creating IRSB of %s at %#x", arch, addr)
|
|
249
250
|
try:
|
|
250
251
|
for subphase in range(2):
|
|
@@ -287,7 +288,9 @@ class VEXLifter(SimEngineBase):
|
|
|
287
288
|
l.debug("Using bytes: %r", pyvex.ffi.buffer(buff, size))
|
|
288
289
|
raise SimTranslationError("Unable to translate bytecode") from e
|
|
289
290
|
|
|
290
|
-
def _load_bytes(
|
|
291
|
+
def _load_bytes(
|
|
292
|
+
self, addr, max_size, state=None, clemory: cle.Clemory | cle.ClemoryReadOnlyView | None = None
|
|
293
|
+
) -> tuple[bytes, int, int]:
|
|
291
294
|
if clemory is None and state is None:
|
|
292
295
|
raise SimEngineError("state and clemory cannot both be None in _load_bytes().")
|
|
293
296
|
|
|
@@ -308,7 +311,7 @@ class VEXLifter(SimEngineBase):
|
|
|
308
311
|
|
|
309
312
|
# Load from the clemory if we can
|
|
310
313
|
if not load_from_state or not state:
|
|
311
|
-
if isinstance(clemory, cle.Clemory):
|
|
314
|
+
if isinstance(clemory, (cle.Clemory, cle.ClemoryReadOnlyView)):
|
|
312
315
|
try:
|
|
313
316
|
start, backer = next(clemory.backers(addr))
|
|
314
317
|
except StopIteration:
|
angr/flirt/build_sig.py
CHANGED
|
@@ -22,9 +22,7 @@ def get_basic_info(ar_path: str) -> dict[str, str]:
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
with tempfile.TemporaryDirectory() as tempdirname:
|
|
25
|
-
cwd
|
|
26
|
-
os.chdir(tempdirname)
|
|
27
|
-
subprocess.call(["ar", "x", ar_path])
|
|
25
|
+
subprocess.call(["ar", "x", ar_path], cwd=tempdirname)
|
|
28
26
|
|
|
29
27
|
# Load arch and OS information from the first .o file
|
|
30
28
|
o_files = [f for f in os.listdir(".") if f.endswith(".o")]
|
|
@@ -32,8 +30,8 @@ def get_basic_info(ar_path: str) -> dict[str, str]:
|
|
|
32
30
|
proj = angr.Project(o_files[0], auto_load_libs=False)
|
|
33
31
|
arch_name = proj.arch.name.lower()
|
|
34
32
|
os_name = proj.simos.name.lower()
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
else:
|
|
34
|
+
raise ValueError("No .o files found in the archive.")
|
|
37
35
|
|
|
38
36
|
return {
|
|
39
37
|
"arch": arch_name,
|
|
@@ -64,9 +62,7 @@ def get_unique_strings(ar_path: str) -> list[str]:
|
|
|
64
62
|
# extract the archive file into a temporary directory
|
|
65
63
|
all_strings = set()
|
|
66
64
|
with tempfile.TemporaryDirectory() as tempdirname:
|
|
67
|
-
cwd
|
|
68
|
-
os.chdir(tempdirname)
|
|
69
|
-
subprocess.call(["ar", "x", ar_path])
|
|
65
|
+
subprocess.call(["ar", "x", ar_path], cwd=tempdirname)
|
|
70
66
|
|
|
71
67
|
for filename in os.listdir("."):
|
|
72
68
|
if filename.endswith(".o"):
|
|
@@ -93,8 +89,6 @@ def get_unique_strings(ar_path: str) -> list[str]:
|
|
|
93
89
|
non_symbol_strings.add(s)
|
|
94
90
|
all_strings |= non_symbol_strings
|
|
95
91
|
|
|
96
|
-
os.chdir(cwd)
|
|
97
|
-
|
|
98
92
|
grouped_strings = defaultdict(set)
|
|
99
93
|
for s in all_strings:
|
|
100
94
|
grouped_strings[s[:5]].add(s)
|
|
@@ -138,7 +132,7 @@ def process_exc_file(exc_path: str):
|
|
|
138
132
|
|
|
139
133
|
TODO: Add caller-callee-based de-duplication.
|
|
140
134
|
"""
|
|
141
|
-
with open(exc_path) as f:
|
|
135
|
+
with open(exc_path, encoding="utf-8") as f:
|
|
142
136
|
data = f.read()
|
|
143
137
|
lines = data.split("\n")
|
|
144
138
|
|
|
@@ -184,7 +178,7 @@ def process_exc_file(exc_path: str):
|
|
|
184
178
|
g[the_chosen_one] = "+" + line
|
|
185
179
|
|
|
186
180
|
# output
|
|
187
|
-
with open(exc_path, "w") as f:
|
|
181
|
+
with open(exc_path, "w", encoding="utf-8") as f:
|
|
188
182
|
for g in groups.values():
|
|
189
183
|
for line in g.values():
|
|
190
184
|
f.write(line + "\n")
|
|
@@ -273,8 +267,7 @@ def main():
|
|
|
273
267
|
basename = os.path.basename(ar_path)
|
|
274
268
|
|
|
275
269
|
# sanitize basename since otherwise sigmake is not happy with it
|
|
276
|
-
|
|
277
|
-
basename = basename[:-2]
|
|
270
|
+
basename = basename.removesuffix(".a")
|
|
278
271
|
basename = basename.replace("+", "plus")
|
|
279
272
|
|
|
280
273
|
# sanitize signame as well
|
|
@@ -292,7 +285,7 @@ def main():
|
|
|
292
285
|
|
|
293
286
|
assert not has_collision
|
|
294
287
|
|
|
295
|
-
with open(meta_path, "w") as f:
|
|
288
|
+
with open(meta_path, "w", encoding="utf-8") as f:
|
|
296
289
|
metadata = {
|
|
297
290
|
"unique_strings": unique_strings,
|
|
298
291
|
}
|
|
@@ -70,13 +70,10 @@ class Function(Serializable):
|
|
|
70
70
|
"is_simprocedure",
|
|
71
71
|
"is_syscall",
|
|
72
72
|
"normalized",
|
|
73
|
-
"prepared_registers",
|
|
74
|
-
"prepared_stack_variables",
|
|
75
73
|
"previous_names",
|
|
76
74
|
"prototype",
|
|
77
75
|
"prototype_libname",
|
|
78
76
|
"ran_cca",
|
|
79
|
-
"registers_read_afterwards",
|
|
80
77
|
"retaddr_on_stack",
|
|
81
78
|
"sp_delta",
|
|
82
79
|
"startpoint",
|
|
@@ -149,9 +146,6 @@ class Function(Serializable):
|
|
|
149
146
|
self.is_prototype_guessed: bool = True
|
|
150
147
|
# Whether this function returns or not. `None` means it's not determined yet
|
|
151
148
|
self._returning = None
|
|
152
|
-
self.prepared_registers = set()
|
|
153
|
-
self.prepared_stack_variables = set()
|
|
154
|
-
self.registers_read_afterwards = set()
|
|
155
149
|
|
|
156
150
|
self._addr_to_block_node = {} # map addresses to nodes. it's a cache of blocks. if a block is removed from the
|
|
157
151
|
# function, it may not be removed from _addr_to_block_node. if you want to list
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
# pylint:disable=super-init-not-called
|
|
1
2
|
from __future__ import annotations
|
|
2
3
|
import os
|
|
3
|
-
import networkx
|
|
4
4
|
from collections import defaultdict
|
|
5
|
+
|
|
6
|
+
import networkx
|
|
7
|
+
|
|
8
|
+
from angr.codenode import BlockNode
|
|
5
9
|
from .function import Function
|
|
6
10
|
|
|
7
11
|
|
|
@@ -88,10 +92,6 @@ class SootFunction(Function):
|
|
|
88
92
|
if hooker and hasattr(hooker, "NO_RET"):
|
|
89
93
|
self.returning = not hooker.NO_RET
|
|
90
94
|
|
|
91
|
-
self.prepared_registers = set()
|
|
92
|
-
self.prepared_stack_variables = set()
|
|
93
|
-
self.registers_read_afterwards = set()
|
|
94
|
-
|
|
95
95
|
# startpoint can always be None if this CFGNode is a syscall node
|
|
96
96
|
self.startpoint = None
|
|
97
97
|
|
|
@@ -126,6 +126,3 @@ class SootFunction(Function):
|
|
|
126
126
|
if isinstance(node, BlockNode) and node.addr not in self._addr_to_block_node:
|
|
127
127
|
self._addr_to_block_node[node.addr] = node
|
|
128
128
|
return node
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
from angr.codenode import BlockNode
|