angr 9.2.120__py3-none-win_amd64.whl → 9.2.121__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.

Files changed (76) hide show
  1. angr/__init__.py +1 -1
  2. angr/analyses/cfg/cfg_fast.py +2 -1
  3. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +2 -0
  4. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +2 -0
  5. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +10 -6
  6. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +138 -367
  7. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
  8. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +20 -0
  9. angr/analyses/typehoon/typevars.py +37 -16
  10. angr/angrdb/db.py +1 -1
  11. angr/block.py +9 -1
  12. angr/calling_conventions.py +1 -1
  13. angr/engines/engine.py +8 -15
  14. angr/engines/pcode/lifter.py +8 -0
  15. angr/engines/successors.py +1 -1
  16. angr/engines/vex/claripy/ccall.py +1 -1
  17. angr/engines/vex/claripy/datalayer.py +7 -10
  18. angr/engines/vex/heavy/actions.py +19 -24
  19. angr/engines/vex/heavy/heavy.py +7 -1
  20. angr/engines/vex/lifter.py +3 -1
  21. angr/engines/vex/light/light.py +2 -2
  22. angr/factory.py +5 -0
  23. angr/knowledge_plugins/cfg/memory_data.py +1 -0
  24. angr/lib/angr_native.dll +0 -0
  25. angr/protos/cfg_pb2.py +23 -15
  26. angr/protos/function_pb2.py +19 -21
  27. angr/protos/primitives_pb2.py +46 -112
  28. angr/protos/variables_pb2.py +38 -114
  29. angr/protos/xrefs_pb2.py +17 -18
  30. angr/sim_state.py +2 -78
  31. angr/state_plugins/solver.py +72 -15
  32. angr/storage/__init__.py +1 -2
  33. angr/storage/memory_mixins/__init__.py +5 -160
  34. angr/storage/memory_mixins/actions_mixin.py +1 -1
  35. angr/storage/memory_mixins/address_concretization_mixin.py +1 -1
  36. angr/storage/memory_mixins/bvv_conversion_mixin.py +1 -1
  37. angr/storage/memory_mixins/clouseau_mixin.py +2 -1
  38. angr/storage/memory_mixins/conditional_store_mixin.py +1 -1
  39. angr/storage/memory_mixins/convenient_mappings_mixin.py +1 -1
  40. angr/storage/memory_mixins/default_filler_mixin.py +1 -1
  41. angr/storage/memory_mixins/dirty_addrs_mixin.py +2 -1
  42. angr/storage/memory_mixins/hex_dumper_mixin.py +1 -1
  43. angr/storage/memory_mixins/javavm_memory_mixin.py +1 -1
  44. angr/storage/memory_mixins/keyvalue_memory_mixin.py +1 -1
  45. angr/storage/memory_mixins/label_merger_mixin.py +1 -1
  46. angr/storage/memory_mixins/memory_mixin.py +163 -0
  47. angr/storage/memory_mixins/multi_value_merger_mixin.py +1 -1
  48. angr/storage/memory_mixins/name_resolution_mixin.py +3 -1
  49. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +1 -1
  50. angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +2 -1
  51. angr/storage/memory_mixins/paged_memory/pages/__init__.py +1 -1
  52. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +1 -1
  53. angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +2 -1
  54. angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +1 -1
  55. angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +2 -1
  56. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +1 -1
  57. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +1 -2
  58. angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +2 -1
  59. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +1 -1
  60. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +1 -1
  61. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +2 -2
  62. angr/storage/memory_mixins/simple_interface_mixin.py +2 -1
  63. angr/storage/memory_mixins/simplification_mixin.py +2 -1
  64. angr/storage/memory_mixins/size_resolution_mixin.py +1 -1
  65. angr/storage/memory_mixins/slotted_memory.py +2 -2
  66. angr/storage/memory_mixins/smart_find_mixin.py +1 -1
  67. angr/storage/memory_mixins/symbolic_merger_mixin.py +2 -1
  68. angr/storage/memory_mixins/top_merger_mixin.py +3 -2
  69. angr/storage/memory_mixins/underconstrained_mixin.py +4 -2
  70. angr/storage/memory_mixins/unwrapper_mixin.py +2 -1
  71. {angr-9.2.120.dist-info → angr-9.2.121.dist-info}/METADATA +7 -7
  72. {angr-9.2.120.dist-info → angr-9.2.121.dist-info}/RECORD +76 -74
  73. {angr-9.2.120.dist-info → angr-9.2.121.dist-info}/LICENSE +0 -0
  74. {angr-9.2.120.dist-info → angr-9.2.121.dist-info}/WHEEL +0 -0
  75. {angr-9.2.120.dist-info → angr-9.2.121.dist-info}/entry_points.txt +0 -0
  76. {angr-9.2.120.dist-info → angr-9.2.121.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,148 @@
1
+ # pylint:disable=too-many-positional-arguments
2
+ from __future__ import annotations
3
+ import logging
4
+
5
+ from capstone.mips_const import (
6
+ MIPS_REG_T7,
7
+ MIPS_REG_T8,
8
+ MIPS_REG_T9,
9
+ MIPS_REG_RA,
10
+ MIPS_REG_ZERO,
11
+ MIPS_OP_REG,
12
+ MIPS_OP_IMM,
13
+ )
14
+
15
+ import cle
16
+
17
+ from .resolver import IndirectJumpResolver
18
+
19
+ l = logging.getLogger(name=__name__)
20
+
21
+
22
+ class MipsElfGotResolver(IndirectJumpResolver):
23
+ """
24
+ A timeless indirect jump resolver that resolves GOT stub entries in MIPS ELF binaries.
25
+
26
+ Reference: MIPS Assembly Language Programmer's Guide, Calling Position Independent Functions
27
+ """
28
+
29
+ def __init__(self, project):
30
+ super().__init__(project, timeless=True)
31
+
32
+ self._section_cache: dict[tuple[int, str], int] = {}
33
+ self._simproc_cache: dict[str, int] | None = None
34
+
35
+ def filter(self, cfg, addr, func_addr, block, jumpkind):
36
+ return jumpkind == "Ijk_Call" and addr == func_addr
37
+
38
+ def resolve( # pylint:disable=unused-argument
39
+ self, cfg, addr, func_addr, block, jumpkind, func_graph_complete: bool = True, **kwargs
40
+ ):
41
+ # The stub must look like the following:
42
+ # 585b80 lw $t9, -0x7ff0($gp)
43
+ # 585b84 move $t7, $ra
44
+ # 585b88 jalr $t9
45
+ # 585b8c addiu $t8, $zero, 0x84b
46
+
47
+ obj = self.project.loader.find_object_containing(addr)
48
+ if obj is None:
49
+ return False, []
50
+ if not isinstance(obj, cle.ELF):
51
+ return False, []
52
+ dynsym_addr = self._find_and_cache_section_addr(obj, ".dynsym")
53
+ if dynsym_addr is None:
54
+ return None
55
+
56
+ dynstr_addr = self._find_and_cache_section_addr(obj, ".dynstr")
57
+ if dynstr_addr is None:
58
+ return None
59
+
60
+ if block.size != 16:
61
+ return False, []
62
+ the_block = self.project.factory.block(block.addr, size=block.size)
63
+ if len(the_block.capstone.insns) != 4:
64
+ return False, []
65
+
66
+ insn0 = the_block.capstone.insns[0]
67
+ if not (
68
+ insn0.insn.mnemonic == "lw"
69
+ and insn0.insn.operands[0].type == MIPS_OP_REG
70
+ and insn0.insn.operands[0].reg == MIPS_REG_T9
71
+ ):
72
+ return False, []
73
+
74
+ insn1 = the_block.capstone.insns[1]
75
+ if not (
76
+ insn1.insn.mnemonic == "move"
77
+ and insn1.insn.operands[0].type == MIPS_OP_REG
78
+ and insn1.insn.operands[0].reg == MIPS_REG_T7
79
+ and insn1.insn.operands[1].type == MIPS_OP_REG
80
+ and insn1.insn.operands[1].reg == MIPS_REG_RA
81
+ ):
82
+ return False, []
83
+
84
+ insn2 = the_block.capstone.insns[2]
85
+ if not (
86
+ insn2.insn.mnemonic == "jalr"
87
+ and insn2.insn.operands[0].type == MIPS_OP_REG
88
+ and insn2.insn.operands[0].reg == MIPS_REG_T9
89
+ ):
90
+ return False, []
91
+
92
+ insn3 = the_block.capstone.insns[3]
93
+ if not (
94
+ insn3.insn.mnemonic == "addiu"
95
+ and insn3.insn.operands[0].type == MIPS_OP_REG
96
+ and insn3.insn.operands[0].reg == MIPS_REG_T8
97
+ and insn3.insn.operands[1].type == MIPS_OP_REG
98
+ and insn3.insn.operands[1].reg == MIPS_REG_ZERO
99
+ and insn3.insn.operands[2].type == MIPS_OP_IMM
100
+ ):
101
+ return False, []
102
+
103
+ dynsym_index = insn3.insn.operands[2].imm
104
+ symbol_addr = dynsym_addr + dynsym_index * 16
105
+
106
+ symbol_name_index = self.project.loader.memory.unpack_word(symbol_addr, size=4)
107
+ symbol_name_addr = dynstr_addr + symbol_name_index
108
+ symbol_name_bytes = self.project.loader.memory.load_null_terminated_bytes(symbol_name_addr, 512)
109
+
110
+ try:
111
+ symbol_name = symbol_name_bytes.strip(b"\x00").decode("ascii")
112
+ except UnicodeDecodeError:
113
+ return False, []
114
+
115
+ symbol = obj.symbols_by_name.get(symbol_name, None)
116
+ if symbol is None:
117
+ return False, []
118
+
119
+ if symbol.rebased_addr != func_addr:
120
+ l.debug("Resolved target to %s @ %#x", symbol_name, symbol.rebased_addr)
121
+ return True, [symbol.rebased_addr]
122
+
123
+ # find out if there is a SimProcedure for this import symbol
124
+ simproc_addr = self._cache_and_find_simproc_by_name(symbol_name)
125
+ if simproc_addr is not None:
126
+ l.debug("Resolved target to %s @ %#x", symbol_name, simproc_addr)
127
+ return True, [simproc_addr]
128
+ return False, []
129
+
130
+ def _find_and_cache_section_addr(self, obj, section_name: str) -> int | None:
131
+ cache_key = (obj.min_addr, section_name)
132
+ if cache_key in self._section_cache:
133
+ return self._section_cache[cache_key]
134
+
135
+ for sec in obj.sections:
136
+ if sec.name == section_name:
137
+ # cache it
138
+ self._section_cache[cache_key] = sec.vaddr
139
+ return sec.vaddr
140
+ return None
141
+
142
+ def _cache_and_find_simproc_by_name(self, symbol_name: str) -> int | None:
143
+ if self._simproc_cache is None:
144
+ self._simproc_cache = {}
145
+ for addr, simproc in self.project._sim_procedures.items():
146
+ self._simproc_cache[simproc.display_name] = addr
147
+
148
+ return self._simproc_cache.get(symbol_name)
@@ -240,6 +240,26 @@ class AMD64CCallRewriter(CCallRewriterBase):
240
240
 
241
241
  r = Expr.BinaryOp(ccall.idx, expr_op, (masked_dep, zero), False, **ccall.tags)
242
242
  return Expr.Convert(None, r.bits, ccall.bits, False, r, **ccall.tags)
243
+ if op_v in {
244
+ AMD64_OpTypes["G_CC_OP_DECB"],
245
+ AMD64_OpTypes["G_CC_OP_DECW"],
246
+ AMD64_OpTypes["G_CC_OP_DECL"],
247
+ AMD64_OpTypes["G_CC_OP_DECQ"],
248
+ }:
249
+ # dep_1 == 0 or dep_1 != 0
250
+ dep_1 = self._fix_size(
251
+ dep_1,
252
+ op_v,
253
+ AMD64_OpTypes["G_CC_OP_SHRB"],
254
+ AMD64_OpTypes["G_CC_OP_SHRW"],
255
+ AMD64_OpTypes["G_CC_OP_SHRL"],
256
+ ccall.tags,
257
+ )
258
+ expr_op = "CmpEQ" if cond_v == AMD64_CondTypes["CondZ"] else "CmpNE"
259
+
260
+ zero = Expr.Const(None, None, 0, dep_1.bits)
261
+ r = Expr.BinaryOp(ccall.idx, expr_op, (dep_1, zero), False, **ccall.tags)
262
+ return Expr.Convert(None, r.bits, ccall.bits, False, r, **ccall.tags)
243
263
  elif cond_v == AMD64_CondTypes["CondL"]:
244
264
  if op_v in {
245
265
  AMD64_OpTypes["G_CC_OP_SUBB"],
@@ -28,11 +28,13 @@ class Equivalence(TypeConstraint):
28
28
  __slots__ = (
29
29
  "type_a",
30
30
  "type_b",
31
+ "_cached_hash",
31
32
  )
32
33
 
33
34
  def __init__(self, type_a, type_b):
34
35
  self.type_a = type_a
35
36
  self.type_b = type_b
37
+ self._cached_hash = hash((Equivalence, self.type_a, self.type_b))
36
38
 
37
39
  def pp_str(self, mapping: dict[TypeVariable, Any]) -> str:
38
40
  return f"{self.type_a.pp_str(mapping)} == {self.type_b.pp_str(mapping)}"
@@ -49,14 +51,15 @@ class Equivalence(TypeConstraint):
49
51
  )
50
52
 
51
53
  def __hash__(self):
52
- return hash((Equivalence, tuple(sorted((hash(self.type_a), hash(self.type_b))))))
54
+ return self._cached_hash
53
55
 
54
56
 
55
57
  class Existence(TypeConstraint):
56
- __slots__ = ("type_",)
58
+ __slots__ = ("type_", "_cached_hash")
57
59
 
58
60
  def __init__(self, type_):
59
61
  self.type_ = type_
62
+ self._cached_hash = hash((Existence, self.type_))
60
63
 
61
64
  def pp_str(self, mapping: dict[TypeVariable, Any]) -> str:
62
65
  return f"V {self.type_.pp_str(mapping)}"
@@ -68,7 +71,7 @@ class Existence(TypeConstraint):
68
71
  return type(other) is Existence and self.type_ == other.type_
69
72
 
70
73
  def __hash__(self):
71
- return hash((Existence, self.type_))
74
+ return self._cached_hash
72
75
 
73
76
  def replace(self, replacements):
74
77
  if self.type_ in replacements:
@@ -84,11 +87,13 @@ class Subtype(TypeConstraint):
84
87
  __slots__ = (
85
88
  "super_type",
86
89
  "sub_type",
90
+ "_cached_hash",
87
91
  )
88
92
 
89
93
  def __init__(self, sub_type: TypeType, super_type: TypeType):
90
94
  self.super_type = super_type
91
95
  self.sub_type = sub_type
96
+ self._cached_hash = hash((Subtype, self.sub_type, self.super_type))
92
97
 
93
98
  def pp_str(self, mapping: dict[TypeVariable, Any]) -> str:
94
99
  return f"{self.sub_type.pp_str(mapping)} <: {self.super_type.pp_str(mapping)}"
@@ -100,7 +105,7 @@ class Subtype(TypeConstraint):
100
105
  return type(other) is Subtype and self.sub_type == other.sub_type and self.super_type == other.super_type
101
106
 
102
107
  def __hash__(self):
103
- return hash((Subtype, hash(self.sub_type), hash(self.super_type)))
108
+ return self._cached_hash
104
109
 
105
110
  def replace(self, replacements):
106
111
  subtype, supertype = None, None
@@ -139,12 +144,14 @@ class Add(TypeConstraint):
139
144
  "type_0",
140
145
  "type_1",
141
146
  "type_r",
147
+ "_cached_hash",
142
148
  )
