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.

Files changed (248) hide show
  1. angr/__init__.py +4 -1
  2. angr/analyses/decompiler/clinic.py +16 -0
  3. angr/analyses/decompiler/decompiler.py +3 -0
  4. angr/analyses/decompiler/optimization_passes/__init__.py +5 -0
  5. angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +108 -0
  6. angr/analyses/decompiler/optimization_passes/optimization_pass.py +17 -4
  7. angr/analyses/decompiler/optimization_passes/return_duplicator.py +4 -32
  8. angr/analyses/decompiler/structured_codegen/c.py +12 -2
  9. angr/analyses/decompiler/utils.py +13 -0
  10. angr/analyses/typehoon/dfa.py +108 -0
  11. angr/analyses/typehoon/lifter.py +34 -2
  12. angr/analyses/typehoon/simple_solver.py +1043 -503
  13. angr/analyses/typehoon/translator.py +13 -4
  14. angr/analyses/typehoon/typeconsts.py +117 -36
  15. angr/analyses/typehoon/typehoon.py +31 -11
  16. angr/analyses/typehoon/typevars.py +88 -21
  17. angr/analyses/typehoon/variance.py +10 -0
  18. angr/analyses/variable_recovery/engine_ail.py +28 -9
  19. angr/analyses/variable_recovery/engine_base.py +50 -43
  20. angr/analyses/variable_recovery/variable_recovery_base.py +16 -3
  21. angr/analyses/variable_recovery/variable_recovery_fast.py +14 -5
  22. angr/exploration_techniques/tracer.py +2 -0
  23. angr/misc/autoimport.py +26 -0
  24. angr/procedures/definitions/__init__.py +32 -3
  25. angr/utils/constants.py +1 -0
  26. angr/utils/graph.py +20 -1
  27. {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/METADATA +7 -6
  28. {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/RECORD +32 -244
  29. angr-9.2.89.dist-info/top_level.txt +1 -0
  30. angr/procedures/definitions/ntdll.py +0 -12
  31. angr-9.2.87.dist-info/top_level.txt +0 -2
  32. tests/__init__.py +0 -0
  33. tests/analyses/__init__.py +0 -0
  34. tests/analyses/cfg/__init__.py +0 -0
  35. tests/analyses/cfg/test_cfg_clflush.py +0 -43
  36. tests/analyses/cfg/test_cfg_get_any_node.py +0 -34
  37. tests/analyses/cfg/test_cfg_manager.py +0 -32
  38. tests/analyses/cfg/test_cfg_model.py +0 -55
  39. tests/analyses/cfg/test_cfg_patching.py +0 -378
  40. tests/analyses/cfg/test_cfg_rust_got_resolution.py +0 -36
  41. tests/analyses/cfg/test_cfg_thumb_firmware.py +0 -50
  42. tests/analyses/cfg/test_cfg_vex_postprocessor.py +0 -27
  43. tests/analyses/cfg/test_cfgemulated.py +0 -634
  44. tests/analyses/cfg/test_cfgfast.py +0 -1123
  45. tests/analyses/cfg/test_cfgfast_soot.py +0 -38
  46. tests/analyses/cfg/test_const_resolver.py +0 -38
  47. tests/analyses/cfg/test_iat_resolver.py +0 -37
  48. tests/analyses/cfg/test_jumptables.py +0 -3008
  49. tests/analyses/cfg/test_noop_blocks.py +0 -54
  50. tests/analyses/cfg_slice_to_sink/__init__.py +0 -0
  51. tests/analyses/cfg_slice_to_sink/test_cfg_slice_to_sink.py +0 -93
  52. tests/analyses/cfg_slice_to_sink/test_graph.py +0 -114
  53. tests/analyses/cfg_slice_to_sink/test_transitions.py +0 -28
  54. tests/analyses/decompiler/__init__.py +0 -0
  55. tests/analyses/decompiler/test_baseptr_save_simplifier.py +0 -80
  56. tests/analyses/decompiler/test_decompiler.py +0 -3336
  57. tests/analyses/decompiler/test_peephole_optimizations.py +0 -48
  58. tests/analyses/decompiler/test_propagator_loops.py +0 -101
  59. tests/analyses/decompiler/test_structurer.py +0 -275
  60. tests/analyses/reaching_definitions/__init__.py +0 -0
  61. tests/analyses/reaching_definitions/test_dep_graph.py +0 -432
  62. tests/analyses/reaching_definitions/test_function_handler.py +0 -131
  63. tests/analyses/reaching_definitions/test_heap_allocator.py +0 -46
  64. tests/analyses/reaching_definitions/test_rd_state.py +0 -78
  65. tests/analyses/reaching_definitions/test_reachingdefinitions.py +0 -463
  66. tests/analyses/reaching_definitions/test_subject.py +0 -76
  67. tests/analyses/test_bindiff.py +0 -52
  68. tests/analyses/test_block_simplifier.py +0 -112
  69. tests/analyses/test_boyscout.py +0 -104
  70. tests/analyses/test_calling_convention_analysis.py +0 -352
  71. tests/analyses/test_callsite_maker.py +0 -60
  72. tests/analyses/test_cdg.py +0 -165
  73. tests/analyses/test_cfb.py +0 -37
  74. tests/analyses/test_class_identifier.py +0 -46
  75. tests/analyses/test_clinic.py +0 -30
  76. tests/analyses/test_codetagging.py +0 -32
  77. tests/analyses/test_constantpropagation.py +0 -88
  78. tests/analyses/test_ddg.py +0 -95
  79. tests/analyses/test_ddg_global_var_dependencies.py +0 -83
  80. tests/analyses/test_ddg_memvar_addresses.py +0 -40
  81. tests/analyses/test_disassembly.py +0 -121
  82. tests/analyses/test_find_objects_static.py +0 -35
  83. tests/analyses/test_flirt.py +0 -49
  84. tests/analyses/test_identifier.py +0 -33
  85. tests/analyses/test_init_finder.py +0 -38
  86. tests/analyses/test_proximitygraph.py +0 -31
  87. tests/analyses/test_reassembler.py +0 -295
  88. tests/analyses/test_regionidentifier.py +0 -27
  89. tests/analyses/test_slicing.py +0 -164
  90. tests/analyses/test_stack_pointer_tracker.py +0 -74
  91. tests/analyses/test_static_hooker.py +0 -28
  92. tests/analyses/test_typehoon.py +0 -55
  93. tests/analyses/test_variablerecovery.py +0 -464
  94. tests/analyses/test_vfg.py +0 -221
  95. tests/analyses/test_vtable.py +0 -31
  96. tests/analyses/test_xrefs.py +0 -77
  97. tests/common.py +0 -128
  98. tests/engines/__init__.py +0 -0
  99. tests/engines/light/__init__.py +0 -0
  100. tests/engines/light/test_data.py +0 -17
  101. tests/engines/pcode/__init__.py +0 -0
  102. tests/engines/pcode/test_emulate.py +0 -607
  103. tests/engines/pcode/test_pcode.py +0 -84
  104. tests/engines/test_actions.py +0 -27
  105. tests/engines/test_hook.py +0 -112
  106. tests/engines/test_java.py +0 -697
  107. tests/engines/test_unicorn.py +0 -518
  108. tests/engines/vex/__init__.py +0 -0
  109. tests/engines/vex/test_lifter.py +0 -124
  110. tests/engines/vex/test_vex.py +0 -574
  111. tests/exploration_techniques/__init__.py +0 -0
  112. tests/exploration_techniques/test_cacher.py +0 -45
  113. tests/exploration_techniques/test_director.py +0 -67
  114. tests/exploration_techniques/test_driller_core.py +0 -48
  115. tests/exploration_techniques/test_loop_seer.py +0 -158
  116. tests/exploration_techniques/test_memory_watcher.py +0 -46
  117. tests/exploration_techniques/test_oppologist.py +0 -65
  118. tests/exploration_techniques/test_spiller.py +0 -82
  119. tests/exploration_techniques/test_stochastic.py +0 -40
  120. tests/exploration_techniques/test_tech_builder.py +0 -61
  121. tests/exploration_techniques/test_tracer.py +0 -856
  122. tests/exploration_techniques/test_unique.py +0 -40
  123. tests/exploration_techniques/test_veritesting.py +0 -120
  124. tests/factory/__init__.py +0 -0
  125. tests/factory/block/__init__.py +0 -0
  126. tests/factory/block/test_block_cache.py +0 -33
  127. tests/factory/block/test_keystone.py +0 -106
  128. tests/factory/test_argc.py +0 -101
  129. tests/factory/test_argc_sym.py +0 -110
  130. tests/factory/test_argv.py +0 -158
  131. tests/factory/test_callable.py +0 -266
  132. tests/factory/test_windows_args.py +0 -36
  133. tests/knowledge_plugins/__init__.py +0 -0
  134. tests/knowledge_plugins/cfg/__init__.py +0 -0
  135. tests/knowledge_plugins/cfg/test_cfg_manager.py +0 -36
  136. tests/knowledge_plugins/functions/__init__.py +0 -0
  137. tests/knowledge_plugins/functions/test_function.py +0 -91
  138. tests/knowledge_plugins/functions/test_function2.py +0 -79
  139. tests/knowledge_plugins/functions/test_function_manager.py +0 -139
  140. tests/knowledge_plugins/functions/test_prototypes.py +0 -53
  141. tests/knowledge_plugins/key_definitions/__init__.py +0 -0
  142. tests/knowledge_plugins/key_definitions/test_atoms.py +0 -24
  143. tests/knowledge_plugins/key_definitions/test_environment.py +0 -126
  144. tests/knowledge_plugins/key_definitions/test_heap_address.py +0 -27
  145. tests/knowledge_plugins/key_definitions/test_live_definitions.py +0 -72
  146. tests/knowledge_plugins/test_dwarf_variables.py +0 -240
  147. tests/knowledge_plugins/test_kb_plugins.py +0 -91
  148. tests/knowledge_plugins/test_kb_plugins_dwarf.py +0 -36
  149. tests/knowledge_plugins/test_patches.py +0 -48
  150. tests/misc/__init__.py +0 -0
  151. tests/misc/test_hookset.py +0 -57
  152. tests/perf/__init__.py +0 -0
  153. tests/perf/perf_cfgemulated.py +0 -19
  154. tests/perf/perf_cfgfast.py +0 -18
  155. tests/perf/perf_concrete_execution.py +0 -41
  156. tests/perf/perf_siminspect_nop.py +0 -36
  157. tests/perf/perf_state_copy.py +0 -33
  158. tests/perf/perf_unicorn_0.py +0 -27
  159. tests/perf/perf_unicorn_1.py +0 -23
  160. tests/procedures/__init__.py +0 -0
  161. tests/procedures/glibc/__init__.py +0 -0
  162. tests/procedures/glibc/test_ctype_locale.py +0 -164
  163. tests/procedures/libc/__init__.py +0 -0
  164. tests/procedures/libc/test_fgets.py +0 -53
  165. tests/procedures/libc/test_scanf.py +0 -205
  166. tests/procedures/libc/test_sprintf.py +0 -44
  167. tests/procedures/libc/test_sscanf.py +0 -63
  168. tests/procedures/libc/test_strcasecmp.py +0 -37
  169. tests/procedures/libc/test_string.py +0 -1102
  170. tests/procedures/libc/test_strtol.py +0 -78
  171. tests/procedures/linux_kernel/__init__.py +0 -0
  172. tests/procedures/linux_kernel/test_lseek.py +0 -174
  173. tests/procedures/posix/__init__.py +0 -0
  174. tests/procedures/posix/test_chroot.py +0 -33
  175. tests/procedures/posix/test_getenv.py +0 -78
  176. tests/procedures/posix/test_pwrite_pread.py +0 -57
  177. tests/procedures/posix/test_sim_time.py +0 -46
  178. tests/procedures/posix/test_unlink.py +0 -46
  179. tests/procedures/test_project_resolve_simproc.py +0 -43
  180. tests/procedures/test_sim_procedure.py +0 -117
  181. tests/procedures/test_stub_procedure_args.py +0 -53
  182. tests/serialization/__init__.py +0 -0
  183. tests/serialization/test_db.py +0 -197
  184. tests/serialization/test_pickle.py +0 -95
  185. tests/serialization/test_serialization.py +0 -132
  186. tests/serialization/test_vault.py +0 -169
  187. tests/sim/__init__.py +0 -3
  188. tests/sim/exec_func/__init__.py +0 -0
  189. tests/sim/exec_func/test_mem_funcs.py +0 -55
  190. tests/sim/exec_func/test_str_funcs.py +0 -93
  191. tests/sim/exec_func/test_syscall_result.py +0 -39
  192. tests/sim/exec_insn/__init__.py +0 -0
  193. tests/sim/exec_insn/test_adc.py +0 -44
  194. tests/sim/exec_insn/test_ops.py +0 -83
  195. tests/sim/exec_insn/test_rcr.py +0 -26
  196. tests/sim/exec_insn/test_rol.py +0 -51
  197. tests/sim/exec_insn/test_signed_div.py +0 -34
  198. tests/sim/exec_insn/test_sqrt.py +0 -56
  199. tests/sim/options/__init__.py +0 -0
  200. tests/sim/options/test_0div.py +0 -54
  201. tests/sim/options/test_symbolic_fd.py +0 -59
  202. tests/sim/options/test_unsupported.py +0 -34
  203. tests/sim/test_accuracy.py +0 -137
  204. tests/sim/test_checkbyte.py +0 -53
  205. tests/sim/test_echo.py +0 -36
  206. tests/sim/test_fauxware.py +0 -202
  207. tests/sim/test_self_modifying_code.py +0 -65
  208. tests/sim/test_simple_api.py +0 -36
  209. tests/sim/test_simulation_manager.py +0 -147
  210. tests/sim/test_stack_alignment.py +0 -65
  211. tests/sim/test_state.py +0 -303
  212. tests/sim/test_state_customization.py +0 -54
  213. tests/sim/test_symbol_hooked_by.py +0 -49
  214. tests/simos/__init__.py +0 -0
  215. tests/simos/windows/__init__.py +0 -0
  216. tests/simos/windows/test_windows_stack_cookie.py +0 -58
  217. tests/state_plugins/__init__.py +0 -0
  218. tests/state_plugins/inspect/__init__.py +0 -0
  219. tests/state_plugins/inspect/test_inspect.py +0 -310
  220. tests/state_plugins/inspect/test_syscall_override.py +0 -90
  221. tests/state_plugins/posix/__init__.py +0 -0
  222. tests/state_plugins/posix/test_file_struct_funcs.py +0 -56
  223. tests/state_plugins/posix/test_files.py +0 -69
  224. tests/state_plugins/posix/test_posix.py +0 -72
  225. tests/state_plugins/solver/__init__.py +0 -0
  226. tests/state_plugins/solver/test_simsolver.py +0 -58
  227. tests/state_plugins/solver/test_symbolic.py +0 -153
  228. tests/state_plugins/solver/test_variable_registration.py +0 -46
  229. tests/state_plugins/test_callstack.py +0 -54
  230. tests/state_plugins/test_gdb_plugin.py +0 -35
  231. tests/state_plugins/test_multi_open_file.py +0 -47
  232. tests/state_plugins/test_symbolization.py +0 -38
  233. tests/storage/__init__.py +0 -0
  234. tests/storage/test_memory.py +0 -960
  235. tests/storage/test_memory_merge.py +0 -114
  236. tests/storage/test_memview.py +0 -205
  237. tests/storage/test_mmap.py +0 -26
  238. tests/storage/test_multivalues.py +0 -44
  239. tests/storage/test_permissions.py +0 -32
  240. tests/storage/test_ptmalloc.py +0 -291
  241. tests/storage/test_relro_perm.py +0 -49
  242. tests/test_calling_conventions.py +0 -86
  243. tests/test_types.py +0 -329
  244. tests/utils/__init__.py +0 -0
  245. tests/utils/test_graph.py +0 -41
  246. {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/LICENSE +0 -0
  247. {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/WHEEL +0 -0
  248. {angr-9.2.87.dist-info → angr-9.2.89.dist-info}/entry_points.txt +0 -0
@@ -1,378 +0,0 @@
1
- #!/usr/bin/env python3
2
- # pylint:disable=no-self-use
3
- __package__ = __package__ or "tests.analyses.cfg" # pylint:disable=redefined-builtin
4
-
5
- import os
6
- import unittest
7
- import logging
8
- import tempfile
9
- from typing import TYPE_CHECKING, List, Sequence, Tuple
10
-
11
- import angr
12
- from angr.analyses import CFGFast
13
- from angr.knowledge_plugins.cfg import MemoryData, MemoryDataSort
14
-
15
- if TYPE_CHECKING:
16
- from angr.knowledge_plugins.cfg import CFGModel
17
- from angr.knowledge_plugins.functions import Function, FunctionManager
18
-
19
- from ...common import bin_location
20
-
21
-
22
- log = logging.getLogger(__name__)
23
- log.setLevel(logging.DEBUG)
24
- FAUXWARE_PATH = os.path.join(bin_location, "tests", "x86_64", "fauxware")
25
-
26
-
27
- def apply_patches(proj: angr.Project, patches: List[Tuple[int, str]]):
28
- for addr, asm in patches:
29
- patch_bytes = proj.arch.keystone.asm(asm, addr, as_bytes=True)[0]
30
- proj.kb.patches.add_patch(addr, patch_bytes)
31
-
32
-
33
- def assert_models_equal(model_a: "CFGModel", model_b: "CFGModel"):
34
- assert model_a.graph.nodes() == model_b.graph.nodes()
35
- assert model_a.graph.edges() == model_b.graph.edges()
36
- # FIXME: Check more
37
-
38
-
39
- def assert_function_graphs_equal(function_a: "Function", function_b: "Function"):
40
- nodes_a = function_a.graph.nodes()
41
- nodes_b = function_b.graph.nodes()
42
- if nodes_a != nodes_b:
43
- log.error("Differing nodes!\nFunction:%s\nNodes A: %s\nNodes B: %s", function_a, nodes_a, nodes_b)
44
- assert False
45
- # FIXME: Check more
46
-
47
-
48
- def assert_all_function_equal(functions_a: "FunctionManager", functions_b: "FunctionManager"):
49
- for f in functions_b:
50
- assert f in functions_a, f"Extra function: {functions_b[f]}"
51
- for f in functions_a:
52
- assert f in functions_b, f"Missing function: {functions_a[f]}"
53
- assert_function_graphs_equal(functions_a[f], functions_b[f])
54
-
55
-
56
- class TestCfgCombination(unittest.TestCase):
57
- """
58
- Tests that CFGFast can run with a prior model.
59
- """
60
-
61
- def test_cfgfast_combine_with_full_model(self):
62
- """Run CFGFast once, then again with the model of the first."""
63
- proj = angr.Project(FAUXWARE_PATH, auto_load_libs=False)
64
- cfg_a = proj.analyses[CFGFast].prep()()
65
- cfg_b = proj.analyses[CFGFast].prep()(model=cfg_a.model.copy())
66
- assert_models_equal(cfg_a.model, cfg_b.model)
67
- assert_all_function_equal(cfg_a.functions, cfg_b.functions)
68
-
69
- def test_cfgfast_combine_with_partial_model(self):
70
- """Run CFGFast on a region, then again on a second region with the model of the first."""
71
-
72
- # Initial analysis just to pick up expected addresses
73
- proj = angr.Project(FAUXWARE_PATH, auto_load_libs=False)
74
- cfg = proj.analyses[CFGFast].prep()()
75
- accepted_addr = cfg.functions["accepted"].addr
76
- rejected_addr = cfg.functions["rejected"].addr
77
- accepted_regions = [(n.addr, n.addr + n.size) for n in cfg.functions["accepted"].nodes]
78
- rejected_regions = [(n.addr, n.addr + n.size) for n in cfg.functions["rejected"].nodes]
79
-
80
- # Run partial analysis on the nodes we care about
81
- proj = angr.Project(FAUXWARE_PATH, auto_load_libs=False)
82
- cfg = proj.analyses[CFGFast].prep()(regions=accepted_regions)
83
- assert accepted_addr in cfg.functions.function_addrs_set
84
- assert rejected_addr not in cfg.functions.function_addrs_set
85
-
86
- # Check continued analysis over another region combines correctly
87
- cfg = proj.analyses[CFGFast].prep()(regions=rejected_regions, model=cfg.model.copy())
88
- assert accepted_addr in cfg.functions.function_addrs_set
89
- assert rejected_addr in cfg.functions.function_addrs_set
90
-
91
- # Check analysis over union of regions yields same result
92
- proj = angr.Project(FAUXWARE_PATH, auto_load_libs=False)
93
- regions = accepted_regions + rejected_regions
94
- cfg_combined = proj.analyses[CFGFast].prep()(regions=regions)
95
- assert_models_equal(cfg.model, cfg_combined.model)
96
- assert_all_function_equal(cfg.functions, cfg_combined.functions)
97
-
98
- # FIXME: Add test of first analyzing a function A, then analyzing a function B called by A
99
-
100
-
101
- class TestCfgReclassification(unittest.TestCase):
102
- """
103
- Tests that code/data can be reclassified in CFG.
104
- """
105
-
106
- def test_cfgfast_preclassify_code_as_data(self):
107
- """Classify a code region as data in an empty model, run CFGFast, ensure region remains classified as data."""
108
- proj = angr.Project(FAUXWARE_PATH, auto_load_libs=False)
109
- model = proj.kb.cfgs.new_model("initial")
110
- md = MemoryData(0x40069D, 22, MemoryDataSort.String)
111
- model.memory_data[md.addr] = md.copy()
112
- cfg = proj.analyses[CFGFast].prep()(model=model)
113
- assert cfg.model.memory_data[md.addr] == md
114
-
115
- # Make sure the memory data item is not covered by any node
116
- assert len(cfg.functions["authenticate"].graph.nodes) == 5
117
- for n in cfg.functions["authenticate"].graph.nodes:
118
- assert md.addr >= (n.addr + n.size) or n.addr >= (md.addr + md.size)
119
- if (n.addr + n.size) == md.addr:
120
- log.debug("Found adjacent node %s", n)
121
- # FIXME: Successor address is still the same
122
-
123
- # FIXME: Also test at function boundary
124
-
125
- def test_cfgfast_reclassify_code_as_data(self):
126
- """Run CFGFast, re-classify code within a function as data, then re-flow the function."""
127
- proj = angr.Project(FAUXWARE_PATH, auto_load_libs=False)
128
-
129
- # Initial analysis
130
- cfg = proj.analyses[CFGFast].prep()()
131
- func = cfg.functions["authenticate"]
132
- function_addr = func.addr
133
- original_number_of_nodes = len(func.graph.nodes)
134
-
135
- # Define the data region and run analysis for function reconstruction
136
- md = MemoryData(0x40069D, 22, MemoryDataSort.String)
137
- cfg.model.memory_data[md.addr] = md.copy()
138
- cfg.model.clear_region_for_reflow(func.addr)
139
- cfg = proj.analyses[CFGFast].prep()(
140
- symbols=False,
141
- function_prologues=False,
142
- start_at_entry=False,
143
- force_smart_scan=False,
144
- force_complete_scan=False,
145
- function_starts=[function_addr],
146
- model=cfg.model,
147
- )
148
-
149
- # Check memory data remains as configured and is not overlapped by any node
150
- assert cfg.model.memory_data[md.addr] == md
151
- assert len(cfg.functions["authenticate"].graph.nodes) == 5
152
- for n in cfg.functions["authenticate"].graph.nodes:
153
- assert md.addr >= (n.addr + n.size) or n.addr >= (md.addr + md.size)
154
-
155
- # Now re-define the data as code again and ensure we have the correct number of nodes
156
- del cfg.model.memory_data[md.addr]
157
- cfg.model.clear_region_for_reflow(func.addr)
158
- cfg = proj.analyses[CFGFast].prep()(
159
- symbols=False,
160
- function_prologues=False,
161
- start_at_entry=False,
162
- force_smart_scan=False,
163
- force_complete_scan=False,
164
- function_starts=[function_addr],
165
- model=cfg.model,
166
- )
167
-
168
- assert len(cfg.functions["authenticate"].graph.nodes) == original_number_of_nodes
169
-
170
- # FIXME: Test at function boundary
171
-
172
- # FIXME: Test at partial offset into some data item
173
- def test_cfgfast_preclassify_data_as_code(self):
174
- """Classify some code that would not normally be classified as code."""
175
- code = """
176
- _start:
177
- ret
178
-
179
- not_discovered:
180
- xor rax, rax
181
- mov rcx, 5
182
- .here:
183
- inc rax
184
- dec rcx
185
- jnz .here
186
- ret
187
- """
188
-
189
- not_discovered_addr = 0x1
190
- proj = angr.load_shellcode(code, "AMD64")
191
- cfg = proj.analyses[CFGFast].prep()(force_smart_scan=False)
192
- assert len(cfg.functions) == 1
193
-
194
- proj = angr.load_shellcode(code, "AMD64")
195
- cfg = proj.analyses[CFGFast].prep()(force_smart_scan=False, function_starts=[not_discovered_addr])
196
- assert len(cfg.functions) == 2
197
- assert len(cfg.functions[not_discovered_addr].block_addrs) == 3
198
-
199
- def test_cfgfast_reclassify_data_as_code(self):
200
- """Run CFGFast, then re-classify some assumed data as code and run again."""
201
- code = """
202
- _start:
203
- mov rax, [not_discovered]
204
- ret
205
-
206
- not_discovered:
207
- xor rax, rax
208
- mov rcx, 5
209
- .here:
210
- inc rax
211
- dec rcx
212
- jnz .here
213
- ret
214
- """
215
-
216
- proj = angr.load_shellcode(code, "AMD64")
217
- cfg = proj.analyses[CFGFast].prep()(force_smart_scan=False)
218
- assert len(cfg.functions) == 1
219
- not_discovered_addr = 0xB
220
- del cfg.model.memory_data[not_discovered_addr]
221
- cfg = proj.analyses[CFGFast].prep()(
222
- start_at_entry=False, force_smart_scan=False, function_starts=[not_discovered_addr], model=cfg.model
223
- )
224
- assert len(cfg.functions) == 2
225
- assert len(cfg.functions[0xB].block_addrs) == 3
226
-
227
-
228
- class TestCfgPatching(unittest.TestCase):
229
- """
230
- Test that patches made to the binary are correctly reflected in CFG.
231
- """
232
-
233
- def _test_patch(self, patches: Sequence[Tuple[int, str]]):
234
- unpatched_binary_path = FAUXWARE_PATH
235
- common_cfg_options = {
236
- "normalize": True,
237
- "resolve_indirect_jumps": True,
238
- "data_references": True,
239
- # "force_smart_scan": False,
240
- }
241
-
242
- # Create and load a pre-patched binary
243
- log.debug("Recovering pre-patched CFG")
244
- proj = angr.Project(unpatched_binary_path, auto_load_libs=False)
245
- apply_patches(proj, patches)
246
-
247
- with tempfile.NamedTemporaryFile(prefix="fauxware-patched-", delete=False) as f:
248
- f.write(proj.kb.patches.apply_patches_to_binary())
249
- f.close()
250
- prepatched_proj = angr.Project(f.name, auto_load_libs=False)
251
- expected_cfg = prepatched_proj.analyses[CFGFast].prep()(**common_cfg_options)
252
-
253
- # Now create a new project, recover CFG, then patch and recover CFG again
254
- proj = angr.Project(unpatched_binary_path, auto_load_libs=False)
255
- log.debug("Recovering CFG before patching")
256
- cfg_before_patching = proj.analyses[CFGFast].prep()(**common_cfg_options)
257
- apply_patches(proj, patches)
258
-
259
- log.debug("Recovering CFG after patching")
260
- for p in proj.kb.patches.values():
261
- cfg_before_patching.model.clear_region_for_reflow(p.addr, len(p.new_bytes))
262
- cfg_after_patching = proj.analyses[CFGFast].prep()(**common_cfg_options, model=cfg_before_patching.model)
263
-
264
- # Verify that the CFG of the patched binary matches the CFG of the pre-patched binary
265
- assert_models_equal(expected_cfg.model, cfg_after_patching.model)
266
-
267
- os.unlink(f.name)
268
-
269
- #
270
- # Patches that do not change block or function size
271
- #
272
-
273
- def test_cfg_patch_const_operand(self):
274
- """
275
- Patch a block, changing a data reference, with no effect on control.
276
-
277
- Change print of "Username: " to "Password: ".
278
- """
279
- self._test_patch([(0x400734, "mov edi, 0x400920")])
280
-
281
- def test_cfg_patch_ret_value(self):
282
- """
283
- Patch a block to redirect control, without changing the graph.
284
-
285
- Change return value of `authenticate` in rejection branch to 1.
286
- """
287
- self._test_patch([(0x4006E6, "mov eax, 1")])
288
-
289
- def test_cfg_patch_branch(self):
290
- """
291
- Patch a block, changing the graph.
292
-
293
- Patch `authenticate` to always jump to accept branch, eliminating 1 block.
294
- """
295
- self._test_patch([(0x4006DD, "jne 0x4006df")])
296
-
297
- def test_cfg_patch_call_target(self):
298
- """
299
- Patch a block, changing the graph, eliminate a cross reference.
300
-
301
- Change call of `rejected` to `accepted`.
302
- """
303
- self._test_patch([(0x4007CE, "call 0x4006ed")])
304
-
305
- # FIXME: Patches that change indirect jumps
306
-
307
- #
308
- # Patches that shrink blocks/function
309
- #
310
-
311
- def test_cfg_patch_shrink_encoding(self):
312
- """
313
- Shorten a block, but do not change graph.
314
-
315
- Use a shorter instruction encoding.
316
- """
317
- self._test_patch([(0x4006DF, "xor eax, eax; inc eax; jmp 0x4006eb")])
318
-
319
- def test_cfg_patch_shrink_branch(self):
320
- """
321
- Shorten a block, changing the graph.
322
-
323
- Remove `strcmp` check in `authenticate`, just jump to accept branch.
324
- """
325
- self._test_patch([(0x4006DB, "jmp 0x4006df")])
326
-
327
- def test_cfg_patch_shrink_ret_value(self):
328
- """
329
- Shorten a block, truncating a function.
330
-
331
- Patch `authenticate` to always return 1
332
- """
333
- self._test_patch([(0x400664, "xor rax, rax; inc rax; ret")])
334
-
335
- #
336
- # Patches that grow blocks
337
- #
338
-
339
- def test_cfg_patch_grow_block_fallthru(self):
340
- """
341
- Patch a block to cover another block.
342
-
343
- Ignore return value of `authenticate`, fallthru to accept branch.
344
- """
345
- self._test_patch([(0x4007BB, "nop; nop;")])
346
-
347
- def test_cfg_patch_grow_nocall(self):
348
- """
349
- Patch a block to eliminate all cross references to a function.
350
-
351
- Patch out call to `authenticate`, fall thru.
352
- """
353
- self._test_patch([(0x4007AE, "xor rax, rax; nop; nop")])
354
-
355
- def test_cfg_patch_grow_into_inter_function_padding(self):
356
- """
357
- Patch a block to grow into padded space between functions.
358
-
359
- Prepend several NOPs to the last block of `main`.
360
- """
361
- self._test_patch([(0x4007D3, "nop; nop; nop; nop; leave; ret")])
362
-
363
- def test_cfg_patch_grow_function_fallthru(self):
364
- """
365
- Patch a block that extends into another function.
366
-
367
- Cut off the end of `authenticate` so it falls into `accepted`.
368
- """
369
- self._test_patch([(0x4006EC, "nop")])
370
- # Will we have two functions? accepted() is still called so it will probably mark a function
371
-
372
-
373
- if __name__ == "__main__":
374
- logging.basicConfig()
375
- log.setLevel(logging.DEBUG)
376
- logging.getLogger("angr.analyses.cfg.cfg_fast").setLevel(logging.DEBUG)
377
- logging.getLogger("angr.analyses.cfg.cfg_base").setLevel(logging.DEBUG)
378
- unittest.main()
@@ -1,36 +0,0 @@
1
- #!/usr/bin/env python3
2
- __package__ = __package__ or "tests.analyses.cfg" # pylint:disable=redefined-builtin
3
-
4
- import os
5
- import unittest
6
-
7
- import angr
8
-
9
- from ...common import bin_location, slow_test
10
-
11
-
12
- test_location = os.path.join(bin_location, "tests")
13
-
14
-
15
- # pylint: disable=missing-class-docstring
16
- # pylint: disable=no-self-use
17
- class TestCfgRustGotResolution(unittest.TestCase):
18
- @slow_test
19
- def test_rust_got_resolution(self):
20
- # Test a simple Rust binary sample.
21
- #
22
- # Rust compiler may insert some non-external functions into GOT.
23
- # This tests whether angr can resolve indirect function calls to GOT entries in Rust binaries.
24
-
25
- path = os.path.join(test_location, "x86_64", "rust_hello_world")
26
- p = angr.Project(path, auto_load_libs=False)
27
-
28
- cfg = p.analyses.CFGFast(resolve_indirect_jumps=True)
29
-
30
- # angr should be able to resolve the indirect call in main function
31
- main = cfg.kb.functions[p.loader.find_symbol("_ZN16rust_hello_world4main17h932c4676a11c63c3E").rebased_addr]
32
- assert not main.has_unresolved_calls
33
-
34
-
35
- if __name__ == "__main__":
36
- unittest.main()
@@ -1,50 +0,0 @@
1
- #!/usr/bin/env python3
2
- __package__ = __package__ or "tests.analyses.cfg" # pylint:disable=redefined-builtin
3
-
4
- import os
5
- import unittest
6
-
7
- import angr
8
-
9
- from ...common import bin_location
10
-
11
-
12
- test_location = os.path.join(bin_location, "tests")
13
-
14
-
15
- # pylint: disable=missing-class-docstring
16
- # pylint: disable=no-self-use
17
- class TestCfgThumbFirmware(unittest.TestCase):
18
- def test_thumb_firmware_cfg(self):
19
- # Test an ARM firmware sample.
20
- #
21
- # This tests CFG, but also the Gym (the ThumbSpotter, etc)
22
- # Also requires proper relocs support, or You're Gonna Have a Bad Time(tm)
23
- # In short, a very comprehensive high level test
24
-
25
- path = os.path.join(test_location, "armel", "i2c_master_read-nucleol152re.elf")
26
- p = angr.Project(path, auto_load_libs=False)
27
-
28
- # This is the canonical way to carve up a nasty firmware thing.
29
-
30
- cfg = p.analyses.CFGFast(
31
- resolve_indirect_jumps=True, force_smart_scan=False, force_complete_scan=False, normalize=True
32
- )
33
-
34
- # vfprintf should return; this function has a weird C++ thing that gets compiled as a tail-call.
35
- # The function itself must return, and _NOT_ contain its callee.
36
- vfprintf = cfg.kb.functions[p.loader.find_symbol("vfprintf").rebased_addr]
37
- assert vfprintf.returning
38
- assert len(list(vfprintf.blocks)) == 1
39
- # The function should have one "transition"
40
- block = list(vfprintf.endpoints_with_type["transition"])[0]
41
- assert len(block.successors()) == 1
42
- succ = list(block.successors())[0]
43
- assert succ.addr == 0x080081DD
44
- f2 = p.kb.functions[succ.addr]
45
- assert f2.name == "_vfprintf_r"
46
- assert f2.returning
47
-
48
-
49
- if __name__ == "__main__":
50
- unittest.main()
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env python3
2
- __package__ = __package__ or "tests.analyses.cfg" # pylint:disable=redefined-builtin
3
-
4
- import os
5
- import unittest
6
-
7
- import angr
8
-
9
- from ...common import bin_location
10
-
11
-
12
- test_location = os.path.join(bin_location, "tests")
13
-
14
-
15
- # pylint: disable=missing-class-docstring
16
- # pylint: disable=no-self-use
17
- class TestCfgVexPostprocessor(unittest.TestCase):
18
- def test_issue_1172(self):
19
- path = os.path.join(test_location, "x86_64", "cfg_issue_1172")
20
- p = angr.Project(path, auto_load_libs=False)
21
-
22
- # it should not crash
23
- _ = p.analyses.CFG()
24
-
25
-
26
- if __name__ == "__main__":
27
- unittest.main()