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
|
@@ -139,7 +139,7 @@ class LoweredSwitchSimplifier(OptimizationPass):
|
|
|
139
139
|
"AMD64",
|
|
140
140
|
]
|
|
141
141
|
PLATFORMS = ["linux", "windows"]
|
|
142
|
-
STAGE = OptimizationPassStage.
|
|
142
|
+
STAGE = OptimizationPassStage.DURING_REGION_IDENTIFICATION
|
|
143
143
|
NAME = "Convert lowered switch-cases (if-else) to switch-cases"
|
|
144
144
|
DESCRIPTION = (
|
|
145
145
|
"Convert lowered switch-cases (if-else) to switch-cases. Only works when the Phoenix structuring "
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
from ailment import Expr
|
|
4
|
+
from unique_log_filter import UniqueLogFilter
|
|
4
5
|
|
|
5
6
|
from .engine_base import SimplifierAILEngine, SimplifierAILState
|
|
6
7
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
7
8
|
|
|
8
9
|
_l = logging.getLogger(name=__name__)
|
|
10
|
+
_l.addFilter(UniqueLogFilter())
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class ModSimplifierAILEngine(SimplifierAILEngine):
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
from ailment import Expr
|
|
4
|
+
from unique_log_filter import UniqueLogFilter
|
|
4
5
|
|
|
5
6
|
from .engine_base import SimplifierAILEngine, SimplifierAILState
|
|
6
7
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
7
8
|
|
|
8
9
|
_l = logging.getLogger(name=__name__)
|
|
10
|
+
_l.addFilter(UniqueLogFilter())
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class MultiSimplifierAILEngine(SimplifierAILEngine):
|
|
@@ -3,9 +3,12 @@ from typing import Optional, Dict, Set, Tuple, Generator, TYPE_CHECKING
|
|
|
3
3
|
from enum import Enum
|
|
4
4
|
|
|
5
5
|
import networkx # pylint:disable=unused-import
|
|
6
|
-
|
|
7
6
|
import ailment
|
|
8
7
|
|
|
8
|
+
from angr.analyses.decompiler import RegionIdentifier
|
|
9
|
+
from angr.analyses.decompiler.goto_manager import GotoManager
|
|
10
|
+
from angr.analyses.decompiler.structuring import RecursiveStructurer, PhoenixStructurer
|
|
11
|
+
from angr.analyses.decompiler.utils import add_labels
|
|
9
12
|
|
|
10
13
|
if TYPE_CHECKING:
|
|
11
14
|
from angr.knowledge_plugins.functions import Function
|
|
@@ -17,8 +20,6 @@ class MultipleBlocksException(Exception):
|
|
|
17
20
|
requested.
|
|
18
21
|
"""
|
|
19
22
|
|
|
20
|
-
pass
|
|
21
|
-
|
|
22
23
|
|
|
23
24
|
class OptimizationPassStage(Enum):
|
|
24
25
|
"""
|
|
@@ -234,3 +235,130 @@ class SequenceOptimizationPass(BaseOptimizationPass):
|
|
|
234
235
|
super().__init__(func)
|
|
235
236
|
self.seq = seq
|
|
236
237
|
self.out_seq = None
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class StructuringOptimizationPass(OptimizationPass):
|
|
241
|
+
"""
|
|
242
|
+
The base class for any optimization pass that requires structuring. Optimization passes that inherit from this class
|
|
243
|
+
should directly depend on structuring artifacts, such as regions and gotos. Otherwise, they should use
|
|
244
|
+
OptimizationPass. This is the heaviest (computation time) optimization pass class.
|
|
245
|
+
"""
|
|
246
|
+
|
|
247
|
+
ARCHES = None
|
|
248
|
+
PLATFORMS = None
|
|
249
|
+
STAGE = OptimizationPassStage.DURING_REGION_IDENTIFICATION
|
|
250
|
+
|
|
251
|
+
def __init__(
|
|
252
|
+
self, func, prevent_new_gotos=True, recover_structure_fails=True, max_opt_iters=1, simplify_ail=True, **kwargs
|
|
253
|
+
):
|
|
254
|
+
super().__init__(func, **kwargs)
|
|
255
|
+
self._prevent_new_gotos = prevent_new_gotos
|
|
256
|
+
self._recover_structure_fails = recover_structure_fails
|
|
257
|
+
self._max_opt_iters = max_opt_iters
|
|
258
|
+
self._simplify_ail = simplify_ail
|
|
259
|
+
|
|
260
|
+
self._goto_manager: Optional[GotoManager] = None
|
|
261
|
+
self._prev_graph: Optional[networkx.DiGraph] = None
|
|
262
|
+
|
|
263
|
+
def _analyze(self, cache=None) -> bool:
|
|
264
|
+
raise NotImplementedError()
|
|
265
|
+
|
|
266
|
+
def analyze(self):
|
|
267
|
+
"""
|
|
268
|
+
Wrapper for _analyze() that verifies the graph is structurable before and after the optimization.
|
|
269
|
+
"""
|
|
270
|
+
if not self._graph_is_structurable(self._graph):
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
initial_gotos = self._goto_manager.gotos.copy()
|
|
274
|
+
# replace the normal check in OptimizationPass.analyze()
|
|
275
|
+
ret, cache = self._check()
|
|
276
|
+
if not ret:
|
|
277
|
+
return
|
|
278
|
+
|
|
279
|
+
# setup for the very first analysis
|
|
280
|
+
self.out_graph = networkx.DiGraph(self._graph)
|
|
281
|
+
if self._max_opt_iters > 1:
|
|
282
|
+
self._fixed_point_analyze(cache=cache)
|
|
283
|
+
else:
|
|
284
|
+
updates = self._analyze(cache=cache)
|
|
285
|
+
if not updates:
|
|
286
|
+
self.out_graph = None
|
|
287
|
+
|
|
288
|
+
# analysis is complete, no out_graph means it failed somewhere along the way
|
|
289
|
+
if self.out_graph is None:
|
|
290
|
+
return
|
|
291
|
+
|
|
292
|
+
if not self._graph_is_structurable(self.out_graph):
|
|
293
|
+
self.out_graph = None
|
|
294
|
+
return
|
|
295
|
+
|
|
296
|
+
# simplify the AIL graph
|
|
297
|
+
if self._simplify_ail:
|
|
298
|
+
# this should not (TM) change the structure of the graph but is needed for later optimizations
|
|
299
|
+
self.out_graph = self._simplify_ail_graph(self.out_graph)
|
|
300
|
+
|
|
301
|
+
if self._prevent_new_gotos and (len(self._goto_manager.gotos) > len(initial_gotos)):
|
|
302
|
+
self.out_graph = None
|
|
303
|
+
return
|
|
304
|
+
|
|
305
|
+
def _fixed_point_analyze(self, cache=None):
|
|
306
|
+
for _ in range(self._max_opt_iters):
|
|
307
|
+
# backup the graph before the optimization
|
|
308
|
+
if self._recover_structure_fails and self.out_graph is not None:
|
|
309
|
+
self._prev_graph = networkx.DiGraph(self.out_graph)
|
|
310
|
+
|
|
311
|
+
# run the optimization, output applied to self.out_graph
|
|
312
|
+
changes = self._analyze(cache=cache)
|
|
313
|
+
if not changes:
|
|
314
|
+
break
|
|
315
|
+
|
|
316
|
+
# check if the graph is structurable
|
|
317
|
+
if not self._graph_is_structurable(self.out_graph):
|
|
318
|
+
self.out_graph = self._prev_graph if self._recover_structure_fails else None
|
|
319
|
+
break
|
|
320
|
+
|
|
321
|
+
def _simplify_ail_graph(self, graph):
|
|
322
|
+
simp = self.project.analyses.AILSimplifier(
|
|
323
|
+
self._func,
|
|
324
|
+
func_graph=graph,
|
|
325
|
+
gp=self._func.info.get("gp", None) if self.project.arch.name in {"MIPS32", "MIPS64"} else None,
|
|
326
|
+
)
|
|
327
|
+
return simp.func_graph if simp.simplified else graph
|
|
328
|
+
|
|
329
|
+
def _graph_is_structurable(self, graph, readd_labels=False) -> bool:
|
|
330
|
+
"""
|
|
331
|
+
Checks weather the input graph is structurable under the Phoenix schema-matching structuring algorithm.
|
|
332
|
+
As a side effect, this will also update the region identifier and goto manager of this optimization pass.
|
|
333
|
+
Consequently, a true return guarantees up-to-date goto information in the goto manager.
|
|
334
|
+
"""
|
|
335
|
+
if readd_labels:
|
|
336
|
+
graph = add_labels(graph)
|
|
337
|
+
|
|
338
|
+
self._ri = self.project.analyses[RegionIdentifier].prep(kb=self.kb)(
|
|
339
|
+
self._func,
|
|
340
|
+
graph=graph,
|
|
341
|
+
# never update the graph in-place, we need to keep the original graph for later use
|
|
342
|
+
update_graph=False,
|
|
343
|
+
cond_proc=self._ri.cond_proc,
|
|
344
|
+
force_loop_single_exit=False,
|
|
345
|
+
complete_successors=True,
|
|
346
|
+
)
|
|
347
|
+
if self._ri is None:
|
|
348
|
+
return False
|
|
349
|
+
|
|
350
|
+
rs = self.project.analyses[RecursiveStructurer].prep(kb=self.kb)(
|
|
351
|
+
self._ri.region,
|
|
352
|
+
cond_proc=self._ri.cond_proc,
|
|
353
|
+
func=self._func,
|
|
354
|
+
structurer_cls=PhoenixStructurer,
|
|
355
|
+
)
|
|
356
|
+
if not rs or not rs.result or not rs.result.nodes:
|
|
357
|
+
return False
|
|
358
|
+
|
|
359
|
+
rs = self.project.analyses.RegionSimplifier(self._func, rs.result, kb=self.kb, variable_kb=self._variable_kb)
|
|
360
|
+
if not rs or rs.goto_manager is None:
|
|
361
|
+
return False
|
|
362
|
+
|
|
363
|
+
self._goto_manager = rs.goto_manager
|
|
364
|
+
return True
|
|
@@ -6,7 +6,7 @@ from ailment import Block
|
|
|
6
6
|
from ailment.statement import ConditionalJump, Return
|
|
7
7
|
|
|
8
8
|
from ....utils.graph import subgraph_between_nodes
|
|
9
|
-
from ..utils import remove_labels, to_ail_supergraph
|
|
9
|
+
from ..utils import remove_labels, to_ail_supergraph, update_labels
|
|
10
10
|
from .optimization_pass import OptimizationPass, OptimizationPassStage
|
|
11
11
|
|
|
12
12
|
|
|
@@ -26,7 +26,7 @@ class ReturnDeduplicator(OptimizationPass):
|
|
|
26
26
|
|
|
27
27
|
ARCHES = ["X86", "AMD64", "ARMEL", "ARMHF", "ARMCortexM", "MIPS32", "MIPS64"]
|
|
28
28
|
PLATFORMS = ["windows", "linux", "cgc"]
|
|
29
|
-
STAGE = OptimizationPassStage.
|
|
29
|
+
STAGE = OptimizationPassStage.DURING_REGION_IDENTIFICATION
|
|
30
30
|
NAME = "Deduplicates return statements that may have been duplicated"
|
|
31
31
|
DESCRIPTION = __doc__.strip()
|
|
32
32
|
|
|
@@ -44,7 +44,7 @@ class ReturnDeduplicator(OptimizationPass):
|
|
|
44
44
|
graph_updated |= self._fix_if_ret_region(region_head, true_child, false_child, super_true, super_false)
|
|
45
45
|
|
|
46
46
|
if graph_updated:
|
|
47
|
-
self.out_graph = self._graph
|
|
47
|
+
self.out_graph = update_labels(self._graph)
|
|
48
48
|
|
|
49
49
|
def _fix_if_ret_region(self, region_head, true_child, false_child, super_true, super_false):
|
|
50
50
|
"""
|