143
149
 
144
150
  def __init__(self, type_0, type_1, type_r):
145
151
  self.type_0 = type_0
146
152
  self.type_1 = type_1
147
153
  self.type_r = type_r
154
+ self._cached_hash = hash((Add, self.type_0, self.type_1, self.type_r))
148
155
 
149
156
  def pp_str(self, mapping: dict[TypeVariable, Any]) -> str:
150
157
  return f"{self.type_r.pp_str(mapping)} == {self.type_0.pp_str(mapping)} + {self.type_1.pp_str(mapping)}"
@@ -161,7 +168,7 @@ class Add(TypeConstraint):
161
168
  )
162
169
 
163
170
  def __hash__(self):
164
- return hash((Add, self.type_0, self.type_1, self.type_r))
171
+ return self._cached_hash
165
172
 
166
173
  def replace(self, replacements):
167
174
  t0, t1, tr = None, None, None
@@ -206,12 +213,14 @@ class Sub(TypeConstraint):
206
213
  "type_0",
207
214
  "type_1",
208
215
  "type_r",
216
+ "_cached_hash",
209
217
  )
210
218
 
211
219
  def __init__(self, type_0, type_1, type_r):
212
220
  self.type_0 = type_0
213
221
  self.type_1 = type_1
214
222
  self.type_r = type_r
