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,1123 +0,0 @@
1
- #!/usr/bin/env python3
2
- # pylint:disable=missing-class-docstring,no-self-use,wrong-import-order
3
- __package__ = __package__ or "tests.analyses.cfg" # pylint:disable=redefined-builtin
4
-
5
- import os
6
- import logging
7
- import unittest
8
-
9
- import archinfo
10
- import angr
11
- from angr.analyses.cfg.cfg_fast import SegmentList
12
- from angr.knowledge_plugins.cfg import CFGNode, CFGModel, MemoryDataSort
13
- from angr.analyses.cfg.indirect_jump_resolvers import mips_elf_fast
14
-
15
- from ...common import bin_location, slow_test
16
-
17
- l = logging.getLogger("angr.tests.test_cfgfast")
18
-
19
- test_location = os.path.join(bin_location, "tests")
20
-
21
-
22
- def cstring_to_unicode_string(cstr: bytes) -> bytes:
23
- return b"".join((bytes([ch]) + b"\x00") for ch in cstr)
24
-
25
-
26
- class TestCfgfast(unittest.TestCase):
27
- def cfg_fast_functions_check(self, arch, binary_path, func_addrs, func_features):
28
- """
29
- Generate a fast CFG on the given binary, and test if all specified functions are found
30
-
31
- :param str arch: the architecture, will be prepended to `binary_path`
32
- :param str binary_path: path to the binary under the architecture directory
33
- :param dict func_addrs: A collection of function addresses that should be recovered
34
- :param dict func_features: A collection of features for some of the functions
35
- :return: None
36
- """
37
-
38
- path = os.path.join(test_location, arch, binary_path)
39
- proj = angr.Project(path, load_options={"auto_load_libs": False})
40
-
41
- cfg = proj.analyses.CFGFast()
42
- assert set(cfg.kb.functions.keys()).issuperset(func_addrs)
43
-
44
- for func_addr, feature_dict in func_features.items():
45
- returning = feature_dict.get("returning", "undefined")
46
- if returning != "undefined":
47
- assert cfg.kb.functions.function(addr=func_addr).returning is returning
48
-
49
- # Segment only
50
- cfg = proj.analyses.CFGFast(force_segment=True)
51
- assert set(cfg.kb.functions.keys()).issuperset(func_addrs)
52
-
53
- for func_addr, feature_dict in func_features.items():
54
- returning = feature_dict.get("returning", "undefined")
55
- if returning != "undefined":
56
- assert cfg.kb.functions.function(addr=func_addr).returning is returning
57
-
58
- # with normalization enabled
59
- cfg = proj.analyses.CFGFast(force_segment=True, normalize=True)
60
- assert set(cfg.kb.functions.keys()).issuperset(func_addrs)
61
-
62
- for func_addr, feature_dict in func_features.items():
63
- returning = feature_dict.get("returning", "undefined")
64
- if returning != "undefined":
65
- assert cfg.kb.functions.function(addr=func_addr).returning is returning
66
-
67
- def cfg_fast_edges_check(self, arch, binary_path, edges):
68
- """
69
- Generate a fast CFG on the given binary, and test if all edges are found.
70
-
71
- :param str arch: the architecture, will be prepended to `binary_path`
72
- :param str binary_path: path to the binary under the architecture directory
73
- :param list edges: a list of edges
74
- :return: None
75
- """
76
-
77
- path = os.path.join(test_location, arch, binary_path)
78
- proj = angr.Project(path, load_options={"auto_load_libs": False})
79
-
80
- cfg = proj.analyses.CFGFast()
81
-
82
- for src, dst in edges:
83
- src_node = cfg.model.get_any_node(src)
84
- dst_node = cfg.model.get_any_node(dst)
85
- assert src_node is not None, "CFG node 0x%x is not found." % src
86
- assert dst_node is not None, "CFG node 0x%x is not found." % dst
87
- assert dst_node in src_node.successors, "CFG edge {}-{} is not found.".format(
88
- src_node,
89
- dst_node,
90
- )
91
-
92
- def test_cfg_0(self):
93
- functions = {
94
- 0x400410,
95
- 0x400420,
96
- 0x400430,
97
- 0x400440,
98
- 0x400470,
99
- 0x40052C,
100
- 0x40053C,
101
- }
102
-
103
- function_features = {}
104
-
105
- self.cfg_fast_functions_check("x86_64", "cfg_0", functions, function_features)
106
-
107
- def test_cfg_0_pe(self):
108
- functions = {
109
- # 0x40150a, # currently angr identifies 0x40150e due to the way _func_addrs_from_prologues() is
110
- # implemented. this issue can be resolved with a properly implemented approach like Byte-Weight
111
- 0x4014F0,
112
- }
113
-
114
- function_features = {}
115
-
116
- self.cfg_fast_functions_check("x86_64", "cfg_0_pe", functions, function_features)
117
-
118
- def test_arm_function_merge(self):
119
- # function 0x7bb88 is created due to a data hint in another block. this function should be merged with the
120
- # previous function 0x7ba84
121
-
122
- path = os.path.join(test_location, "armel", "tenda-httpd")
123
- proj = angr.Project(path, auto_load_libs=False)
124
-
125
- cfg = proj.analyses.CFGFast()
126
-
127
- node_7bb88 = cfg.model.get_any_node(0x7BB88)
128
- assert node_7bb88 is not None
129
- assert node_7bb88.function_address == 0x7BA84
130
-
131
- @slow_test
132
- def test_busybox(self):
133
- edges = {
134
- (0x4091EC, 0x408DE0),
135
- # call to putenv. address of putenv may change in the future
136
- (
137
- 0x449ACC,
138
- 0x5003B8,
139
- ),
140
- # call to free. address of free may change in the future
141
- (
142
- 0x467CFC,
143
- 0x500014,
144
- ),
145
- }
146
-
147
- self.cfg_fast_edges_check("mipsel", "busybox", edges)
148
-
149
- @slow_test
150
- @unittest.skipUnless(
151
- os.path.isfile("C:\\Windows\\System32\\ntoskrnl.exe"),
152
- "ntoskrnl.exe does not exist on this system.",
153
- )
154
- def test_ntoskrnl(self):
155
- # we cannot distribute ntoskrnl.exe. as a result, this test case is manual
156
- path = "C:\\Windows\\System32\\ntoskrnl.exe"
157
- proj = angr.Project(path, auto_load_libs=False)
158
- _ = proj.analyses.CFG(data_references=True, normalize=True, show_progressbar=True)
159
-
160
- # nothing should prevent us from finish creating the CFG
161
-
162
- def test_fauxware_function_feauters_x86_64(self):
163
- functions = {
164
- 0x4004E0,
165
- 0x400510,
166
- 0x400520,
167
- 0x400530,
168
- 0x400540,
169
- 0x400550,
170
- 0x400560,
171
- 0x400570, # .plt._exit
172
- 0x400580, # _start
173
- 0x4005AC,
174
- 0x4005D0,
175
- 0x400640,
176
- 0x400664,
177
- 0x4006ED,
178
- 0x4006FD,
179
- 0x40071D, # main
180
- 0x4007E0,
181
- 0x400870,
182
- 0x400880,
183
- 0x4008B8,
184
- }
185
-
186
- function_features = {
187
- 0x400570: {"returning": False}, # plt.exit
188
- 0x4006FD: {"returning": False}, # rejected
189
- }
190
-
191
- return_edges = {
192
- (0x4006FB, 0x4007C7),
193
- } # return from accepted to main
194
-
195
- self.cfg_fast_functions_check("x86_64", "fauxware", functions, function_features)
196
- self.cfg_fast_edges_check("x86_64", "fauxware", return_edges)
197
-
198
- def test_fauxware_function_features_mips(self):
199
- functions = {
200
- 0x400534, # _init
201
- 0x400574,
202
- 0x400598,
203
- 0x4005D0, # _ftext
204
- 0x4005DC,
205
- 0x400630, # __do_global_dtors_aux
206
- 0x4006D4, # frame_dummy
207
- 0x400708,
208
- 0x400710, # authenticate
209
- 0x400814, # accepted
210
- 0x400868, # rejected
211
- 0x4008C0, # main
212
- 0x400A34,
213
- 0x400A48, # __libc_csu_init
214
- 0x400AF8,
215
- 0x400B00, # __do_global_ctors_aux
216
- 0x400B58,
217
- ### plt entries
218
- 0x400B60, # strcmp
219
- 0x400B70, # read
220
- 0x400B80, # printf
221
- 0x400B90, # puts
222
- 0x400BA0, # exit
223
- 0x400BB0, # open
224
- 0x400BC0, # __libc_start_main
225
- }
226
-
227
- function_features = {
228
- 0x400868: { # rejected
229
- "returning": False,
230
- }
231
- }
232
-
233
- return_edges = {
234
- (0x40084C, 0x400A04),
235
- } # returning edge from accepted to main
236
-
237
- self.cfg_fast_functions_check("mips", "fauxware", functions, function_features)
238
- self.cfg_fast_edges_check("mips", "fauxware", return_edges)
239
-
240
- def test_mips_elf_fast_indirect_jump_resolver(self):
241
- bin_path = os.path.join(test_location, "mips", "fauxware")
242
- proj = angr.Project(bin_path, auto_load_libs=False)
243
- # enable profiling for MipsElfFast
244
- # FIXME: The result might be different if other test cases that run in parallel mess with the profiling setting
245
- mips_elf_fast.enable_profiling()
246
- _ = proj.analyses.CFG()
247
- mips_elf_fast.disable_profiling()
248
- assert mips_elf_fast.HITS_CASE_0 >= 10
249
-
250
- def test_cfg_loop_unrolling(self):
251
- edges = {
252
- (0x400658, 0x400636),
253
- (0x400658, 0x400661),
254
- (0x400651, 0x400636),
255
- (0x400651, 0x400661),
256
- }
257
-
258
- self.cfg_fast_edges_check("x86_64", "cfg_loop_unrolling", edges)
259
-
260
- def test_cfg_switches_x86_64(self):
261
- edges = {
262
- # jump table 0 in func_0
263
- (0x40053A, 0x400547),
264
- (0x40053A, 0x400552),
265
- (0x40053A, 0x40055D),
266
- (0x40053A, 0x400568),
267
- (0x40053A, 0x400573),
268
- (0x40053A, 0x400580),
269
- (0x40053A, 0x40058D),
270
- # jump table 0 in func_1
271
- (0x4005BC, 0x4005C9),
272
- (0x4005BC, 0x4005D8),
273
- (0x4005BC, 0x4005E7),
274
- (0x4005BC, 0x4005F6),
275
- (0x4005BC, 0x400605),
276
- (0x4005BC, 0x400614),
277
- (0x4005BC, 0x400623),
278
- (0x4005BC, 0x400632),
279
- (0x4005BC, 0x40063E),
280
- (0x4005BC, 0x40064A),
281
- (0x4005BC, 0x4006B0),
282
- # jump table 1 in func_1
283
- (0x40065A, 0x400667),
284
- (0x40065A, 0x400673),
285
- (0x40065A, 0x40067F),
286
- (0x40065A, 0x40068B),
287
- (0x40065A, 0x400697),
288
- (0x40065A, 0x4006A3),
289
- # jump table 0 in main
290
- (0x4006E1, 0x4006EE),
291
- (0x4006E1, 0x4006FA),
292
- (0x4006E1, 0x40070B),
293
- (0x4006E1, 0x40071C),
294
- (0x4006E1, 0x40072D),
295
- (0x4006E1, 0x40073E),
296
- (0x4006E1, 0x40074F),
297
- (0x4006E1, 0x40075B),
298
- }
299
-
300
- self.cfg_fast_edges_check("x86_64", "cfg_switches", edges)
301
-
302
- def test_cfg_switches_armel(self):
303
- edges = {
304
- # jump table 0 in func_0
305
- (0x10434, 0x10488),
306
- (0x10434, 0x104E8),
307
- (0x10434, 0x10498),
308
- (0x10434, 0x104A8),
309
- (0x10434, 0x104B8),
310
- (0x10434, 0x104C8),
311
- (0x10434, 0x104D8),
312
- (0x10454, 0x104E8), # default case
313
- # jump table 0 in func_1
314
- (0x10524, 0x105CC),
315
- (0x10524, 0x106B4),
316
- (0x10524, 0x105D8),
317
- (0x10524, 0x105E4),
318
- (0x10524, 0x105F0),
319
- (0x10524, 0x105FC),
320
- (0x10524, 0x10608),
321
- (0x10524, 0x10614),
322
- (0x10524, 0x10620),
323
- (0x10524, 0x1062C),
324
- (0x10524, 0x10638),
325
- (0x10534, 0x106B4), # default case
326
- # jump table 1 in func_1
327
- (0x10650, 0x106A4), # default case
328
- (0x10640, 0x10668),
329
- (0x10640, 0x10674),
330
- (0x10640, 0x10680),
331
- (0x10640, 0x1068C),
332
- (0x10640, 0x10698),
333
- # jump table 0 in main
334
- (0x10734, 0x107FC),
335
- (0x10734, 0x10808),
336
- (0x10734, 0x10818),
337
- (0x10734, 0x10828),
338
- (0x10734, 0x10838),
339
- (0x10734, 0x10848),
340
- (0x10734, 0x10858),
341
- (0x10734, 0x10864),
342
- (0x10744, 0x10864), # default case
343
- }
344
-
345
- self.cfg_fast_edges_check("armel", "cfg_switches", edges)
346
-
347
- def test_cfg_switches_s390x(self):
348
- edges = {
349
- # jump table 0 in func_0
350
- (0x4007D4, 0x4007EA), # case 1
351
- (0x4007D4, 0x4007F4), # case 3
352
- (0x4007D4, 0x4007FE), # case 5
353
- (0x4007D4, 0x400808), # case 7
354
- (0x4007D4, 0x400812), # case 9
355
- (0x4007D4, 0x40081C), # case 12
356
- (0x4007C0, 0x4007CA), # default case
357
- # jump table 0 in func_1
358
- (0x400872, 0x4008AE), # case 2
359
- (0x400872, 0x4008BE), # case 10
360
- (0x400872, 0x4008CE), # case 12
361
- (0x400872, 0x4008DE), # case 14
362
- (0x400872, 0x4008EE), # case 15
363
- (0x400872, 0x4008FE), # case 16
364
- (0x400872, 0x40090E), # case 22
365
- (0x400872, 0x40091E), # case 24
366
- (0x400872, 0x40092E), # case 28
367
- (0x400872, 0x400888), # case 38
368
- (0x400848, 0x400854), # default case (1)
369
- (0x400872, 0x400854), # default case (2)
370
- # jump table 1 in func_1
371
- (0x40093E, 0x400984), # case 1
372
- (0x40093E, 0x400974), # case 2
373
- (0x40093E, 0x400964), # case 3
374
- (0x40093E, 0x400954), # case 4
375
- (0x40093E, 0x400994), # case 5
376
- (0x400898, 0x40089E), # default case (1)
377
- # jump table 0 in main
378
- # case 1, 3, 5, 7, 9: optimized out
379
- (0x400638, 0x40064E), # case 2
380
- (0x400638, 0x400692), # case 4
381
- (0x400638, 0x4006A4), # case 6
382
- (0x400638, 0x40066E), # case 8
383
- (0x400638, 0x400680), # case 10
384
- # case 45: optimized out
385
- (0x40062C, 0x40065C), # default case
386
- }
387
-
388
- self.cfg_fast_edges_check("s390x", "cfg_switches", edges)
389
-
390
- def test_cfg_about_time(self):
391
- # This is to test the correctness of the PLT stub removal in CFGBase
392
- proj = angr.Project(os.path.join(test_location, "x86_64", "about_time"), auto_load_libs=False)
393
- cfg = proj.analyses.CFG()
394
-
395
- # a PLT stub that should be removed
396
- assert 0x401026 not in cfg.kb.functions
397
- # a PLT stub that should be removed
398
- assert 0x4010A6 not in cfg.kb.functions
399
- # a PLT stub that should be removed
400
- assert 0x40115E not in cfg.kb.functions
401
- # the start function that should not be removed
402
- assert proj.entry in cfg.kb.functions
403
-
404
- def test_segment_list_0(self):
405
- seg_list = SegmentList()
406
- seg_list.occupy(0, 1, "code")
407
- seg_list.occupy(2, 3, "code")
408
-
409
- assert len(seg_list) == 2
410
- assert seg_list._list[0].end == 1
411
- assert seg_list._list[1].end == 5
412
- assert seg_list.is_occupied(4)
413
- assert seg_list.is_occupied(5) is False
414
-
415
- def test_segment_list_1(self):
416
- seg_list = SegmentList()
417
-
418
- # They should be merged
419
- seg_list.occupy(0, 1, "code")
420
- seg_list.occupy(1, 2, "code")
421
-
422
- assert len(seg_list) == 1
423
- assert seg_list._list[0].start == 0
424
- assert seg_list._list[0].end == 3
425
-
426
- def test_segment_list_2(self):
427
- seg_list = SegmentList()
428
-
429
- # They should not be merged
430
- seg_list.occupy(0, 1, "code")
431
- seg_list.occupy(1, 2, "data")
432
-
433
- assert len(seg_list) == 2
434
- assert seg_list._list[0].start == 0
435
- assert seg_list._list[0].end == 1
436
- assert seg_list._list[1].start == 1
437
- assert seg_list._list[1].end == 3
438
-
439
- def test_segment_list_3(self):
440
- seg_list = SegmentList()
441
-
442
- # They should be merged, and create three different segments
443
- seg_list.occupy(0, 5, "code")
444
- seg_list.occupy(5, 5, "code")
445
- seg_list.occupy(1, 2, "data")
446
-
447
- assert len(seg_list) == 3
448
-
449
- assert seg_list._list[0].start == 0
450
- assert seg_list._list[0].end == 1
451
- assert seg_list._list[0].sort == "code"
452
-
453
- assert seg_list._list[1].start == 1
454
- assert seg_list._list[1].end == 3
455
- assert seg_list._list[1].sort == "data"
456
-
457
- assert seg_list._list[2].start == 3
458
- assert seg_list._list[2].end == 10
459
- assert seg_list._list[2].sort == "code"
460
-
461
- def test_segment_list_4(self):
462
- seg_list = SegmentList()
463
-
464
- seg_list.occupy(5, 5, "code")
465
- seg_list.occupy(4, 1, "code")
466
- seg_list.occupy(2, 2, "code")
467
-
468
- assert len(seg_list) == 1
469
- assert seg_list._list[0].start == 2
470
- assert seg_list._list[0].end == 10
471
-
472
- def test_segment_list_5(self):
473
- seg_list = SegmentList()
474
-
475
- seg_list.occupy(5, 5, "data")
476
- seg_list.occupy(4, 1, "code")
477
- seg_list.occupy(2, 2, "data")
478
-
479
- assert len(seg_list) == 3
480
- assert seg_list._list[0].start == 2
481
- assert seg_list._list[2].end == 10
482
-
483
- seg_list.occupy(3, 2, "data")
484
-
485
- assert len(seg_list) == 1
486
- assert seg_list._list[0].start == 2
487
- assert seg_list._list[0].end == 10
488
-
489
- def test_segment_list_6(self):
490
- seg_list = SegmentList()
491
-
492
- seg_list.occupy(10, 20, "code")
493
- seg_list.occupy(9, 2, "data")
494
-
495
- assert len(seg_list) == 2
496
- assert seg_list._list[0].start == 9
497
- assert seg_list._list[0].end == 11
498
- assert seg_list._list[0].sort == "data"
499
-
500
- assert seg_list._list[1].start == 11
501
- assert seg_list._list[1].end == 30
502
- assert seg_list._list[1].sort == "code"
503
-
504
- #
505
- # Serialization
506
- #
507
-
508
- def test_serialization_cfgnode(self):
509
- path = os.path.join(test_location, "x86_64", "fauxware")
510
- proj = angr.Project(path, auto_load_libs=False)
511
-
512
- cfg = proj.analyses.CFGFast()
513
- # the first node
514
- node = cfg.model.get_any_node(proj.entry)
515
- assert node is not None
516
-
517
- b = node.serialize()
518
- assert len(b) > 0
519
- new_node = CFGNode.parse(b)
520
- assert new_node.addr == node.addr
521
- assert new_node.size == node.size
522
- assert new_node.block_id == node.block_id
523
-
524
- def test_serialization_cfgfast(self):
525
- path = os.path.join(test_location, "x86_64", "fauxware")
526
- proj1 = angr.Project(path, auto_load_libs=False)
527
- proj2 = angr.Project(path, auto_load_libs=False)
528
-
529
- cfg = proj1.analyses.CFGFast()
530
- # parse the entire graph
531
- b = cfg.model.serialize()
532
- assert len(b) > 0
533
-
534
- # simulate importing a cfg from another tool
535
- cfg_model = CFGModel.parse(b, cfg_manager=proj2.kb.cfgs)
536
-
537
- assert len(cfg_model.graph.nodes) == len(cfg.graph.nodes)
538
- assert len(cfg_model.graph.edges) == len(cfg.graph.edges)
539
-
540
- n1 = cfg.model.get_any_node(proj1.entry)
541
- n2 = cfg_model.get_any_node(proj1.entry)
542
- assert n1 == n2
543
-
544
- #
545
- # CFG instance copy
546
- #
547
-
548
- def test_cfg_copy(self):
549
- path = os.path.join(test_location, "cgc", "CADET_00002")
550
- proj = angr.Project(path, auto_load_libs=False)
551
-
552
- cfg = proj.analyses.CFGFast()
553
- cfg_copy = cfg.copy()
554
- for attribute in cfg_copy.__dict__:
555
- if attribute in ["_graph", "_seg_list", "_model"]:
556
- continue
557
- assert getattr(cfg, attribute) == getattr(cfg_copy, attribute)
558
-
559
- assert id(cfg.model) != id(cfg_copy.model)
560
- assert id(cfg.model.graph) != id(cfg_copy.model.graph)
561
- assert id(cfg._seg_list) != id(cfg_copy._seg_list)
562
-
563
- #
564
- # Alignment bytes
565
- #
566
-
567
- def test_cfg_0_pe_msvc_debug_nocc(self):
568
- filename = os.path.join("windows", "msvc_cfg_0_debug.exe")
569
- proj = angr.Project(os.path.join(test_location, "x86_64", filename), auto_load_libs=False)
570
- cfg = proj.analyses.CFGFast()
571
-
572
- # make sure 0x140015683 is marked as alignments
573
- sort = cfg._seg_list.occupied_by_sort(0x140016583)
574
- assert sort == "alignment"
575
-
576
- assert 0x140015683 not in cfg.kb.functions
577
-
578
- #
579
- # Indirect jump resolvers
580
- #
581
-
582
- # For test cases for jump table resolver, please refer to test_jumptables.py
583
-
584
- def test_resolve_x86_elf_pic_plt(self):
585
- path = os.path.join(test_location, "i386", "fauxware_pie")
586
- proj = angr.Project(path, load_options={"auto_load_libs": False})
587
-
588
- cfg = proj.analyses.CFGFast()
589
-
590
- # puts
591
- puts_node = cfg.model.get_any_node(0x4005B0)
592
- assert puts_node is not None
593
-
594
- # there should be only one successor, which jumps to SimProcedure puts
595
- assert len(puts_node.successors) == 1
596
- puts_successor = puts_node.successors[0]
597
- assert puts_successor.addr == proj.loader.find_symbol("puts").rebased_addr
598
-
599
- # the SimProcedure puts should have more than one successors, which are all return targets
600
- assert len(puts_successor.successors) == 3
601
- simputs_successor = puts_successor.successors
602
- return_targets = {a.addr for a in simputs_successor}
603
- assert return_targets == {0x400800, 0x40087E, 0x4008B6}
604
-
605
- #
606
- # Function names
607
- #
608
-
609
- def test_function_names_for_unloaded_libraries(self):
610
- path = os.path.join(test_location, "i386", "fauxware_pie")
611
- proj = angr.Project(path, load_options={"auto_load_libs": False})
612
-
613
- cfg = proj.analyses.CFGFast()
614
-
615
- function_names = [f.name if not f.is_plt else "plt_" + f.name for f in cfg.functions.values()]
616
-
617
- assert "plt_puts" in function_names
618
- assert "plt_read" in function_names
619
- assert "plt___stack_chk_fail" in function_names
620
- assert "plt_exit" in function_names
621
- assert "puts" in function_names
622
- assert "read" in function_names
623
- assert "__stack_chk_fail" in function_names
624
- assert "exit" in function_names
625
-
626
- #
627
- # Basic blocks
628
- #
629
-
630
- def test_block_instruction_addresses_armhf(self):
631
- path = os.path.join(test_location, "armhf", "fauxware")
632
- proj = angr.Project(path, auto_load_libs=False)
633
-
634
- cfg = proj.analyses.CFGFast()
635
-
636
- main_func = cfg.kb.functions["main"]
637
-
638
- # all instruction addresses of the block must be odd
639
- block = next(b for b in main_func.blocks if b.addr == main_func.addr)
640
-
641
- assert len(block.instruction_addrs) == 12
642
- for instr_addr in block.instruction_addrs:
643
- assert instr_addr % 2 == 1
644
-
645
- main_node = cfg.model.get_any_node(main_func.addr)
646
- assert main_node is not None
647
- assert len(main_node.instruction_addrs) == 12
648
- for instr_addr in main_node.instruction_addrs:
649
- assert instr_addr % 2 == 1
650
-
651
- #
652
- # Tail-call optimization detection
653
- #
654
-
655
- def test_tail_call_optimization_detection_armel(self):
656
- # GitHub issue #1286
657
-
658
- path = os.path.join(test_location, "armel", "Nucleo_read_hyperterminal-stripped.elf")
659
- proj = angr.Project(path, auto_load_libs=False)
660
-
661
- cfg = proj.analyses.CFGFast(
662
- resolve_indirect_jumps=True,
663
- force_complete_scan=False,
664
- normalize=True,
665
- symbols=False,
666
- detect_tail_calls=True,
667
- data_references=True,
668
- )
669
-
670
- all_func_addrs = set(cfg.functions.keys())
671
- assert 0x80010B5 not in all_func_addrs
672
- assert 0x8003EF9 not in all_func_addrs
673
- assert 0x8008419 not in all_func_addrs
674
-
675
- # Functions that are jumped to from tail-calls
676
- tail_call_funcs = [
677
- 0x8002BC1,
678
- 0x80046C1,
679
- 0x8000281,
680
- 0x8001BDB,
681
- 0x8002839,
682
- 0x80037AD,
683
- 0x8002C09,
684
- 0x8004165,
685
- 0x8004BE1,
686
- 0x8002EB1,
687
- ]
688
- for member in tail_call_funcs:
689
- assert member in all_func_addrs
690
-
691
- # also test for tailcall return addresses
692
-
693
- # mapping of return blocks to return addrs that are the actual callers of certain tail-calls endpoints
694
- tail_call_return_addrs = {
695
- 0x8002BD9: [0x800275F], # 0x8002bc1
696
- 0x80046D7: [0x800275F], # 0x80046c1
697
- 0x80046ED: [0x800275F], # 0x80046c1
698
- 0x8001BE7: [0x800068D, 0x8000695], # 0x8001bdb ??
699
- 0x800284D: [0x800028B, 0x80006E1, 0x80006E7], # 0x8002839
700
- 0x80037F5: [0x800270B, 0x8002733, 0x8002759, 0x800098F, 0x8000997], # 0x80037ad
701
- 0x80037EF: [0x800270B, 0x8002733, 0x8002759, 0x800098F, 0x8000997], # 0x80037ad
702
- 0x8002CC9: [
703
- 0x8002D3B,
704
- 0x8002B99,
705
- 0x8002E9F,
706
- 0x80041AD,
707
- 0x8004C87,
708
- 0x8004D35,
709
- 0x8002EFB,
710
- 0x8002BE9,
711
- 0x80046EB,
712
- 0x800464F,
713
- 0x8002A09,
714
- 0x800325F,
715
- 0x80047C1,
716
- ], # 0x8002c09
717
- 0x8004183: [0x8002713], # 0x8004165
718
- 0x8004C31: [0x8002713], # 0x8004be1
719
- 0x8004C69: [0x8002713], # 0x8004be1
720
- 0x8002EF1: [0x800273B],
721
- } # 0x8002eb1
722
-
723
- # check all expected return addrs are present
724
- for returning_block_addr, expected_return_addrs in tail_call_return_addrs.items():
725
- returning_block = cfg.model.get_any_node(returning_block_addr)
726
- return_block_addrs = [rb.addr for rb in cfg.model.get_successors(returning_block)]
727
- msg = "%x: unequal sizes of expected_addrs [%d] and return_block_addrs [%d]" % (
728
- returning_block_addr,
729
- len(expected_return_addrs),
730
- len(return_block_addrs),
731
- )
732
- assert len(return_block_addrs) == len(expected_return_addrs), msg
733
- for expected_addr in expected_return_addrs:
734
- msg = "expected retaddr {:x} not found for returning_block {:x}".format(
735
- expected_addr,
736
- returning_block_addr,
737
- )
738
- assert expected_addr in return_block_addrs, msg
739
-
740
- #
741
- # Incorrect function-leading blocks merging
742
- #
743
-
744
- def test_function_leading_blocks_merging(self):
745
- # GitHub issue #1312
746
-
747
- path = os.path.join(test_location, "armel", "Nucleo_read_hyperterminal-stripped.elf")
748
- proj = angr.Project(path, arch=archinfo.ArchARMCortexM(), auto_load_libs=False)
749
-
750
- cfg = proj.analyses.CFGFast(
751
- resolve_indirect_jumps=True,
752
- force_complete_scan=True,
753
- normalize=True,
754
- symbols=False,
755
- detect_tail_calls=True,
756
- )
757
-
758
- assert 0x8000799 in cfg.kb.functions
759
- assert 0x800079B not in cfg.kb.functions
760
- assert 0x800079B not in cfg.kb.functions[0x8000799].block_addrs_set
761
- assert 0x8000799 in cfg.kb.functions[0x8000799].block_addrs_set
762
- assert next(iter(b for b in cfg.kb.functions[0x8000799].blocks if b.addr == 0x8000799)).size == 6
763
-
764
- #
765
- # Blanket
766
- #
767
-
768
- def test_blanket_fauxware(self):
769
- path = os.path.join(test_location, "x86_64", "fauxware")
770
- proj = angr.Project(path, auto_load_libs=False)
771
-
772
- cfg = proj.analyses.CFGFast()
773
-
774
- cfb = proj.analyses.CFBlanket(kb=cfg.kb)
775
-
776
- # it should raise a key error when calling floor_addr on address 0 because nothing is mapped there
777
- # an instruction (or a block) starts at 0x400580
778
- assert cfb.floor_addr(0x400581) == 0x400580
779
- # a block ends at 0x4005a9 (exclusive)
780
- assert cfb.ceiling_addr(0x400581) == 0x4005A9
781
-
782
- #
783
- # CFG with patches
784
- #
785
-
786
- def test_unresolvable_targets(self):
787
- path = os.path.join(test_location, "cgc", "CADET_00002")
788
- proj = angr.Project(path, auto_load_libs=False)
789
-
790
- proj.analyses.CFGFast(normalize=True)
791
- func = proj.kb.functions[0x080489E0]
792
-
793
- true_endpoint_addrs = {0x8048BBC, 0x8048AF5, 0x8048B5C, 0x8048A41, 0x8048AA8}
794
- endpoint_addrs = {node.addr for node in func.endpoints}
795
- assert len(endpoint_addrs.symmetric_difference(true_endpoint_addrs)) == 0
796
-
797
- def test_indirect_jump_to_outside(self):
798
- # an indirect jump might be jumping to outside as well
799
- path = os.path.join(test_location, "mipsel", "libndpi.so.4.0.0")
800
- proj = angr.Project(path, auto_load_libs=False)
801
-
802
- cfg = proj.analyses.CFGFast()
803
-
804
- assert len(list(cfg.functions[0x404EE4].blocks)) == 3
805
- assert {ep.addr for ep in cfg.functions[0x404EE4].endpoints} == {
806
- 0x404F00,
807
- 0x404F08,
808
- }
809
-
810
- def test_plt_stub_has_one_jumpout_site(self):
811
- # each PLT stub must have exactly one jumpout site
812
- path = os.path.join(test_location, "x86_64", "1after909")
813
- proj = angr.Project(path, auto_load_libs=False)
814
- cfg = proj.analyses.CFGFast()
815
-
816
- for func in cfg.kb.functions.values():
817
- if func.is_plt:
818
- assert len(func.jumpout_sites) == 1
819
-
820
- def test_generate_special_info(self):
821
- path = os.path.join(test_location, "mipsel", "fauxware")
822
- proj = angr.Project(path, auto_load_libs=False)
823
-
824
- cfg = proj.analyses.CFGFast()
825
-
826
- assert any(func.info for func in cfg.functions.values())
827
- assert cfg.functions["main"].info["gp"] == 0x418CA0
828
-
829
- def test_load_from_shellcode(self):
830
- proj = angr.load_shellcode("loop: dec ecx; jnz loop; ret", "x86")
831
- cfg = proj.analyses.CFGFast()
832
-
833
- assert len(cfg.model.nodes()) == 2
834
-
835
- def test_starting_point_ordering(self):
836
- # project entry should always be first
837
- # so edge/path to unlabeled main function from _start
838
- # is correctly generated
839
-
840
- path = os.path.join(test_location, "armel", "start_ordering")
841
- proj = angr.Project(path, auto_load_libs=False)
842
- cfg = proj.analyses.CFGFast()
843
-
844
- # if ordering is incorrect, edge to function 0x103D4 will not exist
845
- n = cfg.model.get_any_node(proj.entry)
846
- assert n is not None
847
- assert len(n.successors) > 0
848
- assert len(n.successors[0].successors) > 0
849
- assert len(n.successors[0].successors[0].successors) == 3
850
-
851
- # now checking if path to the "real main" exists
852
- assert len(n.successors[0].successors[0].successors[1].successors) > 0
853
- n = n.successors[0].successors[0].successors[1].successors[0]
854
-
855
- assert len(n.successors) > 0
856
- assert len(n.successors[0].successors) > 0
857
- assert len(n.successors[0].successors[0].successors) > 0
858
- assert n.successors[0].successors[0].successors[0].addr == 0x103D4
859
-
860
- def test_error_returning(self):
861
- # error() is a great function: its returning depends on the value of the first argument...
862
- path = os.path.join(test_location, "x86_64", "mv_-O2")
863
- proj = angr.Project(path, auto_load_libs=False)
864
- cfg = proj.analyses.CFGFast()
865
-
866
- error_not_returning = [
867
- 0x4030D4,
868
- 0x403100,
869
- 0x40313C,
870
- 0x4031F5,
871
- 0x40348A,
872
- ]
873
-
874
- error_returning = [0x403179, 0x4031A2, 0x403981, 0x403E30, 0x40403B]
875
-
876
- for error_site in error_not_returning:
877
- node = cfg.model.get_any_node(error_site)
878
- assert len(list(cfg.model.get_successors(node, excluding_fakeret=False))) == 1 # only the call successor
879
-
880
- for error_site in error_returning:
881
- node = cfg.model.get_any_node(error_site)
882
- assert len(list(cfg.model.get_successors(node, excluding_fakeret=False))) == 2 # both a call and a fakeret
883
-
884
- def test_kepler_server_armhf(self):
885
- binary_path = os.path.join(test_location, "armhf", "kepler_server")
886
- proj = angr.Project(binary_path, auto_load_libs=False)
887
- cfg = proj.analyses.CFG(
888
- normalize=True,
889
- indirect_calls_always_return=False,
890
- )
891
-
892
- func_main = cfg.kb.functions[0x10329]
893
- assert func_main.returning is False
894
-
895
- func_0 = cfg.kb.functions[0x15EE9]
896
- assert func_0.returning is False
897
- assert len(func_0.block_addrs_set) == 1
898
-
899
- func_1 = cfg.kb.functions[0x15D2D]
900
- assert func_1.returning is False
901
-
902
- func_2 = cfg.kb.functions[0x228C5]
903
- assert func_2.returning is False
904
-
905
- func_3 = cfg.kb.functions[0x12631]
906
- assert func_3.returning is True
907
-
908
- def test_func_in_added_segment_by_patcherex_arm(self):
909
- path = os.path.join(test_location, "armel", "patcherex", "replace_function_patch_with_function_reference")
910
- proj = angr.Project(path, auto_load_libs=False)
911
- cfg = proj.analyses.CFGFast(
912
- normalize=True,
913
- function_starts={0xA00081},
914
- regions=[
915
- (4195232, 4195244),
916
- (4195244, 4195324),
917
- (4195324, 4196016),
918
- (4196016, 4196024),
919
- (10485888, 10485950),
920
- ],
921
- )
922
-
923
- # Check whether the target function is in the functions list
924
- assert 0xA00081 in cfg.kb.functions
925
- # Check the number of basic blocks
926
- assert len(list(cfg.functions[0xA00081].blocks)) == 8
927
-
928
- def test_func_in_added_segment_by_patcherex_x64(self):
929
- path = os.path.join(test_location, "x86_64", "patchrex", "replace_function_patch_with_function_reference")
930
- proj = angr.Project(path, auto_load_libs=False)
931
- cfg = proj.analyses.CFGFast(
932
- normalize=True,
933
- function_starts={0xA0013D},
934
- regions=[
935
- (4195568, 4195591),
936
- (4195600, 4195632),
937
- (4195632, 4195640),
938
- (4195648, 4196418),
939
- (4196420, 4196429),
940
- (10486064, 10486213),
941
- ],
942
- )
943
-
944
- # Check whether the target function is in the functions list
945
- assert 0xA0013D in cfg.kb.functions
946
- # Check the number of basic blocks
947
- assert len(list(cfg.functions[0xA0013D].blocks)) == 7
948
-
949
- def test_indirect_calls_always_return_overly_aggressive(self):
950
- path = os.path.join(test_location, "x86_64", "ls_ubuntu_2004")
951
- proj = angr.Project(path, auto_load_libs=False)
952
- cfg = proj.analyses.CFGFast(normalize=True)
953
- node = cfg.model.get_any_node(0x404DB4)
954
- assert node is not None
955
- assert node.function_address == 0x40F770
956
-
957
- def test_removing_lock_edges(self):
958
- path = os.path.join(
959
- test_location, "x86_64", "windows", "6f289eb8c8cd826525d79b195b1cf187df509d56120427b10ea3fb1b4db1b7b5.sys"
960
- )
961
- proj = angr.Project(path, auto_load_libs=False)
962
- cfg = proj.analyses.CFGFast(normalize=True)
963
- node = cfg.model.get_any_node(0x1400061C2)
964
- assert {n.addr for n in cfg.model.graph.successors(node)} == {0x1400060DC, 0x1400061D4}
965
-
966
- def test_security_init_cookie_identification(self):
967
- path = os.path.join(test_location, "x86_64", "windows", "3ware.sys")
968
- proj = angr.Project(path, auto_load_libs=False)
969
- cfg = proj.analyses.CFGFast()
970
- assert cfg.kb.functions[0x1C001A018].name == "_security_init_cookie"
971
- assert cfg.kb.functions[0x1C0010100].name == "_security_check_cookie"
972
-
973
- def test_security_init_cookie_identification_a(self):
974
- path = os.path.join(
975
- test_location, "x86_64", "windows", "1817a5bf9c01035bcf8a975c9f1d94b0ce7f6a200339485d8f93859f8f6d730c.exe"
976
- )
977
- proj = angr.Project(path, auto_load_libs=False)
978
- cfg = proj.analyses.CFGFast()
979
- assert cfg.kb.functions[0x21514B5600].name == "_security_init_cookie"
980
-
981
-
982
- class TestCfgfastDataReferences(unittest.TestCase):
983
- def test_data_references_x86_64(self):
984
- path = os.path.join(test_location, "x86_64", "fauxware")
985
- proj = angr.Project(path, auto_load_libs=False)
986
-
987
- cfg = proj.analyses.CFGFast(data_references=True)
988
-
989
- memory_data = cfg.memory_data
990
- # There is no code reference
991
- code_ref_count = len([d for d in memory_data.values() if d.sort == MemoryDataSort.CodeReference])
992
- assert code_ref_count >= 0, "There should be no code reference."
993
-
994
- # There are at least 2 pointer arrays
995
- ptr_array_count = len([d for d in memory_data.values() if d.sort == MemoryDataSort.PointerArray])
996
- assert ptr_array_count > 2, "Missing some pointer arrays."
997
-
998
- assert 0x4008D0 in memory_data
999
- sneaky_str = memory_data[0x4008D0]
1000
- assert sneaky_str.sort == "string"
1001
- assert sneaky_str.content == b"SOSNEAKY"
1002
-
1003
- def test_data_references_mipsel(self):
1004
- path = os.path.join(test_location, "mipsel", "fauxware")
1005
- proj = angr.Project(path, auto_load_libs=False)
1006
-
1007
- cfg = proj.analyses.CFGFast(data_references=True)
1008
-
1009
- memory_data = cfg.memory_data
1010
- # There is no code reference
1011
- code_ref_count = len([d for d in memory_data.values() if d.sort == MemoryDataSort.CodeReference])
1012
- assert code_ref_count >= 0, "There should be no code reference."
1013
-
1014
- # There are at least 2 pointer arrays
1015
- ptr_array_count = len([d for d in memory_data.values() if d.sort == MemoryDataSort.PointerArray])
1016
- assert ptr_array_count >= 1, "Missing some pointer arrays."
1017
-
1018
- assert 0x400C00 in memory_data
1019
- sneaky_str = memory_data[0x400C00]
1020
- assert sneaky_str.sort == "string"
1021
- assert sneaky_str.content == b"SOSNEAKY"
1022
-
1023
- assert 0x400C0C in memory_data
1024
- str_ = memory_data[0x400C0C]
1025
- assert str_.sort == "string"
1026
- assert str_.content == b"Welcome to the admin console, trusted user!"
1027
-
1028
- assert 0x400C38 in memory_data
1029
- str_ = memory_data[0x400C38]
1030
- assert str_.sort == "string"
1031
- assert str_.content == b"Go away!"
1032
-
1033
- assert 0x400C44 in memory_data
1034
- str_ = memory_data[0x400C44]
1035
- assert str_.sort == "string"
1036
- assert str_.content == b"Username: "
1037
-
1038
- assert 0x400C50 in memory_data
1039
- str_ = memory_data[0x400C50]
1040
- assert str_.sort == "string"
1041
- assert str_.content == b"Password: "
1042
-
1043
- def test_data_references_mips64(self):
1044
- path = os.path.join(test_location, "mips64", "true")
1045
- proj = angr.Project(path, auto_load_libs=False)
1046
-
1047
- cfg = proj.analyses.CFGFast(data_references=True, cross_references=True)
1048
- memory_data = cfg.memory_data
1049
-
1050
- assert 0x120007DD8 in memory_data
1051
- assert memory_data[0x120007DD8].sort == "string"
1052
- assert memory_data[0x120007DD8].content == b"coreutils"
1053
-
1054
- xrefs = proj.kb.xrefs
1055
- refs = list(xrefs.get_xrefs_by_dst(0x120007DD8))
1056
- assert len(refs) == 2
1057
- assert {x.ins_addr for x in refs} == {0x1200020E8, 0x120002108}
1058
-
1059
- def test_data_references_i386_gcc_pie(self):
1060
- path = os.path.join(test_location, "i386", "nl")
1061
- proj = angr.Project(path, auto_load_libs=False)
1062
-
1063
- cfg = proj.analyses.CFGFast(data_references=True, cross_references=True)
1064
- memory_data = cfg.memory_data
1065
-
1066
- assert 0x405BB0 in memory_data
1067
- assert memory_data[0x405BB0].sort == "string"
1068
- assert memory_data[0x405BB0].content == b"/usr/local/share/locale"
1069
-
1070
- xrefs = proj.kb.xrefs
1071
- refs = list(xrefs.get_xrefs_by_dst(0x405BB0))
1072
- assert len(refs) == 1
1073
- assert {x.ins_addr for x in refs} == {0x4011DD}
1074
-
1075
- def test_data_references_wide_string(self):
1076
- path = os.path.join(test_location, "x86_64", "windows", "fauxware-wide.exe")
1077
- proj = angr.Project(path, auto_load_libs=False)
1078
-
1079
- cfg = proj.analyses.CFGFast(data_references=True)
1080
- recovered_strings = [d.content for d in cfg.memory_data.values() if d.sort == MemoryDataSort.UnicodeString]
1081
-
1082
- for testme in ("SOSNEAKY", "Welcome to the admin console, trusted user!\n", "Go away!\n", "Username: \n"):
1083
- assert testme.encode("utf-16-le") in recovered_strings
1084
-
1085
- def test_data_references_lea_string_addr(self):
1086
- path = os.path.join(test_location, "x86_64", "windows", "3ware.sys")
1087
- proj = angr.Project(path, auto_load_libs=False)
1088
-
1089
- cfg = proj.analyses.CFGFast(data_references=True)
1090
- assert cfg.memory_data[0x1C0010A20].sort == MemoryDataSort.String
1091
- assert cfg.memory_data[0x1C0010A20].content == b"Initialize> %s"
1092
-
1093
- def test_arm_function_hints_from_data_references(self):
1094
- path = os.path.join(test_location, "armel", "sha224sum")
1095
- proj = angr.Project(path, auto_load_libs=False)
1096
-
1097
- proj.analyses.CFGFast(data_references=True)
1098
- funcs = proj.kb.functions
1099
- assert funcs.contains_addr(0x129C4)
1100
- func = funcs[0x129C4]
1101
- assert len(list(func.blocks)) == 1
1102
- assert list(func.blocks)[0].size == 16
1103
-
1104
- def test_data_references_windows_driver_utf16_strings(self):
1105
- path = os.path.join(
1106
- test_location, "x86_64", "windows", "aaba7db353eb9400e3471eaaa1cf0105f6d1fab0ce63f1a2665c8ba0e8963a05.bin"
1107
- )
1108
- proj = angr.Project(path, auto_load_libs=False)
1109
-
1110
- cfg = proj.analyses.CFGFast()
1111
-
1112
- assert cfg.model.memory_data[0x1DCE0].sort == MemoryDataSort.UnicodeString
1113
- assert cfg.model.memory_data[0x1DCE0].content == cstring_to_unicode_string(
1114
- b"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\WinApi"
1115
- )
1116
- assert cfg.model.memory_data[0x1DCE0].size == 116
1117
- assert cfg.model.memory_data[0x1DD90].sort == MemoryDataSort.UnicodeString
1118
- assert cfg.model.memory_data[0x1DD90].content == cstring_to_unicode_string(b"ntdll.dll")
1119
- assert cfg.model.memory_data[0x1DD90].size == 20
1120
-
1121
-
1122
- if __name__ == "__main__":
1123
- unittest.main()