angr 9.2.83__py3-none-win_amd64.whl → 9.2.85__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +1 -1
- angr/analyses/cfg/cfg_base.py +6 -1
- angr/analyses/cfg/cfg_fast.py +32 -10
- angr/analyses/decompiler/clinic.py +204 -4
- angr/analyses/decompiler/condition_processor.py +8 -2
- angr/analyses/decompiler/decompilation_options.py +10 -0
- angr/analyses/decompiler/decompiler.py +19 -17
- angr/analyses/decompiler/goto_manager.py +34 -51
- angr/analyses/decompiler/optimization_passes/__init__.py +5 -5
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +2 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +131 -3
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +3 -3
- angr/analyses/decompiler/optimization_passes/return_duplicator.py +519 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +14 -2
- angr/analyses/decompiler/region_identifier.py +8 -2
- angr/analyses/decompiler/region_simplifiers/goto.py +5 -4
- angr/analyses/decompiler/structured_codegen/c.py +66 -5
- angr/analyses/decompiler/structuring/phoenix.py +3 -1
- angr/analyses/decompiler/structuring/structurer_nodes.py +11 -5
- angr/analyses/decompiler/utils.py +50 -0
- angr/analyses/disassembly.py +10 -3
- angr/analyses/propagator/engine_ail.py +125 -0
- angr/analyses/reaching_definitions/engine_ail.py +36 -2
- angr/analyses/reaching_definitions/rd_initializer.py +15 -1
- angr/analyses/reaching_definitions/rd_state.py +9 -4
- angr/analyses/stack_pointer_tracker.py +10 -17
- angr/analyses/variable_recovery/engine_ail.py +27 -1
- angr/angrdb/serializers/loader.py +10 -3
- angr/calling_conventions.py +2 -0
- angr/engines/pcode/behavior.py +7 -2
- angr/engines/pcode/cc.py +1 -0
- angr/engines/pcode/emulate.py +144 -104
- angr/engines/pcode/lifter.py +135 -79
- angr/knowledge_plugins/functions/function.py +28 -0
- angr/knowledge_plugins/functions/function_manager.py +48 -5
- angr/knowledge_plugins/propagations/states.py +14 -0
- angr/lib/angr_native.dll +0 -0
- angr/procedures/cgc/deallocate.py +5 -2
- angr/procedures/posix/gethostbyname.py +23 -8
- angr/project.py +4 -0
- angr/simos/__init__.py +2 -0
- angr/simos/simos.py +1 -0
- angr/simos/snimmuc_nxp.py +152 -0
- angr/state_plugins/history.py +3 -1
- angr/utils/graph.py +20 -18
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/METADATA +9 -8
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/RECORD +61 -59
- tests/analyses/cfg/test_cfg_rust_got_resolution.py +2 -1
- tests/analyses/cfg/test_jumptables.py +2 -1
- tests/analyses/decompiler/test_decompiler.py +155 -103
- tests/engines/pcode/test_emulate.py +607 -0
- tests/engines/test_java.py +609 -663
- tests/knowledge_plugins/functions/test_function_manager.py +13 -0
- tests/serialization/test_db.py +30 -0
- angr/analyses/decompiler/optimization_passes/eager_returns.py +0 -285
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/LICENSE +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/WHEEL +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/entry_points.txt +0 -0
- {angr-9.2.83.dist-info → angr-9.2.85.dist-info}/top_level.txt +0 -0
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
from typing import Optional, Dict, List, Tuple, Set, Any, Union, TYPE_CHECKING, Callable
|
|
3
3
|
from collections import defaultdict
|
|
4
4
|
import logging
|
|
5
|
+
import struct
|
|
5
6
|
from functools import reduce
|
|
6
7
|
|
|
7
8
|
from ailment import Block, Expr, Stmt, Tmp
|
|
8
9
|
from ailment.expression import StackBaseOffset, BinaryOp
|
|
10
|
+
from unique_log_filter import UniqueLogFilter
|
|
9
11
|
|
|
10
12
|
from ....sim_type import (
|
|
11
13
|
SimTypeLongLong,
|
|
@@ -57,6 +59,8 @@ if TYPE_CHECKING:
|
|
|
57
59
|
|
|
58
60
|
|
|
59
61
|
l = logging.getLogger(name=__name__)
|
|
62
|
+
l.addFilter(UniqueLogFilter())
|
|
63
|
+
|
|
60
64
|
|
|
61
65
|
INDENT_DELTA = 4
|
|
62
66
|
|
|
@@ -1177,6 +1181,7 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1177
1181
|
"tags",
|
|
1178
1182
|
"is_expr",
|
|
1179
1183
|
"show_demangled_name",
|
|
1184
|
+
"show_disambiguated_name",
|
|
1180
1185
|
)
|
|
1181
1186
|
|
|
1182
1187
|
def __init__(
|
|
@@ -1189,6 +1194,7 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1189
1194
|
tags=None,
|
|
1190
1195
|
is_expr: bool = False,
|
|
1191
1196
|
show_demangled_name=True,
|
|
1197
|
+
show_disambiguated_name: bool = True,
|
|
1192
1198
|
**kwargs,
|
|
1193
1199
|
):
|
|
1194
1200
|
super().__init__(**kwargs)
|
|
@@ -1201,6 +1207,7 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1201
1207
|
self.tags = tags
|
|
1202
1208
|
self.is_expr = is_expr
|
|
1203
1209
|
self.show_demangled_name = show_demangled_name
|
|
1210
|
+
self.show_disambiguated_name = show_disambiguated_name
|
|
1204
1211
|
|
|
1205
1212
|
@property
|
|
1206
1213
|
def prototype(self) -> Optional[SimTypeFunction]: # TODO there should be a prototype for each callsite!
|
|
@@ -1216,6 +1223,23 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1216
1223
|
else:
|
|
1217
1224
|
raise RuntimeError("CFunctionCall.type should not be accessed if the function call is used as a statement.")
|
|
1218
1225
|
|
|
1226
|
+
def _is_target_ambiguous(self, func_name: str) -> bool:
|
|
1227
|
+
"""
|
|
1228
|
+
Check for call target name ambiguity.
|
|
1229
|
+
"""
|
|
1230
|
+
caller, callee = self.codegen._func, self.callee_func
|
|
1231
|
+
|
|
1232
|
+
for var in self.codegen._variables_in_use.values():
|
|
1233
|
+
if func_name == var.name:
|
|
1234
|
+
return True
|
|
1235
|
+
|
|
1236
|
+
# FIXME: Handle name mangle
|
|
1237
|
+
for func in self.codegen.kb.functions.get_by_name(callee.name):
|
|
1238
|
+
if func is not callee and (caller.binary is not callee.binary or func.binary is callee.binary):
|
|
1239
|
+
return True
|
|
1240
|
+
|
|
1241
|
+
return False
|
|
1242
|
+
|
|
1219
1243
|
def c_repr_chunks(self, indent=0, asexpr: bool = False):
|
|
1220
1244
|
"""
|
|
1221
1245
|
|
|
@@ -1235,6 +1259,8 @@ class CFunctionCall(CStatement, CExpression):
|
|
|
1235
1259
|
func_name = get_cpp_function_name(self.callee_func.demangled_name, specialized=False, qualified=True)
|
|
1236
1260
|
else:
|
|
1237
1261
|
func_name = self.callee_func.name
|
|
1262
|
+
if self.show_disambiguated_name and self._is_target_ambiguous(func_name):
|
|
1263
|
+
func_name = self.callee_func.get_unambiguous_name(display_name=func_name)
|
|
1238
1264
|
yield func_name, self
|
|
1239
1265
|
else:
|
|
1240
1266
|
yield from CExpression._try_c_repr_chunks(self.callee_target)
|
|
@@ -1443,15 +1469,19 @@ class CVariable(CExpression):
|
|
|
1443
1469
|
def type(self):
|
|
1444
1470
|
return self.variable_type
|
|
1445
1471
|
|
|
1446
|
-
|
|
1472
|
+
@property
|
|
1473
|
+
def name(self):
|
|
1447
1474
|
v = self.variable if self.unified_variable is None else self.unified_variable
|
|
1448
1475
|
|
|
1449
1476
|
if v.name:
|
|
1450
|
-
|
|
1477
|
+
return v.name
|
|
1451
1478
|
elif isinstance(v, SimTemporaryVariable):
|
|
1452
|
-
|
|
1479
|
+
return "tmp_%d" % v.tmp_id
|
|
1453
1480
|
else:
|
|
1454
|
-
|
|
1481
|
+
return str(v)
|
|
1482
|
+
|
|
1483
|
+
def c_repr_chunks(self, indent=0, asexpr=False):
|
|
1484
|
+
yield self.name, self
|
|
1455
1485
|
|
|
1456
1486
|
|
|
1457
1487
|
class CIndexedVariable(CExpression):
|
|
@@ -1702,6 +1732,7 @@ class CBinaryOp(CExpression):
|
|
|
1702
1732
|
# lowest precedence
|
|
1703
1733
|
["Concat"],
|
|
1704
1734
|
["LogicalOr"],
|
|
1735
|
+
["LogicalXor"],
|
|
1705
1736
|
["LogicalAnd"],
|
|
1706
1737
|
["Or"],
|
|
1707
1738
|
["Xor"],
|
|
@@ -1711,6 +1742,7 @@ class CBinaryOp(CExpression):
|
|
|
1711
1742
|
["Shl", "Shr", "Sar"],
|
|
1712
1743
|
["Add", "Sub"],
|
|
1713
1744
|
["Mul", "Div"],
|
|
1745
|
+
["SBorrow", "SCarry", "Carry"],
|
|
1714
1746
|
# highest precedence
|
|
1715
1747
|
]
|
|
1716
1748
|
for i, sublist in enumerate(precedence_list):
|
|
@@ -1739,6 +1771,7 @@ class CBinaryOp(CExpression):
|
|
|
1739
1771
|
"Sar": self._c_repr_chunks_sar,
|
|
1740
1772
|
"LogicalAnd": self._c_repr_chunks_logicaland,
|
|
1741
1773
|
"LogicalOr": self._c_repr_chunks_logicalor,
|
|
1774
|
+
"LogicalXor": self._c_repr_chunks_logicalxor,
|
|
1742
1775
|
"CmpLE": self._c_repr_chunks_cmple,
|
|
1743
1776
|
"CmpLEs": self._c_repr_chunks_cmple,
|
|
1744
1777
|
"CmpLT": self._c_repr_chunks_cmplt,
|
|
@@ -1758,7 +1791,7 @@ class CBinaryOp(CExpression):
|
|
|
1758
1791
|
if handler is not None:
|
|
1759
1792
|
yield from handler()
|
|
1760
1793
|
else:
|
|
1761
|
-
yield
|
|
1794
|
+
yield from self._c_repr_chunks_opfirst(self.op)
|
|
1762
1795
|
|
|
1763
1796
|
def _has_const_null_rhs(self) -> bool:
|
|
1764
1797
|
return isinstance(self.rhs, CConstant) and self.rhs.value == 0
|
|
@@ -1799,6 +1832,15 @@ class CBinaryOp(CExpression):
|
|
|
1799
1832
|
else:
|
|
1800
1833
|
yield from self._try_c_repr_chunks(self.rhs)
|
|
1801
1834
|
|
|
1835
|
+
def _c_repr_chunks_opfirst(self, op):
|
|
1836
|
+
yield op, self
|
|
1837
|
+
paren = CClosingObject("(")
|
|
1838
|
+
yield "(", paren
|
|
1839
|
+
yield from self._try_c_repr_chunks(self.lhs)
|
|
1840
|
+
yield ", ", None
|
|
1841
|
+
yield from self._try_c_repr_chunks(self.rhs)
|
|
1842
|
+
yield ")", paren
|
|
1843
|
+
|
|
1802
1844
|
def _c_repr_chunks_add(self):
|
|
1803
1845
|
yield from self._c_repr_chunks(" + ")
|
|
1804
1846
|
|
|
@@ -1844,6 +1886,9 @@ class CBinaryOp(CExpression):
|
|
|
1844
1886
|
def _c_repr_chunks_logicalor(self):
|
|
1845
1887
|
yield from self._c_repr_chunks(" || ")
|
|
1846
1888
|
|
|
1889
|
+
def _c_repr_chunks_logicalxor(self):
|
|
1890
|
+
yield from self._c_repr_chunks(" ^ ")
|
|
1891
|
+
|
|
1847
1892
|
def _c_repr_chunks_cmple(self):
|
|
1848
1893
|
yield from self._c_repr_chunks(" <= ")
|
|
1849
1894
|
|
|
@@ -2004,6 +2049,14 @@ class CConstant(CExpression):
|
|
|
2004
2049
|
def fmt_char(self, v: bool):
|
|
2005
2050
|
self._fmt_setter["char"] = v
|
|
2006
2051
|
|
|
2052
|
+
@property
|
|
2053
|
+
def fmt_float(self):
|
|
2054
|
+
return self.fmt.get("float", False)
|
|
2055
|
+
|
|
2056
|
+
@fmt_float.setter
|
|
2057
|
+
def fmt_float(self, v: bool):
|
|
2058
|
+
self._fmt_setter["float"] = v
|
|
2059
|
+
|
|
2007
2060
|
@property
|
|
2008
2061
|
def type(self):
|
|
2009
2062
|
return self._type
|
|
@@ -2088,6 +2141,11 @@ class CConstant(CExpression):
|
|
|
2088
2141
|
:return: The formatted string.
|
|
2089
2142
|
"""
|
|
2090
2143
|
|
|
2144
|
+
if self.fmt_float:
|
|
2145
|
+
if 0 < value <= 0xFFFF_FFFF:
|
|
2146
|
+
str_value = str(struct.unpack("f", struct.pack("I", value))[0])
|
|
2147
|
+
return str_value
|
|
2148
|
+
|
|
2091
2149
|
if self.fmt_neg:
|
|
2092
2150
|
if value > 0:
|
|
2093
2151
|
value = value - 2**self._type.size
|
|
@@ -2272,6 +2330,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2272
2330
|
externs=None,
|
|
2273
2331
|
const_formats=None,
|
|
2274
2332
|
show_demangled_name=True,
|
|
2333
|
+
show_disambiguated_name=True,
|
|
2275
2334
|
ail_graph=None,
|
|
2276
2335
|
simplify_else_scope=True,
|
|
2277
2336
|
cstyle_ifs=True,
|
|
@@ -2338,6 +2397,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
2338
2397
|
self.externs = externs or set()
|
|
2339
2398
|
self.show_externs = show_externs
|
|
2340
2399
|
self.show_demangled_name = show_demangled_name
|
|
2400
|
+
self.show_disambiguated_name = show_disambiguated_name
|
|
2341
2401
|
self.ail_graph = ail_graph
|
|
2342
2402
|
self.simplify_else_scope = simplify_else_scope
|
|
2343
2403
|
self.cstyle_ifs = cstyle_ifs
|
|
@@ -3115,6 +3175,7 @@ class CStructuredCodeGenerator(BaseStructuredCodeGenerator, Analysis):
|
|
|
3115
3175
|
tags=stmt.tags,
|
|
3116
3176
|
is_expr=is_expr,
|
|
3117
3177
|
show_demangled_name=self.show_demangled_name,
|
|
3178
|
+
show_disambiguated_name=self.show_disambiguated_name,
|
|
3118
3179
|
codegen=self,
|
|
3119
3180
|
)
|
|
3120
3181
|
|
|
@@ -114,6 +114,8 @@ class PhoenixStructurer(StructurerBase):
|
|
|
114
114
|
self._edge_virtualization_hints = []
|
|
115
115
|
|
|
116
116
|
self._use_multistmtexprs = use_multistmtexprs
|
|
117
|
+
if not self._phoenix_improved:
|
|
118
|
+
self._use_multistmtexprs = MultiStmtExprMode.NEVER
|
|
117
119
|
|
|
118
120
|
self._analyze()
|
|
119
121
|
|
|
@@ -2141,7 +2143,7 @@ class PhoenixStructurer(StructurerBase):
|
|
|
2141
2143
|
pass
|
|
2142
2144
|
else:
|
|
2143
2145
|
# insert a Jump at the end
|
|
2144
|
-
stmt_addr =
|
|
2146
|
+
stmt_addr = src.addr
|
|
2145
2147
|
goto_node = Block(
|
|
2146
2148
|
stmt_addr,
|
|
2147
2149
|
0,
|
|
@@ -3,6 +3,7 @@ from typing import List, Tuple, Any, Optional, Union, OrderedDict as ODict
|
|
|
3
3
|
|
|
4
4
|
import claripy
|
|
5
5
|
import ailment
|
|
6
|
+
import ailment.utils
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
INDENT_DELTA = 2
|
|
@@ -387,11 +388,7 @@ class IncompleteSwitchCaseHeadStatement(ailment.statement.Statement):
|
|
|
387
388
|
Describes a switch-case head. This is only created by LoweredSwitchSimplifier.
|
|
388
389
|
"""
|
|
389
390
|
|
|
390
|
-
__slots__ = (
|
|
391
|
-
"addr",
|
|
392
|
-
"switch_variable",
|
|
393
|
-
"case_addrs",
|
|
394
|
-
)
|
|
391
|
+
__slots__ = ("addr", "switch_variable", "case_addrs", "_case_addrs_str")
|
|
395
392
|
|
|
396
393
|
def __init__(self, idx, switch_variable, case_addrs, **kwargs):
|
|
397
394
|
super().__init__(idx, **kwargs)
|
|
@@ -399,9 +396,18 @@ class IncompleteSwitchCaseHeadStatement(ailment.statement.Statement):
|
|
|
399
396
|
# original cmp node, case value | "default", address of the case node, idx of the case node,
|
|
400
397
|
# address of the next cmp node
|
|
401
398
|
self.case_addrs: List[Tuple[ailment.Block, Union[int, str], int, Optional[int], int]] = case_addrs
|
|
399
|
+
# a string representation of the addresses of all cases, used for hashing
|
|
400
|
+
self._case_addrs_str = str(sorted([c[0].addr for c in self.case_addrs if c[0] is not None]))
|
|
402
401
|
|
|
403
402
|
def __repr__(self):
|
|
404
403
|
return f"SwitchCaseHead: switch {self.switch_variable} with {len(self.case_addrs)} cases"
|
|
405
404
|
|
|
406
405
|
def __str__(self):
|
|
407
406
|
return f"switch ({str(self.switch_variable)}): {len(self.case_addrs)} cases"
|
|
407
|
+
|
|
408
|
+
__hash__ = ailment.statement.TaggedObject.__hash__
|
|
409
|
+
|
|
410
|
+
def _hash_core(self):
|
|
411
|
+
return ailment.utils.stable_hash(
|
|
412
|
+
(IncompleteSwitchCaseHeadStatement, self.idx, self.switch_variable, self._case_addrs_str)
|
|
413
|
+
)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
# pylint:disable=wrong-import-position
|
|
1
2
|
import pathlib
|
|
3
|
+
import copy
|
|
2
4
|
from typing import Optional, Tuple, Any, Union, List, Iterable
|
|
3
5
|
import logging
|
|
4
6
|
|
|
@@ -378,6 +380,30 @@ def remove_labels(graph: networkx.DiGraph):
|
|
|
378
380
|
return new_graph
|
|
379
381
|
|
|
380
382
|
|
|
383
|
+
def add_labels(graph: networkx.DiGraph):
|
|
384
|
+
new_graph = networkx.DiGraph()
|
|
385
|
+
nodes_map = {}
|
|
386
|
+
for node in graph:
|
|
387
|
+
lbl = ailment.Stmt.Label(None, f"LABEL_{node.addr:x}", node.addr, block_idx=node.idx)
|
|
388
|
+
node_copy = node.copy()
|
|
389
|
+
node_copy.statements = [lbl] + node_copy.statements
|
|
390
|
+
nodes_map[node] = node_copy
|
|
391
|
+
|
|
392
|
+
new_graph.add_nodes_from(nodes_map.values())
|
|
393
|
+
for src, dst in graph.edges:
|
|
394
|
+
new_graph.add_edge(nodes_map[src], nodes_map[dst])
|
|
395
|
+
|
|
396
|
+
return new_graph
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def update_labels(graph: networkx.DiGraph):
|
|
400
|
+
"""
|
|
401
|
+
A utility function to recreate the labels for every node in an AIL graph. This useful when you are working with
|
|
402
|
+
a graph where only _some_ of the nodes have labels.
|
|
403
|
+
"""
|
|
404
|
+
return add_labels(remove_labels(graph))
|
|
405
|
+
|
|
406
|
+
|
|
381
407
|
def structured_node_is_simple_return(node: Union["SequenceNode", "MultiNode"], graph: networkx.DiGraph) -> bool:
|
|
382
408
|
"""
|
|
383
409
|
Will check if a "simple return" is contained within the node a simple returns looks like this:
|
|
@@ -510,6 +536,30 @@ def peephole_optimize_expr(expr, expr_opts):
|
|
|
510
536
|
return new_expr
|
|
511
537
|
|
|
512
538
|
|
|
539
|
+
def copy_graph(graph: networkx.DiGraph):
|
|
540
|
+
"""
|
|
541
|
+
Copy AIL Graph.
|
|
542
|
+
|
|
543
|
+
:return: A copy of the AIl graph.
|
|
544
|
+
"""
|
|
545
|
+
graph_copy = networkx.DiGraph()
|
|
546
|
+
block_mapping = {}
|
|
547
|
+
# copy all blocks
|
|
548
|
+
for block in graph.nodes():
|
|
549
|
+
new_block = copy.copy(block)
|
|
550
|
+
new_stmts = copy.copy(block.statements)
|
|
551
|
+
new_block.statements = new_stmts
|
|
552
|
+
block_mapping[block] = new_block
|
|
553
|
+
graph_copy.add_node(new_block)
|
|
554
|
+
|
|
555
|
+
# copy all edges
|
|
556
|
+
for src, dst, data in graph.edges(data=True):
|
|
557
|
+
new_src = block_mapping[src]
|
|
558
|
+
new_dst = block_mapping[dst]
|
|
559
|
+
graph_copy.add_edge(new_src, new_dst, **data)
|
|
560
|
+
return graph_copy
|
|
561
|
+
|
|
562
|
+
|
|
513
563
|
def peephole_optimize_stmts(block, stmt_opts):
|
|
514
564
|
any_update = False
|
|
515
565
|
statements = []
|
angr/analyses/disassembly.py
CHANGED
|
@@ -133,6 +133,8 @@ class IROp(DisassemblyPiece):
|
|
|
133
133
|
self.irsb = irsb
|
|
134
134
|
|
|
135
135
|
def __str__(self):
|
|
136
|
+
if pcode and isinstance(self.obj, pypcode.PcodeOp):
|
|
137
|
+
return pypcode.PcodePrettyPrinter.fmt_op(self.obj)
|
|
136
138
|
return str(self.obj)
|
|
137
139
|
|
|
138
140
|
def _render(self, formatting): # pylint:disable=unused-argument
|
|
@@ -1078,9 +1080,14 @@ class Disassembly(Analysis):
|
|
|
1078
1080
|
|
|
1079
1081
|
if irsb.statements is not None:
|
|
1080
1082
|
if pcode is not None and isinstance(self.project.factory.default_engine, pcode.HeavyPcodeMixin):
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1083
|
+
addr = None
|
|
1084
|
+
stmt_idx = 0
|
|
1085
|
+
for op in irsb._ops:
|
|
1086
|
+
if op.opcode == pypcode.OpCode.IMARK:
|
|
1087
|
+
addr = op.inputs[0].offset
|
|
1088
|
+
else:
|
|
1089
|
+
addr_to_ops_map[addr].append(IROp(addr, stmt_idx, op, irsb))
|
|
1090
|
+
stmt_idx += 1
|
|
1084
1091
|
else:
|
|
1085
1092
|
for seq, stmt in enumerate(irsb.statements):
|
|
1086
1093
|
if isinstance(stmt, pyvex.stmt.IMark):
|
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
|
|
5
5
|
import claripy
|
|
6
6
|
from ailment import Stmt, Expr
|
|
7
|
+
from unique_log_filter import UniqueLogFilter
|
|
7
8
|
|
|
8
9
|
from angr.knowledge_plugins.propagations.prop_value import PropValue, Detail
|
|
9
10
|
from angr.knowledge_plugins.key_definitions.atoms import Register
|
|
@@ -20,6 +21,7 @@ if TYPE_CHECKING:
|
|
|
20
21
|
from angr.code_location import CodeLocation
|
|
21
22
|
|
|
22
23
|
l = logging.getLogger(name=__name__)
|
|
24
|
+
l.addFilter(UniqueLogFilter())
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
class SimEnginePropagatorAIL(
|
|
@@ -1268,6 +1270,129 @@ class SimEnginePropagatorAIL(
|
|
|
1268
1270
|
)
|
|
1269
1271
|
return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
|
|
1270
1272
|
|
|
1273
|
+
def _ail_handle_LogicalOr(self, expr: Expr.BinaryOp):
|
|
1274
|
+
o0_value = self._expr(expr.operands[0])
|
|
1275
|
+
o1_value = self._expr(expr.operands[1])
|
|
1276
|
+
|
|
1277
|
+
value = self.state.top(expr.bits)
|
|
1278
|
+
if o0_value is None or o1_value is None:
|
|
1279
|
+
new_expr = expr
|
|
1280
|
+
else:
|
|
1281
|
+
o0_expr = o0_value.one_expr
|
|
1282
|
+
o1_expr = o1_value.one_expr
|
|
1283
|
+
|
|
1284
|
+
value = self.state.top(expr.bits)
|
|
1285
|
+
new_expr = Expr.BinaryOp(
|
|
1286
|
+
expr.idx,
|
|
1287
|
+
"LogicalOr",
|
|
1288
|
+
[
|
|
1289
|
+
o0_expr if o0_expr is not None else expr.operands[0],
|
|
1290
|
+
o1_expr if o1_expr is not None else expr.operands[1],
|
|
1291
|
+
],
|
|
1292
|
+
expr.signed,
|
|
1293
|
+
**expr.tags,
|
|
1294
|
+
)
|
|
1295
|
+
return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
|
|
1296
|
+
|
|
1297
|
+
def _ail_handle_LogicalXor(self, expr: Expr.BinaryOp):
|
|
1298
|
+
o0_value = self._expr(expr.operands[0])
|
|
1299
|
+
o1_value = self._expr(expr.operands[1])
|
|
1300
|
+
|
|
1301
|
+
value = self.state.top(expr.bits)
|
|
1302
|
+
if o0_value is None or o1_value is None:
|
|
1303
|
+
new_expr = expr
|
|
1304
|
+
else:
|
|
1305
|
+
o0_expr = o0_value.one_expr
|
|
1306
|
+
o1_expr = o1_value.one_expr
|
|
1307
|
+
|
|
1308
|
+
value = self.state.top(expr.bits)
|
|
1309
|
+
new_expr = Expr.BinaryOp(
|
|
1310
|
+
expr.idx,
|
|
1311
|
+
"LogicalXor",
|
|
1312
|
+
[
|
|
1313
|
+
o0_expr if o0_expr is not None else expr.operands[0],
|
|
1314
|
+
o1_expr if o1_expr is not None else expr.operands[1],
|
|
1315
|
+
],
|
|
1316
|
+
expr.signed,
|
|
1317
|
+
**expr.tags,
|
|
1318
|
+
)
|
|
1319
|
+
return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
|
|
1320
|
+
|
|
1321
|
+
def _ail_handle_Carry(self, expr: Expr.BinaryOp):
|
|
1322
|
+
o0_value = self._expr(expr.operands[0])
|
|
1323
|
+
o1_value = self._expr(expr.operands[1])
|
|
1324
|
+
|
|
1325
|
+
value = self.state.top(expr.bits)
|
|
1326
|
+
if o0_value is None or o1_value is None:
|
|
1327
|
+
new_expr = expr
|
|
1328
|
+
else:
|
|
1329
|
+
o0_expr = o0_value.one_expr
|
|
1330
|
+
o1_expr = o1_value.one_expr
|
|
1331
|
+
new_expr = Expr.BinaryOp(
|
|
1332
|
+
expr.idx,
|
|
1333
|
+
"Carry",
|
|
1334
|
+
[
|
|
1335
|
+
o0_expr if o0_expr is not None else expr.operands[0],
|
|
1336
|
+
o1_expr if o1_expr is not None else expr.operands[1],
|
|
1337
|
+
],
|
|
1338
|
+
expr.signed,
|
|
1339
|
+
bits=expr.bits,
|
|
1340
|
+
floating_point=expr.floating_point,
|
|
1341
|
+
rounding_mode=expr.rounding_mode,
|
|
1342
|
+
**expr.tags,
|
|
1343
|
+
)
|
|
1344
|
+
return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
|
|
1345
|
+
|
|
1346
|
+
def _ail_handle_SCarry(self, expr: Expr.BinaryOp):
|
|
1347
|
+
o0_value = self._expr(expr.operands[0])
|
|
1348
|
+
o1_value = self._expr(expr.operands[1])
|
|
1349
|
+
|
|
1350
|
+
value = self.state.top(expr.bits)
|
|
1351
|
+
if o0_value is None or o1_value is None:
|
|
1352
|
+
new_expr = expr
|
|
1353
|
+
else:
|
|
1354
|
+
o0_expr = o0_value.one_expr
|
|
1355
|
+
o1_expr = o1_value.one_expr
|
|
1356
|
+
new_expr = Expr.BinaryOp(
|
|
1357
|
+
expr.idx,
|
|
1358
|
+
"SCarry",
|
|
1359
|
+
[
|
|
1360
|
+
o0_expr if o0_expr is not None else expr.operands[0],
|
|
1361
|
+
o1_expr if o1_expr is not None else expr.operands[1],
|
|
1362
|
+
],
|
|
1363
|
+
expr.signed,
|
|
1364
|
+
bits=expr.bits,
|
|
1365
|
+
floating_point=expr.floating_point,
|
|
1366
|
+
rounding_mode=expr.rounding_mode,
|
|
1367
|
+
**expr.tags,
|
|
1368
|
+
)
|
|
1369
|
+
return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
|
|
1370
|
+
|
|
1371
|
+
def _ail_handle_SBorrow(self, expr: Expr.BinaryOp):
|
|
1372
|
+
o0_value = self._expr(expr.operands[0])
|
|
1373
|
+
o1_value = self._expr(expr.operands[1])
|
|
1374
|
+
|
|
1375
|
+
value = self.state.top(expr.bits)
|
|
1376
|
+
if o0_value is None or o1_value is None:
|
|
1377
|
+
new_expr = expr
|
|
1378
|
+
else:
|
|
1379
|
+
o0_expr = o0_value.one_expr
|
|
1380
|
+
o1_expr = o1_value.one_expr
|
|
1381
|
+
new_expr = Expr.BinaryOp(
|
|
1382
|
+
expr.idx,
|
|
1383
|
+
"SBorrow",
|
|
1384
|
+
[
|
|
1385
|
+
o0_expr if o0_expr is not None else expr.operands[0],
|
|
1386
|
+
o1_expr if o1_expr is not None else expr.operands[1],
|
|
1387
|
+
],
|
|
1388
|
+
expr.signed,
|
|
1389
|
+
bits=expr.bits,
|
|
1390
|
+
floating_point=expr.floating_point,
|
|
1391
|
+
rounding_mode=expr.rounding_mode,
|
|
1392
|
+
**expr.tags,
|
|
1393
|
+
)
|
|
1394
|
+
return PropValue.from_value_and_details(value, expr.size, new_expr, self._codeloc())
|
|
1395
|
+
|
|
1271
1396
|
def _ail_handle_TernaryOp(self, expr: Expr.TernaryOp):
|
|
1272
1397
|
o0_value = self._expr(expr.operands[0])
|
|
1273
1398
|
o1_value = self._expr(expr.operands[1])
|
|
@@ -981,7 +981,6 @@ class SimEngineRDAIL(
|
|
|
981
981
|
expr1: MultiValues = self._expr(expr.operands[1])
|
|
982
982
|
bits = expr.bits
|
|
983
983
|
|
|
984
|
-
r = None
|
|
985
984
|
expr0_v = expr0.one_value()
|
|
986
985
|
expr1_v = expr1.one_value()
|
|
987
986
|
|
|
@@ -999,7 +998,6 @@ class SimEngineRDAIL(
|
|
|
999
998
|
expr1: MultiValues = self._expr(expr.operands[1])
|
|
1000
999
|
bits = expr.bits
|
|
1001
1000
|
|
|
1002
|
-
r = None
|
|
1003
1001
|
expr0_v = expr0.one_value()
|
|
1004
1002
|
expr1_v = expr1.one_value()
|
|
1005
1003
|
|
|
@@ -1010,6 +1008,21 @@ class SimEngineRDAIL(
|
|
|
1010
1008
|
r = MultiValues(claripy.If(expr0_v != 0, expr0_v, expr1_v))
|
|
1011
1009
|
return r
|
|
1012
1010
|
|
|
1011
|
+
def _ail_handle_LogicalXor(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
|
|
1012
|
+
expr0: MultiValues = self._expr(expr.operands[0])
|
|
1013
|
+
expr1: MultiValues = self._expr(expr.operands[1])
|
|
1014
|
+
bits = expr.bits
|
|
1015
|
+
|
|
1016
|
+
expr0_v = expr0.one_value()
|
|
1017
|
+
expr1_v = expr1.one_value()
|
|
1018
|
+
|
|
1019
|
+
if expr0_v is None or expr1_v is None:
|
|
1020
|
+
r = MultiValues(self.state.top(bits))
|
|
1021
|
+
return r
|
|
1022
|
+
|
|
1023
|
+
r = MultiValues(claripy.If(expr0_v != 0, expr1_v, expr0_v))
|
|
1024
|
+
return r
|
|
1025
|
+
|
|
1013
1026
|
def _ail_handle_Xor(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
|
|
1014
1027
|
expr0: MultiValues = self._expr(expr.operands[0])
|
|
1015
1028
|
expr1: MultiValues = self._expr(expr.operands[1])
|
|
@@ -1042,6 +1055,27 @@ class SimEngineRDAIL(
|
|
|
1042
1055
|
|
|
1043
1056
|
return r
|
|
1044
1057
|
|
|
1058
|
+
def _ail_handle_Carry(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
|
|
1059
|
+
_ = self._expr(expr.operands[0])
|
|
1060
|
+
_ = self._expr(expr.operands[1])
|
|
1061
|
+
bits = expr.bits
|
|
1062
|
+
r = MultiValues(self.state.top(bits))
|
|
1063
|
+
return r
|
|
1064
|
+
|
|
1065
|
+
def _ail_handle_SCarry(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
|
|
1066
|
+
_ = self._expr(expr.operands[0])
|
|
1067
|
+
_ = self._expr(expr.operands[1])
|
|
1068
|
+
bits = expr.bits
|
|
1069
|
+
r = MultiValues(self.state.top(bits))
|
|
1070
|
+
return r
|
|
1071
|
+
|
|
1072
|
+
def _ail_handle_SBorrow(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
|
|
1073
|
+
_ = self._expr(expr.operands[0])
|
|
1074
|
+
_ = self._expr(expr.operands[1])
|
|
1075
|
+
bits = expr.bits
|
|
1076
|
+
r = MultiValues(self.state.top(bits))
|
|
1077
|
+
return r
|
|
1078
|
+
|
|
1045
1079
|
def _ail_handle_Concat(self, expr: ailment.Expr.BinaryOp) -> MultiValues:
|
|
1046
1080
|
expr0: MultiValues = self._expr(expr.operands[0])
|
|
1047
1081
|
expr1: MultiValues = self._expr(expr.operands[1])
|
|
@@ -33,8 +33,9 @@ class RDAStateInitializer:
|
|
|
33
33
|
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
|
-
def __init__(self, arch: Arch):
|
|
36
|
+
def __init__(self, arch: Arch, project=None):
|
|
37
37
|
self.arch: Arch = arch
|
|
38
|
+
self.project = project
|
|
38
39
|
|
|
39
40
|
def initialize_function_state(
|
|
40
41
|
self, state: "ReachingDefinitionsState", cc: Optional[SimCC], func_addr: int, rtoc_value: Optional[int] = None
|
|
@@ -171,6 +172,19 @@ class RDAStateInitializer:
|
|
|
171
172
|
t9 = state.annotate_with_def(claripy.BVV(func_addr, self.arch.bits), t9_def)
|
|
172
173
|
state.registers.store(t9_offset, t9)
|
|
173
174
|
|
|
175
|
+
# project-specific initialization
|
|
176
|
+
if self.project is not None:
|
|
177
|
+
if self.project.simos is not None and self.project.simos.function_initial_registers:
|
|
178
|
+
for reg_name, reg_value in self.project.simos.function_initial_registers.items():
|
|
179
|
+
reg_offset = self.arch.registers[reg_name][0]
|
|
180
|
+
reg_atom = Register(reg_offset, self.arch.registers[reg_name][1])
|
|
181
|
+
reg_def = Definition(reg_atom, ex_loc, tags={InitialValueTag()})
|
|
182
|
+
state.all_definitions.add(reg_def)
|
|
183
|
+
if state.analysis is not None:
|
|
184
|
+
state.analysis.model.add_def(reg_def)
|
|
185
|
+
reg = state.annotate_with_def(claripy.BVV(reg_value, self.arch.registers[reg_name][1]), reg_def)
|
|
186
|
+
state.registers.store(reg_offset, reg)
|
|
187
|
+
|
|
174
188
|
def _initialize_function_argument_register(
|
|
175
189
|
self,
|
|
176
190
|
state: "ReachingDefinitionsState",
|
|
@@ -124,10 +124,11 @@ class ReachingDefinitionsState:
|
|
|
124
124
|
self.live_definitions = LiveDefinitions(
|
|
125
125
|
self.arch, track_tmps=self._track_tmps, canonical_size=canonical_size
|
|
126
126
|
)
|
|
127
|
-
self._set_initialization_values(subject, rtoc_value, initializer=initializer)
|
|
128
|
-
|
|
129
127
|
if self.analysis is not None:
|
|
130
128
|
self.live_definitions.project = self.analysis.project
|
|
129
|
+
self._set_initialization_values(
|
|
130
|
+
subject, rtoc_value, initializer=initializer, project=self.live_definitions.project
|
|
131
|
+
)
|
|
131
132
|
else:
|
|
132
133
|
# this state is a copy from a previous state. skip the initialization
|
|
133
134
|
self.live_definitions = live_definitions
|
|
@@ -269,10 +270,14 @@ class ReachingDefinitionsState:
|
|
|
269
270
|
return "{%s}" % ctnt
|
|
270
271
|
|
|
271
272
|
def _set_initialization_values(
|
|
272
|
-
self,
|
|
273
|
+
self,
|
|
274
|
+
subject: Subject,
|
|
275
|
+
rtoc_value: Optional[int] = None,
|
|
276
|
+
initializer: Optional[RDAStateInitializer] = None,
|
|
277
|
+
project=None,
|
|
273
278
|
):
|
|
274
279
|
if initializer is None:
|
|
275
|
-
initializer = RDAStateInitializer(self.arch)
|
|
280
|
+
initializer = RDAStateInitializer(self.arch, project=project)
|
|
276
281
|
|
|
277
282
|
if subject.type == SubjectType.Function:
|
|
278
283
|
if isinstance(self.arch, archinfo.arch_ppc64.ArchPPC64) and not rtoc_value:
|
|
@@ -695,28 +695,21 @@ class StackPointerTracker(Analysis, ForwardAnalysis):
|
|
|
695
695
|
else:
|
|
696
696
|
raise CouldNotResolveException()
|
|
697
697
|
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
698
|
+
is_call = False
|
|
699
|
+
for op in pcode_irsb._ops:
|
|
700
|
+
if op.opcode == pypcode.OpCode.IMARK:
|
|
701
|
+
if curr_stmt_start_addr is not None:
|
|
702
|
+
# we've reached a new instruction. Time to store the post state
|
|
703
|
+
self._set_post_state(curr_stmt_start_addr, state.freeze())
|
|
704
|
+
curr_stmt_start_addr = op.inputs[0].offset
|
|
705
|
+
self._set_pre_state(curr_stmt_start_addr, state.freeze())
|
|
706
|
+
else:
|
|
707
707
|
try:
|
|
708
708
|
resolve_op(op)
|
|
709
709
|
except CouldNotResolveException:
|
|
710
710
|
pass
|
|
711
711
|
|
|
712
|
-
|
|
713
|
-
is_call = False
|
|
714
|
-
if pcode_irsb._instructions:
|
|
715
|
-
last_instr = pcode_irsb._instructions[-1]
|
|
716
|
-
if last_instr.ops:
|
|
717
|
-
last_op = last_instr.ops[-1]
|
|
718
|
-
if last_op.opcode == pypcode.OpCode.CALL:
|
|
719
|
-
is_call = True
|
|
712
|
+
is_call |= op.opcode == pypcode.OpCode.CALL
|
|
720
713
|
|
|
721
714
|
# stack pointer adjustment
|
|
722
715
|
if self.project.arch.sp_offset in self.reg_offsets and is_call:
|