223
+ self._cached_hash = hash((Sub, self.type_0, self.type_1, self.type_r))
215
224
 
216
225
  def pp_str(self, mapping: dict[TypeVariable, Any]) -> str:
217
226
  return f"{self.type_r.pp_str(mapping)} == {self.type_0.pp_str(mapping)} - {self.type_1.pp_str(mapping)}"
@@ -228,7 +237,7 @@ class Sub(TypeConstraint):
228
237
  )
229
238
 
230
239
  def __hash__(self):
231
- return hash((Sub, self.type_0, self.type_1, self.type_r))
240
+ return self._cached_hash
232
241
 
233
242
  def replace(self, replacements):
234
243
  t0, t1, tr = None, None, None
@@ -268,7 +277,7 @@ _typevariable_counter = count()
268
277
 
269
278
 
270
279
  class TypeVariable:
271
- __slots__ = ("idx", "name")
280
+ __slots__ = ("idx", "name", "_cached_hash")
272
281
 
273
282
  def __init__(self, idx: int | None = None, name: str | None = None):
274
283
  if idx is None:
@@ -277,6 +286,8 @@ class TypeVariable:
277
286
  self.idx: int = idx
278
287
  self.name = name
279
288
 
289
+ self._cached_hash = hash((TypeVariable, self.name if self.name else self.idx))
290
+
280
291
  def pp_str(self, mapping: dict[TypeVariable, Any]) -> str:
