angr 9.2.75__py3-none-manylinux2014_x86_64.whl → 9.2.77__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/cfg/cfg_fast.py +37 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +7 -1
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +7 -1
- angr/analyses/decompiler/clinic.py +4 -1
- angr/analyses/decompiler/condition_processor.py +4 -0
- angr/analyses/decompiler/decompiler.py +4 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +4 -3
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +1 -1
- angr/analyses/decompiler/structured_codegen/c.py +32 -21
- angr/analyses/propagator/engine_ail.py +1 -1
- angr/analyses/reaching_definitions/engine_ail.py +3 -6
- angr/analyses/reaching_definitions/engine_vex.py +32 -2
- angr/analyses/reaching_definitions/function_handler.py +1 -1
- angr/analyses/reaching_definitions/rd_initializer.py +6 -6
- angr/analyses/reaching_definitions/rd_state.py +9 -11
- angr/analyses/typehoon/typevars.py +19 -29
- angr/analyses/variable_recovery/irsb_scanner.py +16 -0
- angr/analyses/variable_recovery/variable_recovery_fast.py +33 -31
- angr/engines/light/engine.py +1 -1
- angr/keyed_region.py +19 -3
- angr/knowledge_plugins/cfg/cfg_model.py +25 -16
- angr/knowledge_plugins/cfg/memory_data.py +1 -1
- angr/knowledge_plugins/functions/function.py +8 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +53 -44
- angr/knowledge_plugins/key_definitions/liveness.py +102 -34
- angr/knowledge_plugins/key_definitions/rd_model.py +4 -4
- angr/knowledge_plugins/propagations/states.py +3 -1
- angr/knowledge_plugins/variables/variable_manager.py +51 -25
- angr/misc/bug_report.py +2 -2
- angr/sim_type.py +46 -0
- angr/storage/memory_mixins/__init__.py +3 -2
- angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +63 -0
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +5 -0
- {angr-9.2.75.dist-info → angr-9.2.77.dist-info}/METADATA +6 -6
- {angr-9.2.75.dist-info → angr-9.2.77.dist-info}/RECORD +50 -49
- tests/analyses/cfg/test_cfgfast.py +21 -0
- tests/analyses/decompiler/test_decompiler.py +22 -1
- tests/analyses/test_flirt.py +3 -1
- tests/analyses/test_identifier.py +2 -0
- tests/engines/test_unicorn.py +4 -0
- tests/exploration_techniques/test_driller_core.py +4 -0
- tests/exploration_techniques/test_oppologist.py +2 -0
- tests/exploration_techniques/test_tracer.py +9 -0
- tests/procedures/libc/test_string.py +2 -1
- tests/sim/options/test_0div.py +2 -0
- tests/state_plugins/posix/test_files.py +2 -0
- {angr-9.2.75.dist-info → angr-9.2.77.dist-info}/LICENSE +0 -0
- {angr-9.2.75.dist-info → angr-9.2.77.dist-info}/WHEEL +0 -0
- {angr-9.2.75.dist-info → angr-9.2.77.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
angr/analyses/cfg/cfg_fast.py
CHANGED
|
@@ -1017,6 +1017,40 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1017
1017
|
# no string is found
|
|
1018
1018
|
return 0
|
|
1019
1019
|
|
|
1020
|
+
def _scan_for_printable_widestrings(self, start_addr: int):
|
|
1021
|
+
addr = start_addr
|
|
1022
|
+
sz = []
|
|
1023
|
+
is_sz = True
|
|
1024
|
+
|
|
1025
|
+
# Get data until we meet two null bytes
|
|
1026
|
+
while self._inside_regions(addr):
|
|
1027
|
+
l.debug("Searching address %x", addr)
|
|
1028
|
+
val0 = self._load_a_byte_as_int(addr)
|
|
1029
|
+
if val0 is None:
|
|
1030
|
+
break
|
|
1031
|
+
val1 = self._load_a_byte_as_int(addr + 1)
|
|
1032
|
+
if val1 is None:
|
|
1033
|
+
break
|
|
1034
|
+
if val0 == 0 and val1 == 0:
|
|
1035
|
+
if len(sz) <= 10:
|
|
1036
|
+
is_sz = False
|
|
1037
|
+
break
|
|
1038
|
+
if val0 != 0 and val1 == 0 and val0 in self.PRINTABLES:
|
|
1039
|
+
sz += [val0, val1]
|
|
1040
|
+
addr += 2
|
|
1041
|
+
continue
|
|
1042
|
+
|
|
1043
|
+
is_sz = False
|
|
1044
|
+
break
|
|
1045
|
+
|
|
1046
|
+
if sz and is_sz:
|
|
1047
|
+
l.debug("Got a wide-string of %d wide chars", len(sz))
|
|
1048
|
+
string_length = len(sz) + 2
|
|
1049
|
+
return string_length
|
|
1050
|
+
|
|
1051
|
+
# no wide string is found
|
|
1052
|
+
return 0
|
|
1053
|
+
|
|
1020
1054
|
def _scan_for_repeating_bytes(self, start_addr, repeating_byte, threshold=2):
|
|
1021
1055
|
"""
|
|
1022
1056
|
Scan from a given address and determine the occurrences of a given byte.
|
|
@@ -1061,6 +1095,9 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1061
1095
|
|
|
1062
1096
|
while True:
|
|
1063
1097
|
string_length = self._scan_for_printable_strings(start_addr)
|
|
1098
|
+
if string_length == 0:
|
|
1099
|
+
string_length = self._scan_for_printable_widestrings(start_addr)
|
|
1100
|
+
|
|
1064
1101
|
if string_length:
|
|
1065
1102
|
self._seg_list.occupy(start_addr, string_length, "string")
|
|
1066
1103
|
start_addr += string_length
|
|
@@ -22,7 +22,13 @@ class AMD64PeIatResolver(IndirectJumpResolver):
|
|
|
22
22
|
if jumpkind not in {"Ijk_Call", "Ijk_Boring"}:
|
|
23
23
|
return False
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
insns = self.project.factory.block(addr).capstone.insns
|
|
26
|
+
if not insns:
|
|
27
|
+
return False
|
|
28
|
+
if not insns[-1].insn.operands:
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
opnd = insns[-1].insn.operands[0]
|
|
26
32
|
# Must be of the form: call qword ptr [0xABCD]
|
|
27
33
|
if opnd.type == X86_OP_MEM and opnd.mem.disp and opnd.mem.base == X86_REG_RIP and opnd.mem.index == 0:
|
|
28
34
|
return True
|
|
@@ -22,7 +22,13 @@ class X86PeIatResolver(IndirectJumpResolver):
|
|
|
22
22
|
if jumpkind != "Ijk_Call":
|
|
23
23
|
return False
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
insns = self.project.factory.block(addr).capstone.insns
|
|
26
|
+
if not insns:
|
|
27
|
+
return False
|
|
28
|
+
if not insns[-1].insn.operands:
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
opnd = insns[-1].insn.operands[0]
|
|
26
32
|
# Must be of the form: call ds:0xABCD
|
|
27
33
|
if opnd.type == X86_OP_MEM and opnd.mem.disp and not opnd.mem.base and not opnd.mem.index:
|
|
28
34
|
return True
|
|
@@ -1399,7 +1399,10 @@ class Clinic(Analysis):
|
|
|
1399
1399
|
)
|
|
1400
1400
|
end_block_ail = ailment.IRSBConverter.convert(end_block.vex, self._ail_manager)
|
|
1401
1401
|
else:
|
|
1402
|
-
|
|
1402
|
+
try:
|
|
1403
|
+
end_block_ail = next(iter(b for b in ail_graph if b.addr == end_block_addr))
|
|
1404
|
+
except StopIteration:
|
|
1405
|
+
return None
|
|
1403
1406
|
|
|
1404
1407
|
# last check: if the first instruction of the end block has Sar, then we bail (due to the peephole optimization
|
|
1405
1408
|
# SarToSignedDiv)
|
|
@@ -102,6 +102,7 @@ _ail2claripy_op_mapping = {
|
|
|
102
102
|
"Shr": lambda expr, conv, _: _op_with_unified_size(claripy.LShR, conv, expr.operands[0], expr.operands[1]),
|
|
103
103
|
"Shl": lambda expr, conv, _: _op_with_unified_size(operator.lshift, conv, expr.operands[0], expr.operands[1]),
|
|
104
104
|
"Sar": lambda expr, conv, _: _op_with_unified_size(operator.rshift, conv, expr.operands[0], expr.operands[1]),
|
|
105
|
+
"Concat": lambda expr, conv, _: claripy.Concat(*[conv(operand) for operand in expr.operands]),
|
|
105
106
|
# There are no corresponding claripy operations for the following operations
|
|
106
107
|
"DivMod": lambda expr, _, m: _dummy_bvs(expr, m),
|
|
107
108
|
"CmpF": lambda expr, _, m: _dummy_bvs(expr, m),
|
|
@@ -686,6 +687,9 @@ class ConditionProcessor:
|
|
|
686
687
|
if cond_.args[0] is True
|
|
687
688
|
else ailment.Expr.Const(None, None, False, 1, **tags),
|
|
688
689
|
"Extract": lambda cond_, tags: self._convert_extract(*cond_.args, tags, memo=memo),
|
|
690
|
+
"ZeroExt": lambda cond_, tags: _binary_op_reduce(
|
|
691
|
+
"Concat", [claripy.BVV(0, cond_.args[0]), cond_.args[1]], tags
|
|
692
|
+
),
|
|
689
693
|
}
|
|
690
694
|
|
|
691
695
|
if cond.op in _mapping:
|
|
@@ -90,6 +90,7 @@ class Decompiler(Analysis):
|
|
|
90
90
|
self.cache: Optional[DecompilationCache] = None
|
|
91
91
|
self.options_by_class = None
|
|
92
92
|
self.seq_node = None
|
|
93
|
+
self.unmodified_clinic_graph = None
|
|
93
94
|
|
|
94
95
|
if decompile:
|
|
95
96
|
self._decompile()
|
|
@@ -183,6 +184,9 @@ class Decompiler(Analysis):
|
|
|
183
184
|
# the function is empty
|
|
184
185
|
return
|
|
185
186
|
|
|
187
|
+
# expose a copy of the graph before structuring optimizations happen
|
|
188
|
+
# use this graph if you need a reference of exact mapping of instructions to AIL statements
|
|
189
|
+
self.unmodified_clinic_graph = clinic.copy_graph()
|
|
186
190
|
cond_proc = ConditionProcessor(self.project.arch)
|
|
187
191
|
|
|
188
192
|
clinic.graph = self._run_graph_simplification_passes(
|
|
@@ -146,14 +146,15 @@ class ITERegionConverter(OptimizationPass):
|
|
|
146
146
|
#
|
|
147
147
|
|
|
148
148
|
new_region_head = region_head.copy()
|
|
149
|
+
addr_obj = true_stmt.src if "ins_addr" in true_stmt.src.tags else true_stmt
|
|
149
150
|
ternary_expr = ITE(
|
|
150
151
|
None,
|
|
151
152
|
region_head.statements[-1].condition,
|
|
152
153
|
true_stmt.src,
|
|
153
154
|
false_stmt.src,
|
|
154
|
-
ins_addr=
|
|
155
|
-
vex_block_addr=
|
|
156
|
-
vex_stmt_idx=
|
|
155
|
+
ins_addr=addr_obj.ins_addr,
|
|
156
|
+
vex_block_addr=addr_obj.vex_block_addr,
|
|
157
|
+
vex_stmt_idx=addr_obj.vex_stmt_idx,
|
|
157
158
|
)
|
|
158
159
|
new_assignment = true_stmt.copy()
|
|
159
160
|
new_assignment.src = ternary_expr
|
|
@@ -21,7 +21,7 @@ class MultiSimplifierAILEngine(SimplifierAILEngine):
|
|
|
21
21
|
if type(operand_0) in [Expr.Convert, Expr.Register]:
|
|
22
22
|
if isinstance(operand_1, (Expr.Convert, Expr.Register)):
|
|
23
23
|
if operand_0 == operand_1:
|
|
24
|
-
count = Expr.Const(expr.idx, None, 2,
|
|
24
|
+
count = Expr.Const(expr.idx, None, 2, operand_1.bits)
|
|
25
25
|
return Expr.BinaryOp(expr.idx, "Mul", [operand_1, count], expr.signed, **expr.tags)
|
|
26
26
|
# 2*x + x = 3*x
|
|
27
27
|
if Expr.BinaryOp in [type(operand_0), type(operand_1)]:
|
|
@@ -12,6 +12,7 @@ from ....sim_type import (
|
|
|
12
12
|
SimTypeInt,
|
|
13
13
|
SimTypeShort,
|
|
14
14
|
SimTypeChar,
|
|
15
|
+
SimTypeWideChar,
|
|
15
16
|
SimTypePointer,
|
|
16
17
|
SimStruct,
|
|
17
18
|
SimType,
|
|
@@ -273,9 +274,6 @@ class CConstruct:
|
|
|
273
274
|
|
|
274
275
|
last_insn_addr = None
|
|
275
276
|
|
|
276
|
-
# track all Function Calls for highlighting
|
|
277
|
-
used_func_calls = set()
|
|
278
|
-
|
|
279
277
|
# track all variables so we can tell if this is a declaration or not
|
|
280
278
|
used_vars = set()
|
|
281
279
|
|
|
@@ -310,15 +308,11 @@ class CConstruct:
|
|
|
310
308
|
CBinaryOp,
|
|
311
309
|
CUnaryOp,
|
|
312
310
|
CAssignment,
|
|
311
|
+
CFunctionCall,
|
|
313
312
|
),
|
|
314
313
|
):
|
|
315
314
|
if pos_to_node is not None:
|
|
316
315
|
pos_to_node.add_mapping(pos, len(s), obj)
|
|
317
|
-
elif isinstance(obj, CFunctionCall):
|
|
318
|
-
if obj not in used_func_calls:
|
|
319
|
-
used_func_calls.add(obj)
|
|
320
|
-
if pos_to_node is not None:
|
|
321
|
-
pos_to_node.add_mapping(pos, len(s), obj)
|
|
322
316
|
|
|
323
317
|
# add (), {}, [], and [20] to mapping for highlighting as well as the full functions name
|
|
324
318
|
elif isinstance(obj, (CClosingObject, CFunction, CArrayTypeLength, CStructFieldNameDef)):
|
|
@@ -1247,15 +1241,15 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1247
1241
|
|
|
1248
1242
|
for i, arg in enumerate(self.args):
|
|
1249
1243
|
if i:
|
|
1250
|
-
yield ", ",
|
|
1244
|
+
yield ", ", None
|
|
1251
1245
|
yield from CExpression._try_c_repr_chunks(arg)
|
|
1252
1246
|
|
|
1253
1247
|
yield ")", paren
|
|
1254
1248
|
|
|
1255
1249
|
if not self.is_expr and not asexpr:
|
|
1256
|
-
yield ";",
|
|
1250
|
+
yield ";", None
|
|
1257
1251
|
if not self.returning:
|
|
1258
|
-
yield " /* do not return */",
|
|
1252
|
+
yield " /* do not return */", None
|
|
1259
1253
|
yield "\n", None
|
|
1260
1254
|
|
|
1261
1255
|
|
|
@@ -2012,14 +2006,14 @@ class CConstant(CExpression):
|
|
|
2012
2006
|
return self._type
|
|
2013
2007
|
|
|
2014
2008
|
@staticmethod
|
|
2015
|
-
def str_to_c_str(_str):
|
|
2009
|
+
def str_to_c_str(_str, prefix: str = ""):
|
|
2016
2010
|
repr_str = repr(_str)
|
|
2017
2011
|
base_str = repr_str[1:-1]
|
|
2018
2012
|
if repr_str[0] == "'":
|
|
2019
2013
|
# check if there's double quotes in the body
|
|
2020
2014
|
if '"' in base_str:
|
|
2021
2015
|
base_str = base_str.replace('"', '\\"')
|
|
2022
|
-
return f'"{base_str}"'
|
|
2016
|
+
return f'{prefix}"{base_str}"'
|
|
2023
2017
|
|
|
2024
2018
|
def c_repr_chunks(self, indent=0, asexpr=False):
|
|
2025
2019
|
if self.collapsed:
|
|
@@ -2045,6 +2039,9 @@ class CConstant(CExpression):
|
|
|
2045
2039
|
elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeChar):
|
|
2046
2040
|
refval = self.reference_values[self._type] # angr.knowledge_plugin.cfg.MemoryData
|
|
2047
2041
|
yield CConstant.str_to_c_str(refval.content.decode("utf-8")), self
|
|
2042
|
+
elif isinstance(self._type, SimTypePointer) and isinstance(self._type.pts_to, SimTypeWideChar):
|
|
2043
|
+
refval = self.reference_values[self._type] # angr.knowledge_plugin.cfg.MemoryData
|
|
2044
|
+
yield CConstant.str_to_c_str(refval.content.decode("utf_16_le"), prefix="L"), self
|
|
2048
2045
|
else:
|
|
2049
2046
|
if isinstance(self.reference_values[self._type], int):
|
|
2050
2047
|
yield self.fmt_int(self.reference_values[self._type]), self
|
|
@@ -2724,6 +2721,9 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2724
2721
|
o_constant, o_terms = extract_terms(expr)
|
|
2725
2722
|
|
|
2726
2723
|
def bail_out():
|
|
2724
|
+
if len(o_terms) == 0:
|
|
2725
|
+
# probably a plain integer, return as is
|
|
2726
|
+
return expr
|
|
2727
2727
|
result = reduce(
|
|
2728
2728
|
lambda a1, a2: CBinaryOp("Add", a1, a2, codegen=self),
|
|
2729
2729
|
(
|
|
@@ -3234,15 +3234,26 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3234
3234
|
and expr.bits == self.project.arch.bits
|
|
3235
3235
|
and expr.value > 0x10000
|
|
3236
3236
|
and expr.value in self._cfg.memory_data
|
|
3237
|
-
and self._cfg.memory_data[expr.value].sort == MemoryDataSort.String
|
|
3238
3237
|
):
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3238
|
+
md = self._cfg.memory_data[expr.value]
|
|
3239
|
+
if md.sort == MemoryDataSort.String:
|
|
3240
|
+
type_ = SimTypePointer(SimTypeChar().with_arch(self.project.arch)).with_arch(self.project.arch)
|
|
3241
|
+
reference_values[type_] = self._cfg.memory_data[expr.value]
|
|
3242
|
+
# is it a constant string?
|
|
3243
|
+
if is_in_readonly_segment(self.project, expr.value) or is_in_readonly_section(
|
|
3244
|
+
self.project, expr.value
|
|
3245
|
+
):
|
|
3246
|
+
inline_string = True
|
|
3247
|
+
elif md.sort == MemoryDataSort.UnicodeString:
|
|
3248
|
+
type_ = SimTypePointer(SimTypeWideChar().with_arch(self.project.arch)).with_arch(
|
|
3249
|
+
self.project.arch
|
|
3250
|
+
)
|
|
3251
|
+
reference_values[type_] = self._cfg.memory_data[expr.value]
|
|
3252
|
+
# is it a constant string?
|
|
3253
|
+
if is_in_readonly_segment(self.project, expr.value) or is_in_readonly_section(
|
|
3254
|
+
self.project, expr.value
|
|
3255
|
+
):
|
|
3256
|
+
inline_string = True
|
|
3246
3257
|
|
|
3247
3258
|
if type_ is None:
|
|
3248
3259
|
# default to int
|
|
@@ -1204,7 +1204,7 @@ class SimEnginePropagatorAIL(
|
|
|
1204
1204
|
o1_expr if o1_expr is not None else expr.operands[1],
|
|
1205
1205
|
],
|
|
1206
1206
|
expr.signed,
|
|
1207
|
-
bits=
|
|
1207
|
+
bits=expr.bits,
|
|
1208
1208
|
floating_point=expr.floating_point,
|
|
1209
1209
|
rounding_mode=expr.rounding_mode,
|
|
1210
1210
|
**expr.tags,
|
|
@@ -118,9 +118,6 @@ class SimEngineRDAIL(
|
|
|
118
118
|
def _process_Stmt(self, whitelist=None):
|
|
119
119
|
super()._process_Stmt(whitelist=whitelist)
|
|
120
120
|
|
|
121
|
-
if self.state.analysis:
|
|
122
|
-
self.state.analysis.model.complete_loc()
|
|
123
|
-
|
|
124
121
|
def _handle_Stmt(self, stmt):
|
|
125
122
|
if self.state.analysis:
|
|
126
123
|
self.state.analysis.stmt_observe(self.stmt_idx, stmt, self.block, self.state, OP_BEFORE)
|
|
@@ -801,7 +798,7 @@ class SimEngineRDAIL(
|
|
|
801
798
|
elif expr0_v is None and expr1_v is not None:
|
|
802
799
|
# each value in expr0 >> expr1_v
|
|
803
800
|
if expr0.count() == 1 and 0 in expr0:
|
|
804
|
-
if all(v.concrete for v in expr0[0]):
|
|
801
|
+
if all(v.concrete for v in expr0[0]) and expr1_v.concrete:
|
|
805
802
|
vs = {
|
|
806
803
|
(claripy.LShR(v, expr1_v.concrete_value) if v.concrete else self.state.top(bits))
|
|
807
804
|
for v in expr0[0]
|
|
@@ -839,7 +836,7 @@ class SimEngineRDAIL(
|
|
|
839
836
|
elif expr0_v is None and expr1_v is not None:
|
|
840
837
|
# each value in expr0 >> expr1_v
|
|
841
838
|
if expr0.count() == 1 and 0 in expr0:
|
|
842
|
-
if all(v.concrete for v in expr0[0]):
|
|
839
|
+
if all(v.concrete for v in expr0[0]) and expr1_v.concrete:
|
|
843
840
|
vs = {
|
|
844
841
|
(claripy.LShR(v, expr1_v.concrete_value) if v.concrete else self.state.top(bits))
|
|
845
842
|
for v in expr0[0]
|
|
@@ -877,7 +874,7 @@ class SimEngineRDAIL(
|
|
|
877
874
|
elif expr0_v is None and expr1_v is not None:
|
|
878
875
|
# each value in expr0 << expr1_v
|
|
879
876
|
if expr0.count() == 1 and 0 in expr0:
|
|
880
|
-
if all(v.concrete for v in expr0[0]):
|
|
877
|
+
if all(v.concrete for v in expr0[0]) and expr1_v.concrete:
|
|
881
878
|
vs = {((v << expr1_v.concrete_value) if v.concrete else self.state.top(bits)) for v in expr0[0]}
|
|
882
879
|
r = MultiValues(offset_to_values={0: vs})
|
|
883
880
|
elif expr0_v is not None and expr1_v is None:
|
|
@@ -147,11 +147,11 @@ class SimEngineRDVEX(
|
|
|
147
147
|
if self.state.is_heap_address(d):
|
|
148
148
|
heap_offset = self.state.get_heap_offset(d)
|
|
149
149
|
if heap_offset is not None:
|
|
150
|
-
self.state.add_heap_use(heap_offset, 1
|
|
150
|
+
self.state.add_heap_use(heap_offset, 1)
|
|
151
151
|
elif self.state.is_stack_address(d):
|
|
152
152
|
stack_offset = self.state.get_stack_offset(d)
|
|
153
153
|
if stack_offset is not None:
|
|
154
|
-
self.state.add_stack_use(stack_offset, 1
|
|
154
|
+
self.state.add_stack_use(stack_offset, 1)
|
|
155
155
|
|
|
156
156
|
if self.state.exit_observed and reg_offset == self.arch.sp_offset:
|
|
157
157
|
return
|
|
@@ -989,6 +989,34 @@ class SimEngineRDVEX(
|
|
|
989
989
|
return MultiValues(claripy.BVV(0, 1))
|
|
990
990
|
return MultiValues(self.state.top(1))
|
|
991
991
|
|
|
992
|
+
def _handle_CmpGT(self, expr):
|
|
993
|
+
arg0, arg1 = expr.args
|
|
994
|
+
expr_0 = self._expr(arg0)
|
|
995
|
+
expr_1 = self._expr(arg1)
|
|
996
|
+
|
|
997
|
+
e0 = expr_0.one_value()
|
|
998
|
+
e1 = expr_1.one_value()
|
|
999
|
+
if e0 is not None and e1 is not None:
|
|
1000
|
+
if not e0.symbolic and not e1.symbolic:
|
|
1001
|
+
return MultiValues(claripy.BVV(1, 1) if e0.concrete_value > e1.concrete_value else claripy.BVV(0, 1))
|
|
1002
|
+
elif e0 is e1:
|
|
1003
|
+
return MultiValues(claripy.BVV(0, 1))
|
|
1004
|
+
return MultiValues(self.state.top(1))
|
|
1005
|
+
|
|
1006
|
+
def _handle_CmpGE(self, expr):
|
|
1007
|
+
arg0, arg1 = expr.args
|
|
1008
|
+
expr_0 = self._expr(arg0)
|
|
1009
|
+
expr_1 = self._expr(arg1)
|
|
1010
|
+
|
|
1011
|
+
e0 = expr_0.one_value()
|
|
1012
|
+
e1 = expr_1.one_value()
|
|
1013
|
+
if e0 is not None and e1 is not None:
|
|
1014
|
+
if not e0.symbolic and not e1.symbolic:
|
|
1015
|
+
return MultiValues(claripy.BVV(1, 1) if e0.concrete_value >= e1.concrete_value else claripy.BVV(0, 1))
|
|
1016
|
+
elif e0 is e1:
|
|
1017
|
+
return MultiValues(claripy.BVV(0, 1))
|
|
1018
|
+
return MultiValues(self.state.top(1))
|
|
1019
|
+
|
|
992
1020
|
# ppc only
|
|
993
1021
|
def _handle_CmpORD(self, expr):
|
|
994
1022
|
arg0, arg1 = expr.args
|
|
@@ -1001,6 +1029,8 @@ class SimEngineRDVEX(
|
|
|
1001
1029
|
|
|
1002
1030
|
if e0 is not None and e1 is not None:
|
|
1003
1031
|
if not e0.symbolic and not e1.symbolic:
|
|
1032
|
+
e0 = e0.concrete_value
|
|
1033
|
+
e1 = e1.concrete_value
|
|
1004
1034
|
if e0 < e1:
|
|
1005
1035
|
return MultiValues(claripy.BVV(0x8, bits))
|
|
1006
1036
|
elif e0 > e1:
|
|
@@ -409,7 +409,7 @@ class FunctionHandler:
|
|
|
409
409
|
# translate all the dep atoms into dep defns
|
|
410
410
|
for effect in data.effects:
|
|
411
411
|
if effect.sources_defns is None and effect.sources:
|
|
412
|
-
effect.sources_defns = set().union(*(
|
|
412
|
+
effect.sources_defns = set().union(*(state.get_definitions(atom) for atom in effect.sources))
|
|
413
413
|
if not effect.sources_defns:
|
|
414
414
|
effect.sources_defns = {Definition(atom, ExternalCodeLocation()) for atom in effect.sources}
|
|
415
415
|
other_input_defns |= effect.sources_defns - all_args_defns
|
|
@@ -63,7 +63,7 @@ class RDAStateInitializer:
|
|
|
63
63
|
self.initialize_architectural_state(state, func_addr, ex_loc, rtoc_value)
|
|
64
64
|
|
|
65
65
|
if state.analysis is not None:
|
|
66
|
-
state.analysis.model.
|
|
66
|
+
state.analysis.model.make_liveness_snapshot()
|
|
67
67
|
|
|
68
68
|
def initialize_all_function_arguments(
|
|
69
69
|
self,
|
|
@@ -147,7 +147,7 @@ class RDAStateInitializer:
|
|
|
147
147
|
rtoc_def = Definition(rtoc_atom, ex_loc, tags={InitialValueTag()})
|
|
148
148
|
state.all_definitions.add(rtoc_def)
|
|
149
149
|
if state.analysis is not None:
|
|
150
|
-
state.analysis.model.add_def(rtoc_def
|
|
150
|
+
state.analysis.model.add_def(rtoc_def)
|
|
151
151
|
rtoc = state.annotate_with_def(claripy.BVV(rtoc_value, self.arch.bits), rtoc_def)
|
|
152
152
|
state.registers.store(offset, rtoc)
|
|
153
153
|
elif self.arch.name.startswith("MIPS64"):
|
|
@@ -156,7 +156,7 @@ class RDAStateInitializer:
|
|
|
156
156
|
t9_def = Definition(t9_atom, ex_loc, tags={InitialValueTag()})
|
|
157
157
|
state.all_definitions.add(t9_def)
|
|
158
158
|
if state.analysis is not None:
|
|
159
|
-
state.analysis.model.add_def(t9_def
|
|
159
|
+
state.analysis.model.add_def(t9_def)
|
|
160
160
|
t9 = state.annotate_with_def(claripy.BVV(func_addr, self.arch.bits), t9_def)
|
|
161
161
|
state.registers.store(offset, t9)
|
|
162
162
|
elif self.arch.name.startswith("MIPS"):
|
|
@@ -167,7 +167,7 @@ class RDAStateInitializer:
|
|
|
167
167
|
t9_def = Definition(t9_atom, ex_loc, tags={InitialValueTag()})
|
|
168
168
|
state.all_definitions.add(t9_def)
|
|
169
169
|
if state.analysis is not None:
|
|
170
|
-
state.analysis.model.add_def(t9_def
|
|
170
|
+
state.analysis.model.add_def(t9_def)
|
|
171
171
|
t9 = state.annotate_with_def(claripy.BVV(func_addr, self.arch.bits), t9_def)
|
|
172
172
|
state.registers.store(t9_offset, t9)
|
|
173
173
|
|
|
@@ -185,7 +185,7 @@ class RDAStateInitializer:
|
|
|
185
185
|
reg_def = Definition(reg_atom, ex_loc, tags={ParameterTag(function=func_addr)})
|
|
186
186
|
state.all_definitions.add(reg_def)
|
|
187
187
|
if state.analysis is not None:
|
|
188
|
-
state.analysis.model.add_def(reg_def
|
|
188
|
+
state.analysis.model.add_def(reg_def)
|
|
189
189
|
if value is None:
|
|
190
190
|
value = state.top(self.arch.bits)
|
|
191
191
|
reg = state.annotate_with_def(value, reg_def)
|
|
@@ -198,7 +198,7 @@ class RDAStateInitializer:
|
|
|
198
198
|
ml_def = Definition(ml_atom, ex_loc, tags={ParameterTag(function=func_addr)})
|
|
199
199
|
state.all_definitions.add(ml_def)
|
|
200
200
|
if state.analysis is not None:
|
|
201
|
-
state.analysis.model.add_def(ml_def
|
|
201
|
+
state.analysis.model.add_def(ml_def)
|
|
202
202
|
ml = state.annotate_with_def(state.top(self.arch.bits), ml_def)
|
|
203
203
|
stack_address = state.get_stack_address(state.stack_address(arg.stack_offset))
|
|
204
204
|
state.stack.store(stack_address, ml, endness=self.arch.memory_endness)
|
|
@@ -328,7 +328,7 @@ class ReachingDefinitionsState:
|
|
|
328
328
|
Overwrite existing definitions w.r.t 'atom' with a dummy definition instance. A dummy definition will not be
|
|
329
329
|
removed during simplification.
|
|
330
330
|
"""
|
|
331
|
-
existing_defs =
|
|
331
|
+
existing_defs = self.live_definitions.get_definitions(atom)
|
|
332
332
|
|
|
333
333
|
self.live_definitions.kill_definitions(atom)
|
|
334
334
|
|
|
@@ -347,7 +347,7 @@ class ReachingDefinitionsState:
|
|
|
347
347
|
override_codeloc: Optional[CodeLocation] = None,
|
|
348
348
|
) -> Tuple[Optional[MultiValues], Set[Definition]]:
|
|
349
349
|
codeloc = override_codeloc or self.codeloc
|
|
350
|
-
existing_defs =
|
|
350
|
+
existing_defs = self.live_definitions.get_definitions(atom)
|
|
351
351
|
mv = self.live_definitions.kill_and_add_definition(
|
|
352
352
|
atom, codeloc, data, dummy=dummy, tags=tags, endness=endness, annotated=annotated
|
|
353
353
|
)
|
|
@@ -417,7 +417,7 @@ class ReachingDefinitionsState:
|
|
|
417
417
|
for def_ in existing_defs:
|
|
418
418
|
self.analysis.model.kill_def(def_)
|
|
419
419
|
for def_ in defs:
|
|
420
|
-
self.analysis.model.add_def(def_
|
|
420
|
+
self.analysis.model.add_def(def_)
|
|
421
421
|
|
|
422
422
|
return mv, defs
|
|
423
423
|
|
|
@@ -450,8 +450,8 @@ class ReachingDefinitionsState:
|
|
|
450
450
|
self.codeloc_uses.add(definition)
|
|
451
451
|
self.live_definitions.add_register_use_by_def(definition, self.codeloc, expr=expr)
|
|
452
452
|
|
|
453
|
-
def add_stack_use(self, stack_offset: int, size: int,
|
|
454
|
-
defs = self.live_definitions.get_stack_definitions(stack_offset, size
|
|
453
|
+
def add_stack_use(self, stack_offset: int, size: int, expr: Optional[Any] = None) -> None:
|
|
454
|
+
defs = self.live_definitions.get_stack_definitions(stack_offset, size)
|
|
455
455
|
self.add_stack_use_by_defs(defs, expr=expr)
|
|
456
456
|
|
|
457
457
|
def add_stack_use_by_defs(self, defs: Iterable[Definition], expr: Optional[Any] = None):
|
|
@@ -459,8 +459,8 @@ class ReachingDefinitionsState:
|
|
|
459
459
|
self.codeloc_uses.add(definition)
|
|
460
460
|
self.live_definitions.add_stack_use_by_def(definition, self.codeloc, expr=expr)
|
|
461
461
|
|
|
462
|
-
def add_heap_use(self, heap_offset: int, size: int,
|
|
463
|
-
defs = self.live_definitions.get_heap_definitions(heap_offset, size
|
|
462
|
+
def add_heap_use(self, heap_offset: int, size: int, expr: Optional[Any] = None) -> None:
|
|
463
|
+
defs = self.live_definitions.get_heap_definitions(heap_offset, size)
|
|
464
464
|
self.add_heap_use_by_defs(defs, expr=expr)
|
|
465
465
|
|
|
466
466
|
def add_heap_use_by_defs(self, defs: Iterable[Definition], expr: Optional[Any] = None):
|
|
@@ -477,10 +477,8 @@ class ReachingDefinitionsState:
|
|
|
477
477
|
self.codeloc_uses.add(definition)
|
|
478
478
|
self.live_definitions.add_memory_use_by_def(definition, self.codeloc, expr=expr)
|
|
479
479
|
|
|
480
|
-
def get_definitions(
|
|
481
|
-
self
|
|
482
|
-
) -> Iterable[Definition]:
|
|
483
|
-
yield from self.live_definitions.get_definitions(atom)
|
|
480
|
+
def get_definitions(self, atom: Union[Atom, Definition, Iterable[Atom], Iterable[Definition]]) -> Set[Definition]:
|
|
481
|
+
return self.live_definitions.get_definitions(atom)
|
|
484
482
|
|
|
485
483
|
def get_values(self, spec: Union[Atom, Definition, Iterable[Atom]]) -> Optional[MultiValues]:
|
|
486
484
|
return self.live_definitions.get_values(spec)
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# pylint:disable=missing-class-docstring
|
|
2
|
-
from typing import Dict, Any, Optional, TYPE_CHECKING
|
|
2
|
+
from typing import Dict, Any, Optional, Set, TYPE_CHECKING
|
|
3
3
|
from itertools import count
|
|
4
4
|
|
|
5
|
-
from ...utils.cowdict import ChainMapCOW
|
|
6
|
-
|
|
7
5
|
if TYPE_CHECKING:
|
|
8
6
|
from angr.sim_variable import SimVariable
|
|
9
7
|
|
|
@@ -340,25 +338,20 @@ class DerivedTypeVariable(TypeVariable):
|
|
|
340
338
|
|
|
341
339
|
|
|
342
340
|
class TypeVariables:
|
|
343
|
-
__slots__ = (
|
|
341
|
+
__slots__ = (
|
|
342
|
+
"_typevars",
|
|
343
|
+
"_last_typevars",
|
|
344
|
+
)
|
|
344
345
|
|
|
345
346
|
def __init__(self):
|
|
346
|
-
self._typevars: Dict["SimVariable", TypeVariable] =
|
|
347
|
-
|
|
348
|
-
def merge(self, tvs):
|
|
349
|
-
merged = TypeVariables()
|
|
350
|
-
|
|
351
|
-
# TODO: Replace this with a real lattice-based merging
|
|
352
|
-
merged._typevars = self._typevars.copy()
|
|
353
|
-
if tvs._typevars:
|
|
354
|
-
merged._typevars = merged._typevars.clean()
|
|
355
|
-
merged._typevars.update(tvs._typevars)
|
|
356
|
-
|
|
357
|
-
return merged
|
|
347
|
+
self._typevars: Dict["SimVariable", Set[TypeVariable]] = {}
|
|
348
|
+
self._last_typevars: Dict[SimVariable, TypeVariable] = {}
|
|
358
349
|
|
|
359
350
|
def copy(self):
|
|
360
351
|
copied = TypeVariables()
|
|
361
|
-
|
|
352
|
+
for var, typevars in self._typevars.items():
|
|
353
|
+
copied._typevars[var] = typevars.copy()
|
|
354
|
+
copied._last_typevars = self._last_typevars.copy()
|
|
362
355
|
return copied
|
|
363
356
|
|
|
364
357
|
def __repr__(self):
|
|
@@ -369,27 +362,24 @@ class TypeVariables:
|
|
|
369
362
|
return "{TypeVars: %d items}" % len(self._typevars)
|
|
370
363
|
|
|
371
364
|
def add_type_variable(self, var: "SimVariable", codeloc, typevar: TypeVariable): # pylint:disable=unused-argument
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
self.
|
|
378
|
-
self._typevars[var] = typevar
|
|
365
|
+
if var not in self._typevars:
|
|
366
|
+
self._typevars[var] = set()
|
|
367
|
+
elif typevar in self._typevars[var]:
|
|
368
|
+
return
|
|
369
|
+
self._typevars[var].add(typevar)
|
|
370
|
+
self._last_typevars[var] = typevar
|
|
379
371
|
|
|
380
372
|
def get_type_variable(self, var, codeloc): # pylint:disable=unused-argument
|
|
381
|
-
return self.
|
|
373
|
+
return self._last_typevars[var]
|
|
382
374
|
|
|
383
375
|
def has_type_variable_for(self, var: "SimVariable", codeloc): # pylint:disable=unused-argument
|
|
384
|
-
|
|
385
|
-
return False
|
|
386
|
-
return True
|
|
376
|
+
return var in self._typevars
|
|
387
377
|
# if codeloc not in self._typevars[var]:
|
|
388
378
|
# return False
|
|
389
379
|
# return True
|
|
390
380
|
|
|
391
381
|
def __getitem__(self, var):
|
|
392
|
-
return self.
|
|
382
|
+
return self._last_typevars[var]
|
|
393
383
|
|
|
394
384
|
def __contains__(self, var):
|
|
395
385
|
return var in self._typevars
|
|
@@ -97,6 +97,22 @@ class VEXIRSBScanner(SimEngineLightVEXMixin):
|
|
|
97
97
|
if tmp_src in self.tmps_with_64bit_regs:
|
|
98
98
|
self.tmps_converted_to_32bit.add(tmp_src)
|
|
99
99
|
|
|
100
|
+
def _handle_16HLto32(self, expr):
|
|
101
|
+
pass
|
|
102
|
+
|
|
103
|
+
def _handle_Cmp_v(self, expr, _vector_size, _vector_count):
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
_handle_CmpEQ_v = _handle_Cmp_v
|
|
107
|
+
_handle_CmpNE_v = _handle_Cmp_v
|
|
108
|
+
_handle_CmpLE_v = _handle_Cmp_v
|
|
109
|
+
_handle_CmpLT_v = _handle_Cmp_v
|
|
110
|
+
_handle_CmpGE_v = _handle_Cmp_v
|
|
111
|
+
_handle_CmpGT_v = _handle_Cmp_v
|
|
112
|
+
|
|
113
|
+
def _handle_ExpCmpNE64(self, expr):
|
|
114
|
+
pass
|
|
115
|
+
|
|
100
116
|
def _handle_CCall(self, expr):
|
|
101
117
|
pass
|
|
102
118
|
|