angr 9.2.87__py3-none-manylinux2014_x86_64.whl → 9.2.89__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 +4 -1
- angr/analyses/decompiler/clinic.py +16 -0
- angr/analyses/decompiler/decompiler.py +3 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +5 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +108 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +17 -4
- angr/analyses/decompiler/optimization_passes/return_duplicator.py +4 -32
- angr/analyses/decompiler/structured_codegen/c.py +12 -2
- angr/analyses/decompiler/utils.py +13 -0
- angr/analyses/typehoon/dfa.py +108 -0
- angr/analyses/typehoon/lifter.py +34 -2
- angr/analyses/typehoon/simple_solver.py +1043 -503
- angr/analyses/typehoon/translator.py +13 -4
- angr/analyses/typehoon/typeconsts.py +117 -36
- angr/analyses/typehoon/typehoon.py +31 -11
- angr/analyses/typehoon/typevars.py +88 -21
- angr/analyses/typehoon/variance.py +10 -0
- angr/analyses/variable_recovery/engine_ail.py +28 -9
- angr/analyses/variable_recovery/engine_base.py +50 -43
- angr/analyses/variable_recovery/variable_recovery_base.py +16 -3
- angr/analyses/variable_recovery/variable_recovery_fast.py +14 -5
- angr/exploration_techniques/tracer.py +2 -0
- angr/misc/autoimport.py +26 -0
- angr/procedures/definitions/__init__.py +32 -3
- angr/utils/constants.py +1 -0
- angr/utils/graph.py +20 -1
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/METADATA +7 -6
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/RECORD +32 -244
- angr-9.2.89.dist-info/top_level.txt +1 -0
- angr/procedures/definitions/ntdll.py +0 -12
- angr-9.2.87.dist-info/top_level.txt +0 -2
- tests/__init__.py +0 -0
- tests/analyses/__init__.py +0 -0
- tests/analyses/cfg/__init__.py +0 -0
- tests/analyses/cfg/test_cfg_clflush.py +0 -43
- tests/analyses/cfg/test_cfg_get_any_node.py +0 -34
- tests/analyses/cfg/test_cfg_manager.py +0 -32
- tests/analyses/cfg/test_cfg_model.py +0 -55
- tests/analyses/cfg/test_cfg_patching.py +0 -378
- tests/analyses/cfg/test_cfg_rust_got_resolution.py +0 -36
- tests/analyses/cfg/test_cfg_thumb_firmware.py +0 -50
- tests/analyses/cfg/test_cfg_vex_postprocessor.py +0 -27
- tests/analyses/cfg/test_cfgemulated.py +0 -634
- tests/analyses/cfg/test_cfgfast.py +0 -1123
- tests/analyses/cfg/test_cfgfast_soot.py +0 -38
- tests/analyses/cfg/test_const_resolver.py +0 -38
- tests/analyses/cfg/test_iat_resolver.py +0 -37
- tests/analyses/cfg/test_jumptables.py +0 -3008
- tests/analyses/cfg/test_noop_blocks.py +0 -54
- tests/analyses/cfg_slice_to_sink/__init__.py +0 -0
- tests/analyses/cfg_slice_to_sink/test_cfg_slice_to_sink.py +0 -93
- tests/analyses/cfg_slice_to_sink/test_graph.py +0 -114
- tests/analyses/cfg_slice_to_sink/test_transitions.py +0 -28
- tests/analyses/decompiler/__init__.py +0 -0
- tests/analyses/decompiler/test_baseptr_save_simplifier.py +0 -80
- tests/analyses/decompiler/test_decompiler.py +0 -3336
- tests/analyses/decompiler/test_peephole_optimizations.py +0 -48
- tests/analyses/decompiler/test_propagator_loops.py +0 -101
- tests/analyses/decompiler/test_structurer.py +0 -275
- tests/analyses/reaching_definitions/__init__.py +0 -0
- tests/analyses/reaching_definitions/test_dep_graph.py +0 -432
- tests/analyses/reaching_definitions/test_function_handler.py +0 -131
- tests/analyses/reaching_definitions/test_heap_allocator.py +0 -46
- tests/analyses/reaching_definitions/test_rd_state.py +0 -78
- tests/analyses/reaching_definitions/test_reachingdefinitions.py +0 -463
- tests/analyses/reaching_definitions/test_subject.py +0 -76
- tests/analyses/test_bindiff.py +0 -52
- tests/analyses/test_block_simplifier.py +0 -112
- tests/analyses/test_boyscout.py +0 -104
- tests/analyses/test_calling_convention_analysis.py +0 -352
- tests/analyses/test_callsite_maker.py +0 -60
- tests/analyses/test_cdg.py +0 -165
- tests/analyses/test_cfb.py +0 -37
- tests/analyses/test_class_identifier.py +0 -46
- tests/analyses/test_clinic.py +0 -30
- tests/analyses/test_codetagging.py +0 -32
- tests/analyses/test_constantpropagation.py +0 -88
- tests/analyses/test_ddg.py +0 -95
- tests/analyses/test_ddg_global_var_dependencies.py +0 -83
- tests/analyses/test_ddg_memvar_addresses.py +0 -40
- tests/analyses/test_disassembly.py +0 -121
- tests/analyses/test_find_objects_static.py +0 -35
- tests/analyses/test_flirt.py +0 -49
- tests/analyses/test_identifier.py +0 -33
- tests/analyses/test_init_finder.py +0 -38
- tests/analyses/test_proximitygraph.py +0 -31
- tests/analyses/test_reassembler.py +0 -295
- tests/analyses/test_regionidentifier.py +0 -27
- tests/analyses/test_slicing.py +0 -164
- tests/analyses/test_stack_pointer_tracker.py +0 -74
- tests/analyses/test_static_hooker.py +0 -28
- tests/analyses/test_typehoon.py +0 -55
- tests/analyses/test_variablerecovery.py +0 -464
- tests/analyses/test_vfg.py +0 -221
- tests/analyses/test_vtable.py +0 -31
- tests/analyses/test_xrefs.py +0 -77
- tests/common.py +0 -128
- tests/engines/__init__.py +0 -0
- tests/engines/light/__init__.py +0 -0
- tests/engines/light/test_data.py +0 -17
- tests/engines/pcode/__init__.py +0 -0
- tests/engines/pcode/test_emulate.py +0 -607
- tests/engines/pcode/test_pcode.py +0 -84
- tests/engines/test_actions.py +0 -27
- tests/engines/test_hook.py +0 -112
- tests/engines/test_java.py +0 -697
- tests/engines/test_unicorn.py +0 -518
- tests/engines/vex/__init__.py +0 -0
- tests/engines/vex/test_lifter.py +0 -124
- tests/engines/vex/test_vex.py +0 -574
- tests/exploration_techniques/__init__.py +0 -0
- tests/exploration_techniques/test_cacher.py +0 -45
- tests/exploration_techniques/test_director.py +0 -67
- tests/exploration_techniques/test_driller_core.py +0 -48
- tests/exploration_techniques/test_loop_seer.py +0 -158
- tests/exploration_techniques/test_memory_watcher.py +0 -46
- tests/exploration_techniques/test_oppologist.py +0 -65
- tests/exploration_techniques/test_spiller.py +0 -82
- tests/exploration_techniques/test_stochastic.py +0 -40
- tests/exploration_techniques/test_tech_builder.py +0 -61
- tests/exploration_techniques/test_tracer.py +0 -856
- tests/exploration_techniques/test_unique.py +0 -40
- tests/exploration_techniques/test_veritesting.py +0 -120
- tests/factory/__init__.py +0 -0
- tests/factory/block/__init__.py +0 -0
- tests/factory/block/test_block_cache.py +0 -33
- tests/factory/block/test_keystone.py +0 -106
- tests/factory/test_argc.py +0 -101
- tests/factory/test_argc_sym.py +0 -110
- tests/factory/test_argv.py +0 -158
- tests/factory/test_callable.py +0 -266
- tests/factory/test_windows_args.py +0 -36
- tests/knowledge_plugins/__init__.py +0 -0
- tests/knowledge_plugins/cfg/__init__.py +0 -0
- tests/knowledge_plugins/cfg/test_cfg_manager.py +0 -36
- tests/knowledge_plugins/functions/__init__.py +0 -0
- tests/knowledge_plugins/functions/test_function.py +0 -91
- tests/knowledge_plugins/functions/test_function2.py +0 -79
- tests/knowledge_plugins/functions/test_function_manager.py +0 -139
- tests/knowledge_plugins/functions/test_prototypes.py +0 -53
- tests/knowledge_plugins/key_definitions/__init__.py +0 -0
- tests/knowledge_plugins/key_definitions/test_atoms.py +0 -24
- tests/knowledge_plugins/key_definitions/test_environment.py +0 -126
- tests/knowledge_plugins/key_definitions/test_heap_address.py +0 -27
- tests/knowledge_plugins/key_definitions/test_live_definitions.py +0 -72
- tests/knowledge_plugins/test_dwarf_variables.py +0 -240
- tests/knowledge_plugins/test_kb_plugins.py +0 -91
- tests/knowledge_plugins/test_kb_plugins_dwarf.py +0 -36
- tests/knowledge_plugins/test_patches.py +0 -48
- tests/misc/__init__.py +0 -0
- tests/misc/test_hookset.py +0 -57
- tests/perf/__init__.py +0 -0
- tests/perf/perf_cfgemulated.py +0 -19
- tests/perf/perf_cfgfast.py +0 -18
- tests/perf/perf_concrete_execution.py +0 -41
- tests/perf/perf_siminspect_nop.py +0 -36
- tests/perf/perf_state_copy.py +0 -33
- tests/perf/perf_unicorn_0.py +0 -27
- tests/perf/perf_unicorn_1.py +0 -23
- tests/procedures/__init__.py +0 -0
- tests/procedures/glibc/__init__.py +0 -0
- tests/procedures/glibc/test_ctype_locale.py +0 -164
- tests/procedures/libc/__init__.py +0 -0
- tests/procedures/libc/test_fgets.py +0 -53
- tests/procedures/libc/test_scanf.py +0 -205
- tests/procedures/libc/test_sprintf.py +0 -44
- tests/procedures/libc/test_sscanf.py +0 -63
- tests/procedures/libc/test_strcasecmp.py +0 -37
- tests/procedures/libc/test_string.py +0 -1102
- tests/procedures/libc/test_strtol.py +0 -78
- tests/procedures/linux_kernel/__init__.py +0 -0
- tests/procedures/linux_kernel/test_lseek.py +0 -174
- tests/procedures/posix/__init__.py +0 -0
- tests/procedures/posix/test_chroot.py +0 -33
- tests/procedures/posix/test_getenv.py +0 -78
- tests/procedures/posix/test_pwrite_pread.py +0 -57
- tests/procedures/posix/test_sim_time.py +0 -46
- tests/procedures/posix/test_unlink.py +0 -46
- tests/procedures/test_project_resolve_simproc.py +0 -43
- tests/procedures/test_sim_procedure.py +0 -117
- tests/procedures/test_stub_procedure_args.py +0 -53
- tests/serialization/__init__.py +0 -0
- tests/serialization/test_db.py +0 -197
- tests/serialization/test_pickle.py +0 -95
- tests/serialization/test_serialization.py +0 -132
- tests/serialization/test_vault.py +0 -169
- tests/sim/__init__.py +0 -3
- tests/sim/exec_func/__init__.py +0 -0
- tests/sim/exec_func/test_mem_funcs.py +0 -55
- tests/sim/exec_func/test_str_funcs.py +0 -93
- tests/sim/exec_func/test_syscall_result.py +0 -39
- tests/sim/exec_insn/__init__.py +0 -0
- tests/sim/exec_insn/test_adc.py +0 -44
- tests/sim/exec_insn/test_ops.py +0 -83
- tests/sim/exec_insn/test_rcr.py +0 -26
- tests/sim/exec_insn/test_rol.py +0 -51
- tests/sim/exec_insn/test_signed_div.py +0 -34
- tests/sim/exec_insn/test_sqrt.py +0 -56
- tests/sim/options/__init__.py +0 -0
- tests/sim/options/test_0div.py +0 -54
- tests/sim/options/test_symbolic_fd.py +0 -59
- tests/sim/options/test_unsupported.py +0 -34
- tests/sim/test_accuracy.py +0 -137
- tests/sim/test_checkbyte.py +0 -53
- tests/sim/test_echo.py +0 -36
- tests/sim/test_fauxware.py +0 -202
- tests/sim/test_self_modifying_code.py +0 -65
- tests/sim/test_simple_api.py +0 -36
- tests/sim/test_simulation_manager.py +0 -147
- tests/sim/test_stack_alignment.py +0 -65
- tests/sim/test_state.py +0 -303
- tests/sim/test_state_customization.py +0 -54
- tests/sim/test_symbol_hooked_by.py +0 -49
- tests/simos/__init__.py +0 -0
- tests/simos/windows/__init__.py +0 -0
- tests/simos/windows/test_windows_stack_cookie.py +0 -58
- tests/state_plugins/__init__.py +0 -0
- tests/state_plugins/inspect/__init__.py +0 -0
- tests/state_plugins/inspect/test_inspect.py +0 -310
- tests/state_plugins/inspect/test_syscall_override.py +0 -90
- tests/state_plugins/posix/__init__.py +0 -0
- tests/state_plugins/posix/test_file_struct_funcs.py +0 -56
- tests/state_plugins/posix/test_files.py +0 -69
- tests/state_plugins/posix/test_posix.py +0 -72
- tests/state_plugins/solver/__init__.py +0 -0
- tests/state_plugins/solver/test_simsolver.py +0 -58
- tests/state_plugins/solver/test_symbolic.py +0 -153
- tests/state_plugins/solver/test_variable_registration.py +0 -46
- tests/state_plugins/test_callstack.py +0 -54
- tests/state_plugins/test_gdb_plugin.py +0 -35
- tests/state_plugins/test_multi_open_file.py +0 -47
- tests/state_plugins/test_symbolization.py +0 -38
- tests/storage/__init__.py +0 -0
- tests/storage/test_memory.py +0 -960
- tests/storage/test_memory_merge.py +0 -114
- tests/storage/test_memview.py +0 -205
- tests/storage/test_mmap.py +0 -26
- tests/storage/test_multivalues.py +0 -44
- tests/storage/test_permissions.py +0 -32
- tests/storage/test_ptmalloc.py +0 -291
- tests/storage/test_relro_perm.py +0 -49
- tests/test_calling_conventions.py +0 -86
- tests/test_types.py +0 -329
- tests/utils/__init__.py +0 -0
- tests/utils/test_graph.py +0 -41
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/LICENSE +0 -0
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/WHEEL +0 -0
- {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/entry_points.txt +0 -0
|
@@ -1,634 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
__package__ = __package__ or "tests.analyses.cfg" # pylint:disable=redefined-builtin
|
|
3
|
-
|
|
4
|
-
import time
|
|
5
|
-
import pickle
|
|
6
|
-
import networkx
|
|
7
|
-
|
|
8
|
-
import logging
|
|
9
|
-
import os
|
|
10
|
-
import unittest
|
|
11
|
-
|
|
12
|
-
import angr
|
|
13
|
-
from angr import options as o
|
|
14
|
-
|
|
15
|
-
from ...common import bin_location, broken
|
|
16
|
-
|
|
17
|
-
l = logging.getLogger("angr.tests.test_cfgemulated")
|
|
18
|
-
|
|
19
|
-
test_location = os.path.join(bin_location, "tests")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# pylint: disable=missing-class-docstring
|
|
23
|
-
# pylint: disable=no-self-use
|
|
24
|
-
class TestCfgemulate(unittest.TestCase):
|
|
25
|
-
def compare_cfg(self, standard, g, function_list):
|
|
26
|
-
"""
|
|
27
|
-
Standard graph comes with addresses only, and it is based on instructions, not on basic blocks
|
|
28
|
-
"""
|
|
29
|
-
|
|
30
|
-
def get_function_name(addr):
|
|
31
|
-
start = 0
|
|
32
|
-
end = len(function_list) - 1
|
|
33
|
-
|
|
34
|
-
while start <= end:
|
|
35
|
-
mid = (start + end) / 2
|
|
36
|
-
f = function_list[mid]
|
|
37
|
-
if addr < f["start"]:
|
|
38
|
-
end = mid - 1
|
|
39
|
-
elif addr > f["end"]:
|
|
40
|
-
start = mid + 1
|
|
41
|
-
else:
|
|
42
|
-
return f["name"]
|
|
43
|
-
|
|
44
|
-
return None
|
|
45
|
-
|
|
46
|
-
# Sort function list
|
|
47
|
-
function_list = sorted(function_list, key=lambda x: x["start"])
|
|
48
|
-
|
|
49
|
-
# Convert the IDA-style CFG into VEX-style CFG
|
|
50
|
-
s_graph = networkx.DiGraph()
|
|
51
|
-
all_nodes = sorted(standard.nodes())
|
|
52
|
-
addr_to_basicblock = {}
|
|
53
|
-
last_basicblock = None
|
|
54
|
-
for n in all_nodes:
|
|
55
|
-
if last_basicblock is None:
|
|
56
|
-
last_basicblock = (n, n)
|
|
57
|
-
|
|
58
|
-
block = last_basicblock
|
|
59
|
-
successors = standard.successors(n)
|
|
60
|
-
if len(successors) == 1 and successors[0] >= block[0]:
|
|
61
|
-
last_basicblock = (block[0], successors[0])
|
|
62
|
-
else:
|
|
63
|
-
# Save the existing block
|
|
64
|
-
addr_to_basicblock[block[0]] = block
|
|
65
|
-
|
|
66
|
-
# Create edges
|
|
67
|
-
for s in successors:
|
|
68
|
-
s_graph.add_edge(block[0], s)
|
|
69
|
-
|
|
70
|
-
# Clear last_basicblock so that we create a new basicblock next time
|
|
71
|
-
last_basicblock = None
|
|
72
|
-
|
|
73
|
-
graph = networkx.DiGraph()
|
|
74
|
-
for src, dst in g.edges():
|
|
75
|
-
graph.add_edge(src.addr, dst.addr)
|
|
76
|
-
|
|
77
|
-
# Graph comparison
|
|
78
|
-
for src, dst in s_graph.edges():
|
|
79
|
-
if graph.has_edge(src, dst):
|
|
80
|
-
continue
|
|
81
|
-
else:
|
|
82
|
-
# Edge doesn't exist in our CFG
|
|
83
|
-
l.error(
|
|
84
|
-
"Edge (%s-0x%x, %s-0x%x) only exists in IDA CFG.",
|
|
85
|
-
get_function_name(src),
|
|
86
|
-
src,
|
|
87
|
-
get_function_name(dst),
|
|
88
|
-
dst,
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
for src, dst in graph.edges():
|
|
92
|
-
if s_graph.has_edge(src, dst):
|
|
93
|
-
continue
|
|
94
|
-
else:
|
|
95
|
-
# Edge doesn't exist in our CFG
|
|
96
|
-
l.error(
|
|
97
|
-
"Edge (%s-0x%x, %s-0x%x) only exists in angr's CFG.",
|
|
98
|
-
get_function_name(src),
|
|
99
|
-
src,
|
|
100
|
-
get_function_name(dst),
|
|
101
|
-
dst,
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
def perform_single(self, binary_path, cfg_path=None):
|
|
105
|
-
proj = angr.Project(
|
|
106
|
-
binary_path,
|
|
107
|
-
use_sim_procedures=True,
|
|
108
|
-
default_analysis_mode="symbolic",
|
|
109
|
-
load_options={"auto_load_libs": False},
|
|
110
|
-
)
|
|
111
|
-
start = time.time()
|
|
112
|
-
cfg = proj.analyses.CFGEmulated(context_sensitivity_level=1, fail_fast=True)
|
|
113
|
-
end = time.time()
|
|
114
|
-
duration = end - start
|
|
115
|
-
bbl_dict = cfg.nodes()
|
|
116
|
-
|
|
117
|
-
l.info("CFG generated in %f seconds.", duration)
|
|
118
|
-
l.info("Contains %d members in BBL dict.", len(bbl_dict))
|
|
119
|
-
|
|
120
|
-
if cfg_path is not None and os.path.isfile(cfg_path):
|
|
121
|
-
# Compare the graph with a predefined CFG
|
|
122
|
-
info = pickle.load(open(cfg_path, "rb"))
|
|
123
|
-
standard = info["cfg"]
|
|
124
|
-
functions = info["functions"]
|
|
125
|
-
graph = cfg.graph
|
|
126
|
-
|
|
127
|
-
self.compare_cfg(standard, graph, functions)
|
|
128
|
-
else:
|
|
129
|
-
l.warning("No standard CFG specified.")
|
|
130
|
-
|
|
131
|
-
@broken
|
|
132
|
-
def test_cfg_0(self):
|
|
133
|
-
binary_path = os.path.join(test_location, "x86_64", "cfg_0")
|
|
134
|
-
cfg_path = binary_path + ".cfg"
|
|
135
|
-
self.perform_single(binary_path, cfg_path)
|
|
136
|
-
|
|
137
|
-
@broken
|
|
138
|
-
def test_cfg_1(self):
|
|
139
|
-
binary_path = os.path.join(test_location, "x86_64", "cfg_1")
|
|
140
|
-
cfg_path = binary_path + ".cfg"
|
|
141
|
-
self.perform_single(binary_path, cfg_path)
|
|
142
|
-
|
|
143
|
-
@broken
|
|
144
|
-
def test_cfg_2(self):
|
|
145
|
-
binary_path = os.path.join(test_location, "armel", "test_division")
|
|
146
|
-
cfg_path = binary_path + ".cfg"
|
|
147
|
-
self.perform_single(binary_path, cfg_path)
|
|
148
|
-
|
|
149
|
-
@broken
|
|
150
|
-
def test_cfg_3(self):
|
|
151
|
-
binary_path = os.path.join(test_location, "mips", "test_arrays")
|
|
152
|
-
cfg_path = binary_path + ".cfg"
|
|
153
|
-
self.perform_single(binary_path, cfg_path)
|
|
154
|
-
|
|
155
|
-
@broken
|
|
156
|
-
def test_cfg_4(self):
|
|
157
|
-
binary_path = os.path.join(test_location, "mipsel", "darpa_ping")
|
|
158
|
-
cfg_path = binary_path + ".cfg"
|
|
159
|
-
self.perform_single(binary_path, cfg_path)
|
|
160
|
-
|
|
161
|
-
def test_additional_edges(self):
|
|
162
|
-
# Test the `additional_edges` parameter for CFG generation
|
|
163
|
-
|
|
164
|
-
binary_path = os.path.join(test_location, "x86_64", "switch")
|
|
165
|
-
proj = angr.Project(
|
|
166
|
-
binary_path,
|
|
167
|
-
use_sim_procedures=True,
|
|
168
|
-
default_analysis_mode="symbolic",
|
|
169
|
-
load_options={"auto_load_libs": False},
|
|
170
|
-
)
|
|
171
|
-
additional_edges = {0x400573: [0x400580, 0x40058F, 0x40059E]}
|
|
172
|
-
cfg = proj.analyses.CFGEmulated(
|
|
173
|
-
context_sensitivity_level=0,
|
|
174
|
-
additional_edges=additional_edges,
|
|
175
|
-
fail_fast=True,
|
|
176
|
-
resolve_indirect_jumps=False, # For this test case, we need to disable the
|
|
177
|
-
# jump table resolving, otherwise CFGEmulated
|
|
178
|
-
# can automatically find the node 0x4005ad.
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
assert cfg.get_any_node(0x400580) is not None
|
|
182
|
-
assert cfg.get_any_node(0x40058F) is not None
|
|
183
|
-
assert cfg.get_any_node(0x40059E) is not None
|
|
184
|
-
assert cfg.get_any_node(0x4005AD) is None
|
|
185
|
-
|
|
186
|
-
def test_not_returning(self):
|
|
187
|
-
# Make sure we are properly labeling functions that do not return in function manager
|
|
188
|
-
|
|
189
|
-
binary_path = os.path.join(test_location, "x86_64", "not_returning")
|
|
190
|
-
proj = angr.Project(binary_path, use_sim_procedures=True, load_options={"auto_load_libs": False})
|
|
191
|
-
proj.analyses.CFGEmulated(context_sensitivity_level=0, fail_fast=True) # pylint:disable=unused-variable
|
|
192
|
-
|
|
193
|
-
# function_a returns
|
|
194
|
-
assert proj.kb.functions.function(name="function_a") is not None
|
|
195
|
-
assert proj.kb.functions.function(name="function_a").returning
|
|
196
|
-
|
|
197
|
-
# function_b does not return
|
|
198
|
-
assert proj.kb.functions.function(name="function_b") is not None
|
|
199
|
-
assert not proj.kb.functions.function(name="function_b").returning
|
|
200
|
-
|
|
201
|
-
# function_c does not return
|
|
202
|
-
assert proj.kb.functions.function(name="function_c") is not None
|
|
203
|
-
assert not proj.kb.functions.function(name="function_c").returning
|
|
204
|
-
|
|
205
|
-
# main does not return
|
|
206
|
-
assert proj.kb.functions.function(name="main") is not None
|
|
207
|
-
assert not proj.kb.functions.function(name="main").returning
|
|
208
|
-
|
|
209
|
-
# function_d should not be reachable
|
|
210
|
-
assert proj.kb.functions.function(name="function_d") is None
|
|
211
|
-
|
|
212
|
-
@broken
|
|
213
|
-
def test_cfg_5(self):
|
|
214
|
-
binary_path = os.path.join(test_location, "mipsel", "busybox")
|
|
215
|
-
cfg_path = binary_path + ".cfg"
|
|
216
|
-
|
|
217
|
-
self.perform_single(binary_path, cfg_path)
|
|
218
|
-
|
|
219
|
-
def test_cfg_6(self):
|
|
220
|
-
function_addresses = [
|
|
221
|
-
0xFA630,
|
|
222
|
-
0xFA683,
|
|
223
|
-
0xFA6D4,
|
|
224
|
-
0xFA707,
|
|
225
|
-
0xFA754,
|
|
226
|
-
0xFA779,
|
|
227
|
-
0xFA7A9,
|
|
228
|
-
0xFA7D6,
|
|
229
|
-
0xFA844,
|
|
230
|
-
0xFA857,
|
|
231
|
-
0xFA8D9,
|
|
232
|
-
0xFA92F,
|
|
233
|
-
0xFA959,
|
|
234
|
-
0xFA9FB,
|
|
235
|
-
0xFABD6,
|
|
236
|
-
0xFAC61,
|
|
237
|
-
0xFACC2,
|
|
238
|
-
0xFAD29,
|
|
239
|
-
0xFAF94,
|
|
240
|
-
0xFBD07,
|
|
241
|
-
0xFC100,
|
|
242
|
-
0xFC101,
|
|
243
|
-
0xFC14F,
|
|
244
|
-
0xFC18E,
|
|
245
|
-
0xFC25E,
|
|
246
|
-
0xFC261,
|
|
247
|
-
0xFC3C6,
|
|
248
|
-
0xFC42F,
|
|
249
|
-
0xFC4A3,
|
|
250
|
-
0xFC4CF,
|
|
251
|
-
0xFC4DB,
|
|
252
|
-
0xFC5BA,
|
|
253
|
-
0xFC5EF,
|
|
254
|
-
0xFC5FE,
|
|
255
|
-
0xFC611,
|
|
256
|
-
0xFC682,
|
|
257
|
-
0xFC6B7,
|
|
258
|
-
0xFC7FC,
|
|
259
|
-
0xFC8A8,
|
|
260
|
-
0xFC8E7,
|
|
261
|
-
0xFCB42,
|
|
262
|
-
0xFCB50,
|
|
263
|
-
0xFCB72,
|
|
264
|
-
0xFCC3B,
|
|
265
|
-
0xFCC7A,
|
|
266
|
-
0xFCC8B,
|
|
267
|
-
0xFCCDC,
|
|
268
|
-
0xFD1A3,
|
|
269
|
-
0xFF06E,
|
|
270
|
-
]
|
|
271
|
-
|
|
272
|
-
# We need to add DO_CCALLS to resolve long jmp and support real mode
|
|
273
|
-
o.modes["fastpath"] |= {o.DO_CCALLS}
|
|
274
|
-
binary_path = test_location + "/i386/bios.bin.elf"
|
|
275
|
-
proj = angr.Project(binary_path, use_sim_procedures=True, page_size=1, auto_load_libs=False)
|
|
276
|
-
proj.analyses.CFGEmulated(context_sensitivity_level=1, fail_fast=True) # pylint:disable=unused-variable
|
|
277
|
-
assert {f for f in proj.kb.functions} >= set(function_addresses)
|
|
278
|
-
o.modes["fastpath"] ^= {o.DO_CCALLS}
|
|
279
|
-
|
|
280
|
-
def test_fauxware(self):
|
|
281
|
-
binary_path = os.path.join(test_location, "x86_64", "fauxware")
|
|
282
|
-
cfg_path = binary_path + ".cfg"
|
|
283
|
-
|
|
284
|
-
self.perform_single(binary_path, cfg_path)
|
|
285
|
-
|
|
286
|
-
@broken
|
|
287
|
-
def test_loop_unrolling(self):
|
|
288
|
-
binary_path = os.path.join(test_location, "x86_64", "cfg_loop_unrolling")
|
|
289
|
-
|
|
290
|
-
p = angr.Project(binary_path, auto_load_libs=True)
|
|
291
|
-
cfg = p.analyses.CFGEmulated(fail_fast=True)
|
|
292
|
-
|
|
293
|
-
cfg.normalize()
|
|
294
|
-
cfg.unroll_loops(5)
|
|
295
|
-
|
|
296
|
-
assert len(cfg.get_all_nodes(0x400636)) == 7
|
|
297
|
-
|
|
298
|
-
def test_thumb_mode(self):
|
|
299
|
-
# In thumb mode, all addresses of instructions and in function manager should be odd numbers, which loyally
|
|
300
|
-
# reflect VEX's trick to encode the THUMB state in the address.
|
|
301
|
-
|
|
302
|
-
binary_path = os.path.join(test_location, "armhf", "test_arrays")
|
|
303
|
-
p = angr.Project(binary_path, auto_load_libs=False)
|
|
304
|
-
cfg = p.analyses.CFGEmulated(fail_fast=True)
|
|
305
|
-
|
|
306
|
-
def check_addr(a):
|
|
307
|
-
if a % 2 == 1:
|
|
308
|
-
assert cfg.is_thumb_addr(a)
|
|
309
|
-
else:
|
|
310
|
-
assert not cfg.is_thumb_addr(a)
|
|
311
|
-
|
|
312
|
-
# CFGNodes
|
|
313
|
-
cfg_node_addrs = [n.addr for n in cfg.graph.nodes() if not n.is_simprocedure]
|
|
314
|
-
for a in cfg_node_addrs:
|
|
315
|
-
check_addr(a)
|
|
316
|
-
|
|
317
|
-
# Functions in function manager
|
|
318
|
-
for f_addr, f in p.kb.functions.items():
|
|
319
|
-
if f.is_simprocedure:
|
|
320
|
-
continue
|
|
321
|
-
check_addr(f_addr)
|
|
322
|
-
if f.startpoint is not None:
|
|
323
|
-
check_addr(f.startpoint.addr)
|
|
324
|
-
|
|
325
|
-
def test_fakeret_edges_0(self):
|
|
326
|
-
# Test the bug where a fakeret edge can be missing in certain cases
|
|
327
|
-
# Reported by Attila Axt (GitHub: @axt)
|
|
328
|
-
# Ref: https://github.com/angr/angr/issues/72
|
|
329
|
-
|
|
330
|
-
binary_path = os.path.join(test_location, "x86_64", "cfg_3")
|
|
331
|
-
|
|
332
|
-
p = angr.Project(binary_path, auto_load_libs=False)
|
|
333
|
-
cfg = p.analyses.CFGEmulated(context_sensitivity_level=3, fail_fast=True)
|
|
334
|
-
|
|
335
|
-
putchar_plt = cfg.functions.function(name="putchar", plt=True)
|
|
336
|
-
assert putchar_plt.returning
|
|
337
|
-
|
|
338
|
-
putchar = cfg.functions.function(name="putchar", plt=False)
|
|
339
|
-
assert putchar.returning
|
|
340
|
-
|
|
341
|
-
# Since context sensitivity is 3, there should be two different putchar nodes
|
|
342
|
-
putchar_cfgnodes = cfg.get_all_nodes(putchar.addr)
|
|
343
|
-
assert len(putchar_cfgnodes) == 2
|
|
344
|
-
|
|
345
|
-
# Each putchar node has a different predecessor as their PLT entry
|
|
346
|
-
plt_entry_0 = cfg.get_predecessors(putchar_cfgnodes[0])
|
|
347
|
-
assert len(plt_entry_0) == 1
|
|
348
|
-
plt_entry_0 = plt_entry_0[0]
|
|
349
|
-
|
|
350
|
-
plt_entry_1 = cfg.get_predecessors(putchar_cfgnodes[1])
|
|
351
|
-
assert len(plt_entry_1) == 1
|
|
352
|
-
plt_entry_1 = plt_entry_1[0]
|
|
353
|
-
|
|
354
|
-
assert plt_entry_0 is not plt_entry_1
|
|
355
|
-
|
|
356
|
-
# Each PLT entry should have a FakeRet edge
|
|
357
|
-
preds_0 = cfg.get_predecessors(plt_entry_0)
|
|
358
|
-
assert len(preds_0) == 1
|
|
359
|
-
preds_1 = cfg.get_predecessors(plt_entry_1)
|
|
360
|
-
assert len(preds_1) == 1
|
|
361
|
-
|
|
362
|
-
# Each predecessor must have a call edge and a FakeRet edge
|
|
363
|
-
edges_0 = cfg.get_successors_and_jumpkind(preds_0[0], excluding_fakeret=False)
|
|
364
|
-
assert len(edges_0) == 2
|
|
365
|
-
jumpkinds = {jumpkind for _, jumpkind in edges_0}
|
|
366
|
-
assert jumpkinds == {"Ijk_Call", "Ijk_FakeRet"}
|
|
367
|
-
|
|
368
|
-
edges_1 = cfg.get_successors_and_jumpkind(preds_1[0], excluding_fakeret=False)
|
|
369
|
-
assert len(edges_1) == 2
|
|
370
|
-
jumpkinds = {jumpkind for _, jumpkind in edges_1}
|
|
371
|
-
assert jumpkinds == {"Ijk_Call", "Ijk_FakeRet"}
|
|
372
|
-
|
|
373
|
-
def test_string_references(self):
|
|
374
|
-
# Test AttributeError on 'addr' which occurs when searching for string
|
|
375
|
-
# references
|
|
376
|
-
|
|
377
|
-
binary_path = os.path.join(test_location, "i386", "ctf_nuclear")
|
|
378
|
-
b = angr.Project(binary_path, load_options={"auto_load_libs": False})
|
|
379
|
-
cfg = b.analyses.CFGEmulated(keep_state=True, fail_fast=True)
|
|
380
|
-
|
|
381
|
-
string_references = []
|
|
382
|
-
for f in cfg.functions.values():
|
|
383
|
-
string_references.append(list(f.string_references()))
|
|
384
|
-
|
|
385
|
-
# test passes if hasn't thrown an exception
|
|
386
|
-
|
|
387
|
-
def test_arrays(self):
|
|
388
|
-
binary_path = os.path.join(test_location, "armhf", "test_arrays")
|
|
389
|
-
b = angr.Project(binary_path, load_options={"auto_load_libs": False})
|
|
390
|
-
cfg = b.analyses.CFGEmulated(fail_fast=True)
|
|
391
|
-
|
|
392
|
-
node = cfg.model.get_any_node(0x10415)
|
|
393
|
-
assert node is not None
|
|
394
|
-
|
|
395
|
-
successors = cfg.model.get_successors(node)
|
|
396
|
-
assert len(successors) == 2
|
|
397
|
-
|
|
398
|
-
def test_max_steps(self):
|
|
399
|
-
binary_path = os.path.join(test_location, "x86_64", "fauxware")
|
|
400
|
-
b = angr.Project(binary_path, load_options={"auto_load_libs": False})
|
|
401
|
-
cfg = b.analyses.CFGEmulated(max_steps=5, fail_fast=True)
|
|
402
|
-
|
|
403
|
-
dfs_edges = networkx.dfs_edges(cfg.graph)
|
|
404
|
-
|
|
405
|
-
depth_map = {}
|
|
406
|
-
for src, dst in dfs_edges:
|
|
407
|
-
if src not in depth_map:
|
|
408
|
-
depth_map[src] = 0
|
|
409
|
-
if dst not in depth_map:
|
|
410
|
-
depth_map[dst] = depth_map[src] + 1
|
|
411
|
-
depth_map[dst] = max(depth_map[src] + 1, depth_map[dst])
|
|
412
|
-
|
|
413
|
-
assert max(depth_map.values()) <= 5
|
|
414
|
-
|
|
415
|
-
def test_armel_final_missing_block(self):
|
|
416
|
-
# Due to a stupid bug in CFGEmulated, the last block of a function might go missing in the function graph if the
|
|
417
|
-
# only entry edge to that block is an Ijk_Ret edge. See #475 on GitHub.
|
|
418
|
-
# Thank @gergo for reporting and providing this test binary.
|
|
419
|
-
|
|
420
|
-
binary_path = os.path.join(test_location, "armel", "last_block")
|
|
421
|
-
b = angr.Project(binary_path, auto_load_libs=False)
|
|
422
|
-
cfg = b.analyses.CFGEmulated(fail_fast=True)
|
|
423
|
-
|
|
424
|
-
blocks = list(cfg.kb.functions[0x8000].blocks)
|
|
425
|
-
|
|
426
|
-
assert len(blocks) == 3
|
|
427
|
-
assert {block.addr for block in blocks} == {0x8000, 0x8014, 0x8020}
|
|
428
|
-
|
|
429
|
-
def test_armel_final_missing_block_b(self):
|
|
430
|
-
# When _pending_jobs is not sorted, it is possible that we first process a pending job created earlier and then
|
|
431
|
-
# process another pending job created later. Ideally, we hope that jobs are always processed in a topological
|
|
432
|
-
# order, and the unsorted pending jobs break this assumption. In this test binary, at one point there can be two
|
|
433
|
-
# pending jobs, 0x10b05/0x10ac5(Ijk_FakeRet) and 0x10bbe(Ijk_FakeRet). If 0x10bbe is processed before 0x10b05,
|
|
434
|
-
# we do not # know whether the function 0x10a29(aes) returns or not. As a result, the final block of the main
|
|
435
|
-
# function is not confirmed, and is not added to the function graph of function main.
|
|
436
|
-
#
|
|
437
|
-
# In fact, this also hints a different bug. We should always "confirm" that a function returns if its FakeRet
|
|
438
|
-
# job are processed for whatever reason.
|
|
439
|
-
#
|
|
440
|
-
# Fixing either bug will resolve the issue that the final block does not show up in the function graph of main.
|
|
441
|
-
# To stay on the safe side, both of them are fixed. Thanks @tyb0807 for reporting this issue and providing a
|
|
442
|
-
# test binary.
|
|
443
|
-
# EDG says: This binary is compiled incorrectly.
|
|
444
|
-
# The binary's app code was compiled as CortexM, but linked against ARM libraries.
|
|
445
|
-
# This is illegal, and does not actually execute on a real CortexM.
|
|
446
|
-
# Somebody should recompile it....
|
|
447
|
-
binary_path = os.path.join(test_location, "armel", "aes")
|
|
448
|
-
b = angr.Project(binary_path, arch="ARMEL", auto_load_libs=False)
|
|
449
|
-
|
|
450
|
-
function = b.loader.main_object.get_symbol("main").rebased_addr
|
|
451
|
-
cfg = b.analyses.CFGEmulated(
|
|
452
|
-
starts=[function],
|
|
453
|
-
context_sensitivity_level=0,
|
|
454
|
-
normalize=True,
|
|
455
|
-
fail_fast=True,
|
|
456
|
-
)
|
|
457
|
-
|
|
458
|
-
blocks = list(cfg.kb.functions["main"].blocks)
|
|
459
|
-
|
|
460
|
-
assert len(blocks) == 2
|
|
461
|
-
assert {block.addr for block in blocks} == {0x10B79, 0x10BBF}
|
|
462
|
-
|
|
463
|
-
def test_armel_incorrect_function_detection_caused_by_branch(self):
|
|
464
|
-
# GitHub issue #685
|
|
465
|
-
binary_path = os.path.join(test_location, "armel", "RTOSDemo.axf.issue_685")
|
|
466
|
-
b = angr.Project(binary_path, auto_load_libs=False)
|
|
467
|
-
|
|
468
|
-
cfg = b.analyses.CFGEmulated()
|
|
469
|
-
|
|
470
|
-
# The Main function should be identified as a single function
|
|
471
|
-
assert 0x80A1 in cfg.functions
|
|
472
|
-
main_func = cfg.functions[0x80A1]
|
|
473
|
-
|
|
474
|
-
# All blocks should be there
|
|
475
|
-
block_addrs = sorted([b.addr for b in main_func.blocks])
|
|
476
|
-
assert block_addrs == [0x80A1, 0x80B1, 0x80BB, 0x80CD, 0x80DF, 0x80E3, 0x80ED]
|
|
477
|
-
|
|
478
|
-
# The ResetISR function should be identified as a single function, too
|
|
479
|
-
assert 0x8009 in cfg.functions
|
|
480
|
-
resetisr_func = cfg.functions[0x8009]
|
|
481
|
-
|
|
482
|
-
# All blocks should be there
|
|
483
|
-
block_addrs = sorted([b.addr for b in resetisr_func.blocks])
|
|
484
|
-
assert block_addrs == [0x8009, 0x8011, 0x801F, 0x8027]
|
|
485
|
-
|
|
486
|
-
def test_cfg_switches(self):
|
|
487
|
-
# logging.getLogger('angr.analyses.cfg.cfg_fast').setLevel(logging.INFO)
|
|
488
|
-
# logging.getLogger('angr.analyses.cfg.indirect_jump_resolvers.jumptable').setLevel(logging.DEBUG)
|
|
489
|
-
|
|
490
|
-
filename = "cfg_switches"
|
|
491
|
-
|
|
492
|
-
edges = {
|
|
493
|
-
"x86_64": {
|
|
494
|
-
# jump table 0 in func_0
|
|
495
|
-
(0x40053A, 0x400547),
|
|
496
|
-
(0x40053A, 0x400552),
|
|
497
|
-
(0x40053A, 0x40055D),
|
|
498
|
-
(0x40053A, 0x400568),
|
|
499
|
-
(0x40053A, 0x400573),
|
|
500
|
-
(0x40053A, 0x400580),
|
|
501
|
-
(0x40053A, 0x40058D),
|
|
502
|
-
# jump table 0 in func_1
|
|
503
|
-
(0x4005BC, 0x4005C9),
|
|
504
|
-
(0x4005BC, 0x4005D8),
|
|
505
|
-
(0x4005BC, 0x4005E7),
|
|
506
|
-
(0x4005BC, 0x4005F6),
|
|
507
|
-
(0x4005BC, 0x400605),
|
|
508
|
-
(0x4005BC, 0x400614),
|
|
509
|
-
(0x4005BC, 0x400623),
|
|
510
|
-
(0x4005BC, 0x400632),
|
|
511
|
-
(0x4005BC, 0x40063E),
|
|
512
|
-
(0x4005BC, 0x40064A),
|
|
513
|
-
(0x4005BC, 0x4006B0),
|
|
514
|
-
# jump table 1 in func_1
|
|
515
|
-
(0x40065A, 0x400667),
|
|
516
|
-
(0x40065A, 0x400673),
|
|
517
|
-
(0x40065A, 0x40067F),
|
|
518
|
-
(0x40065A, 0x40068B),
|
|
519
|
-
(0x40065A, 0x400697),
|
|
520
|
-
(0x40065A, 0x4006A3),
|
|
521
|
-
# jump table 0 in main
|
|
522
|
-
(0x4006E1, 0x4006EE),
|
|
523
|
-
(0x4006E1, 0x4006FA),
|
|
524
|
-
(0x4006E1, 0x40070B),
|
|
525
|
-
(0x4006E1, 0x40071C),
|
|
526
|
-
(0x4006E1, 0x40072D),
|
|
527
|
-
(0x4006E1, 0x40073E),
|
|
528
|
-
(0x4006E1, 0x40074F),
|
|
529
|
-
(0x4006E1, 0x40075B),
|
|
530
|
-
},
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
arches = edges.keys()
|
|
534
|
-
|
|
535
|
-
for arch in arches:
|
|
536
|
-
path = os.path.join(test_location, arch, filename)
|
|
537
|
-
proj = angr.Project(path, load_options={"auto_load_libs": False})
|
|
538
|
-
|
|
539
|
-
cfg = proj.analyses.CFGEmulated()
|
|
540
|
-
|
|
541
|
-
for src, dst in edges[arch]:
|
|
542
|
-
src_node = cfg.get_any_node(src)
|
|
543
|
-
dst_node = cfg.get_any_node(dst)
|
|
544
|
-
assert dst_node in src_node.successors, "CFG edge {}-{} is not found.".format(
|
|
545
|
-
src_node,
|
|
546
|
-
dst_node,
|
|
547
|
-
)
|
|
548
|
-
|
|
549
|
-
class CFGEmulatedAborted(angr.analyses.cfg.cfg_emulated.CFGEmulated): # pylint:disable=abstract-method
|
|
550
|
-
"""
|
|
551
|
-
Only used in the test_abort_and_resume test case.
|
|
552
|
-
"""
|
|
553
|
-
|
|
554
|
-
should_abort = False
|
|
555
|
-
|
|
556
|
-
def _intra_analysis(self):
|
|
557
|
-
if self.should_abort:
|
|
558
|
-
self.abort()
|
|
559
|
-
else:
|
|
560
|
-
super()._intra_analysis()
|
|
561
|
-
|
|
562
|
-
def test_abort_and_resume(self):
|
|
563
|
-
angr.analyses.AnalysesHub.register_default("CFGEmulatedAborted", self.CFGEmulatedAborted)
|
|
564
|
-
|
|
565
|
-
self.CFGEmulatedAborted.should_abort = False
|
|
566
|
-
binary_path = os.path.join(test_location, "x86_64", "fauxware")
|
|
567
|
-
b = angr.Project(binary_path, auto_load_libs=False)
|
|
568
|
-
|
|
569
|
-
self.CFGEmulatedAborted.should_abort = True
|
|
570
|
-
cfg = b.analyses.CFGEmulatedAborted()
|
|
571
|
-
assert len(list(cfg.jobs)) > 0 # there should be left-over jobs
|
|
572
|
-
|
|
573
|
-
self.CFGEmulatedAborted.should_abort = False
|
|
574
|
-
cfg.resume()
|
|
575
|
-
|
|
576
|
-
assert len(list(cfg.jobs)) == 0
|
|
577
|
-
|
|
578
|
-
def test_base_graph(self):
|
|
579
|
-
path = os.path.join(test_location, "x86_64", "test_cfgemulated_base_graph")
|
|
580
|
-
|
|
581
|
-
func_addr = 0x401129
|
|
582
|
-
|
|
583
|
-
edges = {
|
|
584
|
-
(0x401129, 0x401144),
|
|
585
|
-
(0x401129, 0x40114D),
|
|
586
|
-
(0x401144, 0x401154),
|
|
587
|
-
(0x40114D, 0x401154),
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
final_states_info = {
|
|
591
|
-
0x401129: 2,
|
|
592
|
-
0x40114D: 1,
|
|
593
|
-
0x401144: 1,
|
|
594
|
-
0x401154: 1,
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
proj = angr.Project(path, load_options={"auto_load_libs": False})
|
|
598
|
-
|
|
599
|
-
cfg_fast = proj.analyses.CFGFast(normalize=True)
|
|
600
|
-
target_function = cfg_fast.kb.functions[func_addr]
|
|
601
|
-
target_function.normalize()
|
|
602
|
-
|
|
603
|
-
target_function_cfg_emulated = proj.analyses.CFGEmulated(
|
|
604
|
-
keep_state=True,
|
|
605
|
-
state_add_options=angr.options.refs,
|
|
606
|
-
base_graph=target_function.graph,
|
|
607
|
-
starts=(func_addr,),
|
|
608
|
-
normalize=True,
|
|
609
|
-
)
|
|
610
|
-
for src, dst in edges:
|
|
611
|
-
src_node = target_function_cfg_emulated.get_any_node(src)
|
|
612
|
-
dst_node = target_function_cfg_emulated.get_any_node(dst)
|
|
613
|
-
assert dst_node in src_node.successors, "CFG edge {}-{} is not found.".format(
|
|
614
|
-
src_node,
|
|
615
|
-
dst_node,
|
|
616
|
-
)
|
|
617
|
-
|
|
618
|
-
for node_addr, final_states_number in final_states_info.items():
|
|
619
|
-
node = target_function_cfg_emulated.get_any_node(node_addr)
|
|
620
|
-
assert final_states_number == len(node.final_states), (
|
|
621
|
-
"CFG node 0x%x has incorrect final states." % node_addr
|
|
622
|
-
)
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
if __name__ == "__main__":
|
|
626
|
-
logging.getLogger("angr.state_plugins.abstract_memory").setLevel(logging.DEBUG)
|
|
627
|
-
# logging.getLogger("angr.state_plugins.symbolic_memory").setLevel(logging.DEBUG)
|
|
628
|
-
# logging.getLogger("angr.analyses.cfg.cfg_emulated").setLevel(logging.DEBUG)
|
|
629
|
-
# logging.getLogger("s_irsb").setLevel(logging.DEBUG)
|
|
630
|
-
# Temporarily disable the warnings of claripy backend
|
|
631
|
-
# logging.getLogger("claripy.backends.backend").setLevel(logging.ERROR)
|
|
632
|
-
# logging.getLogger("claripy.claripy").setLevel(logging.ERROR)
|
|
633
|
-
|
|
634
|
-
unittest.main()
|