281
292
  varname = mapping.get(self, self.name)
282
293
  if varname is None:
@@ -291,12 +302,10 @@ class TypeVariable:
291
302
  return self.idx == other.idx
292
303
 
293
304
  def _hash(self, visited=None): # pylint:disable=unused-argument
294
- if self.name:
295
- return hash((TypeVariable, self.name))
296
- return hash((TypeVariable, self.idx))
305
+ return self._cached_hash
297
306
 
298
307
  def __hash__(self):
299
- return self._hash()
308
+ return self._cached_hash
300
309
 
301
310
  def __repr__(self):
302
311
  if self.name:
@@ -336,6 +345,8 @@ class DerivedTypeVariable(TypeVariable):
336
345
  if not self.labels:
337
346
  raise ValueError("A DerivedTypeVariable must have at least one label")
338
347
 
348
+ self._cached_hash = hash((DerivedTypeVariable, self.type_var, self.labels))
349
+
339
350
  def one_label(self) -> BaseLabel | None:
340
351
  return self.labels[0] if len(self.labels) == 1 else None
341
352
 
@@ -358,10 +369,10 @@ class DerivedTypeVariable(TypeVariable):
358
369
  )
359
370
 
360
371
  def _hash(self, visited=None):
361
- return hash((DerivedTypeVariable, self.type_var, self.labels))
372
+ return self._cached_hash
362
373
 
