angr 9.2.138__py3-none-manylinux2014_x86_64.whl → 9.2.140__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/calling_convention/calling_convention.py +48 -21
- angr/analyses/calling_convention/fact_collector.py +59 -12
- angr/analyses/calling_convention/utils.py +2 -2
- angr/analyses/cfg/cfg_base.py +13 -0
- angr/analyses/cfg/cfg_fast.py +23 -4
- angr/analyses/decompiler/ail_simplifier.py +79 -53
- angr/analyses/decompiler/block_simplifier.py +0 -2
- angr/analyses/decompiler/callsite_maker.py +80 -14
- angr/analyses/decompiler/clinic.py +99 -80
- angr/analyses/decompiler/condition_processor.py +2 -2
- angr/analyses/decompiler/decompiler.py +19 -7
- angr/analyses/decompiler/dephication/rewriting_engine.py +16 -7
- angr/analyses/decompiler/expression_narrower.py +1 -1
- angr/analyses/decompiler/optimization_passes/__init__.py +3 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +149 -0
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +8 -7
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +12 -3
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +1 -1
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +21 -13
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +21 -12
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +17 -9
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +7 -10
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +12 -1
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +61 -25
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +50 -1
- angr/analyses/decompiler/presets/fast.py +2 -0
- angr/analyses/decompiler/presets/full.py +2 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +259 -108
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +28 -9
- angr/analyses/decompiler/ssailification/rewriting_engine.py +20 -2
- angr/analyses/decompiler/ssailification/traversal_engine.py +4 -3
- angr/analyses/decompiler/structured_codegen/c.py +10 -3
- angr/analyses/decompiler/structuring/dream.py +28 -19
- angr/analyses/decompiler/structuring/phoenix.py +253 -89
- angr/analyses/decompiler/structuring/recursive_structurer.py +1 -0
- angr/analyses/decompiler/structuring/structurer_base.py +121 -46
- angr/analyses/decompiler/structuring/structurer_nodes.py +6 -1
- angr/analyses/decompiler/utils.py +60 -1
- angr/analyses/deobfuscator/api_obf_finder.py +13 -5
- angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
- angr/analyses/deobfuscator/string_obf_finder.py +105 -18
- angr/analyses/forward_analysis/forward_analysis.py +1 -1
- angr/analyses/propagator/top_checker_mixin.py +6 -6
- angr/analyses/reaching_definitions/__init__.py +2 -1
- angr/analyses/reaching_definitions/dep_graph.py +1 -12
- angr/analyses/reaching_definitions/engine_vex.py +36 -31
- angr/analyses/reaching_definitions/function_handler.py +15 -2
- angr/analyses/reaching_definitions/rd_state.py +1 -37
- angr/analyses/reaching_definitions/reaching_definitions.py +13 -24
- angr/analyses/s_propagator.py +129 -87
- angr/analyses/s_reaching_definitions/s_rda_model.py +7 -1
- angr/analyses/s_reaching_definitions/s_rda_view.py +2 -2
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +3 -1
- angr/analyses/stack_pointer_tracker.py +36 -22
- angr/analyses/typehoon/simple_solver.py +45 -7
- angr/analyses/typehoon/typeconsts.py +18 -5
- angr/analyses/variable_recovery/engine_ail.py +1 -1
- angr/analyses/variable_recovery/engine_base.py +62 -67
- angr/analyses/variable_recovery/engine_vex.py +1 -1
- angr/analyses/variable_recovery/irsb_scanner.py +2 -2
- angr/block.py +69 -107
- angr/callable.py +14 -7
- angr/calling_conventions.py +81 -10
- angr/distributed/__init__.py +1 -1
- angr/engines/__init__.py +7 -8
- angr/engines/engine.py +3 -138
- angr/engines/failure.py +2 -2
- angr/engines/hook.py +2 -2
- angr/engines/light/engine.py +5 -10
- angr/engines/pcode/emulate.py +2 -2
- angr/engines/pcode/engine.py +2 -14
- angr/engines/pcode/lifter.py +2 -2
- angr/engines/procedure.py +2 -2
- angr/engines/soot/engine.py +2 -2
- angr/engines/soot/statements/switch.py +1 -1
- angr/engines/successors.py +123 -17
- angr/engines/syscall.py +2 -2
- angr/engines/unicorn.py +3 -3
- angr/engines/vex/heavy/heavy.py +3 -15
- angr/engines/vex/lifter.py +2 -2
- angr/engines/vex/light/light.py +2 -2
- angr/factory.py +4 -19
- angr/knowledge_plugins/cfg/cfg_model.py +3 -2
- angr/knowledge_plugins/key_definitions/atoms.py +8 -4
- angr/knowledge_plugins/key_definitions/live_definitions.py +41 -103
- angr/knowledge_plugins/labels.py +2 -2
- angr/knowledge_plugins/obfuscations.py +1 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +4 -0
- angr/sim_type.py +19 -17
- angr/state_plugins/plugin.py +19 -4
- angr/storage/memory_mixins/memory_mixin.py +1 -1
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +10 -5
- angr/utils/ssa/__init__.py +119 -4
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/METADATA +6 -6
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/RECORD +100 -98
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/LICENSE +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/WHEEL +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/entry_points.txt +0 -0
- {angr-9.2.138.dist-info → angr-9.2.140.dist-info}/top_level.txt +0 -0
angr/__init__.py
CHANGED
|
@@ -150,6 +150,8 @@ class CallingConventionAnalysis(Analysis):
|
|
|
150
150
|
The major analysis routine.
|
|
151
151
|
"""
|
|
152
152
|
|
|
153
|
+
assert self._function is not None
|
|
154
|
+
|
|
153
155
|
if self._function.is_simprocedure:
|
|
154
156
|
hooker = self.project.hooked_by(self._function.addr)
|
|
155
157
|
if isinstance(
|
|
@@ -200,8 +202,8 @@ class CallingConventionAnalysis(Analysis):
|
|
|
200
202
|
)
|
|
201
203
|
if prototype.args:
|
|
202
204
|
break
|
|
203
|
-
self.cc = cc
|
|
204
|
-
self.prototype = prototype
|
|
205
|
+
self.cc = cc # type: ignore
|
|
206
|
+
self.prototype = prototype # type: ignore
|
|
205
207
|
return
|
|
206
208
|
if self._function.is_plt:
|
|
207
209
|
r = self._analyze_plt()
|
|
@@ -218,23 +220,33 @@ class CallingConventionAnalysis(Analysis):
|
|
|
218
220
|
if self.analyze_callsites:
|
|
219
221
|
# only take the first 3 because running reaching definition analysis on all functions is costly
|
|
220
222
|
callsite_facts = self._extract_and_analyze_callsites(max_analyzing_callsites=3)
|
|
221
|
-
prototype =
|
|
222
|
-
|
|
223
|
+
prototype = (
|
|
224
|
+
self._adjust_prototype(
|
|
225
|
+
prototype, callsite_facts, update_arguments=UpdateArgumentsOption.UpdateWhenCCHasNoArgs
|
|
226
|
+
)
|
|
227
|
+
if prototype is not None
|
|
228
|
+
else None
|
|
223
229
|
)
|
|
224
230
|
|
|
225
231
|
self.cc = cc
|
|
226
232
|
self.prototype = prototype
|
|
227
233
|
|
|
228
234
|
def _analyze_callsite_only(self):
|
|
235
|
+
assert self.caller_func_addr is not None
|
|
236
|
+
assert self.callsite_block_addr is not None
|
|
237
|
+
assert self.callsite_insn_addr is not None
|
|
238
|
+
cc, prototype = None, None
|
|
239
|
+
|
|
229
240
|
for include_callsite_preds in [False, True]:
|
|
230
|
-
|
|
231
|
-
self.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
241
|
+
fact = self._analyze_callsite(
|
|
242
|
+
self.caller_func_addr,
|
|
243
|
+
self.callsite_block_addr,
|
|
244
|
+
self.callsite_insn_addr,
|
|
245
|
+
include_preds=include_callsite_preds,
|
|
246
|
+
)
|
|
247
|
+
if fact is None:
|
|
248
|
+
continue
|
|
249
|
+
callsite_facts = [fact]
|
|
238
250
|
cc_cls = default_cc(
|
|
239
251
|
self.project.arch.name,
|
|
240
252
|
platform=(
|
|
@@ -258,6 +270,7 @@ class CallingConventionAnalysis(Analysis):
|
|
|
258
270
|
|
|
259
271
|
:return: A calling convention.
|
|
260
272
|
"""
|
|
273
|
+
assert self._function is not None
|
|
261
274
|
|
|
262
275
|
if len(self._function.jumpout_sites) != 1:
|
|
263
276
|
l.warning(
|
|
@@ -314,6 +327,7 @@ class CallingConventionAnalysis(Analysis):
|
|
|
314
327
|
Go over the variable information in variable manager for this function, and return all uninitialized
|
|
315
328
|
register/stack variables.
|
|
316
329
|
"""
|
|
330
|
+
assert self._function is not None
|
|
317
331
|
|
|
318
332
|
if self._function.is_simprocedure or self._function.is_plt:
|
|
319
333
|
# we do not analyze SimProcedures or PLT stubs
|
|
@@ -403,6 +417,8 @@ class CallingConventionAnalysis(Analysis):
|
|
|
403
417
|
returns anything or not.
|
|
404
418
|
"""
|
|
405
419
|
|
|
420
|
+
assert self._function is not None
|
|
421
|
+
|
|
406
422
|
if self._cfg is None:
|
|
407
423
|
l.warning("CFG is not provided. Skip calling convention analysis at call sites.")
|
|
408
424
|
return []
|
|
@@ -656,13 +672,10 @@ class CallingConventionAnalysis(Analysis):
|
|
|
656
672
|
|
|
657
673
|
def _adjust_prototype(
|
|
658
674
|
self,
|
|
659
|
-
proto: SimTypeFunction
|
|
675
|
+
proto: SimTypeFunction,
|
|
660
676
|
facts: list[CallSiteFact],
|
|
661
677
|
update_arguments: int = UpdateArgumentsOption.DoNotUpdate,
|
|
662
|
-
) -> SimTypeFunction
|
|
663
|
-
if proto is None:
|
|
664
|
-
return None
|
|
665
|
-
|
|
678
|
+
) -> SimTypeFunction:
|
|
666
679
|
# is the return value used anywhere?
|
|
667
680
|
if facts:
|
|
668
681
|
if all(fact.return_value_used is False for fact in facts):
|
|
@@ -691,6 +704,8 @@ class CallingConventionAnalysis(Analysis):
|
|
|
691
704
|
:return:
|
|
692
705
|
"""
|
|
693
706
|
|
|
707
|
+
assert self._function is not None
|
|
708
|
+
|
|
694
709
|
args = set()
|
|
695
710
|
ret_addr_offset = 0 if not self.project.arch.call_pushes_ret else self.project.arch.bytes
|
|
696
711
|
|
|
@@ -839,17 +854,27 @@ class CallingConventionAnalysis(Analysis):
|
|
|
839
854
|
return SimTypeBottom()
|
|
840
855
|
|
|
841
856
|
def _guess_retval_type(self, cc: SimCC, ret_val_size: int | None) -> SimType:
|
|
857
|
+
assert self._function is not None
|
|
858
|
+
|
|
842
859
|
if cc.FP_RETURN_VAL and self._function.ret_sites:
|
|
843
860
|
# examine the last block of the function and see which registers are assigned to
|
|
844
861
|
for ret_block in self._function.ret_sites:
|
|
862
|
+
fpretval_updated, retval_updated = False, False
|
|
863
|
+
fp_reg_size = 0
|
|
845
864
|
irsb = self.project.factory.block(ret_block.addr, size=ret_block.size).vex
|
|
846
865
|
for stmt in irsb.statements:
|
|
847
866
|
if isinstance(stmt, Put) and isinstance(stmt.data, RdTmp):
|
|
848
|
-
reg_size = irsb.tyenv.sizeof(stmt.data.tmp) // self.project.arch.byte_width
|
|
867
|
+
reg_size = irsb.tyenv.sizeof(stmt.data.tmp) // self.project.arch.byte_width # type: ignore
|
|
849
868
|
reg_name = self.project.arch.translate_register_name(stmt.offset, size=reg_size)
|
|
850
|
-
if reg_name == cc.FP_RETURN_VAL.reg_name:
|
|
851
|
-
|
|
852
|
-
|
|
869
|
+
if isinstance(cc.FP_RETURN_VAL, SimRegArg) and reg_name == cc.FP_RETURN_VAL.reg_name:
|
|
870
|
+
fpretval_updated = True
|
|
871
|
+
fp_reg_size = reg_size
|
|
872
|
+
elif isinstance(cc.RETURN_VAL, SimRegArg) and reg_name == cc.RETURN_VAL.reg_name:
|
|
873
|
+
retval_updated = True
|
|
874
|
+
|
|
875
|
+
if fpretval_updated and not retval_updated:
|
|
876
|
+
# possibly float
|
|
877
|
+
return SimTypeFloat() if fp_reg_size == 4 else SimTypeDouble()
|
|
853
878
|
|
|
854
879
|
if ret_val_size is not None:
|
|
855
880
|
if ret_val_size == 1:
|
|
@@ -884,6 +909,8 @@ class CallingConventionAnalysis(Analysis):
|
|
|
884
909
|
# TODO: Use a better pattern matching approach
|
|
885
910
|
if len(func.block_addrs_set) < 3:
|
|
886
911
|
return False, None
|
|
912
|
+
if func.startpoint is None:
|
|
913
|
+
return False, None
|
|
887
914
|
|
|
888
915
|
head = func.startpoint
|
|
889
916
|
out_edges = list(func.transition_graph.out_edges(head, data=True))
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# pylint:disable=too-many-boolean-expressions
|
|
1
2
|
from __future__ import annotations
|
|
2
3
|
from typing import Any
|
|
3
4
|
|
|
@@ -332,6 +333,9 @@ class FactCollector(Analysis):
|
|
|
332
333
|
cc_cls = default_cc(
|
|
333
334
|
self.project.arch.name, platform=self.project.simos.name if self.project.simos is not None else None
|
|
334
335
|
)
|
|
336
|
+
if cc_cls is None:
|
|
337
|
+
# don't know what the calling convention may be... give up
|
|
338
|
+
return
|
|
335
339
|
cc = cc_cls(self.project.arch)
|
|
336
340
|
if isinstance(cc.RETURN_VAL, SimRegArg):
|
|
337
341
|
retreg_offset = cc.RETURN_VAL.check_offset(self.project.arch)
|
|
@@ -401,6 +405,16 @@ class FactCollector(Analysis):
|
|
|
401
405
|
func_graph = self.function.transition_graph
|
|
402
406
|
callee_restored_regs = set()
|
|
403
407
|
|
|
408
|
+
sp_masks = {
|
|
409
|
+
0xFFFFFFFE,
|
|
410
|
+
0xFFFFFFFC,
|
|
411
|
+
0xFFFFFFF8,
|
|
412
|
+
0xFFFFFFF0,
|
|
413
|
+
0xFFFFFFFF_FFFFFFFE,
|
|
414
|
+
0xFFFFFFFF_FFFFFFFC,
|
|
415
|
+
0xFFFFFFFF_FFFFFFF8,
|
|
416
|
+
0xFFFFFFFF_FFFFFFF0,
|
|
417
|
+
}
|
|
404
418
|
for endpoint in self.function.endpoints:
|
|
405
419
|
traversed = set()
|
|
406
420
|
queue: list[tuple[int, BlockNode | HookNode]] = [(0, endpoint)]
|
|
@@ -434,17 +448,29 @@ class FactCollector(Analysis):
|
|
|
434
448
|
tmps[stmt.tmp] = "stack_value"
|
|
435
449
|
elif isinstance(stmt.data, pyvex.IRExpr.Const):
|
|
436
450
|
tmps[stmt.tmp] = "const"
|
|
437
|
-
elif isinstance(stmt.data, pyvex.IRExpr.Binop)
|
|
438
|
-
stmt.data.op.startswith("Iop_Add") or stmt.data.op.startswith("Iop_Sub")
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
451
|
+
elif isinstance(stmt.data, pyvex.IRExpr.Binop):
|
|
452
|
+
if stmt.data.op.startswith("Iop_Add") or stmt.data.op.startswith("Iop_Sub"):
|
|
453
|
+
if (
|
|
454
|
+
isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp)
|
|
455
|
+
and tmps.get(stmt.data.args[0].tmp) == "sp"
|
|
456
|
+
) or (
|
|
457
|
+
isinstance(stmt.data.args[1], pyvex.IRExpr.RdTmp)
|
|
458
|
+
and tmps.get(stmt.data.args[1].tmp) == "sp"
|
|
459
|
+
):
|
|
460
|
+
tmps[stmt.tmp] = "sp"
|
|
461
|
+
elif stmt.data.op.startswith("Iop_And"): # noqa: SIM102
|
|
462
|
+
if (
|
|
463
|
+
isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp)
|
|
464
|
+
and tmps.get(stmt.data.args[0].tmp) == "sp"
|
|
465
|
+
and isinstance(stmt.data.args[1], pyvex.IRExpr.Const)
|
|
466
|
+
and stmt.data.args[1].con.value in sp_masks
|
|
467
|
+
) or (
|
|
468
|
+
isinstance(stmt.data.args[1], pyvex.IRExpr.RdTmp)
|
|
469
|
+
and tmps.get(stmt.data.args[1].tmp) == "sp"
|
|
470
|
+
and isinstance(stmt.data.args[0], pyvex.IRExpr.Const)
|
|
471
|
+
and stmt.data.args[0].con.value in sp_masks
|
|
472
|
+
):
|
|
473
|
+
tmps[stmt.tmp] = "sp"
|
|
448
474
|
if isinstance(stmt, pyvex.IRStmt.Put):
|
|
449
475
|
size = stmt.data.result_size(block.vex.tyenv) // self.project.arch.byte_width
|
|
450
476
|
# is the data loaded from the stack?
|
|
@@ -460,7 +486,28 @@ class FactCollector(Analysis):
|
|
|
460
486
|
if pred not in traversed and depth + 1 <= self._max_depth and edge_type == "transition":
|
|
461
487
|
queue.append((depth + 1, pred))
|
|
462
488
|
|
|
463
|
-
return callee_restored_regs
|
|
489
|
+
# remove offsets of registers that may store return values from callee_restored_regs
|
|
490
|
+
ret_reg_offsets = set()
|
|
491
|
+
cc_cls = default_cc(
|
|
492
|
+
self.project.arch.name, platform=self.project.simos.name if self.project.simos is not None else None
|
|
493
|
+
)
|
|
494
|
+
if cc_cls is not None:
|
|
495
|
+
cc = cc_cls(self.project.arch)
|
|
496
|
+
if isinstance(cc.RETURN_VAL, SimRegArg):
|
|
497
|
+
retreg_offset = cc.RETURN_VAL.check_offset(self.project.arch)
|
|
498
|
+
ret_reg_offsets.add(retreg_offset)
|
|
499
|
+
if isinstance(cc.OVERFLOW_RETURN_VAL, SimRegArg):
|
|
500
|
+
retreg_offset = cc.OVERFLOW_RETURN_VAL.check_offset(self.project.arch)
|
|
501
|
+
ret_reg_offsets.add(retreg_offset)
|
|
502
|
+
if isinstance(cc.FP_RETURN_VAL, SimRegArg):
|
|
503
|
+
try:
|
|
504
|
+
retreg_offset = cc.FP_RETURN_VAL.check_offset(self.project.arch)
|
|
505
|
+
ret_reg_offsets.add(retreg_offset)
|
|
506
|
+
except KeyError:
|
|
507
|
+
# register name does not exist
|
|
508
|
+
pass
|
|
509
|
+
|
|
510
|
+
return callee_restored_regs.difference(ret_reg_offsets)
|
|
464
511
|
|
|
465
512
|
def _determine_input_args(self, end_states: list[FactCollectorState], callee_restored_regs: set[int]) -> None:
|
|
466
513
|
self.input_args = []
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
4
|
import archinfo
|
|
5
|
-
from archinfo.arch_arm import is_arm_arch, ArchARMHF
|
|
5
|
+
from archinfo.arch_arm import is_arm_arch, ArchARMHF, ArchARMCortexM
|
|
6
6
|
|
|
7
7
|
from angr.calling_conventions import SimCC
|
|
8
8
|
|
|
@@ -37,7 +37,7 @@ def is_sane_register_variable(arch: archinfo.Arch, reg_offset: int, reg_size: in
|
|
|
37
37
|
# 224 <= reg_offset < 480) # xmm0-xmm7
|
|
38
38
|
|
|
39
39
|
if is_arm_arch(arch):
|
|
40
|
-
if isinstance(arch, ArchARMHF):
|
|
40
|
+
if isinstance(arch, (ArchARMHF, ArchARMCortexM)):
|
|
41
41
|
return 8 <= reg_offset < 24 or 128 <= reg_offset < 160 # r0 - 32 # s0 - s7, or d0 - d4
|
|
42
42
|
return 8 <= reg_offset < 24 # r0-r3
|
|
43
43
|
|
angr/analyses/cfg/cfg_base.py
CHANGED
|
@@ -1421,6 +1421,19 @@ class CFGBase(Analysis):
|
|
|
1421
1421
|
# We gotta create a new one
|
|
1422
1422
|
l.error("normalize(): Please report it to Fish.")
|
|
1423
1423
|
|
|
1424
|
+
# update the jump tables dict and the indirect jumps dict
|
|
1425
|
+
if smallest_node.addr not in self.model.jump_tables:
|
|
1426
|
+
for n in other_nodes:
|
|
1427
|
+
if n.addr in self.model.jump_tables:
|
|
1428
|
+
self.model.jump_tables[n.addr].addr = smallest_node.addr
|
|
1429
|
+
self.model.jump_tables[smallest_node.addr] = self.model.jump_tables[n.addr]
|
|
1430
|
+
break
|
|
1431
|
+
if smallest_node.addr not in self.indirect_jumps:
|
|
1432
|
+
for n in other_nodes:
|
|
1433
|
+
if n.addr in self.indirect_jumps:
|
|
1434
|
+
self.indirect_jumps[n.addr].addr = smallest_node.addr
|
|
1435
|
+
self.indirect_jumps[smallest_node.addr] = self.indirect_jumps[n.addr]
|
|
1436
|
+
break
|
|
1424
1437
|
# deal with duplicated entries in self.jump_tables and self.indirect_jumps
|
|
1425
1438
|
if smallest_node.addr in self.model.jump_tables:
|
|
1426
1439
|
for n in other_nodes:
|
angr/analyses/cfg/cfg_fast.py
CHANGED
|
@@ -1524,6 +1524,17 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
1524
1524
|
}:
|
|
1525
1525
|
func.info["is_rust_probestack"] = True
|
|
1526
1526
|
|
|
1527
|
+
# determine if the function is __alloca_probe
|
|
1528
|
+
if func is not None and len(func.block_addrs_set) == 4:
|
|
1529
|
+
block_bytes = {func.get_block(block_addr).bytes for block_addr in func.block_addrs_set}
|
|
1530
|
+
if block_bytes == {
|
|
1531
|
+
b"H\x83\xec\x10L\x89\x14$L\x89\\$\x08M3\xdbL\x8dT$\x18L+\xd0M\x0fB\xd3eL\x8b\x1c%\x10\x00\x00\x00M;\xd3s\x16",
|
|
1532
|
+
b"fA\x81\xe2\x00\xf0M\x8d\x9b\x00\xf0\xff\xffA\xc6\x03\x00M;\xd3u\xf0",
|
|
1533
|
+
b"M\x8d\x9b\x00\xf0\xff\xffA\xc6\x03\x00M;\xd3u\xf0",
|
|
1534
|
+
b"L\x8b\x14$L\x8b\\$\x08H\x83\xc4\x10\xc3",
|
|
1535
|
+
}:
|
|
1536
|
+
func.info["is_alloca_probe"] = True
|
|
1537
|
+
|
|
1527
1538
|
if self._collect_data_ref and self.project is not None and ":" in self.project.arch.name:
|
|
1528
1539
|
# this is a pcode arch - use Clinic to recover data references
|
|
1529
1540
|
|
|
@@ -2819,11 +2830,13 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2819
2830
|
if sec is not None and sec.is_readable and not sec.is_writable:
|
|
2820
2831
|
# points to a non-writable region. read it out and see if there is another pointer!
|
|
2821
2832
|
v = self._fast_memory_load_pointer(ref.data_addr, ref.data_size)
|
|
2833
|
+
if v is None:
|
|
2834
|
+
return
|
|
2822
2835
|
|
|
2823
2836
|
# this value can either be a pointer or an offset from the pc... we need to try them both
|
|
2824
2837
|
# attempt 1: a direct pointer
|
|
2825
2838
|
sec_2nd = self.project.loader.find_section_containing(v)
|
|
2826
|
-
if sec_2nd is not None and sec_2nd.is_readable
|
|
2839
|
+
if sec_2nd is not None and sec_2nd.is_readable:
|
|
2827
2840
|
# found it!
|
|
2828
2841
|
self._add_data_reference(
|
|
2829
2842
|
irsb_addr,
|
|
@@ -2872,7 +2885,7 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
2872
2885
|
actual_ref_ins_addr = ref.ins_addr + 4
|
|
2873
2886
|
v += 8 + actual_ref_ins_addr
|
|
2874
2887
|
sec_3rd = self.project.loader.find_section_containing(v)
|
|
2875
|
-
if sec_3rd is not None and sec_3rd.is_readable
|
|
2888
|
+
if sec_3rd is not None and sec_3rd.is_readable:
|
|
2876
2889
|
# found it!
|
|
2877
2890
|
self._add_data_reference(
|
|
2878
2891
|
irsb_addr, ref.stmt_idx, actual_ref_ins_addr, v, data_size=None, data_type=MemoryDataSort.Unknown
|
|
@@ -4178,7 +4191,10 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4178
4191
|
for segment in self.project.loader.main_object.segments:
|
|
4179
4192
|
if segment.is_readable and segment.memsize >= 8:
|
|
4180
4193
|
# the gp area is sometimes writable, so we can't test for (not segment.is_writable)
|
|
4181
|
-
|
|
4194
|
+
try:
|
|
4195
|
+
content = self.project.loader.memory.load(segment.vaddr, segment.memsize)
|
|
4196
|
+
except KeyError:
|
|
4197
|
+
continue
|
|
4182
4198
|
content_buf = pyvex.ffi.from_buffer(content)
|
|
4183
4199
|
self._ro_region_cdata_cache.append(content_buf)
|
|
4184
4200
|
pyvex.pvc.register_readonly_region(segment.vaddr, segment.memsize, content_buf)
|
|
@@ -4187,7 +4203,10 @@ class CFGFast(ForwardAnalysis[CFGNode, CFGNode, CFGJob, int], CFGBase): # pylin
|
|
|
4187
4203
|
# also map .got
|
|
4188
4204
|
for section in self.project.loader.main_object.sections:
|
|
4189
4205
|
if section.name == ".got":
|
|
4190
|
-
|
|
4206
|
+
try:
|
|
4207
|
+
content = self.project.loader.memory.load(section.vaddr, section.memsize)
|
|
4208
|
+
except KeyError:
|
|
4209
|
+
continue
|
|
4191
4210
|
content_buf = pyvex.ffi.from_buffer(content)
|
|
4192
4211
|
self._ro_region_cdata_cache.append(content_buf)
|
|
4193
4212
|
pyvex.pvc.register_readonly_region(section.vaddr, section.memsize, content_buf)
|