363
374
  def __hash__(self):
364
- return self._hash()
375
+ return self._cached_hash
365
376
 
366
377
  def __repr__(self):
367
378
  return ".".join([repr(self.type_var)] + [repr(lbl) for lbl in self.labels])
@@ -437,13 +448,16 @@ class TypeVariables:
437
448
 
438
449
 
439
450
  class BaseLabel:
440
- __slots__ = ()
451
+ __slots__ = ("_cached_hash",)
452
+
453
+ def __init__(self):
454
+ self._cached_hash = hash((type(self), *tuple(getattr(self, k) for k in self.__slots__ if k != "_cached_hash")))
441
455
 
442
456
  def __eq__(self, other):
443
- return type(self) is type(other) and hash(self) == hash(other)
457
+ return type(self) is type(other) and self._cached_hash == other._cached_hash
444
458
 
445
459
  def __hash__(self):
446
- return hash((type(self), *tuple(getattr(self, k) for k in self.__slots__)))
460
+ return self._cached_hash
447
461
 
448
462
  @property
449
463
  def variance(self) -> Variance:
@@ -455,6 +469,7 @@ class FuncIn(BaseLabel):
455
469
 
456
470
  def __init__(self, loc):
457
471
  self.loc = loc
472
+ super().__init__()
458
473
 
459
474
  def __repr__(self):
460
475
  return f"in<{self.loc}>"
@@ -465,6 +480,7 @@ class FuncOut(BaseLabel):
465
480
 
466
481
  def __init__(self, loc):
467
482
  self.loc = loc
483
+ super().__init__()
468
484
 
469
485
  def __repr__(self):
470
486
  return f"out<{self.loc}>"
@@ -493,6 +509,7 @@ class AddN(BaseLabel):
493
509
 
494
510
  def __init__(self, n):
495
511
  self.n = n
512
+ super().__init__()
496
513
 
497
514
  def __repr__(self):
498
515
  return "+%d" % self.n
@@ -503,6 +520,7 @@ class SubN(BaseLabel):
503
520
 
504
521
  def __init__(self, n):
505
522
  self.n = n
523
+ super().__init__()
506
524
 
507
525
  def __repr__(self):
508
526
  return "-%d" % self.n
@@ -513,6 +531,7 @@ class ConvertTo(BaseLabel):
513
531
 
514
532
  def __init__(self, to_bits):
515
533
  self.to_bits = to_bits
534
+ super().__init__()
516
535
 
517
536
  def __repr__(self):
518
537
  return "conv(%d)" % self.to_bits
@@ -527,6 +546,7 @@ class ReinterpretAs(BaseLabel):
527
546
  def __init__(self, to_type, to_bits):
528
547
  self.to_type = to_type
529
548
  self.to_bits = to_bits
549
+ super().__init__()
530
550
 
531
551
  def __repr__(self):
532
552
  return f"reinterpret({self.to_type}{self.to_bits})"
@@ -541,6 +561,7 @@ class HasField(BaseLabel):
541
561
  def __init__(self, bits, offset):
542
562
  self.bits = bits
543
563
  self.offset = offset
564
+ super().__init__()
544
565
 
545
566
  def __repr__(self):
546
567
  if self.bits == MAX_POINTSTO_BITS:
angr/angrdb/db.py CHANGED
@@ -43,7 +43,7 @@ class AngrDB:
43
43
  except DatabaseError as ex:
44
44
  raise AngrCorruptDBError("The target file may not be an angr database or it is corrupted.") from ex
45
45
  except Exception as ex:
46
- raise AngrDBError(str(ex)) from ex
46
+ raise AngrDBError from ex
47
47
 
48
48
  @staticmethod
49
49
  @contextmanager
angr/block.py CHANGED
@@ -142,6 +142,7 @@ class Block(Serializable):
142
142
  "_strict_block_end",
143
143
  "_cross_insn_opt",
144
144
  "_load_from_ro_regions",
145
+ "_const_prop",
145
146
  "_initial_regs",
146
147
  ]
147
148
 
@@ -164,6 +165,7 @@ class Block(Serializable):
164
165
  collect_data_refs=False,
165
166
  cross_insn_opt=True,
166
167
  load_from_ro_regions=False,
168
+ const_prop=False,
167
169
  initial_regs=None,
168
170
  skip_stmts=False,
169
171
  ):
@@ -191,7 +193,9 @@ class Block(Serializable):
191
193
  self.thumb = thumb
192
194
  self.addr = addr
193
195
  self._opt_level = opt_level
194
- self._initial_regs: list[tuple[int, int, int]] | None = initial_regs if collect_data_refs else None
196
+ self._initial_regs: list[tuple[int, int, int]] | None = (
197
+ initial_regs if (collect_data_refs or const_prop) else None
198
+ )
195
199
 
196
200
  if self._project is None and byte_string is None:
197
201
  raise ValueError('"byte_string" has to be specified if "project" is not provided.')
@@ -218,6 +222,7 @@ class Block(Serializable):
218
222
  strict_block_end=strict_block_end,
219
223
  collect_data_refs=collect_data_refs,
220
224
  load_from_ro_regions=load_from_ro_regions,
225
+ const_prop=const_prop,
221
226
  cross_insn_opt=cross_insn_opt,
222
227
  skip_stmts=skip_stmts,
223
228
  )
@@ -238,6 +243,7 @@ class Block(Serializable):
238
243
  self._strict_block_end = strict_block_end
239
244
  self._cross_insn_opt = cross_insn_opt
240
245
  self._load_from_ro_regions = load_from_ro_regions
246
+ self._const_prop = const_prop
241
247
 
242
248
  self._instructions = num_inst
243
249
  self._instruction_addrs: list[int] = []
@@ -342,6 +348,7 @@ class Block(Serializable):
342
348
  strict_block_end=self._strict_block_end,
343
349
  cross_insn_opt=self._cross_insn_opt,
344
350
  load_from_ro_regions=self._load_from_ro_regions,
351
+ const_prop=self._const_prop,
345
352
  )
346
353
  if self._initial_regs:
347
354
  self.reset_initial_regs()
@@ -373,6 +380,7 @@ class Block(Serializable):
373
380
  strict_block_end=self._strict_block_end,
374
381
  cross_insn_opt=self._cross_insn_opt,
375
382
  load_from_ro_regions=self._load_from_ro_regions,
383
+ const_prop=self._const_prop,
376
384
  )
377
385
  if self._initial_regs:
378
386
  self.reset_initial_regs()
@@ -69,7 +69,7 @@ class AllocHelper:
69
69
  val.struct, {field: self.translate(subval, base) for field, subval in val._values.items()}
70
70
  )
71
71
  if isinstance(val, claripy.ast.Bits):
72
- return val.replace(self.base, base)
72
+ return claripy.replace(val, self.base, base)
73
73
  if type(val) is list:
74
74
  return [self.translate(subval, base) for subval in val]
75
75
  raise TypeError(type(val))
angr/engines/engine.py CHANGED
@@ -4,10 +4,16 @@ from __future__ import annotations
4
4
  import abc
5
5
  import logging
6
6
  import threading
7
- import angr
8
7
 
9
8
  from archinfo.arch_soot import SootAddressDescriptor
10
9
 
10
+ import angr
11
+ from angr import sim_options as o
12
+ from angr.errors import SimException
13
+ from angr.state_plugins.inspect import BP_AFTER, BP_BEFORE
14
+
15
+ from .successors import SimSuccessors
16
+
11
17
  l = logging.getLogger(name=__name__)
12
18
 
13
19
 
@@ -32,12 +38,6 @@ class SimEngineBase:
32
38
  self.project = state[0]
33
39
  self.state = None
34
40
 
35
- def _is_true(self, v):
36
- return v is True
37
-
38
- def _is_false(self, v):
39
- return v is False
40
-
41
41
 
42
42
  class SimEngine(SimEngineBase, metaclass=abc.ABCMeta):
43
43
  """
@@ -183,7 +183,7 @@ class SuccessorsMixin(SimEngine):
183
183
 
184
184
  return self.successors
185
185
 
186
- def process_successors(self, successors, **kwargs):
186
+ def process_successors(self, successors, **kwargs): # pylint:disable=unused-argument
187
187
  """
188
188
  Implement this function to fill out the SimSuccessors object with the results of stepping state.
189
189
 
@@ -201,10 +201,3 @@ class SuccessorsMixin(SimEngine):
201
201
  :param kwargs: Any extra arguments. Do not fail if you are passed unexpected arguments.
202
202
  """
203
203
  successors.processed = False # mark failure
204
-
205
-
206
- # pylint:disable=wrong-import-position
207
- from angr import sim_options as o
208
- from angr.state_plugins.inspect import BP_BEFORE, BP_AFTER
209
- from .successors import SimSuccessors
210
- from angr.errors import SimException
@@ -122,6 +122,7 @@ class IRSB:
122
122
  "arch",
123
123
  "behaviors",
124
124
  "data_refs",
125
+ "const_vals",
125
126
  "default_exit_target",
126
127
  "jumpkind",
127
128
  "next",
@@ -138,6 +139,7 @@ class IRSB:
138
139
  arch: archinfo.Arch
139
140
  behaviors: BehaviorFactory | None
140
141
  data_refs: Sequence # Note: currently unused
142
+ const_vals: Sequence # Note: currently unused
141
143
  default_exit_target: Optional # Note: currently used
142
144
  jumpkind: str | None
143
145
  next: int | None
@@ -204,6 +206,7 @@ class IRSB:
204
206
  self.arch = arch
205
207
  self.behaviors = None
206
208
  self.data_refs = ()
209
+ self.const_vals = ()
207
210
  self.default_exit_target = None
208
211
  self.jumpkind = None
209
212
  self.next = None
@@ -1043,6 +1046,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
1043
1046
  collect_data_refs: bool = False,
1044
1047
  load_from_ro_regions: bool = False,
1045
1048
  cross_insn_opt: bool | None = None,
1049
+ const_prop: bool | None = None,
1046
1050
  ):
1047
1051
  """
1048
1052
  Temporary compatibility interface for integration with block code.
@@ -1064,6 +1068,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
1064
1068
  collect_data_refs,
1065
1069
  load_from_ro_regions,
1066
1070
  cross_insn_opt,
1071
+ const_prop,
1067
1072
  )
1068
1073
 
1069
1074
  def lift_pcode(
@@ -1084,6 +1089,7 @@ class PcodeLifterEngineMixin(SimEngineBase):
1084
1089
  collect_data_refs: bool = False,
1085
1090
  load_from_ro_regions: bool = False,
1086
1091
  cross_insn_opt: bool | None = None,
1092
+ const_prop: bool | None = None,
1087
1093
  ):
1088
1094
  """
1089
1095
  Lift an IRSB.
@@ -1111,6 +1117,8 @@ class PcodeLifterEngineMixin(SimEngineBase):
1111
1117
  """
1112
1118
  if cross_insn_opt:
1113
1119
  l.debug("cross_insn_opt is ignored for p-code lifter")
1120
+ if const_prop:
1121
+ l.debug("const_prop is ignored for p-code lifter")
1114
1122
  if load_from_ro_regions:
1115
1123
  l.debug("load_from_ro_regions is ignored for p-code lifter")
1116
1124
 
@@ -356,7 +356,7 @@ class SimSuccessors:
356
356
  if o.KEEP_IP_SYMBOLIC in split_state.options:
357
357
  split_state.regs.ip = target
358
358
  else:
359
- split_state.add_constraints(cond, action=True)
359
+ split_state.add_constraints(cond)
360
360
  split_state.regs.ip = a
361
361
  if split_state.supports_inspect:
362
362
  split_state.inspect.downsize()
@@ -43,7 +43,7 @@ def boolean_extend(O, a, b, size):
43
43
  def op_concretize(op):
44
44
  if type(op) is int:
45
45
  return op
46
- op_e = op.ite_excavated
46
+ op_e = claripy.excavate_ite(op)
47
47
  if op_e.op == "If":
48
48
  cases = list(claripy.reverse_ite_cases(op_e))
49
49
  if all(c.op == "BVV" for _, c in cases):
@@ -1,14 +1,15 @@
1
1
  from __future__ import annotations
2
+
2
3
  import logging
3
4
 
4
5
  import claripy
5
6
  import pyvex
6
7
 
7
- from . import irop
8
- from . import ccall
9
- from angr.engines.vex.light import VEXMixin
10
8
  from angr import errors
11
9
  from angr import sim_options as o
10
+ from angr.engines.vex.light import VEXMixin
11
+
12
+ from . import ccall, irop
12
13
 
13
14
  l = logging.getLogger(__name__)
14
15
  zero = claripy.BVV(0, 32)
@@ -39,13 +40,8 @@ class ClaripyDataMixin(VEXMixin):
39
40
 
40
41
  # util methods
41
42
 
42
- def _is_true(self, v):
43
- return claripy.is_true(v)
44
-
45
- def _is_false(self, v):
46
- return claripy.is_false(v)
47
-
48
- def _optimize_guarded_addr(self, addr, guard):
43
+ @staticmethod
44
+ def _optimize_guarded_addr(addr, guard):
49
45
  # optimization: is the guard the same as the condition inside the address? if so, unpack the address and remove
50
46
  # the guarding condition.
51
47
  if (
@@ -65,6 +61,7 @@ class ClaripyDataMixin(VEXMixin):
65
61
 
66
62
  # statements
67
63
 
64
+ # pylint: disable=too-many-positional-arguments
68
65
  def _perform_vex_stmt_LoadG(self, addr, alt, guard, dst, cvt, end):
69
66
  addr = self._optimize_guarded_addr(addr, guard)
70
67
  super()._perform_vex_stmt_LoadG(addr, alt, guard, dst, cvt, end)