angr 9.2.192__cp311-cp311-macosx_10_12_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.
Files changed (1442) hide show
  1. angr/__init__.py +366 -0
  2. angr/__main__.py +182 -0
  3. angr/ail_callable.py +79 -0
  4. angr/ailment/__init__.py +83 -0
  5. angr/ailment/block.py +88 -0
  6. angr/ailment/block_walker.py +856 -0
  7. angr/ailment/constant.py +3 -0
  8. angr/ailment/converter_common.py +11 -0
  9. angr/ailment/converter_pcode.py +648 -0
  10. angr/ailment/converter_vex.py +829 -0
  11. angr/ailment/expression.py +1655 -0
  12. angr/ailment/manager.py +34 -0
  13. angr/ailment/statement.py +973 -0
  14. angr/ailment/tagged_object.py +58 -0
  15. angr/ailment/utils.py +114 -0
  16. angr/analyses/__init__.py +117 -0
  17. angr/analyses/analysis.py +429 -0
  18. angr/analyses/backward_slice.py +686 -0
  19. angr/analyses/binary_optimizer.py +670 -0
  20. angr/analyses/bindiff.py +1512 -0
  21. angr/analyses/boyscout.py +76 -0
  22. angr/analyses/callee_cleanup_finder.py +74 -0
  23. angr/analyses/calling_convention/__init__.py +6 -0
  24. angr/analyses/calling_convention/calling_convention.py +1113 -0
  25. angr/analyses/calling_convention/fact_collector.py +647 -0
  26. angr/analyses/calling_convention/utils.py +60 -0
  27. angr/analyses/cdg.py +189 -0
  28. angr/analyses/cfg/__init__.py +23 -0
  29. angr/analyses/cfg/cfb.py +451 -0
  30. angr/analyses/cfg/cfg.py +74 -0
  31. angr/analyses/cfg/cfg_arch_options.py +95 -0
  32. angr/analyses/cfg/cfg_base.py +2954 -0
  33. angr/analyses/cfg/cfg_emulated.py +3451 -0
  34. angr/analyses/cfg/cfg_fast.py +5431 -0
  35. angr/analyses/cfg/cfg_fast_soot.py +662 -0
  36. angr/analyses/cfg/cfg_job_base.py +203 -0
  37. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +30 -0
  38. angr/analyses/cfg/indirect_jump_resolvers/aarch64_macho_got.py +77 -0
  39. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
  40. angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
  41. angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +159 -0
  42. angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +339 -0
  43. angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
  44. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +82 -0
  45. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2490 -0
  46. angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
  47. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
  48. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
  49. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
  50. angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
  51. angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
  52. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
  53. angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
  54. angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
  55. angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
  56. angr/analyses/cfg_slice_to_sink/graph.py +87 -0
  57. angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
  58. angr/analyses/class_identifier.py +63 -0
  59. angr/analyses/code_tagging.py +123 -0
  60. angr/analyses/codecave.py +77 -0
  61. angr/analyses/complete_calling_conventions.py +475 -0
  62. angr/analyses/congruency_check.py +377 -0
  63. angr/analyses/data_dep/__init__.py +16 -0
  64. angr/analyses/data_dep/data_dependency_analysis.py +595 -0
  65. angr/analyses/data_dep/dep_nodes.py +171 -0
  66. angr/analyses/data_dep/sim_act_location.py +49 -0
  67. angr/analyses/datagraph_meta.py +105 -0
  68. angr/analyses/ddg.py +1670 -0
  69. angr/analyses/decompiler/__init__.py +41 -0
  70. angr/analyses/decompiler/ail_simplifier.py +2246 -0
  71. angr/analyses/decompiler/ailgraph_walker.py +49 -0
  72. angr/analyses/decompiler/block_io_finder.py +302 -0
  73. angr/analyses/decompiler/block_similarity.py +199 -0
  74. angr/analyses/decompiler/block_simplifier.py +397 -0
  75. angr/analyses/decompiler/callsite_maker.py +579 -0
  76. angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
  77. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +618 -0
  78. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +24 -0
  79. angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +354 -0
  80. angr/analyses/decompiler/clinic.py +3662 -0
  81. angr/analyses/decompiler/condition_processor.py +1323 -0
  82. angr/analyses/decompiler/counters/__init__.py +16 -0
  83. angr/analyses/decompiler/counters/boolean_counter.py +27 -0
  84. angr/analyses/decompiler/counters/call_counter.py +77 -0
  85. angr/analyses/decompiler/counters/expression_counters.py +77 -0
  86. angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
  87. angr/analyses/decompiler/decompilation_cache.py +54 -0
  88. angr/analyses/decompiler/decompilation_options.py +317 -0
  89. angr/analyses/decompiler/decompiler.py +796 -0
  90. angr/analyses/decompiler/dephication/__init__.py +6 -0
  91. angr/analyses/decompiler/dephication/dephication_base.py +100 -0
  92. angr/analyses/decompiler/dephication/graph_dephication.py +70 -0
  93. angr/analyses/decompiler/dephication/graph_rewriting.py +112 -0
  94. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +357 -0
  95. angr/analyses/decompiler/dephication/rewriting_engine.py +528 -0
  96. angr/analyses/decompiler/dephication/seqnode_dephication.py +156 -0
  97. angr/analyses/decompiler/dirty_rewriters/__init__.py +7 -0
  98. angr/analyses/decompiler/dirty_rewriters/amd64_dirty.py +74 -0
  99. angr/analyses/decompiler/dirty_rewriters/rewriter_base.py +27 -0
  100. angr/analyses/decompiler/empty_node_remover.py +212 -0
  101. angr/analyses/decompiler/expression_narrower.py +290 -0
  102. angr/analyses/decompiler/goto_manager.py +112 -0
  103. angr/analyses/decompiler/graph_region.py +441 -0
  104. angr/analyses/decompiler/jump_target_collector.py +37 -0
  105. angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
  106. angr/analyses/decompiler/label_collector.py +32 -0
  107. angr/analyses/decompiler/node_replacer.py +42 -0
  108. angr/analyses/decompiler/notes/__init__.py +9 -0
  109. angr/analyses/decompiler/notes/decompilation_note.py +48 -0
  110. angr/analyses/decompiler/notes/deobfuscated_strings.py +56 -0
  111. angr/analyses/decompiler/optimization_passes/__init__.py +164 -0
  112. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
  113. angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
  114. angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
  115. angr/analyses/decompiler/optimization_passes/condition_constprop.py +211 -0
  116. angr/analyses/decompiler/optimization_passes/const_derefs.py +127 -0
  117. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
  118. angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
  119. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
  120. angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
  121. angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
  122. angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
  123. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
  124. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1221 -0
  125. angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
  126. angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
  127. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
  128. angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +236 -0
  129. angr/analyses/decompiler/optimization_passes/eager_std_string_eval.py +186 -0
  130. angr/analyses/decompiler/optimization_passes/engine_base.py +502 -0
  131. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +138 -0
  132. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
  133. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +618 -0
  134. angr/analyses/decompiler/optimization_passes/inlined_strlen_simplifier.py +274 -0
  135. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
  136. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +337 -0
  137. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +939 -0
  138. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
  139. angr/analyses/decompiler/optimization_passes/optimization_pass.py +710 -0
  140. angr/analyses/decompiler/optimization_passes/peephole_simplifier.py +75 -0
  141. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +263 -0
  142. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier_adv.py +198 -0
  143. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
  144. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
  145. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +632 -0
  146. angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
  147. angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +166 -0
  148. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
  149. angr/analyses/decompiler/optimization_passes/static_vvar_rewriter.py +336 -0
  150. angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +166 -0
  151. angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
  152. angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
  153. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +477 -0
  154. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
  155. angr/analyses/decompiler/peephole_optimizations/__init__.py +136 -0
  156. angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
  157. angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
  158. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
  159. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
  160. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
  161. angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
  162. angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
  163. angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
  164. angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
  165. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
  166. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
  167. angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
  168. angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
  169. angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
  170. angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +182 -0
  171. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
  172. angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
  173. angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
  174. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
  175. angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
  176. angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
  177. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +436 -0
  178. angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
  179. angr/analyses/decompiler/peephole_optimizations/inlined_memcpy.py +78 -0
  180. angr/analyses/decompiler/peephole_optimizations/inlined_memset.py +262 -0
  181. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +217 -0
  182. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +106 -0
  183. angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy.py +256 -0
  184. angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy_consolidation.py +296 -0
  185. angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
  186. angr/analyses/decompiler/peephole_optimizations/modulo_simplifier.py +89 -0
  187. angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
  188. angr/analyses/decompiler/peephole_optimizations/optimized_div_simplifier.py +356 -0
  189. angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
  190. angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
  191. angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
  192. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
  193. angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +125 -0
  194. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +273 -0
  195. angr/analyses/decompiler/peephole_optimizations/remove_redundant_derefs.py +21 -0
  196. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
  197. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
  198. angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
  199. angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
  200. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
  201. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +115 -0
  202. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
  203. angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
  204. angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
  205. angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
  206. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
  207. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +143 -0
  208. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
  209. angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
  210. angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +28 -0
  211. angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
  212. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
  213. angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
  214. angr/analyses/decompiler/presets/__init__.py +22 -0
  215. angr/analyses/decompiler/presets/basic.py +36 -0
  216. angr/analyses/decompiler/presets/fast.py +66 -0
  217. angr/analyses/decompiler/presets/full.py +76 -0
  218. angr/analyses/decompiler/presets/malware.py +70 -0
  219. angr/analyses/decompiler/presets/preset.py +37 -0
  220. angr/analyses/decompiler/redundant_label_remover.py +141 -0
  221. angr/analyses/decompiler/region_identifier.py +1319 -0
  222. angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
  223. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
  224. angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
  225. angr/analyses/decompiler/region_simplifiers/expr_folding.py +838 -0
  226. angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
  227. angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
  228. angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
  229. angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
  230. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
  231. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +270 -0
  232. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
  233. angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
  234. angr/analyses/decompiler/region_walker.py +24 -0
  235. angr/analyses/decompiler/return_maker.py +72 -0
  236. angr/analyses/decompiler/semantic_naming/__init__.py +37 -0
  237. angr/analyses/decompiler/semantic_naming/array_index_naming.py +196 -0
  238. angr/analyses/decompiler/semantic_naming/boolean_naming.py +264 -0
  239. angr/analyses/decompiler/semantic_naming/call_result_naming.py +220 -0
  240. angr/analyses/decompiler/semantic_naming/naming_base.py +166 -0
  241. angr/analyses/decompiler/semantic_naming/orchestrator.py +107 -0
  242. angr/analyses/decompiler/semantic_naming/pointer_naming.py +334 -0
  243. angr/analyses/decompiler/semantic_naming/region_loop_counter_naming.py +246 -0
  244. angr/analyses/decompiler/semantic_naming/size_naming.py +137 -0
  245. angr/analyses/decompiler/seq_to_blocks.py +20 -0
  246. angr/analyses/decompiler/sequence_walker.py +261 -0
  247. angr/analyses/decompiler/ssailification/__init__.py +4 -0
  248. angr/analyses/decompiler/ssailification/rewriting.py +451 -0
  249. angr/analyses/decompiler/ssailification/rewriting_engine.py +1091 -0
  250. angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
  251. angr/analyses/decompiler/ssailification/ssailification.py +283 -0
  252. angr/analyses/decompiler/ssailification/traversal.py +127 -0
  253. angr/analyses/decompiler/ssailification/traversal_engine.py +323 -0
  254. angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
  255. angr/analyses/decompiler/stack_item.py +36 -0
  256. angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
  257. angr/analyses/decompiler/structured_codegen/base.py +193 -0
  258. angr/analyses/decompiler/structured_codegen/c.py +4257 -0
  259. angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
  260. angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
  261. angr/analyses/decompiler/structuring/__init__.py +30 -0
  262. angr/analyses/decompiler/structuring/dream.py +1217 -0
  263. angr/analyses/decompiler/structuring/phoenix.py +3636 -0
  264. angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
  265. angr/analyses/decompiler/structuring/sailr.py +120 -0
  266. angr/analyses/decompiler/structuring/structurer_base.py +1140 -0
  267. angr/analyses/decompiler/structuring/structurer_nodes.py +442 -0
  268. angr/analyses/decompiler/utils.py +1224 -0
  269. angr/analyses/deobfuscator/__init__.py +23 -0
  270. angr/analyses/deobfuscator/api_obf_finder.py +333 -0
  271. angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +80 -0
  272. angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
  273. angr/analyses/deobfuscator/data_transformation_embedder.py +633 -0
  274. angr/analyses/deobfuscator/hash_lookup_api_deobfuscator.py +156 -0
  275. angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
  276. angr/analyses/deobfuscator/scope_ops_analyzer.py +68 -0
  277. angr/analyses/deobfuscator/string_obf_finder.py +983 -0
  278. angr/analyses/deobfuscator/string_obf_opt_passes.py +136 -0
  279. angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
  280. angr/analyses/disassembly.py +1351 -0
  281. angr/analyses/disassembly_utils.py +101 -0
  282. angr/analyses/dominance_frontier.py +57 -0
  283. angr/analyses/fcp/__init__.py +4 -0
  284. angr/analyses/fcp/fcp.py +427 -0
  285. angr/analyses/find_objects_static.py +205 -0
  286. angr/analyses/flirt/__init__.py +47 -0
  287. angr/analyses/flirt/consts.py +160 -0
  288. angr/analyses/flirt/flirt.py +249 -0
  289. angr/analyses/flirt/flirt_function.py +20 -0
  290. angr/analyses/flirt/flirt_matcher.py +352 -0
  291. angr/analyses/flirt/flirt_module.py +32 -0
  292. angr/analyses/flirt/flirt_node.py +23 -0
  293. angr/analyses/flirt/flirt_sig.py +359 -0
  294. angr/analyses/flirt/flirt_utils.py +31 -0
  295. angr/analyses/forward_analysis/__init__.py +12 -0
  296. angr/analyses/forward_analysis/forward_analysis.py +619 -0
  297. angr/analyses/forward_analysis/job_info.py +64 -0
  298. angr/analyses/forward_analysis/visitors/__init__.py +14 -0
  299. angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
  300. angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
  301. angr/analyses/forward_analysis/visitors/graph.py +242 -0
  302. angr/analyses/forward_analysis/visitors/loop.py +29 -0
  303. angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
  304. angr/analyses/identifier/__init__.py +5 -0
  305. angr/analyses/identifier/custom_callable.py +137 -0
  306. angr/analyses/identifier/errors.py +10 -0
  307. angr/analyses/identifier/func.py +60 -0
  308. angr/analyses/identifier/functions/__init__.py +37 -0
  309. angr/analyses/identifier/functions/atoi.py +73 -0
  310. angr/analyses/identifier/functions/based_atoi.py +125 -0
  311. angr/analyses/identifier/functions/fdprintf.py +123 -0
  312. angr/analyses/identifier/functions/free.py +64 -0
  313. angr/analyses/identifier/functions/int2str.py +287 -0
  314. angr/analyses/identifier/functions/malloc.py +111 -0
  315. angr/analyses/identifier/functions/memcmp.py +67 -0
  316. angr/analyses/identifier/functions/memcpy.py +89 -0
  317. angr/analyses/identifier/functions/memset.py +43 -0
  318. angr/analyses/identifier/functions/printf.py +123 -0
  319. angr/analyses/identifier/functions/recv_until.py +312 -0
  320. angr/analyses/identifier/functions/skip_calloc.py +73 -0
  321. angr/analyses/identifier/functions/skip_realloc.py +97 -0
  322. angr/analyses/identifier/functions/skip_recv_n.py +105 -0
  323. angr/analyses/identifier/functions/snprintf.py +112 -0
  324. angr/analyses/identifier/functions/sprintf.py +116 -0
  325. angr/analyses/identifier/functions/strcasecmp.py +33 -0
  326. angr/analyses/identifier/functions/strcmp.py +113 -0
  327. angr/analyses/identifier/functions/strcpy.py +43 -0
  328. angr/analyses/identifier/functions/strlen.py +27 -0
  329. angr/analyses/identifier/functions/strncmp.py +104 -0
  330. angr/analyses/identifier/functions/strncpy.py +65 -0
  331. angr/analyses/identifier/functions/strtol.py +89 -0
  332. angr/analyses/identifier/identify.py +825 -0
  333. angr/analyses/identifier/runner.py +360 -0
  334. angr/analyses/init_finder.py +289 -0
  335. angr/analyses/loop_analysis/__init__.py +4 -0
  336. angr/analyses/loop_analysis/loop_analysis.py +464 -0
  337. angr/analyses/loop_analysis.py +349 -0
  338. angr/analyses/loop_unroller/__init__.py +4 -0
  339. angr/analyses/loop_unroller/loop_unroller.py +222 -0
  340. angr/analyses/loopfinder.py +171 -0
  341. angr/analyses/outliner/__init__.py +7 -0
  342. angr/analyses/outliner/outliner.py +402 -0
  343. angr/analyses/patchfinder.py +137 -0
  344. angr/analyses/pathfinder.py +282 -0
  345. angr/analyses/propagator/__init__.py +5 -0
  346. angr/analyses/propagator/engine_base.py +62 -0
  347. angr/analyses/propagator/engine_vex.py +297 -0
  348. angr/analyses/propagator/propagator.py +361 -0
  349. angr/analyses/propagator/top_checker_mixin.py +218 -0
  350. angr/analyses/propagator/values.py +117 -0
  351. angr/analyses/propagator/vex_vars.py +68 -0
  352. angr/analyses/proximity_graph.py +444 -0
  353. angr/analyses/purity/__init__.py +15 -0
  354. angr/analyses/purity/analysis.py +78 -0
  355. angr/analyses/purity/engine.py +593 -0
  356. angr/analyses/reaching_definitions/__init__.py +67 -0
  357. angr/analyses/reaching_definitions/call_trace.py +73 -0
  358. angr/analyses/reaching_definitions/dep_graph.py +433 -0
  359. angr/analyses/reaching_definitions/engine_ail.py +1128 -0
  360. angr/analyses/reaching_definitions/engine_vex.py +1128 -0
  361. angr/analyses/reaching_definitions/external_codeloc.py +0 -0
  362. angr/analyses/reaching_definitions/function_handler.py +639 -0
  363. angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
  364. angr/analyses/reaching_definitions/function_handler_library/stdio.py +269 -0
  365. angr/analyses/reaching_definitions/function_handler_library/stdlib.py +195 -0
  366. angr/analyses/reaching_definitions/function_handler_library/string.py +158 -0
  367. angr/analyses/reaching_definitions/function_handler_library/unistd.py +51 -0
  368. angr/analyses/reaching_definitions/heap_allocator.py +70 -0
  369. angr/analyses/reaching_definitions/rd_initializer.py +237 -0
  370. angr/analyses/reaching_definitions/rd_state.py +579 -0
  371. angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
  372. angr/analyses/reaching_definitions/subject.py +65 -0
  373. angr/analyses/reassembler.py +2900 -0
  374. angr/analyses/s_liveness.py +254 -0
  375. angr/analyses/s_propagator.py +575 -0
  376. angr/analyses/s_reaching_definitions/__init__.py +12 -0
  377. angr/analyses/s_reaching_definitions/s_rda_model.py +145 -0
  378. angr/analyses/s_reaching_definitions/s_rda_view.py +344 -0
  379. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +230 -0
  380. angr/analyses/smc.py +160 -0
  381. angr/analyses/soot_class_hierarchy.py +273 -0
  382. angr/analyses/stack_pointer_tracker.py +954 -0
  383. angr/analyses/static_hooker.py +53 -0
  384. angr/analyses/typehoon/__init__.py +5 -0
  385. angr/analyses/typehoon/dfa.py +118 -0
  386. angr/analyses/typehoon/lifter.py +133 -0
  387. angr/analyses/typehoon/simple_solver.py +2009 -0
  388. angr/analyses/typehoon/translator.py +283 -0
  389. angr/analyses/typehoon/typeconsts.py +439 -0
  390. angr/analyses/typehoon/typehoon.py +338 -0
  391. angr/analyses/typehoon/typevars.py +633 -0
  392. angr/analyses/typehoon/variance.py +11 -0
  393. angr/analyses/unpacker/__init__.py +6 -0
  394. angr/analyses/unpacker/obfuscation_detector.py +103 -0
  395. angr/analyses/unpacker/packing_detector.py +138 -0
  396. angr/analyses/variable_recovery/__init__.py +9 -0
  397. angr/analyses/variable_recovery/annotations.py +58 -0
  398. angr/analyses/variable_recovery/engine_ail.py +978 -0
  399. angr/analyses/variable_recovery/engine_base.py +1256 -0
  400. angr/analyses/variable_recovery/engine_vex.py +594 -0
  401. angr/analyses/variable_recovery/irsb_scanner.py +143 -0
  402. angr/analyses/variable_recovery/variable_recovery.py +574 -0
  403. angr/analyses/variable_recovery/variable_recovery_base.py +489 -0
  404. angr/analyses/variable_recovery/variable_recovery_fast.py +669 -0
  405. angr/analyses/veritesting.py +626 -0
  406. angr/analyses/vfg.py +1898 -0
  407. angr/analyses/vsa_ddg.py +420 -0
  408. angr/analyses/vtable.py +92 -0
  409. angr/analyses/xrefs.py +286 -0
  410. angr/angrdb/__init__.py +14 -0
  411. angr/angrdb/db.py +215 -0
  412. angr/angrdb/models.py +184 -0
  413. angr/angrdb/serializers/__init__.py +10 -0
  414. angr/angrdb/serializers/cfg_model.py +41 -0
  415. angr/angrdb/serializers/comments.py +60 -0
  416. angr/angrdb/serializers/funcs.py +61 -0
  417. angr/angrdb/serializers/kb.py +111 -0
  418. angr/angrdb/serializers/labels.py +59 -0
  419. angr/angrdb/serializers/loader.py +165 -0
  420. angr/angrdb/serializers/structured_code.py +167 -0
  421. angr/angrdb/serializers/variables.py +58 -0
  422. angr/angrdb/serializers/xrefs.py +48 -0
  423. angr/annocfg.py +317 -0
  424. angr/blade.py +431 -0
  425. angr/block.py +509 -0
  426. angr/callable.py +176 -0
  427. angr/calling_conventions.py +2613 -0
  428. angr/code_location.py +249 -0
  429. angr/codenode.py +145 -0
  430. angr/concretization_strategies/__init__.py +32 -0
  431. angr/concretization_strategies/any.py +17 -0
  432. angr/concretization_strategies/any_named.py +35 -0
  433. angr/concretization_strategies/base.py +81 -0
  434. angr/concretization_strategies/controlled_data.py +58 -0
  435. angr/concretization_strategies/eval.py +19 -0
  436. angr/concretization_strategies/logging.py +35 -0
  437. angr/concretization_strategies/max.py +25 -0
  438. angr/concretization_strategies/nonzero.py +16 -0
  439. angr/concretization_strategies/nonzero_range.py +22 -0
  440. angr/concretization_strategies/norepeats.py +37 -0
  441. angr/concretization_strategies/norepeats_range.py +37 -0
  442. angr/concretization_strategies/range.py +19 -0
  443. angr/concretization_strategies/signed_add.py +31 -0
  444. angr/concretization_strategies/single.py +15 -0
  445. angr/concretization_strategies/solutions.py +20 -0
  446. angr/concretization_strategies/unlimited_range.py +17 -0
  447. angr/distributed/__init__.py +9 -0
  448. angr/distributed/server.py +197 -0
  449. angr/distributed/worker.py +185 -0
  450. angr/emulator.py +144 -0
  451. angr/engines/__init__.py +69 -0
  452. angr/engines/ail/__init__.py +16 -0
  453. angr/engines/ail/callstack.py +58 -0
  454. angr/engines/ail/engine_light.py +903 -0
  455. angr/engines/ail/engine_successors.py +24 -0
  456. angr/engines/ail/setup.py +57 -0
  457. angr/engines/concrete.py +66 -0
  458. angr/engines/engine.py +29 -0
  459. angr/engines/failure.py +27 -0
  460. angr/engines/hook.py +93 -0
  461. angr/engines/icicle.py +294 -0
  462. angr/engines/light/__init__.py +23 -0
  463. angr/engines/light/data.py +681 -0
  464. angr/engines/light/engine.py +1297 -0
  465. angr/engines/pcode/__init__.py +9 -0
  466. angr/engines/pcode/behavior.py +998 -0
  467. angr/engines/pcode/cc.py +148 -0
  468. angr/engines/pcode/emulate.py +440 -0
  469. angr/engines/pcode/engine.py +242 -0
  470. angr/engines/pcode/lifter.py +1428 -0
  471. angr/engines/procedure.py +70 -0
  472. angr/engines/soot/__init__.py +5 -0
  473. angr/engines/soot/engine.py +410 -0
  474. angr/engines/soot/exceptions.py +17 -0
  475. angr/engines/soot/expressions/__init__.py +87 -0
  476. angr/engines/soot/expressions/arrayref.py +22 -0
  477. angr/engines/soot/expressions/base.py +21 -0
  478. angr/engines/soot/expressions/binop.py +28 -0
  479. angr/engines/soot/expressions/cast.py +22 -0
  480. angr/engines/soot/expressions/condition.py +35 -0
  481. angr/engines/soot/expressions/constants.py +47 -0
  482. angr/engines/soot/expressions/instanceOf.py +15 -0
  483. angr/engines/soot/expressions/instancefieldref.py +8 -0
  484. angr/engines/soot/expressions/invoke.py +114 -0
  485. angr/engines/soot/expressions/length.py +8 -0
  486. angr/engines/soot/expressions/local.py +8 -0
  487. angr/engines/soot/expressions/new.py +16 -0
  488. angr/engines/soot/expressions/newArray.py +54 -0
  489. angr/engines/soot/expressions/newMultiArray.py +86 -0
  490. angr/engines/soot/expressions/paramref.py +8 -0
  491. angr/engines/soot/expressions/phi.py +30 -0
  492. angr/engines/soot/expressions/staticfieldref.py +8 -0
  493. angr/engines/soot/expressions/thisref.py +7 -0
  494. angr/engines/soot/expressions/unsupported.py +7 -0
  495. angr/engines/soot/field_dispatcher.py +46 -0
  496. angr/engines/soot/method_dispatcher.py +46 -0
  497. angr/engines/soot/statements/__init__.py +44 -0
  498. angr/engines/soot/statements/assign.py +30 -0
  499. angr/engines/soot/statements/base.py +79 -0
  500. angr/engines/soot/statements/goto.py +14 -0
  501. angr/engines/soot/statements/identity.py +15 -0
  502. angr/engines/soot/statements/if_.py +19 -0
  503. angr/engines/soot/statements/invoke.py +12 -0
  504. angr/engines/soot/statements/return_.py +20 -0
  505. angr/engines/soot/statements/switch.py +41 -0
  506. angr/engines/soot/statements/throw.py +15 -0
  507. angr/engines/soot/values/__init__.py +38 -0
  508. angr/engines/soot/values/arrayref.py +122 -0
  509. angr/engines/soot/values/base.py +7 -0
  510. angr/engines/soot/values/constants.py +18 -0
  511. angr/engines/soot/values/instancefieldref.py +44 -0
  512. angr/engines/soot/values/local.py +18 -0
  513. angr/engines/soot/values/paramref.py +18 -0
  514. angr/engines/soot/values/staticfieldref.py +38 -0
  515. angr/engines/soot/values/strref.py +38 -0
  516. angr/engines/soot/values/thisref.py +149 -0
  517. angr/engines/successors.py +608 -0
  518. angr/engines/syscall.py +51 -0
  519. angr/engines/unicorn.py +490 -0
  520. angr/engines/vex/__init__.py +20 -0
  521. angr/engines/vex/claripy/__init__.py +5 -0
  522. angr/engines/vex/claripy/ccall.py +2097 -0
  523. angr/engines/vex/claripy/datalayer.py +141 -0
  524. angr/engines/vex/claripy/irop.py +1276 -0
  525. angr/engines/vex/heavy/__init__.py +16 -0
  526. angr/engines/vex/heavy/actions.py +231 -0
  527. angr/engines/vex/heavy/concretizers.py +403 -0
  528. angr/engines/vex/heavy/dirty.py +466 -0
  529. angr/engines/vex/heavy/heavy.py +370 -0
  530. angr/engines/vex/heavy/inspect.py +52 -0
  531. angr/engines/vex/heavy/resilience.py +85 -0
  532. angr/engines/vex/heavy/super_fastpath.py +34 -0
  533. angr/engines/vex/lifter.py +420 -0
  534. angr/engines/vex/light/__init__.py +11 -0
  535. angr/engines/vex/light/light.py +551 -0
  536. angr/engines/vex/light/resilience.py +74 -0
  537. angr/engines/vex/light/slicing.py +52 -0
  538. angr/errors.py +611 -0
  539. angr/exploration_techniques/__init__.py +53 -0
  540. angr/exploration_techniques/base.py +126 -0
  541. angr/exploration_techniques/bucketizer.py +94 -0
  542. angr/exploration_techniques/common.py +56 -0
  543. angr/exploration_techniques/dfs.py +37 -0
  544. angr/exploration_techniques/director.py +520 -0
  545. angr/exploration_techniques/driller_core.py +100 -0
  546. angr/exploration_techniques/explorer.py +152 -0
  547. angr/exploration_techniques/lengthlimiter.py +22 -0
  548. angr/exploration_techniques/local_loop_seer.py +65 -0
  549. angr/exploration_techniques/loop_seer.py +236 -0
  550. angr/exploration_techniques/manual_mergepoint.py +82 -0
  551. angr/exploration_techniques/memory_watcher.py +43 -0
  552. angr/exploration_techniques/oppologist.py +92 -0
  553. angr/exploration_techniques/slicecutor.py +118 -0
  554. angr/exploration_techniques/spiller.py +280 -0
  555. angr/exploration_techniques/spiller_db.py +27 -0
  556. angr/exploration_techniques/stochastic.py +56 -0
  557. angr/exploration_techniques/stub_stasher.py +19 -0
  558. angr/exploration_techniques/suggestions.py +159 -0
  559. angr/exploration_techniques/tech_builder.py +49 -0
  560. angr/exploration_techniques/threading.py +69 -0
  561. angr/exploration_techniques/timeout.py +34 -0
  562. angr/exploration_techniques/tracer.py +1098 -0
  563. angr/exploration_techniques/unique.py +106 -0
  564. angr/exploration_techniques/veritesting.py +37 -0
  565. angr/factory.py +413 -0
  566. angr/flirt/__init__.py +124 -0
  567. angr/flirt/build_sig.py +305 -0
  568. angr/graph_utils.py +0 -0
  569. angr/keyed_region.py +525 -0
  570. angr/knowledge_base.py +146 -0
  571. angr/knowledge_plugins/__init__.py +43 -0
  572. angr/knowledge_plugins/callsite_prototypes.py +95 -0
  573. angr/knowledge_plugins/cfg/__init__.py +18 -0
  574. angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
  575. angr/knowledge_plugins/cfg/cfg_model.py +1043 -0
  576. angr/knowledge_plugins/cfg/cfg_node.py +536 -0
  577. angr/knowledge_plugins/cfg/indirect_jump.py +131 -0
  578. angr/knowledge_plugins/cfg/memory_data.py +156 -0
  579. angr/knowledge_plugins/comments.py +16 -0
  580. angr/knowledge_plugins/custom_strings.py +38 -0
  581. angr/knowledge_plugins/data.py +22 -0
  582. angr/knowledge_plugins/debug_variables.py +216 -0
  583. angr/knowledge_plugins/functions/__init__.py +9 -0
  584. angr/knowledge_plugins/functions/function.py +1830 -0
  585. angr/knowledge_plugins/functions/function_manager.py +621 -0
  586. angr/knowledge_plugins/functions/function_parser.py +360 -0
  587. angr/knowledge_plugins/functions/soot_function.py +128 -0
  588. angr/knowledge_plugins/indirect_jumps.py +35 -0
  589. angr/knowledge_plugins/key_definitions/__init__.py +17 -0
  590. angr/knowledge_plugins/key_definitions/atoms.py +374 -0
  591. angr/knowledge_plugins/key_definitions/constants.py +29 -0
  592. angr/knowledge_plugins/key_definitions/definition.py +216 -0
  593. angr/knowledge_plugins/key_definitions/environment.py +96 -0
  594. angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
  595. angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
  596. angr/knowledge_plugins/key_definitions/live_definitions.py +1020 -0
  597. angr/knowledge_plugins/key_definitions/liveness.py +165 -0
  598. angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
  599. angr/knowledge_plugins/key_definitions/tag.py +78 -0
  600. angr/knowledge_plugins/key_definitions/undefined.py +70 -0
  601. angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
  602. angr/knowledge_plugins/key_definitions/uses.py +178 -0
  603. angr/knowledge_plugins/labels.py +110 -0
  604. angr/knowledge_plugins/obfuscations.py +40 -0
  605. angr/knowledge_plugins/patches.py +126 -0
  606. angr/knowledge_plugins/plugin.py +24 -0
  607. angr/knowledge_plugins/propagations/__init__.py +10 -0
  608. angr/knowledge_plugins/propagations/prop_value.py +191 -0
  609. angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
  610. angr/knowledge_plugins/propagations/propagation_model.py +80 -0
  611. angr/knowledge_plugins/propagations/states.py +552 -0
  612. angr/knowledge_plugins/structured_code.py +63 -0
  613. angr/knowledge_plugins/types.py +95 -0
  614. angr/knowledge_plugins/variables/__init__.py +8 -0
  615. angr/knowledge_plugins/variables/variable_access.py +113 -0
  616. angr/knowledge_plugins/variables/variable_manager.py +1375 -0
  617. angr/knowledge_plugins/xrefs/__init__.py +12 -0
  618. angr/knowledge_plugins/xrefs/xref.py +150 -0
  619. angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
  620. angr/knowledge_plugins/xrefs/xref_types.py +16 -0
  621. angr/misc/__init__.py +19 -0
  622. angr/misc/ansi.py +47 -0
  623. angr/misc/autoimport.py +90 -0
  624. angr/misc/bug_report.py +126 -0
  625. angr/misc/hookset.py +106 -0
  626. angr/misc/loggers.py +130 -0
  627. angr/misc/picklable_lock.py +46 -0
  628. angr/misc/plugins.py +289 -0
  629. angr/misc/telemetry.py +54 -0
  630. angr/misc/testing.py +24 -0
  631. angr/misc/ux.py +31 -0
  632. angr/procedures/__init__.py +12 -0
  633. angr/procedures/advapi32/__init__.py +0 -0
  634. angr/procedures/cgc/__init__.py +3 -0
  635. angr/procedures/cgc/_terminate.py +11 -0
  636. angr/procedures/cgc/allocate.py +75 -0
  637. angr/procedures/cgc/deallocate.py +67 -0
  638. angr/procedures/cgc/fdwait.py +65 -0
  639. angr/procedures/cgc/random.py +67 -0
  640. angr/procedures/cgc/receive.py +93 -0
  641. angr/procedures/cgc/transmit.py +65 -0
  642. angr/procedures/definitions/__init__.py +1043 -0
  643. angr/procedures/definitions/cgc.py +23 -0
  644. angr/procedures/definitions/common/glibc.json +3516 -0
  645. angr/procedures/definitions/gnulib.py +41 -0
  646. angr/procedures/definitions/libstdcpp.py +25 -0
  647. angr/procedures/definitions/linux_kernel.py +8382 -0
  648. angr/procedures/definitions/linux_loader.py +7 -0
  649. angr/procedures/definitions/macho_libsystem.py +18 -0
  650. angr/procedures/definitions/msvcr.py +25 -0
  651. angr/procedures/definitions/parse_glibc.py +77 -0
  652. angr/procedures/definitions/parse_syscalls_from_local_system.py +54 -0
  653. angr/procedures/definitions/parse_win32json.py +2540 -0
  654. angr/procedures/definitions/types_stl.py +22 -0
  655. angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-4.json +24 -0
  656. angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-6.json +18 -0
  657. angr/procedures/definitions/wdk/clfs.json +189 -0
  658. angr/procedures/definitions/wdk/fltmgr.json +813 -0
  659. angr/procedures/definitions/wdk/fwpkclnt.json +24 -0
  660. angr/procedures/definitions/wdk/fwpuclnt.json +453 -0
  661. angr/procedures/definitions/wdk/gdi32.json +528 -0
  662. angr/procedures/definitions/wdk/hal.json +96 -0
  663. angr/procedures/definitions/wdk/ksecdd.json +72 -0
  664. angr/procedures/definitions/wdk/ndis.json +336 -0
  665. angr/procedures/definitions/wdk/ntoskrnl.json +5158 -0
  666. angr/procedures/definitions/wdk/offreg.json +87 -0
  667. angr/procedures/definitions/wdk/pshed.json +33 -0
  668. angr/procedures/definitions/wdk/secur32.json +39 -0
  669. angr/procedures/definitions/wdk/vhfum.json +30 -0
  670. angr/procedures/definitions/win32/_types_win32.json +34480 -0
  671. angr/procedures/definitions/win32/aclui.json +24 -0
  672. angr/procedures/definitions/win32/activeds.json +81 -0
  673. angr/procedures/definitions/win32/advapi32.json +2505 -0
  674. angr/procedures/definitions/win32/advpack.json +165 -0
  675. angr/procedures/definitions/win32/amsi.json +36 -0
  676. angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-1.json +45 -0
  677. angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-3.json +30 -0
  678. angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-6.json +18 -0
  679. angr/procedures/definitions/win32/api-ms-win-core-apiquery-l2-1-0.json +18 -0
  680. angr/procedures/definitions/win32/api-ms-win-core-backgroundtask-l1-1-0.json +18 -0
  681. angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-1.json +18 -0
  682. angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-2.json +18 -0
  683. angr/procedures/definitions/win32/api-ms-win-core-enclave-l1-1-1.json +24 -0
  684. angr/procedures/definitions/win32/api-ms-win-core-errorhandling-l1-1-3.json +18 -0
  685. angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-0.json +30 -0
  686. angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-1.json +18 -0
  687. angr/procedures/definitions/win32/api-ms-win-core-file-fromapp-l1-1-0.json +48 -0
  688. angr/procedures/definitions/win32/api-ms-win-core-handle-l1-1-0.json +18 -0
  689. angr/procedures/definitions/win32/api-ms-win-core-ioring-l1-1-0.json +51 -0
  690. angr/procedures/definitions/win32/api-ms-win-core-marshal-l1-1-0.json +27 -0
  691. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-3.json +27 -0
  692. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-4.json +18 -0
  693. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-5.json +24 -0
  694. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-6.json +27 -0
  695. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-7.json +21 -0
  696. angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-8.json +24 -0
  697. angr/procedures/definitions/win32/api-ms-win-core-path-l1-1-0.json +81 -0
  698. angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-0.json +21 -0
  699. angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-1.json +21 -0
  700. angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-1.json +24 -0
  701. angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-2.json +24 -0
  702. angr/procedures/definitions/win32/api-ms-win-core-slapi-l1-1-0.json +18 -0
  703. angr/procedures/definitions/win32/api-ms-win-core-state-helpers-l1-1-0.json +18 -0
  704. angr/procedures/definitions/win32/api-ms-win-core-synch-l1-2-0.json +24 -0
  705. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-0.json +18 -0
  706. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-3.json +21 -0
  707. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-4.json +21 -0
  708. angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-6.json +18 -0
  709. angr/procedures/definitions/win32/api-ms-win-core-util-l1-1-1.json +21 -0
  710. angr/procedures/definitions/win32/api-ms-win-core-wow64-l1-1-1.json +24 -0
  711. angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-0.json +42 -0
  712. angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-1.json +30 -0
  713. angr/procedures/definitions/win32/api-ms-win-dx-d3dkmt-l1-1-0.json +18 -0
  714. angr/procedures/definitions/win32/api-ms-win-gaming-deviceinformation-l1-1-0.json +18 -0
  715. angr/procedures/definitions/win32/api-ms-win-gaming-expandedresources-l1-1-0.json +24 -0
  716. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-0.json +36 -0
  717. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-1.json +21 -0
  718. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-2.json +36 -0
  719. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-3.json +21 -0
  720. angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-4.json +39 -0
  721. angr/procedures/definitions/win32/api-ms-win-mm-misc-l1-1-1.json +18 -0
  722. angr/procedures/definitions/win32/api-ms-win-net-isolation-l1-1-0.json +39 -0
  723. angr/procedures/definitions/win32/api-ms-win-security-base-l1-2-2.json +18 -0
  724. angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-0.json +18 -0
  725. angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-1.json +18 -0
  726. angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-3.json +18 -0
  727. angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-4.json +18 -0
  728. angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-5.json +21 -0
  729. angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-0.json +24 -0
  730. angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-1.json +33 -0
  731. angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-2.json +18 -0
  732. angr/procedures/definitions/win32/api-ms-win-wsl-api-l1-1-0.json +36 -0
  733. angr/procedures/definitions/win32/apphelp.json +18 -0
  734. angr/procedures/definitions/win32/authz.json +114 -0
  735. angr/procedures/definitions/win32/avicap32.json +27 -0
  736. angr/procedures/definitions/win32/avifil32.json +195 -0
  737. angr/procedures/definitions/win32/avrt.json +57 -0
  738. angr/procedures/definitions/win32/bcp47mrm.json +21 -0
  739. angr/procedures/definitions/win32/bcrypt.json +174 -0
  740. angr/procedures/definitions/win32/bcryptprimitives.json +21 -0
  741. angr/procedures/definitions/win32/bluetoothapis.json +138 -0
  742. angr/procedures/definitions/win32/bthprops_cpl.json +33 -0
  743. angr/procedures/definitions/win32/cabinet.json +81 -0
  744. angr/procedures/definitions/win32/certadm.json +69 -0
  745. angr/procedures/definitions/win32/certpoleng.json +39 -0
  746. angr/procedures/definitions/win32/cfgmgr32.json +732 -0
  747. angr/procedures/definitions/win32/chakra.json +270 -0
  748. angr/procedures/definitions/win32/cldapi.json +123 -0
  749. angr/procedures/definitions/win32/clfsw32.json +192 -0
  750. angr/procedures/definitions/win32/clusapi.json +855 -0
  751. angr/procedures/definitions/win32/comctl32.json +360 -0
  752. angr/procedures/definitions/win32/comdlg32.json +78 -0
  753. angr/procedures/definitions/win32/compstui.json +27 -0
  754. angr/procedures/definitions/win32/computecore.json +177 -0
  755. angr/procedures/definitions/win32/computenetwork.json +144 -0
  756. angr/procedures/definitions/win32/computestorage.json +51 -0
  757. angr/procedures/definitions/win32/comsvcs.json +36 -0
  758. angr/procedures/definitions/win32/credui.json +72 -0
  759. angr/procedures/definitions/win32/crypt32.json +702 -0
  760. angr/procedures/definitions/win32/cryptnet.json +30 -0
  761. angr/procedures/definitions/win32/cryptui.json +45 -0
  762. angr/procedures/definitions/win32/cryptxml.json +72 -0
  763. angr/procedures/definitions/win32/cscapi.json +27 -0
  764. angr/procedures/definitions/win32/d2d1.json +54 -0
  765. angr/procedures/definitions/win32/d3d10.json +96 -0
  766. angr/procedures/definitions/win32/d3d10_1.json +21 -0
  767. angr/procedures/definitions/win32/d3d11.json +24 -0
  768. angr/procedures/definitions/win32/d3d12.json +39 -0
  769. angr/procedures/definitions/win32/d3d9.json +48 -0
  770. angr/procedures/definitions/win32/d3dcompiler_47.json +93 -0
  771. angr/procedures/definitions/win32/d3dcsx.json +42 -0
  772. angr/procedures/definitions/win32/davclnt.json +69 -0
  773. angr/procedures/definitions/win32/dbgeng.json +27 -0
  774. angr/procedures/definitions/win32/dbghelp.json +663 -0
  775. angr/procedures/definitions/win32/dbgmodel.json +18 -0
  776. angr/procedures/definitions/win32/dciman32.json +75 -0
  777. angr/procedures/definitions/win32/dcomp.json +51 -0
  778. angr/procedures/definitions/win32/ddraw.json +36 -0
  779. angr/procedures/definitions/win32/deviceaccess.json +18 -0
  780. angr/procedures/definitions/win32/dflayout.json +18 -0
  781. angr/procedures/definitions/win32/dhcpcsvc.json +60 -0
  782. angr/procedures/definitions/win32/dhcpcsvc6.json +33 -0
  783. angr/procedures/definitions/win32/dhcpsapi.json +603 -0
  784. angr/procedures/definitions/win32/diagnosticdataquery.json +120 -0
  785. angr/procedures/definitions/win32/dinput8.json +18 -0
  786. angr/procedures/definitions/win32/directml.json +21 -0
  787. angr/procedures/definitions/win32/dmprocessxmlfiltered.json +18 -0
  788. angr/procedures/definitions/win32/dnsapi.json +207 -0
  789. angr/procedures/definitions/win32/drt.json +63 -0
  790. angr/procedures/definitions/win32/drtprov.json +42 -0
  791. angr/procedures/definitions/win32/drttransport.json +21 -0
  792. angr/procedures/definitions/win32/dsound.json +45 -0
  793. angr/procedures/definitions/win32/dsparse.json +72 -0
  794. angr/procedures/definitions/win32/dsprop.json +36 -0
  795. angr/procedures/definitions/win32/dssec.json +27 -0
  796. angr/procedures/definitions/win32/dsuiext.json +27 -0
  797. angr/procedures/definitions/win32/dwmapi.json +108 -0
  798. angr/procedures/definitions/win32/dwrite.json +18 -0
  799. angr/procedures/definitions/win32/dxcompiler.json +21 -0
  800. angr/procedures/definitions/win32/dxcore.json +18 -0
  801. angr/procedures/definitions/win32/dxgi.json +33 -0
  802. angr/procedures/definitions/win32/dxva2.json +129 -0
  803. angr/procedures/definitions/win32/eappcfg.json +57 -0
  804. angr/procedures/definitions/win32/eappprxy.json +69 -0
  805. angr/procedures/definitions/win32/efswrt.json +21 -0
  806. angr/procedures/definitions/win32/elscore.json +30 -0
  807. angr/procedures/definitions/win32/esent.json +702 -0
  808. angr/procedures/definitions/win32/evr.json +36 -0
  809. angr/procedures/definitions/win32/faultrep.json +27 -0
  810. angr/procedures/definitions/win32/fhsvcctl.json +36 -0
  811. angr/procedures/definitions/win32/firewallapi.json +24 -0
  812. angr/procedures/definitions/win32/fltlib.json +99 -0
  813. angr/procedures/definitions/win32/fontsub.json +21 -0
  814. angr/procedures/definitions/win32/forceinline.json +24 -0
  815. angr/procedures/definitions/win32/fwpuclnt.json +591 -0
  816. angr/procedures/definitions/win32/fxsutility.json +21 -0
  817. angr/procedures/definitions/win32/gdi32.json +1308 -0
  818. angr/procedures/definitions/win32/gdiplus.json +1902 -0
  819. angr/procedures/definitions/win32/glu32.json +171 -0
  820. angr/procedures/definitions/win32/gpedit.json +33 -0
  821. angr/procedures/definitions/win32/hhctrl_ocx.json +21 -0
  822. angr/procedures/definitions/win32/hid.json +150 -0
  823. angr/procedures/definitions/win32/hlink.json +99 -0
  824. angr/procedures/definitions/win32/hrtfapo.json +18 -0
  825. angr/procedures/definitions/win32/httpapi.json +144 -0
  826. angr/procedures/definitions/win32/icm32.json +78 -0
  827. angr/procedures/definitions/win32/icmui.json +21 -0
  828. angr/procedures/definitions/win32/icu.json +3090 -0
  829. angr/procedures/definitions/win32/ieframe.json +102 -0
  830. angr/procedures/definitions/win32/imagehlp.json +84 -0
  831. angr/procedures/definitions/win32/imgutil.json +42 -0
  832. angr/procedures/definitions/win32/imm32.json +261 -0
  833. angr/procedures/definitions/win32/infocardapi.json +66 -0
  834. angr/procedures/definitions/win32/inkobjcore.json +96 -0
  835. angr/procedures/definitions/win32/iphlpapi.json +618 -0
  836. angr/procedures/definitions/win32/iscsidsc.json +252 -0
  837. angr/procedures/definitions/win32/isolatedwindowsenvironmentutils.json +21 -0
  838. angr/procedures/definitions/win32/kernel32.json +4566 -0
  839. angr/procedures/definitions/win32/kernelbase.json +33 -0
  840. angr/procedures/definitions/win32/keycredmgr.json +27 -0
  841. angr/procedures/definitions/win32/ksproxy_ax.json +33 -0
  842. angr/procedures/definitions/win32/ksuser.json +39 -0
  843. angr/procedures/definitions/win32/ktmw32.json +132 -0
  844. angr/procedures/definitions/win32/licenseprotection.json +21 -0
  845. angr/procedures/definitions/win32/loadperf.json +51 -0
  846. angr/procedures/definitions/win32/magnification.json +72 -0
  847. angr/procedures/definitions/win32/mapi32.json +213 -0
  848. angr/procedures/definitions/win32/mdmlocalmanagement.json +24 -0
  849. angr/procedures/definitions/win32/mdmregistration.json +60 -0
  850. angr/procedures/definitions/win32/mf.json +201 -0
  851. angr/procedures/definitions/win32/mfcore.json +21 -0
  852. angr/procedures/definitions/win32/mfplat.json +450 -0
  853. angr/procedures/definitions/win32/mfplay.json +18 -0
  854. angr/procedures/definitions/win32/mfreadwrite.json +30 -0
  855. angr/procedures/definitions/win32/mfsensorgroup.json +45 -0
  856. angr/procedures/definitions/win32/mfsrcsnk.json +21 -0
  857. angr/procedures/definitions/win32/mgmtapi.json +42 -0
  858. angr/procedures/definitions/win32/mi.json +18 -0
  859. angr/procedures/definitions/win32/mmdevapi.json +18 -0
  860. angr/procedures/definitions/win32/mpr.json +156 -0
  861. angr/procedures/definitions/win32/mprapi.json +351 -0
  862. angr/procedures/definitions/win32/mqrt.json +117 -0
  863. angr/procedures/definitions/win32/mrmsupport.json +96 -0
  864. angr/procedures/definitions/win32/msacm32.json +141 -0
  865. angr/procedures/definitions/win32/msajapi.json +1656 -0
  866. angr/procedures/definitions/win32/mscms.json +252 -0
  867. angr/procedures/definitions/win32/mscoree.json +96 -0
  868. angr/procedures/definitions/win32/msctfmonitor.json +24 -0
  869. angr/procedures/definitions/win32/msdelta.json +63 -0
  870. angr/procedures/definitions/win32/msdmo.json +48 -0
  871. angr/procedures/definitions/win32/msdrm.json +267 -0
  872. angr/procedures/definitions/win32/msi.json +807 -0
  873. angr/procedures/definitions/win32/msimg32.json +24 -0
  874. angr/procedures/definitions/win32/mspatcha.json +63 -0
  875. angr/procedures/definitions/win32/mspatchc.json +42 -0
  876. angr/procedures/definitions/win32/msports.json +36 -0
  877. angr/procedures/definitions/win32/msrating.json +72 -0
  878. angr/procedures/definitions/win32/mssign32.json +45 -0
  879. angr/procedures/definitions/win32/mstask.json +21 -0
  880. angr/procedures/definitions/win32/msvfw32.json +144 -0
  881. angr/procedures/definitions/win32/mswsock.json +63 -0
  882. angr/procedures/definitions/win32/mtxdm.json +18 -0
  883. angr/procedures/definitions/win32/ncrypt.json +132 -0
  884. angr/procedures/definitions/win32/ndfapi.json +63 -0
  885. angr/procedures/definitions/win32/netapi32.json +633 -0
  886. angr/procedures/definitions/win32/netsh.json +39 -0
  887. angr/procedures/definitions/win32/netshell.json +21 -0
  888. angr/procedures/definitions/win32/newdev.json +48 -0
  889. angr/procedures/definitions/win32/ninput.json +105 -0
  890. angr/procedures/definitions/win32/normaliz.json +21 -0
  891. angr/procedures/definitions/win32/ntdll.json +234 -0
  892. angr/procedures/definitions/win32/ntdllk.json +18 -0
  893. angr/procedures/definitions/win32/ntdsapi.json +258 -0
  894. angr/procedures/definitions/win32/ntlanman.json +45 -0
  895. angr/procedures/definitions/win32/odbc32.json +477 -0
  896. angr/procedures/definitions/win32/odbcbcp.json +96 -0
  897. angr/procedures/definitions/win32/ole32.json +966 -0
  898. angr/procedures/definitions/win32/oleacc.json +66 -0
  899. angr/procedures/definitions/win32/oleaut32.json +1230 -0
  900. angr/procedures/definitions/win32/oledlg.json +84 -0
  901. angr/procedures/definitions/win32/ondemandconnroutehelper.json +30 -0
  902. angr/procedures/definitions/win32/opengl32.json +1080 -0
  903. angr/procedures/definitions/win32/opmxbox.json +24 -0
  904. angr/procedures/definitions/win32/p2p.json +339 -0
  905. angr/procedures/definitions/win32/p2pgraph.json +126 -0
  906. angr/procedures/definitions/win32/pdh.json +309 -0
  907. angr/procedures/definitions/win32/peerdist.json +99 -0
  908. angr/procedures/definitions/win32/powrprof.json +267 -0
  909. angr/procedures/definitions/win32/prntvpt.json +48 -0
  910. angr/procedures/definitions/win32/projectedfslib.json +72 -0
  911. angr/procedures/definitions/win32/propsys.json +669 -0
  912. angr/procedures/definitions/win32/psapi.json +96 -0
  913. angr/procedures/definitions/win32/quartz.json +21 -0
  914. angr/procedures/definitions/win32/query.json +27 -0
  915. angr/procedures/definitions/win32/qwave.json +48 -0
  916. angr/procedures/definitions/win32/rasapi32.json +267 -0
  917. angr/procedures/definitions/win32/rasdlg.json +33 -0
  918. angr/procedures/definitions/win32/resutils.json +375 -0
  919. angr/procedures/definitions/win32/rpcns4.json +198 -0
  920. angr/procedures/definitions/win32/rpcproxy.json +27 -0
  921. angr/procedures/definitions/win32/rpcrt4.json +1356 -0
  922. angr/procedures/definitions/win32/rstrtmgr.json +48 -0
  923. angr/procedures/definitions/win32/rtm.json +243 -0
  924. angr/procedures/definitions/win32/rtutils.json +138 -0
  925. angr/procedures/definitions/win32/rtworkq.json +114 -0
  926. angr/procedures/definitions/win32/sas.json +18 -0
  927. angr/procedures/definitions/win32/scarddlg.json +30 -0
  928. angr/procedures/definitions/win32/schannel.json +42 -0
  929. angr/procedures/definitions/win32/sechost.json +21 -0
  930. angr/procedures/definitions/win32/secur32.json +282 -0
  931. angr/procedures/definitions/win32/sensapi.json +24 -0
  932. angr/procedures/definitions/win32/sensorsutilsv2.json +135 -0
  933. angr/procedures/definitions/win32/setupapi.json +1017 -0
  934. angr/procedures/definitions/win32/sfc.json +33 -0
  935. angr/procedures/definitions/win32/shdocvw.json +24 -0
  936. angr/procedures/definitions/win32/shell32.json +747 -0
  937. angr/procedures/definitions/win32/shlwapi.json +1095 -0
  938. angr/procedures/definitions/win32/slc.json +111 -0
  939. angr/procedures/definitions/win32/slcext.json +27 -0
  940. angr/procedures/definitions/win32/slwga.json +18 -0
  941. angr/procedures/definitions/win32/snmpapi.json +93 -0
  942. angr/procedures/definitions/win32/spoolss.json +93 -0
  943. angr/procedures/definitions/win32/srclient.json +18 -0
  944. angr/procedures/definitions/win32/srpapi.json +48 -0
  945. angr/procedures/definitions/win32/sspicli.json +36 -0
  946. angr/procedures/definitions/win32/sti.json +18 -0
  947. angr/procedures/definitions/win32/t2embed.json +57 -0
  948. angr/procedures/definitions/win32/tapi32.json +762 -0
  949. angr/procedures/definitions/win32/tbs.json +57 -0
  950. angr/procedures/definitions/win32/tdh.json +96 -0
  951. angr/procedures/definitions/win32/tokenbinding.json +45 -0
  952. angr/procedures/definitions/win32/traffic.json +75 -0
  953. angr/procedures/definitions/win32/txfw32.json +42 -0
  954. angr/procedures/definitions/win32/ualapi.json +27 -0
  955. angr/procedures/definitions/win32/uiautomationcore.json +309 -0
  956. angr/procedures/definitions/win32/urlmon.json +246 -0
  957. angr/procedures/definitions/win32/user32.json +2298 -0
  958. angr/procedures/definitions/win32/userenv.json +147 -0
  959. angr/procedures/definitions/win32/usp10.json +135 -0
  960. angr/procedures/definitions/win32/uxtheme.json +246 -0
  961. angr/procedures/definitions/win32/verifier.json +18 -0
  962. angr/procedures/definitions/win32/version.json +57 -0
  963. angr/procedures/definitions/win32/vertdll.json +36 -0
  964. angr/procedures/definitions/win32/virtdisk.json +102 -0
  965. angr/procedures/definitions/win32/vmdevicehost.json +54 -0
  966. angr/procedures/definitions/win32/vmsavedstatedumpprovider.json +144 -0
  967. angr/procedures/definitions/win32/vssapi.json +18 -0
  968. angr/procedures/definitions/win32/wcmapi.json +30 -0
  969. angr/procedures/definitions/win32/wdsbp.json +36 -0
  970. angr/procedures/definitions/win32/wdsclientapi.json +126 -0
  971. angr/procedures/definitions/win32/wdsmc.json +33 -0
  972. angr/procedures/definitions/win32/wdspxe.json +108 -0
  973. angr/procedures/definitions/win32/wdstptc.json +54 -0
  974. angr/procedures/definitions/win32/webauthn.json +54 -0
  975. angr/procedures/definitions/win32/webservices.json +594 -0
  976. angr/procedures/definitions/win32/websocket.json +54 -0
  977. angr/procedures/definitions/win32/wecapi.json +60 -0
  978. angr/procedures/definitions/win32/wer.json +78 -0
  979. angr/procedures/definitions/win32/wevtapi.json +120 -0
  980. angr/procedures/definitions/win32/winbio.json +177 -0
  981. angr/procedures/definitions/win32/windows_ai_machinelearning.json +18 -0
  982. angr/procedures/definitions/win32/windows_media_mediacontrol.json +39 -0
  983. angr/procedures/definitions/win32/windows_networking.json +18 -0
  984. angr/procedures/definitions/win32/windows_ui_xaml.json +21 -0
  985. angr/procedures/definitions/win32/windowscodecs.json +42 -0
  986. angr/procedures/definitions/win32/winfax.json +183 -0
  987. angr/procedures/definitions/win32/winhttp.json +183 -0
  988. angr/procedures/definitions/win32/winhvemulation.json +27 -0
  989. angr/procedures/definitions/win32/winhvplatform.json +213 -0
  990. angr/procedures/definitions/win32/wininet.json +903 -0
  991. angr/procedures/definitions/win32/winml.json +18 -0
  992. angr/procedures/definitions/win32/winmm.json +543 -0
  993. angr/procedures/definitions/win32/winscard.json +225 -0
  994. angr/procedures/definitions/win32/winspool_drv.json +531 -0
  995. angr/procedures/definitions/win32/wintrust.json +195 -0
  996. angr/procedures/definitions/win32/winusb.json +117 -0
  997. angr/procedures/definitions/win32/wlanapi.json +195 -0
  998. angr/procedures/definitions/win32/wlanui.json +18 -0
  999. angr/procedures/definitions/win32/wldap32.json +744 -0
  1000. angr/procedures/definitions/win32/wldp.json +42 -0
  1001. angr/procedures/definitions/win32/wmvcore.json +48 -0
  1002. angr/procedures/definitions/win32/wnvapi.json +21 -0
  1003. angr/procedures/definitions/win32/wofutil.json +48 -0
  1004. angr/procedures/definitions/win32/ws2_32.json +495 -0
  1005. angr/procedures/definitions/win32/wscapi.json +33 -0
  1006. angr/procedures/definitions/win32/wsclient.json +24 -0
  1007. angr/procedures/definitions/win32/wsdapi.json +111 -0
  1008. angr/procedures/definitions/win32/wsmsvc.json +114 -0
  1009. angr/procedures/definitions/win32/wsnmp32.json +162 -0
  1010. angr/procedures/definitions/win32/wtsapi32.json +204 -0
  1011. angr/procedures/definitions/win32/xaudio2_8.json +27 -0
  1012. angr/procedures/definitions/win32/xinput1_4.json +36 -0
  1013. angr/procedures/definitions/win32/xmllite.json +33 -0
  1014. angr/procedures/definitions/win32/xolehlp.json +27 -0
  1015. angr/procedures/definitions/win32/xpsprint.json +21 -0
  1016. angr/procedures/glibc/__ctype_b_loc.py +21 -0
  1017. angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
  1018. angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
  1019. angr/procedures/glibc/__errno_location.py +7 -0
  1020. angr/procedures/glibc/__init__.py +3 -0
  1021. angr/procedures/glibc/__libc_init.py +37 -0
  1022. angr/procedures/glibc/__libc_start_main.py +301 -0
  1023. angr/procedures/glibc/dynamic_loading.py +20 -0
  1024. angr/procedures/glibc/scanf.py +19 -0
  1025. angr/procedures/glibc/sscanf.py +10 -0
  1026. angr/procedures/gnulib/__init__.py +3 -0
  1027. angr/procedures/gnulib/xalloc_die.py +14 -0
  1028. angr/procedures/gnulib/xstrtol_fatal.py +14 -0
  1029. angr/procedures/java/__init__.py +42 -0
  1030. angr/procedures/java/unconstrained.py +65 -0
  1031. angr/procedures/java_io/__init__.py +0 -0
  1032. angr/procedures/java_io/read.py +12 -0
  1033. angr/procedures/java_io/write.py +17 -0
  1034. angr/procedures/java_jni/__init__.py +482 -0
  1035. angr/procedures/java_jni/array_operations.py +312 -0
  1036. angr/procedures/java_jni/class_and_interface_operations.py +31 -0
  1037. angr/procedures/java_jni/field_access.py +173 -0
  1038. angr/procedures/java_jni/global_and_local_refs.py +57 -0
  1039. angr/procedures/java_jni/method_calls.py +365 -0
  1040. angr/procedures/java_jni/not_implemented.py +26 -0
  1041. angr/procedures/java_jni/object_operations.py +94 -0
  1042. angr/procedures/java_jni/string_operations.py +87 -0
  1043. angr/procedures/java_jni/version_information.py +12 -0
  1044. angr/procedures/java_lang/__init__.py +0 -0
  1045. angr/procedures/java_lang/character.py +30 -0
  1046. angr/procedures/java_lang/double.py +24 -0
  1047. angr/procedures/java_lang/exit.py +13 -0
  1048. angr/procedures/java_lang/getsimplename.py +18 -0
  1049. angr/procedures/java_lang/integer.py +43 -0
  1050. angr/procedures/java_lang/load_library.py +9 -0
  1051. angr/procedures/java_lang/math.py +15 -0
  1052. angr/procedures/java_lang/string.py +78 -0
  1053. angr/procedures/java_lang/stringbuilder.py +44 -0
  1054. angr/procedures/java_lang/system.py +18 -0
  1055. angr/procedures/java_util/__init__.py +0 -0
  1056. angr/procedures/java_util/collection.py +35 -0
  1057. angr/procedures/java_util/iterator.py +46 -0
  1058. angr/procedures/java_util/list.py +99 -0
  1059. angr/procedures/java_util/map.py +131 -0
  1060. angr/procedures/java_util/random.py +14 -0
  1061. angr/procedures/java_util/scanner_nextline.py +23 -0
  1062. angr/procedures/libc/__init__.py +3 -0
  1063. angr/procedures/libc/abort.py +9 -0
  1064. angr/procedures/libc/access.py +13 -0
  1065. angr/procedures/libc/atoi.py +14 -0
  1066. angr/procedures/libc/atol.py +13 -0
  1067. angr/procedures/libc/calloc.py +8 -0
  1068. angr/procedures/libc/closelog.py +10 -0
  1069. angr/procedures/libc/err.py +14 -0
  1070. angr/procedures/libc/error.py +54 -0
  1071. angr/procedures/libc/exit.py +11 -0
  1072. angr/procedures/libc/fclose.py +19 -0
  1073. angr/procedures/libc/feof.py +21 -0
  1074. angr/procedures/libc/fflush.py +16 -0
  1075. angr/procedures/libc/fgetc.py +27 -0
  1076. angr/procedures/libc/fgets.py +69 -0
  1077. angr/procedures/libc/fopen.py +63 -0
  1078. angr/procedures/libc/fprintf.py +25 -0
  1079. angr/procedures/libc/fputc.py +23 -0
  1080. angr/procedures/libc/fputs.py +24 -0
  1081. angr/procedures/libc/fread.py +24 -0
  1082. angr/procedures/libc/free.py +9 -0
  1083. angr/procedures/libc/fscanf.py +20 -0
  1084. angr/procedures/libc/fseek.py +34 -0
  1085. angr/procedures/libc/ftell.py +22 -0
  1086. angr/procedures/libc/fwrite.py +19 -0
  1087. angr/procedures/libc/getchar.py +13 -0
  1088. angr/procedures/libc/getdelim.py +99 -0
  1089. angr/procedures/libc/getegid.py +8 -0
  1090. angr/procedures/libc/geteuid.py +8 -0
  1091. angr/procedures/libc/getgid.py +8 -0
  1092. angr/procedures/libc/gets.py +68 -0
  1093. angr/procedures/libc/getuid.py +8 -0
  1094. angr/procedures/libc/malloc.py +12 -0
  1095. angr/procedures/libc/memcmp.py +69 -0
  1096. angr/procedures/libc/memcpy.py +45 -0
  1097. angr/procedures/libc/memset.py +72 -0
  1098. angr/procedures/libc/openlog.py +10 -0
  1099. angr/procedures/libc/perror.py +13 -0
  1100. angr/procedures/libc/printf.py +34 -0
  1101. angr/procedures/libc/putchar.py +13 -0
  1102. angr/procedures/libc/puts.py +19 -0
  1103. angr/procedures/libc/rand.py +8 -0
  1104. angr/procedures/libc/realloc.py +8 -0
  1105. angr/procedures/libc/rewind.py +12 -0
  1106. angr/procedures/libc/scanf.py +20 -0
  1107. angr/procedures/libc/setbuf.py +9 -0
  1108. angr/procedures/libc/setvbuf.py +7 -0
  1109. angr/procedures/libc/snprintf.py +36 -0
  1110. angr/procedures/libc/sprintf.py +25 -0
  1111. angr/procedures/libc/srand.py +7 -0
  1112. angr/procedures/libc/sscanf.py +13 -0
  1113. angr/procedures/libc/stpcpy.py +18 -0
  1114. angr/procedures/libc/strcat.py +14 -0
  1115. angr/procedures/libc/strchr.py +48 -0
  1116. angr/procedures/libc/strcmp.py +31 -0
  1117. angr/procedures/libc/strcpy.py +13 -0
  1118. angr/procedures/libc/strlen.py +114 -0
  1119. angr/procedures/libc/strncat.py +19 -0
  1120. angr/procedures/libc/strncmp.py +183 -0
  1121. angr/procedures/libc/strncpy.py +22 -0
  1122. angr/procedures/libc/strnlen.py +13 -0
  1123. angr/procedures/libc/strstr.py +101 -0
  1124. angr/procedures/libc/strtol.py +261 -0
  1125. angr/procedures/libc/strtoul.py +9 -0
  1126. angr/procedures/libc/system.py +13 -0
  1127. angr/procedures/libc/time.py +9 -0
  1128. angr/procedures/libc/tmpnam.py +20 -0
  1129. angr/procedures/libc/tolower.py +10 -0
  1130. angr/procedures/libc/toupper.py +10 -0
  1131. angr/procedures/libc/ungetc.py +20 -0
  1132. angr/procedures/libc/vsnprintf.py +17 -0
  1133. angr/procedures/libc/wchar.py +16 -0
  1134. angr/procedures/libstdcpp/__init__.py +0 -0
  1135. angr/procedures/libstdcpp/_unwind_resume.py +11 -0
  1136. angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
  1137. angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
  1138. angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
  1139. angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
  1140. angr/procedures/libstdcpp/std__terminate.py +13 -0
  1141. angr/procedures/linux_kernel/__init__.py +3 -0
  1142. angr/procedures/linux_kernel/access.py +18 -0
  1143. angr/procedures/linux_kernel/arch_prctl.py +34 -0
  1144. angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
  1145. angr/procedures/linux_kernel/brk.py +18 -0
  1146. angr/procedures/linux_kernel/cwd.py +28 -0
  1147. angr/procedures/linux_kernel/fstat.py +138 -0
  1148. angr/procedures/linux_kernel/fstat64.py +170 -0
  1149. angr/procedures/linux_kernel/futex.py +17 -0
  1150. angr/procedures/linux_kernel/getegid.py +17 -0
  1151. angr/procedures/linux_kernel/geteuid.py +17 -0
  1152. angr/procedures/linux_kernel/getgid.py +17 -0
  1153. angr/procedures/linux_kernel/getpid.py +14 -0
  1154. angr/procedures/linux_kernel/getrlimit.py +24 -0
  1155. angr/procedures/linux_kernel/gettid.py +9 -0
  1156. angr/procedures/linux_kernel/getuid.py +17 -0
  1157. angr/procedures/linux_kernel/iovec.py +47 -0
  1158. angr/procedures/linux_kernel/lseek.py +42 -0
  1159. angr/procedures/linux_kernel/mmap.py +16 -0
  1160. angr/procedures/linux_kernel/mprotect.py +42 -0
  1161. angr/procedures/linux_kernel/munmap.py +8 -0
  1162. angr/procedures/linux_kernel/openat.py +26 -0
  1163. angr/procedures/linux_kernel/set_tid_address.py +8 -0
  1164. angr/procedures/linux_kernel/sigaction.py +19 -0
  1165. angr/procedures/linux_kernel/sigprocmask.py +23 -0
  1166. angr/procedures/linux_kernel/stat.py +23 -0
  1167. angr/procedures/linux_kernel/sysinfo.py +59 -0
  1168. angr/procedures/linux_kernel/tgkill.py +10 -0
  1169. angr/procedures/linux_kernel/time.py +34 -0
  1170. angr/procedures/linux_kernel/uid.py +30 -0
  1171. angr/procedures/linux_kernel/uname.py +29 -0
  1172. angr/procedures/linux_kernel/unlink.py +22 -0
  1173. angr/procedures/linux_kernel/vsyscall.py +16 -0
  1174. angr/procedures/linux_loader/__init__.py +3 -0
  1175. angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
  1176. angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
  1177. angr/procedures/linux_loader/sim_loader.py +54 -0
  1178. angr/procedures/linux_loader/tls.py +40 -0
  1179. angr/procedures/msvcr/__getmainargs.py +16 -0
  1180. angr/procedures/msvcr/__init__.py +4 -0
  1181. angr/procedures/msvcr/_initterm.py +38 -0
  1182. angr/procedures/msvcr/fmode.py +31 -0
  1183. angr/procedures/ntdll/__init__.py +0 -0
  1184. angr/procedures/ntdll/exceptions.py +60 -0
  1185. angr/procedures/posix/__init__.py +3 -0
  1186. angr/procedures/posix/accept.py +29 -0
  1187. angr/procedures/posix/bind.py +13 -0
  1188. angr/procedures/posix/bzero.py +9 -0
  1189. angr/procedures/posix/chroot.py +27 -0
  1190. angr/procedures/posix/close.py +9 -0
  1191. angr/procedures/posix/closedir.py +7 -0
  1192. angr/procedures/posix/dup.py +56 -0
  1193. angr/procedures/posix/fcntl.py +10 -0
  1194. angr/procedures/posix/fdopen.py +76 -0
  1195. angr/procedures/posix/fileno.py +18 -0
  1196. angr/procedures/posix/fork.py +13 -0
  1197. angr/procedures/posix/getenv.py +35 -0
  1198. angr/procedures/posix/gethostbyname.py +43 -0
  1199. angr/procedures/posix/getpass.py +19 -0
  1200. angr/procedures/posix/getsockopt.py +11 -0
  1201. angr/procedures/posix/htonl.py +11 -0
  1202. angr/procedures/posix/htons.py +11 -0
  1203. angr/procedures/posix/inet_ntoa.py +59 -0
  1204. angr/procedures/posix/listen.py +13 -0
  1205. angr/procedures/posix/mmap.py +144 -0
  1206. angr/procedures/posix/open.py +18 -0
  1207. angr/procedures/posix/opendir.py +10 -0
  1208. angr/procedures/posix/poll.py +55 -0
  1209. angr/procedures/posix/pread64.py +46 -0
  1210. angr/procedures/posix/pthread.py +87 -0
  1211. angr/procedures/posix/pwrite64.py +46 -0
  1212. angr/procedures/posix/read.py +13 -0
  1213. angr/procedures/posix/readdir.py +62 -0
  1214. angr/procedures/posix/recv.py +13 -0
  1215. angr/procedures/posix/recvfrom.py +13 -0
  1216. angr/procedures/posix/select.py +48 -0
  1217. angr/procedures/posix/send.py +23 -0
  1218. angr/procedures/posix/setsockopt.py +9 -0
  1219. angr/procedures/posix/sigaction.py +23 -0
  1220. angr/procedures/posix/sim_time.py +48 -0
  1221. angr/procedures/posix/sleep.py +8 -0
  1222. angr/procedures/posix/socket.py +18 -0
  1223. angr/procedures/posix/strcasecmp.py +26 -0
  1224. angr/procedures/posix/strdup.py +18 -0
  1225. angr/procedures/posix/strtok_r.py +64 -0
  1226. angr/procedures/posix/syslog.py +15 -0
  1227. angr/procedures/posix/tz.py +9 -0
  1228. angr/procedures/posix/unlink.py +11 -0
  1229. angr/procedures/posix/usleep.py +8 -0
  1230. angr/procedures/posix/write.py +13 -0
  1231. angr/procedures/procedure_dict.py +50 -0
  1232. angr/procedures/stubs/CallReturn.py +13 -0
  1233. angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
  1234. angr/procedures/stubs/Nop.py +7 -0
  1235. angr/procedures/stubs/PathTerminator.py +9 -0
  1236. angr/procedures/stubs/Redirect.py +18 -0
  1237. angr/procedures/stubs/ReturnChar.py +11 -0
  1238. angr/procedures/stubs/ReturnUnconstrained.py +24 -0
  1239. angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
  1240. angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
  1241. angr/procedures/stubs/UserHook.py +18 -0
  1242. angr/procedures/stubs/__init__.py +3 -0
  1243. angr/procedures/stubs/b64_decode.py +15 -0
  1244. angr/procedures/stubs/caller.py +14 -0
  1245. angr/procedures/stubs/crazy_scanf.py +20 -0
  1246. angr/procedures/stubs/format_parser.py +669 -0
  1247. angr/procedures/stubs/syscall_stub.py +24 -0
  1248. angr/procedures/testing/__init__.py +3 -0
  1249. angr/procedures/testing/manyargs.py +9 -0
  1250. angr/procedures/testing/retreg.py +8 -0
  1251. angr/procedures/tracer/__init__.py +4 -0
  1252. angr/procedures/tracer/random.py +9 -0
  1253. angr/procedures/tracer/receive.py +23 -0
  1254. angr/procedures/tracer/transmit.py +26 -0
  1255. angr/procedures/uclibc/__init__.py +3 -0
  1256. angr/procedures/uclibc/__uClibc_main.py +10 -0
  1257. angr/procedures/win32/EncodePointer.py +7 -0
  1258. angr/procedures/win32/ExitProcess.py +9 -0
  1259. angr/procedures/win32/GetCommandLine.py +12 -0
  1260. angr/procedures/win32/GetCurrentProcessId.py +7 -0
  1261. angr/procedures/win32/GetCurrentThreadId.py +7 -0
  1262. angr/procedures/win32/GetLastInputInfo.py +40 -0
  1263. angr/procedures/win32/GetModuleHandle.py +29 -0
  1264. angr/procedures/win32/GetProcessAffinityMask.py +37 -0
  1265. angr/procedures/win32/InterlockedExchange.py +15 -0
  1266. angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
  1267. angr/procedures/win32/VirtualAlloc.py +114 -0
  1268. angr/procedures/win32/VirtualProtect.py +60 -0
  1269. angr/procedures/win32/__init__.py +3 -0
  1270. angr/procedures/win32/critical_section.py +12 -0
  1271. angr/procedures/win32/dynamic_loading.py +104 -0
  1272. angr/procedures/win32/file_handles.py +47 -0
  1273. angr/procedures/win32/gethostbyname.py +12 -0
  1274. angr/procedures/win32/heap.py +45 -0
  1275. angr/procedures/win32/is_bad_ptr.py +26 -0
  1276. angr/procedures/win32/local_storage.py +88 -0
  1277. angr/procedures/win32/mutex.py +11 -0
  1278. angr/procedures/win32/sim_time.py +135 -0
  1279. angr/procedures/win32/system_paths.py +35 -0
  1280. angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
  1281. angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
  1282. angr/procedures/win32_kernel/__fastfail.py +15 -0
  1283. angr/procedures/win32_kernel/__init__.py +3 -0
  1284. angr/procedures/win_user32/__init__.py +0 -0
  1285. angr/procedures/win_user32/chars.py +15 -0
  1286. angr/procedures/win_user32/keyboard.py +14 -0
  1287. angr/procedures/win_user32/messagebox.py +49 -0
  1288. angr/project.py +860 -0
  1289. angr/protos/__init__.py +19 -0
  1290. angr/protos/cfg_pb2.py +42 -0
  1291. angr/protos/function_pb2.py +38 -0
  1292. angr/protos/primitives_pb2.py +59 -0
  1293. angr/protos/variables_pb2.py +55 -0
  1294. angr/protos/xrefs_pb2.py +36 -0
  1295. angr/py.typed +1 -0
  1296. angr/rustylib.cpython-311-darwin.so +0 -0
  1297. angr/serializable.py +66 -0
  1298. angr/sim_manager.py +971 -0
  1299. angr/sim_options.py +436 -0
  1300. angr/sim_procedure.py +626 -0
  1301. angr/sim_state.py +926 -0
  1302. angr/sim_state_options.py +403 -0
  1303. angr/sim_type.py +4026 -0
  1304. angr/sim_variable.py +470 -0
  1305. angr/simos/__init__.py +47 -0
  1306. angr/simos/cgc.py +153 -0
  1307. angr/simos/javavm.py +458 -0
  1308. angr/simos/linux.py +509 -0
  1309. angr/simos/simos.py +444 -0
  1310. angr/simos/snimmuc_nxp.py +149 -0
  1311. angr/simos/userland.py +163 -0
  1312. angr/simos/windows.py +615 -0
  1313. angr/simos/xbox.py +32 -0
  1314. angr/slicer.py +352 -0
  1315. angr/state_hierarchy.py +262 -0
  1316. angr/state_plugins/__init__.py +84 -0
  1317. angr/state_plugins/callstack.py +478 -0
  1318. angr/state_plugins/cgc.py +155 -0
  1319. angr/state_plugins/debug_variables.py +192 -0
  1320. angr/state_plugins/filesystem.py +463 -0
  1321. angr/state_plugins/gdb.py +148 -0
  1322. angr/state_plugins/globals.py +65 -0
  1323. angr/state_plugins/heap/__init__.py +15 -0
  1324. angr/state_plugins/heap/heap_base.py +128 -0
  1325. angr/state_plugins/heap/heap_brk.py +136 -0
  1326. angr/state_plugins/heap/heap_freelist.py +213 -0
  1327. angr/state_plugins/heap/heap_libc.py +46 -0
  1328. angr/state_plugins/heap/heap_ptmalloc.py +620 -0
  1329. angr/state_plugins/heap/utils.py +22 -0
  1330. angr/state_plugins/history.py +564 -0
  1331. angr/state_plugins/inspect.py +375 -0
  1332. angr/state_plugins/javavm_classloader.py +134 -0
  1333. angr/state_plugins/jni_references.py +95 -0
  1334. angr/state_plugins/libc.py +1263 -0
  1335. angr/state_plugins/light_registers.py +168 -0
  1336. angr/state_plugins/log.py +84 -0
  1337. angr/state_plugins/loop_data.py +92 -0
  1338. angr/state_plugins/plugin.py +176 -0
  1339. angr/state_plugins/posix.py +703 -0
  1340. angr/state_plugins/preconstrainer.py +196 -0
  1341. angr/state_plugins/scratch.py +173 -0
  1342. angr/state_plugins/sim_action.py +326 -0
  1343. angr/state_plugins/sim_action_object.py +271 -0
  1344. angr/state_plugins/sim_event.py +59 -0
  1345. angr/state_plugins/solver.py +1128 -0
  1346. angr/state_plugins/symbolizer.py +291 -0
  1347. angr/state_plugins/trace_additions.py +738 -0
  1348. angr/state_plugins/uc_manager.py +94 -0
  1349. angr/state_plugins/unicorn_engine.py +1920 -0
  1350. angr/state_plugins/view.py +340 -0
  1351. angr/storage/__init__.py +15 -0
  1352. angr/storage/file.py +1210 -0
  1353. angr/storage/memory_mixins/__init__.py +317 -0
  1354. angr/storage/memory_mixins/actions_mixin.py +72 -0
  1355. angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
  1356. angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
  1357. angr/storage/memory_mixins/clouseau_mixin.py +137 -0
  1358. angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
  1359. angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
  1360. angr/storage/memory_mixins/default_filler_mixin.py +144 -0
  1361. angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
  1362. angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
  1363. angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
  1364. angr/storage/memory_mixins/keyvalue_memory_mixin.py +43 -0
  1365. angr/storage/memory_mixins/label_merger_mixin.py +31 -0
  1366. angr/storage/memory_mixins/memory_mixin.py +175 -0
  1367. angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
  1368. angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
  1369. angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
  1370. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
  1371. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
  1372. angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
  1373. angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
  1374. angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
  1375. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
  1376. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
  1377. angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
  1378. angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
  1379. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
  1380. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
  1381. angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
  1382. angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
  1383. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +529 -0
  1384. angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
  1385. angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
  1386. angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
  1387. angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
  1388. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
  1389. angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
  1390. angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
  1391. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
  1392. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
  1393. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +442 -0
  1394. angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
  1395. angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
  1396. angr/storage/memory_mixins/simplification_mixin.py +15 -0
  1397. angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
  1398. angr/storage/memory_mixins/slotted_memory.py +140 -0
  1399. angr/storage/memory_mixins/smart_find_mixin.py +161 -0
  1400. angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
  1401. angr/storage/memory_mixins/top_merger_mixin.py +25 -0
  1402. angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
  1403. angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
  1404. angr/storage/memory_object.py +195 -0
  1405. angr/tablespecs.py +91 -0
  1406. angr/unicornlib.dylib +0 -0
  1407. angr/utils/__init__.py +46 -0
  1408. angr/utils/ail.py +176 -0
  1409. angr/utils/algo.py +34 -0
  1410. angr/utils/balancer.py +776 -0
  1411. angr/utils/bits.py +46 -0
  1412. angr/utils/constants.py +9 -0
  1413. angr/utils/cowdict.py +63 -0
  1414. angr/utils/cpp.py +17 -0
  1415. angr/utils/doms.py +150 -0
  1416. angr/utils/dynamic_dictlist.py +89 -0
  1417. angr/utils/endness.py +18 -0
  1418. angr/utils/enums_conv.py +97 -0
  1419. angr/utils/env.py +12 -0
  1420. angr/utils/formatting.py +128 -0
  1421. angr/utils/funcid.py +244 -0
  1422. angr/utils/graph.py +981 -0
  1423. angr/utils/lazy_import.py +13 -0
  1424. angr/utils/library.py +236 -0
  1425. angr/utils/loader.py +55 -0
  1426. angr/utils/mp.py +66 -0
  1427. angr/utils/orderedset.py +74 -0
  1428. angr/utils/ssa/__init__.py +455 -0
  1429. angr/utils/ssa/tmp_uses_collector.py +23 -0
  1430. angr/utils/ssa/vvar_uses_collector.py +36 -0
  1431. angr/utils/strings.py +20 -0
  1432. angr/utils/tagged_interval_map.py +112 -0
  1433. angr/utils/timing.py +74 -0
  1434. angr/utils/types.py +193 -0
  1435. angr/utils/vex.py +11 -0
  1436. angr/vaults.py +367 -0
  1437. angr-9.2.192.dist-info/METADATA +112 -0
  1438. angr-9.2.192.dist-info/RECORD +1442 -0
  1439. angr-9.2.192.dist-info/WHEEL +6 -0
  1440. angr-9.2.192.dist-info/entry_points.txt +2 -0
  1441. angr-9.2.192.dist-info/licenses/LICENSE +27 -0
  1442. angr-9.2.192.dist-info/top_level.txt +1 -0
@@ -0,0 +1,3451 @@
1
+ from __future__ import annotations
2
+ from typing import TYPE_CHECKING
3
+ import itertools
4
+ import logging
5
+ import sys
6
+ from collections import defaultdict
7
+ from functools import reduce
8
+ import contextlib
9
+
10
+ import angr
11
+ import claripy
12
+ import networkx
13
+ import pyvex
14
+ from archinfo import ArchARM
15
+
16
+ from angr.analyses import ForwardAnalysis
17
+ from angr.utils.graph import GraphUtils
18
+ from angr.analyses import AnalysesHub
19
+ from angr import BP, BP_BEFORE, BP_AFTER, SIM_PROCEDURES, procedures
20
+ from angr import options as o
21
+ from angr.codenode import BlockNode
22
+ from angr.engines.procedure import ProcedureEngine
23
+ from angr.exploration_techniques.loop_seer import LoopSeer
24
+ from angr.exploration_techniques.slicecutor import Slicecutor
25
+ from angr.exploration_techniques.explorer import Explorer
26
+ from angr.exploration_techniques.lengthlimiter import LengthLimiter
27
+ from angr.errors import (
28
+ AngrCFGError,
29
+ AngrError,
30
+ AngrSkipJobNotice,
31
+ AngrSyscallError,
32
+ SimError,
33
+ SimValueError,
34
+ SimSolverModeError,
35
+ SimFastPathError,
36
+ SimIRSBError,
37
+ AngrExitError,
38
+ SimEmptyCallStackError,
39
+ )
40
+ from angr.sim_state import SimState
41
+ from angr.state_plugins.callstack import CallStack
42
+ from angr.state_plugins.sim_action import SimActionData
43
+ from angr.knowledge_plugins.cfg import CFGENode, IndirectJump
44
+ from angr.utils.constants import DEFAULT_STATEMENT
45
+ from angr.analyses.cdg import CDG
46
+ from angr.analyses.ddg import DDG
47
+ from angr.analyses.backward_slice import BackwardSlice
48
+ from angr.analyses.loopfinder import LoopFinder, Loop
49
+ from .cfg_base import CFGBase
50
+ from .cfg_job_base import BlockID, CFGJobBase
51
+
52
+ if TYPE_CHECKING:
53
+ from angr.knowledge_plugins.cfg import CFGNode
54
+
55
+
56
+ l = logging.getLogger(name=__name__)
57
+
58
+
59
+ class CFGJob(CFGJobBase):
60
+ """
61
+ The job class that CFGEmulated uses.
62
+ """
63
+
64
+ def __init__(self, *args, **kwargs):
65
+ super().__init__(*args, **kwargs)
66
+
67
+ #
68
+ # local variables used during analysis
69
+ #
70
+
71
+ if self.jumpkind is None:
72
+ # load jumpkind from path.state.scratch
73
+ self.jumpkind = "Ijk_Boring" if self.state.history.jumpkind is None else self.state.history.jumpkind
74
+
75
+ self.call_stack_suffix = None
76
+ self.current_function = None
77
+
78
+ self.cfg_node = None
79
+ self.sim_successors = None
80
+ self.exception_info = None
81
+ self.successor_status = None
82
+
83
+ self.extra_info = None
84
+
85
+ @property
86
+ def block_id(self):
87
+ if self._block_id is None:
88
+ # generate a new block ID
89
+ self._block_id = CFGEmulated._generate_block_id(
90
+ self.call_stack.stack_suffix(self._context_sensitivity_level), self.addr, self.is_syscall
91
+ )
92
+ return self._block_id
93
+
94
+ @property
95
+ def is_syscall(self):
96
+ return self.jumpkind is not None and self.jumpkind.startswith("Ijk_Sys")
97
+
98
+ def __hash__(self):
99
+ return hash(self.block_id)
100
+
101
+
102
+ class PendingJob:
103
+ """
104
+ A PendingJob is whatever will be put into our pending_exit list. A pending exit is an entry that created by the
105
+ returning of a call or syscall. It is "pending" since we cannot immediately figure out whether this entry will
106
+ be executed or not. If the corresponding call/syscall intentionally doesn't return, then the pending exit will be
107
+ removed. If the corresponding call/syscall returns, then the pending exit will be removed as well (since a real
108
+ entry is created from the returning and will be analyzed later). If the corresponding call/syscall might
109
+ return, but for some reason (for example, an unsupported instruction is met during the analysis) our analysis
110
+ does not return properly, then the pending exit will be picked up and put into remaining_jobs list.
111
+ """
112
+
113
+ def __init__(
114
+ self, caller_func_addr, returning_source, state, src_block_id, src_exit_stmt_idx, src_exit_ins_addr, call_stack
115
+ ):
116
+ """
117
+ :param returning_source: Address of the callee function. It might be None if address of the callee is not
118
+ resolvable.
119
+ :param state: The state after returning from the callee function. Of course there is no way to get
120
+ a precise state without emulating the execution of the callee, but at least we can
121
+ properly adjust the stack and registers to imitate the real returned state.
122
+ :param call_stack: A callstack.
123
+ """
124
+
125
+ self.caller_func_addr = caller_func_addr
126
+ self.returning_source = returning_source
127
+ self.state = state
128
+ self.src_block_id = src_block_id
129
+ self.src_exit_stmt_idx = src_exit_stmt_idx
130
+ self.src_exit_ins_addr = src_exit_ins_addr
131
+ self.call_stack = call_stack
132
+
133
+ def __repr__(self):
134
+ return "<PendingJob to {}, from function {}>".format(
135
+ self.state.ip, hex(self.returning_source) if self.returning_source is not None else "Unknown"
136
+ )
137
+
138
+ def __hash__(self):
139
+ return hash(
140
+ (
141
+ self.caller_func_addr,
142
+ self.returning_source,
143
+ self.src_block_id,
144
+ self.src_exit_stmt_idx,
145
+ self.src_exit_ins_addr,
146
+ )
147
+ )
148
+
149
+ def __eq__(self, other):
150
+ if not isinstance(other, PendingJob):
151
+ return False
152
+ return (
153
+ self.caller_func_addr == other.caller_func_addr
154
+ and self.returning_source == other.returning_source
155
+ and self.src_block_id == other.src_block_id
156
+ and self.src_exit_stmt_idx == other.src_exit_stmt_idx
157
+ and self.src_exit_ins_addr == other.src_exit_ins_addr
158
+ )
159
+
160
+
161
+ class CFGEmulated(ForwardAnalysis, CFGBase): # pylint: disable=abstract-method
162
+ """
163
+ This class represents a control-flow graph.
164
+ """
165
+
166
+ tag = "CFGEmulated"
167
+
168
+ def __init__(
169
+ self,
170
+ context_sensitivity_level=1,
171
+ start=None,
172
+ avoid_runs=None,
173
+ enable_function_hints=False,
174
+ call_depth=None,
175
+ call_tracing_filter=None,
176
+ initial_state=None,
177
+ starts=None,
178
+ keep_state=False,
179
+ indirect_jump_target_limit=100000,
180
+ resolve_indirect_jumps=True,
181
+ enable_advanced_backward_slicing=False,
182
+ enable_symbolic_back_traversal=False,
183
+ indirect_jump_resolvers=None,
184
+ additional_edges=None,
185
+ no_construct=False,
186
+ normalize=False,
187
+ max_iterations=1,
188
+ address_whitelist=None,
189
+ base_graph=None,
190
+ iropt_level=None,
191
+ max_steps=None,
192
+ state_add_options=None,
193
+ state_remove_options=None,
194
+ model=None,
195
+ ):
196
+ """
197
+ All parameters are optional.
198
+
199
+ :param context_sensitivity_level: The level of context-sensitivity of this CFG (see documentation for
200
+ further details). It ranges from 0 to infinity. Default 1.
201
+ :param avoid_runs: A list of runs to avoid.
202
+ :param enable_function_hints: Whether to use function hints (constants that might be used as exit
203
+ targets) or not.
204
+ :param call_depth: How deep in the call stack to trace.
205
+ :param call_tracing_filter: Filter to apply on a given path and jumpkind to determine if it
206
+ should be skipped when call_depth is reached.
207
+ :param initial_state: An initial state to use to begin analysis.
208
+ :param iterable starts: A collection of starting points to begin analysis. It can contain
209
+ the following three different types of entries: an address specified
210
+ as an integer, a 2-tuple that includes an integer address and a
211
+ jumpkind, or a SimState instance. Unsupported entries in starts will
212
+ lead to an AngrCFGError being raised.
213
+ :param keep_state: Whether to keep the SimStates for each CFGNode.
214
+ :param resolve_indirect_jumps: Whether to enable the indirect jump resolvers for resolving indirect
215
+ jumps
216
+ :param enable_advanced_backward_slicing: Whether to enable an intensive technique for resolving indirect
217
+ jumps
218
+ :param enable_symbolic_back_traversal: Whether to enable an intensive technique for resolving indirect
219
+ jumps
220
+ :param list indirect_jump_resolvers: A custom list of indirect jump resolvers. If this list is None or
221
+ empty,
222
+ default indirect jump resolvers specific to this architecture and
223
+ binary types will be loaded.
224
+ :param additional_edges: A dict mapping addresses of basic blocks to addresses of
225
+ successors to manually include and analyze forward from.
226
+ :param bool no_construct: Skip the construction procedure. Only used in unit-testing.
227
+ :param bool normalize: If the CFG as well as all Function graphs should be normalized or
228
+ not.
229
+ :param int max_iterations: The maximum number of iterations that each basic block should be
230
+ "executed". 1 by default. Larger numbers of iterations are usually
231
+ required for complex analyses like loop analysis.
232
+ :param iterable address_whitelist: A list of allowed addresses. Any basic blocks outside of this
233
+ collection of addresses will be ignored.
234
+ :param networkx.DiGraph base_graph: A basic control flow graph to follow. Each node inside this graph
235
+ must have the following properties: `addr` and `size`. CFG recovery
236
+ will strictly follow nodes and edges shown in the graph, and discard
237
+ any control flow that does not follow an existing edge in the base
238
+ graph. For example, you can pass in a Function local transition
239
+ graph as the base graph, and CFGEmulated will traverse nodes and
240
+ edges and extract useful information.
241
+ :param int iropt_level: The optimization level of VEX IR (0, 1, 2). The default level will
242
+ be used if `iropt_level` is None.
243
+ :param int max_steps: The maximum number of basic blocks to recover forthe longest path
244
+ from each start before pausing the recovery procedure.
245
+ :param state_add_options: State options that will be added to the initial state.
246
+ :param state_remove_options: State options that will be removed from the initial state.
247
+ """
248
+ ForwardAnalysis.__init__(self, order_jobs=base_graph is not None)
249
+ CFGBase.__init__(
250
+ self,
251
+ "emulated",
252
+ context_sensitivity_level,
253
+ normalize=normalize,
254
+ resolve_indirect_jumps=resolve_indirect_jumps,
255
+ indirect_jump_resolvers=indirect_jump_resolvers,
256
+ indirect_jump_target_limit=indirect_jump_target_limit,
257
+ model=model,
258
+ )
259
+
260
+ if start is not None:
261
+ l.warning("`start` is deprecated. Please consider using `starts` instead in your code.")
262
+ self._starts = (start,)
263
+ else:
264
+ if isinstance(starts, (list, set)):
265
+ self._starts = tuple(starts)
266
+ elif isinstance(starts, tuple) or starts is None:
267
+ self._starts = starts
268
+ else:
269
+ raise AngrCFGError("Unsupported type of the `starts` argument.")
270
+
271
+ if enable_advanced_backward_slicing or enable_symbolic_back_traversal:
272
+ l.warning("`advanced backward slicing` and `symbolic back traversal` are deprecated.")
273
+ l.warning(
274
+ "Please use `resolve_indirect_jumps` to resolve indirect jumps using different resolvers instead."
275
+ )
276
+
277
+ self._iropt_level = iropt_level
278
+ self._avoid_runs = avoid_runs
279
+ self._enable_function_hints = enable_function_hints
280
+ self._call_depth = call_depth
281
+ self._call_tracing_filter = call_tracing_filter
282
+ self._initial_state = initial_state
283
+ self._keep_state = keep_state
284
+ self._advanced_backward_slicing = enable_advanced_backward_slicing
285
+ self._enable_symbolic_back_traversal = enable_symbolic_back_traversal
286
+ self._additional_edges = additional_edges if additional_edges else {}
287
+ self._max_steps = max_steps
288
+ self._state_add_options = state_add_options if state_add_options is not None else set()
289
+ self._state_remove_options = state_remove_options if state_remove_options is not None else set()
290
+ self._state_add_options.update([o.SYMBOL_FILL_UNCONSTRAINED_MEMORY, o.SYMBOL_FILL_UNCONSTRAINED_REGISTERS])
291
+
292
+ # add the track_memory_option if the enable function hint flag is set
293
+ if self._enable_function_hints and o.TRACK_MEMORY_ACTIONS not in self._state_add_options:
294
+ self._state_add_options.add(o.TRACK_MEMORY_ACTIONS)
295
+
296
+ # more initialization
297
+
298
+ self._symbolic_function_initial_state = {}
299
+ self._function_input_states = None
300
+ self._unresolvable_runs = set()
301
+
302
+ # Stores the index for each CFGNode in this CFG after a quasi-topological sort (currently a DFS)
303
+ # TODO: remove it since it's no longer used
304
+ self._quasi_topological_order = {}
305
+ # A copy of all entry points in this CFG. Integers
306
+ self._entry_points = []
307
+
308
+ self._max_iterations = max_iterations
309
+ self._address_whitelist = set(address_whitelist) if address_whitelist is not None else None
310
+ self._base_graph = base_graph
311
+ self._node_addr_visiting_order = []
312
+
313
+ if self._base_graph:
314
+ sorted_nodes = GraphUtils.quasi_topological_sort_nodes(self._base_graph)
315
+ self._node_addr_visiting_order = [n.addr for n in sorted_nodes]
316
+
317
+ self._sanitize_parameters()
318
+
319
+ self._executable_address_ranges = []
320
+ self._executable_address_ranges = self._executable_memory_regions()
321
+
322
+ # These save input states of functions. It will be discarded after the CFG is constructed
323
+ self._function_input_states = {}
324
+ self._loop_back_edges = []
325
+ self._overlapped_loop_headers = []
326
+ self._pending_function_hints = set()
327
+ # A dict to log edges and the jumpkind between each basic block
328
+ self._edge_map = defaultdict(list)
329
+
330
+ self._model._iropt_level = self._iropt_level
331
+
332
+ self._start_keys = [] # a list of block IDs of all starts
333
+
334
+ # For each call, we are always getting two exits: an Ijk_Call that
335
+ # stands for the real call exit, and an Ijk_Ret that is a simulated exit
336
+ # for the retn address. There are certain cases that the control flow
337
+ # never returns to the next instruction of a callsite due to
338
+ # imprecision of the concrete execution. So we save those simulated
339
+ # exits here to increase our code coverage. Of course the real retn from
340
+ # that call always precedes those "fake" retns.
341
+ self._pending_jobs = defaultdict(list) # Dict[BlockID, List[PendingJob]]
342
+
343
+ # Counting how many times a basic block is traced into
344
+ self._traced_addrs = defaultdict(lambda: defaultdict(int))
345
+
346
+ # A dict that collects essential parameters to properly reconstruct initial state for a block
347
+ self._block_artifacts = {}
348
+ self._analyzed_addrs = set()
349
+ self._non_returning_functions = set()
350
+
351
+ self._pending_edges = defaultdict(list)
352
+
353
+ if not no_construct:
354
+ self._initialize_cfg()
355
+ self._analyze()
356
+
357
+ #
358
+ # Public methods
359
+ #
360
+
361
+ def copy(self) -> CFGEmulated:
362
+ """
363
+ Make a copy of the CFG.
364
+
365
+ :return: A copy of the CFG instance.
366
+ """
367
+ new_cfg = CFGEmulated.__new__(CFGEmulated)
368
+ super().make_copy(new_cfg)
369
+
370
+ new_cfg._indirect_jump_target_limit = self._indirect_jump_target_limit
371
+ new_cfg.named_errors = defaultdict(list, self.named_errors)
372
+ new_cfg.errors = list(self.errors)
373
+ new_cfg._fail_fast = self._fail_fast
374
+ new_cfg._max_steps = self._max_steps
375
+ new_cfg.project = self.project
376
+
377
+ # Intelligently (or stupidly... you tell me) fill it up
378
+ new_cfg._edge_map = self._edge_map.copy()
379
+ new_cfg._loop_back_edges = self._loop_back_edges[::]
380
+ new_cfg._executable_address_ranges = self._executable_address_ranges[::]
381
+ new_cfg._unresolvable_runs = self._unresolvable_runs.copy()
382
+ new_cfg._overlapped_loop_headers = self._overlapped_loop_headers[::]
383
+ new_cfg._thumb_addrs = self._thumb_addrs.copy()
384
+ new_cfg._keep_state = self._keep_state
385
+
386
+ return new_cfg
387
+
388
+ def resume(self, starts=None, max_steps=None):
389
+ """
390
+ Resume a paused or terminated control flow graph recovery.
391
+
392
+ :param iterable starts: A collection of new starts to resume from. If `starts` is None, we will resume CFG
393
+ recovery from where it was paused before.
394
+ :param int max_steps: The maximum number of blocks on the longest path starting from each start before pausing
395
+ the recovery.
396
+ :return: None
397
+ """
398
+
399
+ self._should_abort = False
400
+
401
+ self._starts = starts
402
+ self._max_steps = max_steps
403
+
404
+ if self._starts is None:
405
+ self._starts = []
406
+
407
+ if self._starts:
408
+ self._sanitize_starts()
409
+
410
+ self._analyze()
411
+
412
+ def remove_cycles(self):
413
+ """
414
+ Forces graph to become acyclic, removes all loop back edges and edges between overlapped loop headers and their
415
+ successors.
416
+ """
417
+ # loop detection
418
+ # only detect loops after potential graph normalization
419
+ if not self._loop_back_edges:
420
+ l.debug("Detecting loops...")
421
+ self._detect_loops()
422
+
423
+ l.debug("Removing cycles...")
424
+ l.debug("There are %d loop back edges.", len(self._loop_back_edges))
425
+ l.debug("And there are %d overlapping loop headers.", len(self._overlapped_loop_headers))
426
+ # First break all detected loops
427
+ for b1, b2 in self._loop_back_edges:
428
+ if self._graph.has_edge(b1, b2):
429
+ l.debug("Removing loop back edge %s -> %s", b1, b2)
430
+ self._graph.remove_edge(b1, b2)
431
+ # Then remove all outedges from overlapped loop headers
432
+ for b in self._overlapped_loop_headers:
433
+ successors = self._graph.successors(b)
434
+ for succ in successors:
435
+ self._graph.remove_edge(b, succ)
436
+ l.debug("Removing partial loop header edge %s -> %s", b, succ)
437
+
438
+ def downsize(self):
439
+ """
440
+ Remove saved states from all CFGNodes to reduce memory usage.
441
+
442
+ :return: None
443
+ """
444
+
445
+ for cfg_node in self._nodes.values():
446
+ cfg_node.downsize()
447
+
448
+ def unroll_loops(self, max_loop_unrolling_times):
449
+ """
450
+ Unroll loops for each function. The resulting CFG may still contain loops due to recursion, function calls, etc.
451
+
452
+ :param int max_loop_unrolling_times: The maximum iterations of unrolling.
453
+ :return: None
454
+ """
455
+
456
+ if not isinstance(max_loop_unrolling_times, int) or max_loop_unrolling_times < 0:
457
+ raise AngrCFGError(
458
+ "Max loop unrolling times must be set to an integer greater than or equal to 0 if "
459
+ + "loop unrolling is enabled."
460
+ )
461
+
462
+ def _unroll(graph: networkx.DiGraph, loop: Loop):
463
+ """
464
+ The loop callback method where loops are unrolled.
465
+
466
+ :param graph: The control flow graph.
467
+ :param loop: The loop instance.
468
+ :return: None
469
+ """
470
+
471
+ for back_edge in loop.continue_edges:
472
+ loop_body_addrs = {n.addr for n in loop.body_nodes}
473
+ src_blocknode: BlockNode = back_edge[0]
474
+ dst_blocknode: BlockNode = back_edge[1]
475
+
476
+ for src in self.model.get_all_nodes(src_blocknode.addr):
477
+ for dst in graph.successors(src):
478
+ if dst.addr != dst_blocknode.addr:
479
+ continue
480
+
481
+ # Duplicate the dst node
482
+ new_dst = dst.copy()
483
+ new_dst.looping_times = dst.looping_times + 1
484
+ if (
485
+ new_dst not in graph
486
+ and
487
+ # If the new_dst is already in the graph, we don't want to keep unrolling
488
+ # the this loop anymore since it may *create* a new loop. Of course we
489
+ # will lose some edges in this way, but in general it is acceptable.
490
+ new_dst.looping_times <= max_loop_unrolling_times
491
+ ):
492
+ # Log all successors of the dst node
493
+ dst_successors = graph.successors(dst)
494
+ # Add new_dst to the graph
495
+ edge_data = graph.get_edge_data(src, dst)
496
+ graph.add_edge(src, new_dst, **edge_data)
497
+ for ds in dst_successors:
498
+ if ds.looping_times == 0 and ds.addr not in loop_body_addrs:
499
+ edge_data = graph.get_edge_data(dst, ds)
500
+ graph.add_edge(new_dst, ds, **edge_data)
501
+
502
+ graph.remove_edge(src, dst)
503
+
504
+ self._detect_loops(loop_callback=_unroll)
505
+
506
+ def force_unroll_loops(self, max_loop_unrolling_times):
507
+ """
508
+ Unroll loops globally. The resulting CFG does not contain any loop, but this method is slow on large graphs.
509
+
510
+ :param int max_loop_unrolling_times: The maximum iterations of unrolling.
511
+ :return: None
512
+ """
513
+
514
+ assert self._starts is not None
515
+
516
+ if not isinstance(max_loop_unrolling_times, int) or max_loop_unrolling_times < 0:
517
+ raise AngrCFGError(
518
+ "Max loop unrolling times must be set to an integer greater than or equal to 0 if "
519
+ + "loop unrolling is enabled."
520
+ )
521
+
522
+ # Traverse the CFG and try to find the beginning of loops
523
+ loop_backedges = []
524
+
525
+ start = self._starts[0]
526
+ if isinstance(start, tuple):
527
+ start, _ = start # pylint: disable=unpacking-non-sequence
528
+ start_node = self.model.get_any_node(start)
529
+ if start_node is None:
530
+ raise AngrCFGError("Cannot find start node when trying to unroll loops. The CFG might be empty.")
531
+
532
+ graph_copy = networkx.DiGraph(self.graph)
533
+
534
+ while True:
535
+ cycles_iter = networkx.simple_cycles(graph_copy)
536
+ try:
537
+ cycle = next(cycles_iter)
538
+ except StopIteration:
539
+ break
540
+
541
+ loop_backedge = (None, None)
542
+
543
+ for n in networkx.dfs_preorder_nodes(graph_copy, source=start_node):
544
+ if n in cycle:
545
+ idx = cycle.index(n)
546
+ loop_backedge = (cycle[-1], cycle[idx]) if idx == 0 else (cycle[idx - 1], cycle[idx])
547
+ break
548
+
549
+ if loop_backedge not in loop_backedges:
550
+ loop_backedges.append(loop_backedge)
551
+
552
+ # Create a common end node for all nodes whose out_degree is 0
553
+ end_nodes = [n for n in graph_copy.nodes() if graph_copy.out_degree(n) == 0]
554
+ new_end_node = "end_node"
555
+
556
+ if not end_nodes:
557
+ # We gotta randomly break a loop
558
+ cycles = sorted(networkx.simple_cycles(graph_copy), key=len)
559
+ first_cycle = cycles[0]
560
+ if len(first_cycle) == 1:
561
+ graph_copy.remove_edge(first_cycle[0], first_cycle[0])
562
+ else:
563
+ graph_copy.remove_edge(first_cycle[0], first_cycle[1])
564
+ end_nodes = [n for n in graph_copy.nodes() if graph_copy.out_degree(n) == 0]
565
+
566
+ for en in end_nodes:
567
+ graph_copy.add_edge(en, new_end_node)
568
+
569
+ # postdoms = self.immediate_postdominators(new_end_node, target_graph=graph_copy)
570
+ # reverse_postdoms = defaultdict(list)
571
+ # for k, v in postdoms.items():
572
+ # reverse_postdoms[v].append(k)
573
+
574
+ # Find all loop bodies
575
+ # for src, dst in loop_backedges:
576
+ # nodes_in_loop = { src, dst }
577
+
578
+ # while True:
579
+ # new_nodes = set()
580
+
581
+ # for n in nodes_in_loop:
582
+ # if n in reverse_postdoms:
583
+ # for node in reverse_postdoms[n]:
584
+ # if node not in nodes_in_loop:
585
+ # new_nodes.add(node)
586
+
587
+ # if not new_nodes:
588
+ # break
589
+
590
+ # nodes_in_loop |= new_nodes
591
+
592
+ # Unroll the loop body
593
+ # TODO: Finish the implementation
594
+
595
+ graph_copy.remove_node(new_end_node)
596
+ src, dst = loop_backedge
597
+ assert src is not None and dst is not None
598
+ if graph_copy.has_edge(src, dst): # It might have been removed before
599
+ # Duplicate the dst node
600
+ new_dst = dst.copy()
601
+ new_dst.looping_times = dst.looping_times + 1
602
+ if (
603
+ new_dst not in graph_copy
604
+ and
605
+ # If the new_dst is already in the graph, we don't want to keep unrolling
606
+ # the this loop anymore since it may *create* a new loop. Of course we
607
+ # will lose some edges in this way, but in general it is acceptable.
608
+ new_dst.looping_times <= max_loop_unrolling_times
609
+ ):
610
+ # Log all successors of the dst node
611
+ dst_successors = list(graph_copy.successors(dst))
612
+ # Add new_dst to the graph
613
+ edge_data = graph_copy.get_edge_data(src, dst)
614
+ graph_copy.add_edge(src, new_dst, **edge_data)
615
+ for ds in dst_successors:
616
+ if ds.looping_times == 0 and ds not in cycle:
617
+ edge_data = graph_copy.get_edge_data(dst, ds)
618
+ graph_copy.add_edge(new_dst, ds, **edge_data)
619
+ # Remove the original edge
620
+ graph_copy.remove_edge(src, dst)
621
+
622
+ # Update loop backedges
623
+ self._loop_back_edges = loop_backedges
624
+
625
+ self.model.graph = graph_copy
626
+
627
+ def immediate_dominators(self, start, target_graph=None):
628
+ """
629
+ Get all immediate dominators of sub graph from given node upwards.
630
+
631
+ :param str start: id of the node to navigate forwards from.
632
+ :param networkx.classes.digraph.DiGraph target_graph: graph to analyse, default is self.graph.
633
+
634
+ :return: each node of graph as index values, with element as respective node's immediate dominator.
635
+ :rtype: dict
636
+ """
637
+ return self._immediate_dominators(start, target_graph=target_graph, reverse_graph=False)
638
+
639
+ def immediate_postdominators(self, end, target_graph=None):
640
+ """
641
+ Get all immediate postdominators of sub graph from given node upwards.
642
+
643
+ :param str start: id of the node to navigate forwards from.
644
+ :param networkx.classes.digraph.DiGraph target_graph: graph to analyse, default is self.graph.
645
+
646
+ :return: each node of graph as index values, with element as respective node's immediate dominator.
647
+ :rtype: dict
648
+ """
649
+ return self._immediate_dominators(end, target_graph=target_graph, reverse_graph=True)
650
+
651
+ def remove_fakerets(self):
652
+ """
653
+ Get rid of fake returns (i.e., Ijk_FakeRet edges) from this CFG
654
+
655
+ :return: None
656
+ """
657
+ fakeret_edges = [
658
+ (src, dst) for src, dst, data in self.graph.edges(data=True) if data["jumpkind"] == "Ijk_FakeRet"
659
+ ]
660
+ self.graph.remove_edges_from(fakeret_edges)
661
+
662
+ def get_topological_order(self, cfg_node):
663
+ """
664
+ Get the topological order of a CFG Node.
665
+
666
+ :param cfg_node: A CFGNode instance.
667
+ :return: An integer representing its order, or None if the CFGNode does not exist in the graph.
668
+ """
669
+
670
+ if not self._quasi_topological_order:
671
+ self._quasi_topological_sort()
672
+
673
+ return self._quasi_topological_order.get(cfg_node, None)
674
+
675
+ def get_subgraph(self, starting_node, block_addresses):
676
+ """
677
+ Get a sub-graph out of a bunch of basic block addresses.
678
+
679
+ :param CFGNode starting_node: The beginning of the subgraph
680
+ :param iterable block_addresses: A collection of block addresses that should be included in the subgraph if
681
+ there is a path between `starting_node` and a CFGNode with the specified
682
+ address, and all nodes on the path should also be included in the subgraph.
683
+ :return: A new CFG that only contain the specific subgraph.
684
+ :rtype: CFGEmulated
685
+ """
686
+
687
+ graph = networkx.DiGraph()
688
+
689
+ if starting_node not in self.graph:
690
+ raise AngrCFGError(
691
+ f'get_subgraph(): the specified "starting_node" {starting_node} does not exist in the current CFG.'
692
+ )
693
+
694
+ addr_set = set(block_addresses)
695
+
696
+ graph.add_node(starting_node)
697
+ queue = [starting_node]
698
+
699
+ while queue:
700
+ node = queue.pop()
701
+ for _, dst, data in self.graph.out_edges([node], data=True):
702
+ if dst not in graph and dst.addr in addr_set:
703
+ graph.add_edge(node, dst, **data)
704
+ queue.append(dst)
705
+
706
+ cfg = self.copy()
707
+ cfg._graph = graph
708
+ cfg._starts = (starting_node.addr,)
709
+
710
+ return cfg
711
+
712
+ def get_function_subgraph(self, start, max_call_depth=None):
713
+ """
714
+ Get a sub-graph of a certain function.
715
+
716
+ :param start: The function start. Currently it should be an integer.
717
+ :param max_call_depth: Call depth limit. None indicates no limit.
718
+ :return: A CFG instance which is a sub-graph of self.graph
719
+ """
720
+
721
+ # FIXME: syscalls are not supported
722
+ # FIXME: start should also take a CFGNode instance
723
+
724
+ start_node = self.model.get_any_node(start)
725
+ assert start_node is not None
726
+
727
+ node_wrapper = (start_node, 0)
728
+ stack: list[tuple[CFGNode, int]] = [node_wrapper]
729
+ traversed_nodes = {start_node}
730
+ subgraph_nodes = {start_node}
731
+
732
+ while stack:
733
+ nw = stack.pop()
734
+ n, call_depth = nw[0], nw[1]
735
+
736
+ # Get successors
737
+ edges = self.graph.out_edges(n, data=True)
738
+
739
+ for _, dst, data in edges:
740
+ assert dst is not None
741
+ if dst not in traversed_nodes:
742
+ # We see a new node!
743
+ traversed_nodes.add(dst)
744
+
745
+ if data["jumpkind"] == "Ijk_Call":
746
+ if max_call_depth is None or (max_call_depth is not None and call_depth < max_call_depth):
747
+ subgraph_nodes.add(dst)
748
+ new_nw = (dst, call_depth + 1)
749
+ stack.append(new_nw)
750
+ elif data["jumpkind"] == "Ijk_Ret":
751
+ if call_depth > 0:
752
+ subgraph_nodes.add(dst)
753
+ new_nw = (dst, call_depth - 1)
754
+ stack.append(new_nw)
755
+ else:
756
+ subgraph_nodes.add(dst)
757
+ new_nw = (dst, call_depth)
758
+ stack.append(new_nw)
759
+
760
+ # subgraph = networkx.subgraph(self.graph, subgraph_nodes)
761
+ subgraph = self.graph.subgraph(subgraph_nodes).copy()
762
+
763
+ # Make it a CFG instance
764
+ subcfg = self.copy()
765
+ subcfg._graph = subgraph
766
+ subcfg._starts = (start,)
767
+
768
+ return subcfg
769
+
770
+ @property
771
+ def context_sensitivity_level(self):
772
+ return self._context_sensitivity_level
773
+
774
+ #
775
+ # Serialization
776
+ #
777
+
778
+ def __setstate__(self, s):
779
+ self.project: angr.Project = s["project"]
780
+ self.indirect_jumps: dict[int, IndirectJump] = s["indirect_jumps"]
781
+ self._loop_back_edges = s["_loop_back_edges"]
782
+ self._thumb_addrs = s["_thumb_addrs"]
783
+ self._unresolvable_runs = s["_unresolvable_runs"]
784
+ self._executable_address_ranges = s["_executable_address_ranges"]
785
+ self._iropt_level = s["_iropt_level"]
786
+ self._model = s["_model"]
787
+
788
+ def __getstate__(self):
789
+ return {
790
+ "project": self.project,
791
+ "indirect_jumps": self.indirect_jumps,
792
+ "_loop_back_edges": self._loop_back_edges,
793
+ "_nodes_by_addr": self._nodes_by_addr,
794
+ "_thumb_addrs": self._thumb_addrs,
795
+ "_unresolvable_runs": self._unresolvable_runs,
796
+ "_executable_address_ranges": self._executable_address_ranges,
797
+ "_iropt_level": self._iropt_level,
798
+ "_model": self._model,
799
+ }
800
+
801
+ #
802
+ # Properties
803
+ #
804
+
805
+ @property
806
+ def graph(self):
807
+ return self._model.graph
808
+
809
+ @property
810
+ def unresolvables(self):
811
+ """
812
+ Get those SimRuns that have non-resolvable exits.
813
+
814
+ :return: A set of SimRuns
815
+ :rtype: set
816
+ """
817
+ return self._unresolvable_runs
818
+
819
+ @property
820
+ def deadends(self):
821
+ """
822
+ Get all CFGNodes that has an out-degree of 0
823
+
824
+ :return: A list of CFGNode instances
825
+ :rtype: list
826
+ """
827
+ if self.graph is None:
828
+ raise AngrCFGError("CFG hasn't been generated yet.")
829
+
830
+ return [i for i in self.graph if self.graph.out_degree(i) == 0]
831
+
832
+ #
833
+ # Private methods
834
+ #
835
+
836
+ # Initialization related methods
837
+
838
+ def _sanitize_parameters(self):
839
+ """
840
+ Perform a sanity check on parameters passed in to CFG.__init__().
841
+ An AngrCFGError is raised if any parameter fails the sanity check.
842
+
843
+ :return: None
844
+ """
845
+
846
+ # Check additional_edges
847
+ if isinstance(self._additional_edges, (list, set, tuple)):
848
+ new_dict = defaultdict(list)
849
+ for s, d in self._additional_edges:
850
+ new_dict[s].append(d)
851
+ self._additional_edges = new_dict
852
+
853
+ elif isinstance(self._additional_edges, dict):
854
+ pass
855
+
856
+ else:
857
+ raise AngrCFGError("Additional edges can only be a list, set, tuple, or a dict.")
858
+
859
+ # Check _advanced_backward_slicing
860
+ if self._advanced_backward_slicing and self._enable_symbolic_back_traversal:
861
+ raise AngrCFGError("Advanced backward slicing and symbolic back traversal cannot both be enabled.")
862
+
863
+ if self._advanced_backward_slicing and not self._keep_state:
864
+ raise AngrCFGError("Keep state must be enabled if advanced backward slicing is enabled.")
865
+
866
+ # Sanitize avoid_runs
867
+ self._avoid_runs = [] if self._avoid_runs is None else self._avoid_runs
868
+ if not isinstance(self._avoid_runs, (list, set)):
869
+ raise AngrCFGError('"avoid_runs" must either be None, or a list or a set.')
870
+
871
+ self._sanitize_starts()
872
+
873
+ def _sanitize_starts(self):
874
+ # Sanitize starts
875
+ # Convert self._starts to a list of SimState instances or tuples of (ip, jumpkind)
876
+ if self._starts is None:
877
+ self._starts = ((self.project.entry, None),)
878
+
879
+ else:
880
+ new_starts = []
881
+ for item in self._starts:
882
+ if isinstance(item, tuple):
883
+ if len(item) != 2:
884
+ raise AngrCFGError(f'Unsupported item in "starts": {item!s}')
885
+
886
+ new_starts.append(item)
887
+ elif isinstance(item, int):
888
+ new_starts.append((item, None))
889
+
890
+ elif isinstance(item, SimState):
891
+ new_starts.append(item)
892
+
893
+ else:
894
+ raise AngrCFGError(f'Unsupported item type in "starts": {type(item)}')
895
+
896
+ self._starts = new_starts
897
+
898
+ if not self._starts:
899
+ raise AngrCFGError("At least one start must be provided")
900
+
901
+ # CFG construction
902
+ # The main loop and sub-methods
903
+
904
+ def _job_key(self, job):
905
+ """
906
+ Get the key for a specific CFG job. The key is a context-sensitive block ID.
907
+
908
+ :param CFGJob job: The CFGJob instance.
909
+ :return: The block ID of the specific CFG job.
910
+ :rtype: BlockID
911
+ """
912
+
913
+ return job.block_id
914
+
915
+ def _job_sorting_key(self, job):
916
+ """
917
+ Get the sorting key of a CFGJob instance.
918
+
919
+ :param CFGJob job: the CFGJob object.
920
+ :return: An integer that determines the order of this job in the queue.
921
+ :rtype: int
922
+ """
923
+
924
+ if self._base_graph is None:
925
+ # we don't do sorting if there is no base_graph
926
+ return 0
927
+
928
+ MAX_JOBS = 1000000
929
+
930
+ if job.addr not in self._node_addr_visiting_order:
931
+ return MAX_JOBS
932
+
933
+ return self._node_addr_visiting_order.index(job.addr)
934
+
935
+ def _pre_analysis(self):
936
+ """
937
+ Initialization work. Executed prior to the analysis.
938
+
939
+ :return: None
940
+ """
941
+
942
+ # Fill up self._starts
943
+ for item in self._starts:
944
+ callstack = None
945
+ if isinstance(item, tuple):
946
+ # (addr, jumpkind)
947
+ ip = item[0]
948
+ state = self._create_initial_state(item[0], item[1])
949
+
950
+ elif isinstance(item, SimState):
951
+ # SimState
952
+ state = item.copy() # pylint: disable=no-member
953
+ ip = state.solver.eval_one(state.ip)
954
+ self._reset_state_mode(state, "fastpath")
955
+
956
+ else:
957
+ raise AngrCFGError(f"Unsupported CFG start type: {type(item)!s}.")
958
+
959
+ self._symbolic_function_initial_state[ip] = state
960
+ path_wrapper = CFGJob(ip, state, self._context_sensitivity_level, None, None, call_stack=callstack)
961
+ key = path_wrapper.block_id
962
+ if key not in self._start_keys:
963
+ self._start_keys.append(key)
964
+
965
+ self._insert_job(path_wrapper)
966
+ self._register_analysis_job(path_wrapper.func_addr, path_wrapper)
967
+
968
+ def _intra_analysis(self):
969
+ """
970
+ During the analysis. We process function hints here.
971
+
972
+ :return: None
973
+ """
974
+
975
+ if self._pending_function_hints:
976
+ self._process_hints(self._analyzed_addrs)
977
+
978
+ def _job_queue_empty(self):
979
+ """
980
+ A callback method called when the job queue is empty.
981
+
982
+ :return: None
983
+ """
984
+
985
+ self._iteratively_clean_pending_exits()
986
+
987
+ while self._pending_jobs:
988
+ # We don't have any exits remaining. Let's pop out a pending exit
989
+ pending_job = self._get_one_pending_job()
990
+ if pending_job is None:
991
+ continue
992
+
993
+ self._insert_job(pending_job)
994
+ self._register_analysis_job(pending_job.func_addr, pending_job)
995
+ break
996
+
997
+ def _create_initial_state(self, ip, jumpkind):
998
+ """
999
+ Obtain a SimState object for a specific address
1000
+
1001
+ Fastpath means the CFG generation will work in an IDA-like way, in which it will not try to execute every
1002
+ single statement in the emulator, but will just do the decoding job. This is much faster than the old way.
1003
+
1004
+ :param int ip: The instruction pointer
1005
+ :param str jumpkind: The jumpkind upon executing the block
1006
+ :return: The newly-generated state
1007
+ :rtype: SimState
1008
+ """
1009
+
1010
+ jumpkind = "Ijk_Boring" if jumpkind is None else jumpkind
1011
+
1012
+ if self._initial_state is None:
1013
+ state = self.project.factory.blank_state(
1014
+ addr=ip,
1015
+ mode="fastpath",
1016
+ add_options=self._state_add_options,
1017
+ remove_options=self._state_remove_options,
1018
+ )
1019
+ self._initial_state = state
1020
+ else:
1021
+ # FIXME: self._initial_state is deprecated. This branch will be removed soon
1022
+ state = self._initial_state.copy()
1023
+ state.history.jumpkind = jumpkind
1024
+ self._reset_state_mode(state, "fastpath")
1025
+ state._ip = claripy.BVV(ip, self.project.arch.bits)
1026
+
1027
+ if jumpkind is not None:
1028
+ state.history.jumpkind = jumpkind
1029
+
1030
+ # THIS IS A HACK FOR MIPS
1031
+ if ip is not None and self.project.arch.name in ("MIPS32", "MIPS64"):
1032
+ # We assume this is a function start
1033
+ state.regs.t9 = ip
1034
+ # TODO there was at one point special logic for the ppc64 table of contents but it seems to have bitrotted
1035
+
1036
+ return state
1037
+
1038
+ def _get_one_pending_job(self):
1039
+ """
1040
+ Retrieve a pending job.
1041
+
1042
+ :return: A CFGJob instance or None
1043
+ """
1044
+
1045
+ pending_job_key = next(iter(self._pending_jobs.keys()))
1046
+ pending_job = self._pending_jobs[pending_job_key].pop()
1047
+ if len(self._pending_jobs[pending_job_key]) == 0:
1048
+ del self._pending_jobs[pending_job_key]
1049
+
1050
+ pending_job_state = pending_job.state
1051
+ pending_job_call_stack = pending_job.call_stack
1052
+ pending_job_src_block_id = pending_job.src_block_id
1053
+ pending_job_src_exit_stmt_idx = pending_job.src_exit_stmt_idx
1054
+
1055
+ self._deregister_analysis_job(pending_job.caller_func_addr, pending_job)
1056
+
1057
+ # Let's check whether this address has been traced before.
1058
+ if pending_job_key in self._nodes:
1059
+ node = self._nodes[pending_job_key]
1060
+ if node in self.graph:
1061
+ pending_exit_addr = self._block_id_addr(pending_job_key)
1062
+ # That block has been traced before. Let's forget about it
1063
+ l.debug("Target 0x%08x has been traced before. Trying the next one...", pending_exit_addr)
1064
+
1065
+ # However, we should still create the FakeRet edge
1066
+ self._graph_add_edge(
1067
+ pending_job_src_block_id,
1068
+ pending_job_key,
1069
+ jumpkind="Ijk_FakeRet",
1070
+ stmt_idx=pending_job_src_exit_stmt_idx,
1071
+ ins_addr=pending_job.src_exit_ins_addr,
1072
+ )
1073
+
1074
+ return None
1075
+
1076
+ pending_job_state.history.jumpkind = "Ijk_FakeRet"
1077
+
1078
+ job = CFGJob(
1079
+ pending_job_state.addr,
1080
+ pending_job_state,
1081
+ self._context_sensitivity_level,
1082
+ src_block_id=pending_job_src_block_id,
1083
+ src_exit_stmt_idx=pending_job_src_exit_stmt_idx,
1084
+ src_ins_addr=pending_job.src_exit_ins_addr,
1085
+ call_stack=pending_job_call_stack,
1086
+ )
1087
+ l.debug("Tracing a missing return exit %s", self._block_id_repr(pending_job_key))
1088
+
1089
+ return job
1090
+
1091
+ def _process_hints(self, analyzed_addrs):
1092
+ """
1093
+ Process function hints in the binary.
1094
+
1095
+ :return: None
1096
+ """
1097
+
1098
+ # Function hints!
1099
+ # Now let's see how many new functions we can get here...
1100
+ while self._pending_function_hints:
1101
+ f = self._pending_function_hints.pop()
1102
+ if f not in analyzed_addrs:
1103
+ new_state = self.project.factory.entry_state(mode="fastpath")
1104
+ new_state.ip = claripy.BVV(f, self.project.arch.bits)
1105
+
1106
+ # TOOD: Specially for MIPS
1107
+ if new_state.arch.name in ("MIPS32", "MIPS64"):
1108
+ # Properly set t9
1109
+ new_state.registers.store("t9", f)
1110
+
1111
+ new_path_wrapper = CFGJob(f, new_state, self._context_sensitivity_level)
1112
+ self._insert_job(new_path_wrapper)
1113
+ self._register_analysis_job(f, new_path_wrapper)
1114
+ l.debug("Picking a function 0x%x from pending function hints.", f)
1115
+ self.kb.functions.function(new_path_wrapper.func_addr, create=True)
1116
+ break
1117
+
1118
+ def _post_analysis(self):
1119
+ """
1120
+ Post-CFG-construction.
1121
+
1122
+ :return: None
1123
+ """
1124
+
1125
+ self._make_completed_functions()
1126
+ new_changes = self._iteratively_analyze_function_features()
1127
+ functions_do_not_return = new_changes["functions_do_not_return"]
1128
+ self._update_function_callsites(functions_do_not_return)
1129
+
1130
+ # Create all pending edges
1131
+ for _, edges in self._pending_edges.items():
1132
+ for src_node, dst_node, data in edges:
1133
+ self._graph_add_edge(src_node, dst_node, **data)
1134
+
1135
+ # Remove those edges that will never be taken!
1136
+ self._remove_non_return_edges()
1137
+
1138
+ CFGBase._post_analysis(self)
1139
+
1140
+ # Job handling
1141
+
1142
+ def _pre_job_handling(self, job): # pylint:disable=arguments-differ
1143
+ """
1144
+ Before processing a CFGJob.
1145
+ Right now each block is traced at most once. If it is traced more than once, we will mark it as "should_skip"
1146
+ before tracing it.
1147
+ An AngrForwardAnalysisSkipJob exception is raised in order to skip analyzing the job.
1148
+
1149
+ :param CFGJob job: The CFG job object.
1150
+ :param dict _locals: A bunch of local variables that will be kept around when handling this job and its
1151
+ corresponding successors.
1152
+ :return: None
1153
+ """
1154
+
1155
+ # Extract initial info the CFGJob
1156
+ job.call_stack_suffix = job.get_call_stack_suffix()
1157
+ job.current_function = self.kb.functions.function(
1158
+ job.func_addr, create=True, syscall=job.jumpkind.startswith("Ijk_Sys")
1159
+ )
1160
+ src_block_id = job.src_block_id
1161
+ src_exit_stmt_idx = job.src_exit_stmt_idx
1162
+ src_ins_addr = job.src_ins_addr
1163
+ addr = job.addr
1164
+
1165
+ # Log this address
1166
+ if l.level == logging.DEBUG:
1167
+ self._analyzed_addrs.add(addr)
1168
+
1169
+ if addr == job.func_addr:
1170
+ # Store the input state of this function
1171
+ self._function_input_states[job.func_addr] = job.state
1172
+
1173
+ # deregister this job
1174
+ self._deregister_analysis_job(job.func_addr, job)
1175
+
1176
+ # Generate a unique key for this job
1177
+ block_id = job.block_id
1178
+
1179
+ # Should we skip tracing this block?
1180
+ should_skip = False
1181
+ if self._traced_addrs[job.call_stack_suffix][addr] >= self._max_iterations or (
1182
+ self._is_call_jumpkind(job.jumpkind)
1183
+ and self._call_depth is not None
1184
+ and len(job.call_stack) > self._call_depth
1185
+ and (self._call_tracing_filter is None or self._call_tracing_filter(job.state, job.jumpkind))
1186
+ ):
1187
+ should_skip = True
1188
+
1189
+ # SimInspect breakpoints support
1190
+ job.state._inspect("cfg_handle_job", BP_BEFORE)
1191
+
1192
+ # Get a SimSuccessors out of current job
1193
+ sim_successors, exception_info, _ = self._get_simsuccessors(addr, job, current_function_addr=job.func_addr)
1194
+
1195
+ # determine the depth of this basic block
1196
+ if self._max_steps is None:
1197
+ # it's unnecessary to track depth when we are not limiting max_steps
1198
+ depth = None
1199
+ else:
1200
+ if src_block_id is None:
1201
+ # oh this is the very first basic block on this path
1202
+ depth = 0
1203
+ else:
1204
+ src_cfgnode = self._nodes[src_block_id]
1205
+ depth = src_cfgnode.depth + 1
1206
+ # the depth will not be updated later on even if this block has a greater depth on another path.
1207
+ # consequently, the `max_steps` limit is not very precise - I didn't see a need to make it precise
1208
+ # though.
1209
+
1210
+ if block_id not in self._nodes:
1211
+ # Create the CFGNode object
1212
+ cfg_node = self._create_cfgnode(
1213
+ sim_successors, job.call_stack, job.func_addr, block_id=block_id, depth=depth
1214
+ )
1215
+
1216
+ self._model.add_node(block_id, cfg_node)
1217
+
1218
+ else:
1219
+ # each block_id should only correspond to one CFGNode
1220
+ # use the existing CFGNode object
1221
+ # note that since we reuse existing CFGNodes, we may miss the following cases:
1222
+ #
1223
+ # mov eax, label_0 mov ebx, label_1
1224
+ # jmp xxx jmp xxx
1225
+ # | |
1226
+ # | |
1227
+ # *----------------------*
1228
+ # |
1229
+ # call eax
1230
+ #
1231
+ # Since the basic block "call eax" will only be traced once, either label_0 or label_1 will be missed in
1232
+ # this case. Indirect jump resolution might be able to get it, but that's another story. Ideally,
1233
+ # "call eax" should be traced twice with *different* sim_successors keys, which requires block ID being flow
1234
+ # sensitive, but it is way too expensive.
1235
+
1236
+ cfg_node = self._nodes[block_id]
1237
+
1238
+ # Increment tracing count for this block
1239
+ self._traced_addrs[job.call_stack_suffix][addr] += 1
1240
+
1241
+ if self._keep_state:
1242
+ # TODO: if we are reusing an existing CFGNode, we will be overwriting the original input state here. we
1243
+ # TODO: should save them all, which, unfortunately, requires some redesigning :-(
1244
+ cfg_node.input_state = sim_successors.initial_state
1245
+
1246
+ # See if this job cancels another FakeRet
1247
+ # This should be done regardless of whether this job should be skipped or not, otherwise edges will go missing
1248
+ # in the CFG or function transition graphs.
1249
+ if job.jumpkind == "Ijk_FakeRet" or (job.jumpkind == "Ijk_Ret" and block_id in self._pending_jobs):
1250
+ # The fake ret is confirmed (since we are returning from the function it calls). Create an edge for it
1251
+ # in the graph.
1252
+
1253
+ the_jobs = []
1254
+ if block_id in self._pending_jobs:
1255
+ the_jobs: PendingJob = self._pending_jobs.pop(block_id)
1256
+ for the_job in the_jobs:
1257
+ self._deregister_analysis_job(the_job.caller_func_addr, the_job)
1258
+ else:
1259
+ the_jobs = [job]
1260
+
1261
+ for the_job in the_jobs:
1262
+ self._graph_add_edge(
1263
+ the_job.src_block_id,
1264
+ block_id,
1265
+ jumpkind="Ijk_FakeRet",
1266
+ stmt_idx=the_job.src_exit_stmt_idx,
1267
+ ins_addr=src_ins_addr,
1268
+ )
1269
+ self._update_function_transition_graph(
1270
+ the_job.src_block_id,
1271
+ block_id,
1272
+ jumpkind="Ijk_FakeRet",
1273
+ ins_addr=src_ins_addr,
1274
+ stmt_idx=the_job.src_exit_stmt_idx,
1275
+ confirmed=True,
1276
+ )
1277
+
1278
+ if sim_successors is None or should_skip:
1279
+ # We cannot retrieve the block, or we should skip the analysis of this node
1280
+ # But we create the edge anyway. If the sim_successors does not exist, it will be an edge from the previous
1281
+ # node to a PathTerminator
1282
+ self._graph_add_edge(
1283
+ src_block_id, block_id, jumpkind=job.jumpkind, stmt_idx=src_exit_stmt_idx, ins_addr=src_ins_addr
1284
+ )
1285
+ self._update_function_transition_graph(
1286
+ src_block_id, block_id, jumpkind=job.jumpkind, ins_addr=src_ins_addr, stmt_idx=src_exit_stmt_idx
1287
+ )
1288
+
1289
+ # We are good. Raise the exception and leave
1290
+ raise AngrSkipJobNotice
1291
+
1292
+ self._update_thumb_addrs(sim_successors, job.state)
1293
+
1294
+ # We store the function hints first. Function hints will be checked at the end of the analysis to avoid
1295
+ # any duplication with existing jumping targets
1296
+ if self._enable_function_hints and sim_successors.sort == "IRSB" and sim_successors.all_successors:
1297
+ function_hints = self._search_for_function_hints(sim_successors.all_successors[0])
1298
+ for f in function_hints:
1299
+ self._pending_function_hints.add(f)
1300
+
1301
+ self._graph_add_edge(
1302
+ src_block_id, block_id, jumpkind=job.jumpkind, stmt_idx=src_exit_stmt_idx, ins_addr=src_ins_addr
1303
+ )
1304
+ self._update_function_transition_graph(
1305
+ src_block_id, block_id, jumpkind=job.jumpkind, ins_addr=src_ins_addr, stmt_idx=src_exit_stmt_idx
1306
+ )
1307
+
1308
+ if block_id in self._pending_edges:
1309
+ # there are some edges waiting to be created. do it here.
1310
+ for src_key, dst_key, data in self._pending_edges[block_id]:
1311
+ self._graph_add_edge(src_key, dst_key, **data)
1312
+ del self._pending_edges[block_id]
1313
+
1314
+ block_info = {
1315
+ reg: sim_successors.initial_state.registers.load(reg) for reg in self.project.arch.persistent_regs
1316
+ }
1317
+ self._block_artifacts[addr] = block_info
1318
+
1319
+ job.cfg_node = cfg_node
1320
+ job.sim_successors = sim_successors
1321
+ job.exception_info = exception_info
1322
+
1323
+ # For debugging purposes!
1324
+ job.successor_status = {}
1325
+
1326
+ def _get_successors(self, job):
1327
+ """
1328
+ Get a collection of successors out of the current job.
1329
+
1330
+ :param CFGJob job: The CFGJob instance.
1331
+ :return: A collection of successors.
1332
+ :rtype: list
1333
+ """
1334
+
1335
+ addr = job.addr
1336
+ sim_successors = job.sim_successors
1337
+ cfg_node = job.cfg_node
1338
+ input_state = job.state
1339
+ func_addr = job.func_addr
1340
+
1341
+ # check step limit
1342
+ if self._max_steps is not None:
1343
+ depth = cfg_node.depth
1344
+ if depth >= self._max_steps:
1345
+ return []
1346
+
1347
+ successors = []
1348
+ is_indirect_jump = sim_successors.sort == "IRSB" and self._is_indirect_jump(cfg_node, sim_successors)
1349
+ indirect_jump_resolved_by_resolvers = False
1350
+
1351
+ if is_indirect_jump and self._resolve_indirect_jumps:
1352
+ # Try to resolve indirect jumps
1353
+ irsb = input_state.block(cross_insn_opt=False).vex
1354
+
1355
+ resolved, resolved_targets, ij = self._indirect_jump_encountered(
1356
+ addr, cfg_node, irsb, func_addr, stmt_idx=DEFAULT_STATEMENT
1357
+ )
1358
+ if resolved:
1359
+ successors = self._convert_indirect_jump_targets_to_states(job, resolved_targets)
1360
+ if ij:
1361
+ self._indirect_jump_resolved(ij, ij.addr, None, resolved_targets)
1362
+ else:
1363
+ # Try to resolve this indirect jump using heavier approaches
1364
+ resolved_targets = self._process_one_indirect_jump(ij, func_graph_complete=False)
1365
+ successors = self._convert_indirect_jump_targets_to_states(job, resolved_targets)
1366
+
1367
+ if successors:
1368
+ indirect_jump_resolved_by_resolvers = True
1369
+ else:
1370
+ # It's unresolved. Add it to the wait list (but apparently we don't have any better way to resolve it
1371
+ # right now).
1372
+ self._indirect_jumps_to_resolve.add(ij)
1373
+
1374
+ if not successors:
1375
+ # Get all successors of this block
1376
+ successors = (
1377
+ (sim_successors.flat_successors + sim_successors.unsat_successors)
1378
+ if addr not in self._avoid_runs
1379
+ else []
1380
+ )
1381
+
1382
+ # Post-process successors
1383
+ successors, job.extra_info = self._post_process_successors(input_state, sim_successors, successors)
1384
+
1385
+ all_successors = successors + sim_successors.unconstrained_successors
1386
+
1387
+ # make sure FakeRets are at the last
1388
+ all_successors = [suc for suc in all_successors if suc.history.jumpkind != "Ijk_FakeRet"] + [
1389
+ suc for suc in all_successors if suc.history.jumpkind == "Ijk_FakeRet"
1390
+ ]
1391
+
1392
+ if self._keep_state:
1393
+ cfg_node.final_states = all_successors[::]
1394
+
1395
+ if is_indirect_jump and not indirect_jump_resolved_by_resolvers:
1396
+ # For indirect jumps, filter successors that do not make sense
1397
+ successors = self._filter_insane_successors(successors)
1398
+
1399
+ successors = self._try_resolving_indirect_jumps(
1400
+ sim_successors, cfg_node, func_addr, successors, job.exception_info, self._block_artifacts
1401
+ )
1402
+ # Remove all successors whose IP is symbolic
1403
+ successors = [s for s in successors if not s.ip.symbolic]
1404
+
1405
+ # Add additional edges supplied by the user
1406
+ successors = self._add_additional_edges(input_state, sim_successors, cfg_node, successors)
1407
+
1408
+ # if base graph is used, add successors implied from the graph
1409
+ if self._base_graph:
1410
+ basegraph_successor_addrs = set()
1411
+ for src_, dst_ in self._base_graph.edges():
1412
+ if src_.addr == addr:
1413
+ basegraph_successor_addrs.add(dst_.addr)
1414
+ successor_addrs = {s.solver.eval(s.ip) for s in successors}
1415
+ extra_successor_addrs = basegraph_successor_addrs - successor_addrs
1416
+
1417
+ if all_successors: # make sure we have a base state to use
1418
+ base_state = all_successors[0] # TODO: for calls, we want to use the fake_ret state
1419
+
1420
+ for s_addr in extra_successor_addrs:
1421
+ # an extra target
1422
+ successor_state = base_state.copy()
1423
+ successor_state.ip = s_addr
1424
+ successors.append(successor_state)
1425
+ else:
1426
+ if extra_successor_addrs:
1427
+ l.error("CFGEmulated terminates at %#x although base graph provided more exits.", addr)
1428
+
1429
+ if not successors:
1430
+ # There is no way out :-(
1431
+ # Log it first
1432
+ self._push_unresolvable_run(addr)
1433
+
1434
+ if sim_successors.sort == "SimProcedure" and isinstance(
1435
+ sim_successors.artifacts["procedure"], SIM_PROCEDURES["stubs"]["PathTerminator"]
1436
+ ):
1437
+ # If there is no valid exit in this branch and it's not
1438
+ # intentional (e.g. caused by a SimProcedure that does not
1439
+ # do_return) , we should make it return to its call-site. However,
1440
+ # we don't want to use its state anymore as it might be corrupted.
1441
+ # Just create an edge in the graph.
1442
+ return_target = job.call_stack.current_return_target
1443
+ if return_target is not None:
1444
+ new_call_stack = job.call_stack_copy()
1445
+ return_target_key = self._generate_block_id(
1446
+ new_call_stack.stack_suffix(self.context_sensitivity_level), return_target, False
1447
+ ) # You can never return to a syscall
1448
+
1449
+ if not cfg_node.instruction_addrs:
1450
+ ret_ins_addr = None
1451
+ else:
1452
+ if self.project.arch.branch_delay_slot:
1453
+ if len(cfg_node.instruction_addrs) > 1:
1454
+ ret_ins_addr = cfg_node.instruction_addrs[-2]
1455
+ else:
1456
+ l.error("At %s: expecting more than one instruction. Only got one.", cfg_node)
1457
+ ret_ins_addr = None
1458
+ else:
1459
+ ret_ins_addr = cfg_node.instruction_addrs[-1]
1460
+
1461
+ # Things might be a bit difficult here. _graph_add_edge() requires both nodes to exist, but here
1462
+ # the return target node may not exist yet. If that's the case, we will put it into a "delayed edge
1463
+ # list", and add this edge later when the return target CFGNode is created.
1464
+ if return_target_key in self._nodes:
1465
+ self._graph_add_edge(
1466
+ job.block_id,
1467
+ return_target_key,
1468
+ jumpkind="Ijk_Ret",
1469
+ stmt_id=DEFAULT_STATEMENT,
1470
+ ins_addr=ret_ins_addr,
1471
+ )
1472
+ else:
1473
+ self._pending_edges[return_target_key].append(
1474
+ (
1475
+ job.block_id,
1476
+ return_target_key,
1477
+ {
1478
+ "jumpkind": "Ijk_Ret",
1479
+ "stmt_id": DEFAULT_STATEMENT,
1480
+ "ins_addr": ret_ins_addr,
1481
+ },
1482
+ )
1483
+ )
1484
+
1485
+ else:
1486
+ # There are no successors, but we still want to update the function graph
1487
+ artifacts = job.sim_successors.artifacts
1488
+ if "irsb" in artifacts and "insn_addrs" in artifacts and artifacts["insn_addrs"]:
1489
+ the_irsb = artifacts["irsb"]
1490
+ insn_addrs = artifacts["insn_addrs"]
1491
+ self._handle_job_without_successors(job, the_irsb, insn_addrs)
1492
+
1493
+ # TODO: replace it with a DDG-based function IO analysis
1494
+ # handle all actions
1495
+ if successors:
1496
+ self._handle_actions(
1497
+ successors[0],
1498
+ sim_successors,
1499
+ job.current_function,
1500
+ job.current_stack_pointer,
1501
+ set(),
1502
+ )
1503
+
1504
+ return successors
1505
+
1506
+ def _post_job_handling(self, job: CFGJob, _new_jobs, successors: list[SimState]): # type: ignore[override]
1507
+ """
1508
+
1509
+ :param CFGJob job:
1510
+ :param successors:
1511
+ :return:
1512
+ """
1513
+
1514
+ # Finally, post-process CFG Node and log the return target
1515
+ if job.extra_info and job.extra_info["is_call_jump"] and job.extra_info["return_target"] is not None:
1516
+ job.cfg_node.return_target = job.extra_info["return_target"]
1517
+
1518
+ # Debugging output if needed
1519
+ if l.level == logging.DEBUG:
1520
+ # Only in DEBUG mode do we process and output all those shit
1521
+ self._post_handle_job_debug(job, successors)
1522
+
1523
+ # SimInspect breakpoints support
1524
+ job.state._inspect("cfg_handle_job", BP_AFTER)
1525
+
1526
+ def _post_process_successors(self, input_state, sim_successors, successors):
1527
+ """
1528
+ Filter the list of successors
1529
+
1530
+ :param SimState input_state: Input state.
1531
+ :param SimSuccessors sim_successors: The SimSuccessors instance.
1532
+ :param list successors: A list of successors generated after processing the current block.
1533
+ :return: A list of successors.
1534
+ :rtype: list
1535
+ """
1536
+
1537
+ if sim_successors.sort == "IRSB" and input_state.thumb:
1538
+ successors = self._arm_thumb_filter_jump_successors(
1539
+ sim_successors.artifacts["irsb"],
1540
+ successors,
1541
+ lambda state: state.scratch.ins_addr,
1542
+ lambda state: state.scratch.exit_stmt_idx,
1543
+ lambda state: state.history.jumpkind,
1544
+ )
1545
+
1546
+ # If there is a call exit, we shouldn't put the default exit (which
1547
+ # is artificial) into the CFG. The exits will be Ijk_Call and
1548
+ # Ijk_FakeRet, and Ijk_Call always goes first
1549
+ extra_info = {
1550
+ "is_call_jump": False,
1551
+ "call_target": None,
1552
+ "return_target": None,
1553
+ "last_call_exit_target": None,
1554
+ "skip_fakeret": False,
1555
+ }
1556
+
1557
+ # Post-process jumpkind before touching all_successors
1558
+ for (
1559
+ suc
1560
+ ) in sim_successors.all_successors: # we process all successors here to include potential unsat successors
1561
+ suc_jumpkind = suc.history.jumpkind
1562
+ if self._is_call_jumpkind(suc_jumpkind):
1563
+ extra_info["is_call_jump"] = True
1564
+ break
1565
+
1566
+ return successors, extra_info
1567
+
1568
+ def _post_handle_job_debug(self, job: CFGJob, successors: list[SimState]) -> None:
1569
+ """
1570
+ Post job handling: print debugging information regarding the current job.
1571
+
1572
+ :param CFGJob job: The current CFGJob instance.
1573
+ :param list successors: All successors of the analysis job.
1574
+ :return: None
1575
+ """
1576
+
1577
+ sim_successors = job.sim_successors
1578
+ call_stack_suffix = job.call_stack_suffix
1579
+ extra_info = job.extra_info
1580
+ successor_status = job.successor_status
1581
+
1582
+ func = self.project.loader.find_symbol(job.func_addr)
1583
+ obj = self.project.loader.find_object_containing(job.addr)
1584
+ function_name = func.name if func is not None else None
1585
+ module_name = obj.provides if obj is not None else None
1586
+
1587
+ node = self.model.get_node(job.block_id)
1588
+ depth_str = f"(D:{node.depth})" if node.depth is not None else ""
1589
+
1590
+ l.debug(
1591
+ "%s [%#x%s | %s]",
1592
+ sim_successors.description,
1593
+ sim_successors.addr,
1594
+ depth_str,
1595
+ "->".join([hex(i) for i in call_stack_suffix if i is not None]),
1596
+ )
1597
+ l.debug("(Function %s of binary %s)", function_name, module_name)
1598
+ l.debug("| Call jump: %s", extra_info["is_call_jump"] if extra_info is not None else "unknown")
1599
+
1600
+ for suc in successors:
1601
+ jumpkind = suc.history.jumpkind
1602
+ exit_type_str = "Simulated Ret" if jumpkind == "Ijk_FakeRet" else "-"
1603
+ try:
1604
+ l.debug(
1605
+ "| target: %#x %s [%s] %s",
1606
+ suc.solver.eval_one(suc.ip),
1607
+ successor_status[suc],
1608
+ exit_type_str,
1609
+ jumpkind,
1610
+ )
1611
+ except (SimValueError, SimSolverModeError):
1612
+ l.debug("| target cannot be concretized. %s [%s] %s", successor_status[suc], exit_type_str, jumpkind)
1613
+ l.debug("%d exits remaining, %d exits pending.", len(self._job_info_queue), len(self._pending_jobs))
1614
+ l.debug("%d unique basic blocks are analyzed so far.", len(self._analyzed_addrs))
1615
+
1616
+ def _iteratively_clean_pending_exits(self):
1617
+ """
1618
+ Iteratively update the completed functions set, analyze whether each function returns or not, and remove
1619
+ pending exits if the callee function does not return. We do this iteratively so that we come to a fixed point
1620
+ in the end. In most cases, the number of outer iteration equals to the maximum levels of wrapped functions
1621
+ whose "returningness" is determined by the very last function it calls.
1622
+
1623
+ :return: None
1624
+ """
1625
+
1626
+ while True:
1627
+ # did we finish analyzing any function?
1628
+ # fill in self._completed_functions
1629
+ self._make_completed_functions()
1630
+
1631
+ if self._pending_jobs:
1632
+ # There are no more remaining jobs, but only pending jobs left. Each pending job corresponds to
1633
+ # a previous job that does not return properly.
1634
+ # Now it's a good time to analyze each function (that we have so far) and determine if it is a)
1635
+ # returning, b) not returning, or c) unknown. For those functions that are definitely not returning,
1636
+ # remove the corresponding pending exits from `pending_jobs` array. Perform this procedure iteratively
1637
+ # until no new not-returning functions appear. Then we pick a pending exit based on the following
1638
+ # priorities:
1639
+ # - Job pended by a returning function
1640
+ # - Job pended by an unknown function
1641
+
1642
+ new_changes = self._iteratively_analyze_function_features()
1643
+ functions_do_not_return = new_changes["functions_do_not_return"]
1644
+
1645
+ self._update_function_callsites(functions_do_not_return)
1646
+
1647
+ if not self._clean_pending_exits():
1648
+ # no more pending exits are removed. we are good to go!
1649
+ break
1650
+ else:
1651
+ break
1652
+
1653
+ def _clean_pending_exits(self):
1654
+ """
1655
+ Remove those pending exits if:
1656
+ a) they are the return exits of non-returning SimProcedures
1657
+ b) they are the return exits of non-returning syscalls
1658
+ c) they are the return exits of non-returning functions
1659
+
1660
+ :return: True if any pending exits are removed, False otherwise
1661
+ :rtype: bool
1662
+ """
1663
+
1664
+ pending_exits_to_remove = []
1665
+
1666
+ for block_id, jobs in self._pending_jobs.items():
1667
+ for pe in jobs:
1668
+ if pe.returning_source is None:
1669
+ # The original call failed. This pending exit must be followed.
1670
+ continue
1671
+
1672
+ func = self.kb.functions.function(pe.returning_source)
1673
+ if func is None:
1674
+ # Why does it happen?
1675
+ l.warning(
1676
+ "An expected function at %s is not found. Please report it to Fish.",
1677
+ hex(pe.returning_source) if pe.returning_source is not None else "None",
1678
+ )
1679
+ continue
1680
+
1681
+ if func.returning is False:
1682
+ # Oops, it's not returning
1683
+ # Remove this pending exit
1684
+ pending_exits_to_remove.append(block_id)
1685
+
1686
+ # We want to mark that call as not returning in the current function
1687
+ current_function_addr = self._block_id_current_func_addr(block_id)
1688
+ if current_function_addr is not None:
1689
+ current_function = self.kb.functions.function(current_function_addr)
1690
+ if current_function is not None:
1691
+ call_site_addr = self._block_id_addr(pe.src_block_id)
1692
+ current_function._call_sites[call_site_addr] = (func.addr, None)
1693
+ else:
1694
+ l.warning(
1695
+ "An expected function at %#x is not found. Please report it to Fish.",
1696
+ current_function_addr,
1697
+ )
1698
+
1699
+ for block_id in pending_exits_to_remove:
1700
+ l.debug(
1701
+ "Removing all pending exits to %#x since the target function does not return",
1702
+ self._block_id_addr(block_id),
1703
+ )
1704
+
1705
+ for to_remove in self._pending_jobs[block_id]:
1706
+ self._deregister_analysis_job(to_remove.caller_func_addr, to_remove)
1707
+
1708
+ del self._pending_jobs[block_id]
1709
+
1710
+ return bool(pending_exits_to_remove)
1711
+
1712
+ # Successor handling
1713
+
1714
+ def _pre_handle_successor_state(self, extra_info, jumpkind, target_addr):
1715
+ """
1716
+
1717
+ :return: None
1718
+ """
1719
+
1720
+ # Fill up extra_info
1721
+ if extra_info["is_call_jump"] and self._is_call_jumpkind(jumpkind):
1722
+ extra_info["call_target"] = target_addr
1723
+
1724
+ if extra_info["is_call_jump"] and jumpkind == "Ijk_FakeRet":
1725
+ extra_info["return_target"] = target_addr
1726
+
1727
+ if jumpkind == "Ijk_Call":
1728
+ extra_info["last_call_exit_target"] = target_addr
1729
+
1730
+ def _handle_successor(self, job, successor: SimState, successors):
1731
+ """
1732
+ Returns a new CFGJob instance for further analysis, or None if there is no immediate state to perform the
1733
+ analysis on.
1734
+
1735
+ :param CFGJob job: The current job.
1736
+ """
1737
+
1738
+ state: SimState = successor
1739
+ all_successor_states = successors
1740
+ addr = job.addr
1741
+
1742
+ # The PathWrapper instance to return
1743
+ pw = None
1744
+
1745
+ job.successor_status[state] = ""
1746
+
1747
+ new_state = state.copy()
1748
+ suc_jumpkind = state.history.jumpkind
1749
+ suc_exit_stmt_idx = state.scratch.exit_stmt_idx
1750
+ suc_exit_ins_addr = state.scratch.exit_ins_addr
1751
+
1752
+ if suc_jumpkind in {
1753
+ "Ijk_EmWarn",
1754
+ "Ijk_NoDecode",
1755
+ "Ijk_MapFail",
1756
+ "Ijk_NoRedir",
1757
+ "Ijk_SigTRAP",
1758
+ "Ijk_SigSEGV",
1759
+ "Ijk_ClientReq",
1760
+ }:
1761
+ # Ignore SimExits that are of these jumpkinds
1762
+ job.successor_status[state] = "Skipped"
1763
+ return []
1764
+
1765
+ call_target = job.extra_info["call_target"]
1766
+ if suc_jumpkind == "Ijk_FakeRet" and call_target is not None and self.project.is_hooked(call_target):
1767
+ # if the call points to a SimProcedure that doesn't return, we don't follow the fakeret anymore
1768
+ sim_proc = self.project._sim_procedures[call_target]
1769
+ if sim_proc.NO_RET:
1770
+ return []
1771
+
1772
+ # Get target address
1773
+ try:
1774
+ target_addr = state.solver.eval_one(state.ip)
1775
+ except (SimValueError, SimSolverModeError):
1776
+ # It cannot be concretized currently. Maybe we can handle it later, maybe it just cannot be concretized
1777
+ target_addr = None
1778
+ if suc_jumpkind == "Ijk_Ret":
1779
+ target_addr = job.call_stack.current_return_target
1780
+ if target_addr is not None:
1781
+ new_state.ip = claripy.BVV(target_addr, new_state.arch.bits)
1782
+
1783
+ if target_addr is None:
1784
+ # Unlucky...
1785
+ return []
1786
+
1787
+ if state.thumb:
1788
+ # Make sure addresses are always odd. It is important to encode this information in the address for the
1789
+ # time being.
1790
+ target_addr |= 1
1791
+
1792
+ # see if the target successor is in our whitelist
1793
+ if self._address_whitelist is not None and target_addr not in self._address_whitelist:
1794
+ l.debug("Successor %#x is not in the address whitelist. Skip.", target_addr)
1795
+ return []
1796
+
1797
+ # see if this edge is in the base graph
1798
+ if self._base_graph is not None:
1799
+ # TODO: make it more efficient. the current implementation is half-assed and extremely slow
1800
+ for src_, dst_ in self._base_graph.edges():
1801
+ if src_.addr == addr and dst_.addr == target_addr:
1802
+ break
1803
+ else:
1804
+ # not found
1805
+ l.debug("Edge (%#x -> %#x) is not found in the base graph. Skip.", addr, target_addr)
1806
+ return []
1807
+
1808
+ # Fix target_addr for syscalls
1809
+ if suc_jumpkind.startswith("Ijk_Sys"):
1810
+ try:
1811
+ syscall_proc = self.project.simos.syscall(new_state)
1812
+ except AngrSyscallError:
1813
+ syscall_proc = None
1814
+ if syscall_proc is not None:
1815
+ target_addr = syscall_proc.addr
1816
+
1817
+ self._pre_handle_successor_state(job.extra_info, suc_jumpkind, target_addr)
1818
+
1819
+ if suc_jumpkind == "Ijk_FakeRet":
1820
+ if target_addr == job.extra_info["last_call_exit_target"]:
1821
+ l.debug("... skipping a fake return exit that has the same target with its call exit.")
1822
+ job.successor_status[state] = "Skipped"
1823
+ return []
1824
+
1825
+ if job.extra_info["skip_fakeret"]:
1826
+ l.debug("... skipping a fake return exit since the function it's calling doesn't return")
1827
+ job.successor_status[state] = "Skipped - non-returning function 0x{:x}".format(
1828
+ job.extra_info["call_target"]
1829
+ )
1830
+ return []
1831
+
1832
+ # TODO: Make it optional
1833
+ if suc_jumpkind == "Ijk_Ret" and self._call_depth is not None and len(job.call_stack) <= 1:
1834
+ # We cannot continue anymore since this is the end of the function where we started tracing
1835
+ l.debug("... reaching the end of the starting function, skip.")
1836
+ job.successor_status[state] = "Skipped - reaching the end of the starting function"
1837
+ return []
1838
+
1839
+ # Create the new call stack of target block
1840
+ new_call_stack = self._create_new_call_stack(addr, all_successor_states, job, target_addr, suc_jumpkind)
1841
+ # Create the callstack suffix
1842
+ new_call_stack_suffix = new_call_stack.stack_suffix(self._context_sensitivity_level)
1843
+ # Tuple that will be used to index this exit
1844
+ new_tpl = self._generate_block_id(new_call_stack_suffix, target_addr, suc_jumpkind.startswith("Ijk_Sys"))
1845
+
1846
+ # We might have changed the mode for this basic block
1847
+ # before. Make sure it is still running in 'fastpath' mode
1848
+ self._reset_state_mode(new_state, "fastpath")
1849
+
1850
+ pw = CFGJob(
1851
+ target_addr,
1852
+ new_state,
1853
+ self._context_sensitivity_level,
1854
+ src_block_id=job.block_id,
1855
+ src_exit_stmt_idx=suc_exit_stmt_idx,
1856
+ src_ins_addr=suc_exit_ins_addr,
1857
+ call_stack=new_call_stack,
1858
+ jumpkind=suc_jumpkind,
1859
+ )
1860
+ # Special case: If the binary has symbols and the target address is a function, but for some reason (e.g.,
1861
+ # a tail-call optimization) the CallStack's function address is still the old function address, we will have to
1862
+ # overwrite it here.
1863
+ if not self._is_call_jumpkind(pw.jumpkind):
1864
+ target_symbol = self.project.loader.find_symbol(target_addr)
1865
+ if target_symbol and target_symbol.is_function:
1866
+ # Force update the function address
1867
+ pw.func_addr = target_addr
1868
+
1869
+ # Generate new exits
1870
+ if suc_jumpkind == "Ijk_Ret":
1871
+ # This is the real return exit
1872
+ job.successor_status[state] = "Appended"
1873
+
1874
+ elif suc_jumpkind == "Ijk_FakeRet":
1875
+ # This is the default "fake" retn that generated at each
1876
+ # call. Save them first, but don't process them right
1877
+ # away
1878
+ # st = self.project._simos.prepare_call_state(new_state, initial_state=saved_state)
1879
+ st = new_state
1880
+ self._reset_state_mode(st, "fastpath")
1881
+
1882
+ pw = None # clear the job
1883
+ pe = PendingJob(
1884
+ job.func_addr,
1885
+ job.extra_info["call_target"],
1886
+ st,
1887
+ job.block_id,
1888
+ suc_exit_stmt_idx,
1889
+ suc_exit_ins_addr,
1890
+ new_call_stack,
1891
+ )
1892
+ self._pending_jobs[new_tpl].append(pe)
1893
+ self._register_analysis_job(pe.caller_func_addr, pe)
1894
+ job.successor_status[state] = "Pended"
1895
+
1896
+ elif self._traced_addrs[new_call_stack_suffix][target_addr] >= 1 and suc_jumpkind == "Ijk_Ret":
1897
+ # This is a corner case for the f****** ARM instruction
1898
+ # like
1899
+ # BLEQ <address>
1900
+ # If we have analyzed the boring exit before returning from that called address, we will lose the link
1901
+ # between the last block of the function being called and the basic block it returns to. We cannot
1902
+ # reanalyze the basic block as we are not flow-sensitive, but we can still record the connection and make
1903
+ # for it afterwards.
1904
+ pass
1905
+
1906
+ else:
1907
+ job.successor_status[state] = "Appended"
1908
+
1909
+ if job.extra_info["is_call_jump"] and job.extra_info["call_target"] in self._non_returning_functions:
1910
+ job.extra_info["skip_fakeret"] = True
1911
+
1912
+ if not pw:
1913
+ return []
1914
+
1915
+ # register the job
1916
+ self._register_analysis_job(pw.func_addr, pw)
1917
+
1918
+ return [pw]
1919
+
1920
+ def _handle_job_without_successors(self, job, irsb, insn_addrs):
1921
+ """
1922
+ A block without successors should still be handled so it can be added to the function graph correctly.
1923
+
1924
+ :param CFGJob job: The current job that do not have any successor.
1925
+ :param IRSB irsb: The related IRSB.
1926
+ :param insn_addrs: A list of instruction addresses of this IRSB.
1927
+ :return: None
1928
+ """
1929
+
1930
+ # it's not an empty block
1931
+
1932
+ # handle all conditional exits
1933
+ ins_addr = job.addr
1934
+ for stmt_idx, stmt in enumerate(irsb.statements):
1935
+ if type(stmt) is pyvex.IRStmt.IMark:
1936
+ ins_addr = stmt.addr + stmt.delta
1937
+ elif type(stmt) is pyvex.IRStmt.Exit:
1938
+ successor_jumpkind = stmt.jk
1939
+ self._update_function_transition_graph(
1940
+ job.block_id,
1941
+ None,
1942
+ jumpkind=successor_jumpkind,
1943
+ ins_addr=ins_addr,
1944
+ stmt_idx=stmt_idx,
1945
+ )
1946
+
1947
+ # handle the default exit
1948
+ successor_jumpkind = irsb.jumpkind
1949
+ successor_last_ins_addr = insn_addrs[-1]
1950
+ self._update_function_transition_graph(
1951
+ job.block_id,
1952
+ None,
1953
+ jumpkind=successor_jumpkind,
1954
+ ins_addr=successor_last_ins_addr,
1955
+ stmt_idx=DEFAULT_STATEMENT,
1956
+ )
1957
+
1958
+ # SimAction handling
1959
+
1960
+ def _handle_actions(self, state, current_run, func, sp_addr, accessed_registers):
1961
+ """
1962
+ For a given state and current location of of execution, will update a function by adding the offsets of
1963
+ appropriate actions to the stack variable or argument registers for the fnc.
1964
+
1965
+ :param SimState state: upcoming state.
1966
+ :param SimSuccessors current_run: possible result states.
1967
+ :param knowledge.Function func: current function.
1968
+ :param int sp_addr: stack pointer address.
1969
+ :param set accessed_registers: set of before accessed registers.
1970
+ """
1971
+ se = state.solver
1972
+
1973
+ if func is not None and sp_addr is not None:
1974
+ # Fix the stack pointer (for example, skip the return address on the stack)
1975
+ new_sp_addr = sp_addr + self.project.arch.call_sp_fix
1976
+
1977
+ actions = [a for a in state.history.recent_actions if a.bbl_addr == current_run.addr]
1978
+
1979
+ for a in actions:
1980
+ if a.type == "mem" and a.action == "read":
1981
+ try:
1982
+ addr = se.eval_one(a.addr.ast, default=0)
1983
+ except (claripy.ClaripyError, SimSolverModeError):
1984
+ continue
1985
+ if (self.project.arch.call_pushes_ret and addr >= new_sp_addr) or (
1986
+ not self.project.arch.call_pushes_ret and addr >= new_sp_addr
1987
+ ):
1988
+ # TODO: What if a variable locates higher than the stack is modified as well? We probably want
1989
+ # TODO: to make sure the accessing address falls in the range of stack
1990
+ offset = addr - new_sp_addr
1991
+ func._add_argument_stack_variable(offset)
1992
+ elif a.type == "reg":
1993
+ offset = a.offset
1994
+ if a.action == "read" and offset not in accessed_registers:
1995
+ func._add_argument_register(offset)
1996
+ elif a.action == "write":
1997
+ accessed_registers.add(offset)
1998
+ else:
1999
+ l.error(
2000
+ "handle_actions: Function not found, or stack pointer is None. It might indicates unbalanced stack."
2001
+ )
2002
+
2003
+ # Private utils - DiGraph construction and manipulation
2004
+
2005
+ def _graph_get_node(self, node_key, terminator_for_nonexistent_node=False):
2006
+ """
2007
+
2008
+ :param node_key:
2009
+ :return:
2010
+ """
2011
+
2012
+ if node_key not in self._nodes:
2013
+ if not terminator_for_nonexistent_node:
2014
+ return None
2015
+ # Generate a PathTerminator node
2016
+ addr = self._block_id_addr(node_key)
2017
+ func_addr = self._block_id_current_func_addr(node_key)
2018
+ if func_addr is None:
2019
+ # We'll have to use the current block address instead
2020
+ # TODO: Is it really OK?
2021
+ func_addr = self._block_id_addr(node_key)
2022
+
2023
+ is_thumb = isinstance(self.project.arch, ArchARM) and addr % 2 == 1
2024
+
2025
+ pt = CFGENode(
2026
+ self._block_id_addr(node_key),
2027
+ None,
2028
+ self.model,
2029
+ input_state=None,
2030
+ simprocedure_name="PathTerminator",
2031
+ function_address=func_addr,
2032
+ callstack_key=self._block_id_callstack_key(node_key),
2033
+ thumb=is_thumb,
2034
+ )
2035
+ if self._keep_state:
2036
+ # We don't have an input state available for it (otherwise we won't have to create a
2037
+ # PathTerminator). This is just a trick to make get_any_irsb() happy.
2038
+ pt.input_state = self.project.factory.entry_state()
2039
+ pt.input_state.ip = pt.addr
2040
+ self._model.add_node(node_key, pt)
2041
+
2042
+ if is_thumb:
2043
+ self._thumb_addrs.add(addr)
2044
+ self._thumb_addrs.add(addr - 1)
2045
+
2046
+ l.debug("Block ID %s does not exist. Create a PathTerminator instead.", self._block_id_repr(node_key))
2047
+
2048
+ return self._nodes[node_key]
2049
+
2050
+ def _graph_add_edge(self, src_node_key, dst_node_key, **kwargs):
2051
+ """
2052
+
2053
+ :param src_node_key:
2054
+ :param dst_node_key:
2055
+ :param jumpkind:
2056
+ :param exit_stmt_idx:
2057
+ :return:
2058
+ """
2059
+
2060
+ dst_node = self._graph_get_node(dst_node_key, terminator_for_nonexistent_node=True)
2061
+
2062
+ if src_node_key is None:
2063
+ self.graph.add_node(dst_node)
2064
+
2065
+ else:
2066
+ src_node = self._graph_get_node(src_node_key, terminator_for_nonexistent_node=True)
2067
+ self.graph.add_edge(src_node, dst_node, **kwargs)
2068
+
2069
+ def _update_function_transition_graph(
2070
+ self, src_node_key, dst_node_key, jumpkind="Ijk_Boring", ins_addr=None, stmt_idx=None, confirmed=None
2071
+ ):
2072
+ """
2073
+ Update transition graphs of functions in function manager based on information passed in.
2074
+
2075
+ :param src_node_key: Node key of the source CFGNode. Might be None.
2076
+ :param dst_node: Node key of the destination CFGNode. Might be None.
2077
+ :param str jumpkind: Jump kind of this transition.
2078
+ :param int ret_addr: The theoretical return address for calls.
2079
+ :param int or None ins_addr: Address of the instruction where this transition is made.
2080
+ :param int or None stmt_idx: ID of the statement where this transition is made.
2081
+ :param bool or None confirmed: Whether this call transition has been confirmed or not.
2082
+ :return: None
2083
+ """
2084
+
2085
+ if dst_node_key is not None:
2086
+ dst_node = self._graph_get_node(dst_node_key, terminator_for_nonexistent_node=True)
2087
+ dst_node_addr = dst_node.addr
2088
+ dst_codenode = dst_node.to_codenode()
2089
+ dst_node_func_addr = dst_node.function_address
2090
+ else:
2091
+ dst_node = None
2092
+ dst_node_addr = None
2093
+ dst_codenode = None
2094
+ dst_node_func_addr = None
2095
+
2096
+ if src_node_key is None:
2097
+ if dst_node is None:
2098
+ raise ValueError("Either src_node_key or dst_node_key must be specified.")
2099
+ self.kb.functions.function(dst_node.function_address, create=True)._register_node(True, dst_codenode)
2100
+ return
2101
+
2102
+ src_node = self._graph_get_node(src_node_key, terminator_for_nonexistent_node=True)
2103
+
2104
+ # Update the transition graph of current function
2105
+ if jumpkind == "Ijk_Call":
2106
+ ret_addr = src_node.return_target
2107
+ ret_node = (
2108
+ self.kb.functions.function(src_node.function_address, create=True)._get_block(ret_addr).codenode
2109
+ if ret_addr
2110
+ else None
2111
+ )
2112
+
2113
+ self.kb.functions._add_call_to(
2114
+ function_addr=src_node.function_address,
2115
+ from_node=src_node.to_codenode(),
2116
+ to_addr=dst_node_addr,
2117
+ retn_node=ret_node,
2118
+ syscall=False,
2119
+ ins_addr=ins_addr,
2120
+ stmt_idx=stmt_idx,
2121
+ )
2122
+
2123
+ if jumpkind.startswith("Ijk_Sys"):
2124
+ self.kb.functions._add_call_to(
2125
+ function_addr=src_node.function_address,
2126
+ from_node=src_node.to_codenode(),
2127
+ to_addr=dst_node_addr,
2128
+ retn_node=src_node.to_codenode(), # For syscalls, they are returning to the address of themselves
2129
+ syscall=True,
2130
+ ins_addr=ins_addr,
2131
+ stmt_idx=stmt_idx,
2132
+ )
2133
+
2134
+ elif jumpkind == "Ijk_Ret":
2135
+ # Create a return site for current function
2136
+ self.kb.functions._add_return_from(
2137
+ function_addr=src_node.function_address,
2138
+ from_node=src_node.to_codenode(),
2139
+ to_node=dst_codenode,
2140
+ )
2141
+
2142
+ if dst_node is not None:
2143
+ # Create a returning edge in the caller function
2144
+ self.kb.functions._add_return_from_call(
2145
+ function_addr=dst_node_func_addr,
2146
+ src_function_addr=src_node.function_address,
2147
+ to_node=dst_codenode,
2148
+ )
2149
+
2150
+ elif jumpkind == "Ijk_FakeRet":
2151
+ self.kb.functions._add_fakeret_to(
2152
+ function_addr=src_node.function_address,
2153
+ from_node=src_node.to_codenode(),
2154
+ to_node=dst_codenode,
2155
+ confirmed=confirmed,
2156
+ )
2157
+
2158
+ elif jumpkind in ("Ijk_Boring", "Ijk_InvalICache"):
2159
+ src_obj = self.project.loader.find_object_containing(src_node.addr)
2160
+ dest_obj = self.project.loader.find_object_containing(dst_node.addr) if dst_node is not None else None
2161
+
2162
+ # if true: Jump/branch within the same object. Might be an outside jump.
2163
+ # if false: Jump/branch between different objects. Must be an outside jump.
2164
+ to_outside = src_node.function_address != dst_node_func_addr if src_obj is dest_obj else True
2165
+
2166
+ if not to_outside:
2167
+ self.kb.functions._add_transition_to(
2168
+ function_addr=src_node.function_address,
2169
+ from_node=src_node.to_codenode(),
2170
+ to_node=dst_codenode,
2171
+ ins_addr=ins_addr,
2172
+ stmt_idx=stmt_idx,
2173
+ )
2174
+
2175
+ else:
2176
+ self.kb.functions._add_outside_transition_to(
2177
+ function_addr=src_node.function_address,
2178
+ from_node=src_node.to_codenode(),
2179
+ to_node=dst_codenode,
2180
+ to_function_addr=dst_node_func_addr,
2181
+ ins_addr=ins_addr,
2182
+ stmt_idx=stmt_idx,
2183
+ )
2184
+
2185
+ def _update_function_callsites(self, noreturns):
2186
+ """
2187
+ Update the callsites of functions (remove return targets) that are calling functions that are just deemed not
2188
+ returning.
2189
+
2190
+ :param iterable func_addrs: A collection of functions for newly-recovered non-returning functions.
2191
+ :return: None
2192
+ """
2193
+
2194
+ for callee_func in noreturns:
2195
+ # consult the callgraph to find callers of each function
2196
+ if callee_func.addr not in self.functions.callgraph:
2197
+ continue
2198
+ caller_addrs = self.functions.callgraph.predecessors(callee_func.addr)
2199
+ for caller_addr in caller_addrs:
2200
+ caller = self.functions[caller_addr]
2201
+ if callee_func not in caller.transition_graph:
2202
+ continue
2203
+ callsites = caller.transition_graph.predecessors(callee_func)
2204
+ for callsite in callsites:
2205
+ caller._add_call_site(callsite.addr, callee_func.addr, None)
2206
+
2207
+ def _add_additional_edges(self, input_state, sim_successors, cfg_node, successors):
2208
+ """
2209
+
2210
+ :return:
2211
+ """
2212
+
2213
+ # If we have additional edges for this block, add them in
2214
+ addr = cfg_node.addr
2215
+
2216
+ if addr in self._additional_edges:
2217
+ dests = self._additional_edges[addr]
2218
+ for dst in dests:
2219
+ if sim_successors.sort == "IRSB":
2220
+ base_state = sim_successors.all_successors[0].copy()
2221
+ else:
2222
+ # If true, we try to use the first successor.
2223
+ # If false, the SimProcedure doesn't have any successor (e.g. it's a PathTerminator)
2224
+ # We'll use its input state instead
2225
+ base_state = successors[0].copy() if successors else input_state
2226
+ base_state.ip = dst
2227
+ # TODO: Allow for sp adjustments
2228
+ successors.append(base_state)
2229
+ l.debug("Additional jump target %#x for block %s is appended.", dst, sim_successors.description)
2230
+
2231
+ return successors
2232
+
2233
+ def _filter_insane_successors(self, successors):
2234
+ """
2235
+ Throw away all successors whose target doesn't make sense
2236
+
2237
+ This method is called after we resolve an indirect jump using an unreliable method (like, not through one of
2238
+ the indirect jump resolvers, but through either pure concrete execution or backward slicing) to filter out the
2239
+ obviously incorrect successors.
2240
+
2241
+ :param list successors: A collection of successors.
2242
+ :return: A filtered list of successors
2243
+ :rtype: list
2244
+ """
2245
+
2246
+ old_successors = successors[::]
2247
+ successors = []
2248
+ for i, suc in enumerate(old_successors):
2249
+ if suc.solver.symbolic(suc.ip):
2250
+ # It's symbolic. Take it, and hopefully we can resolve it later
2251
+ successors.append(suc)
2252
+
2253
+ else:
2254
+ ip_int = suc.solver.eval_one(suc.ip)
2255
+
2256
+ if (
2257
+ self._is_address_executable(ip_int)
2258
+ or self.project.is_hooked(ip_int)
2259
+ or self.project.simos.is_syscall_addr(ip_int)
2260
+ ):
2261
+ successors.append(suc)
2262
+ else:
2263
+ l.debug(
2264
+ "An obviously incorrect successor %d/%d (%#x) is ditched", i + 1, len(old_successors), ip_int
2265
+ )
2266
+
2267
+ return successors
2268
+
2269
+ def _remove_non_return_edges(self):
2270
+ """
2271
+ Remove those return_from_call edges that actually do not return due to
2272
+ calling some not-returning functions.
2273
+ :return: None
2274
+ """
2275
+ for func in self.kb.functions.values():
2276
+ graph = func.transition_graph
2277
+ all_return_edges = [(u, v) for (u, v, data) in graph.edges(data=True) if data["type"] == "return"]
2278
+ for return_from_call_edge in all_return_edges:
2279
+ callsite_block_addr, return_to_addr = return_from_call_edge
2280
+ call_func_addr = func.get_call_target(callsite_block_addr)
2281
+ if call_func_addr is None:
2282
+ continue
2283
+
2284
+ call_func = self.kb.functions.function(call_func_addr)
2285
+ if call_func is None:
2286
+ # Weird...
2287
+ continue
2288
+
2289
+ if call_func.returning is False:
2290
+ # Remove that edge!
2291
+ graph.remove_edge(call_func_addr, return_to_addr)
2292
+ # Remove the edge in CFG
2293
+ nodes = self.model.get_all_nodes(callsite_block_addr)
2294
+ for n in nodes:
2295
+ successors = self.model.get_successors_and_jumpkind(n, excluding_fakeret=False)
2296
+ for successor, jumpkind in successors:
2297
+ if jumpkind == "Ijk_FakeRet" and successor.addr == return_to_addr:
2298
+ self.remove_edge(n, successor)
2299
+
2300
+ # Remove all dangling nodes
2301
+ # wcc = list(networkx.weakly_connected_components(graph))
2302
+ # for nodes in wcc:
2303
+ # if func.startpoint not in nodes:
2304
+ # graph.remove_nodes_from(nodes)
2305
+
2306
+ # Private methods - resolving indirect jumps
2307
+
2308
+ @staticmethod
2309
+ def _convert_indirect_jump_targets_to_states(job, indirect_jump_targets):
2310
+ """
2311
+ Convert each concrete indirect jump target into a SimState. If there are non-zero successors and the original
2312
+ jumpkind is a call, we also generate a fake-ret successor.
2313
+
2314
+ :param job: The CFGJob instance.
2315
+ :param indirect_jump_targets: A collection of concrete jump targets resolved from a indirect jump.
2316
+ :return: A list of SimStates.
2317
+ :rtype: list
2318
+ """
2319
+
2320
+ first_successor = job.sim_successors.all_successors[0]
2321
+ successors = []
2322
+ for t in indirect_jump_targets:
2323
+ # Insert new successors
2324
+ a = first_successor.copy()
2325
+ a.ip = t
2326
+ successors.append(a)
2327
+ # special case: if the indirect jump is in fact an indirect call, we should create a FakeRet successor
2328
+ if successors and first_successor.history.jumpkind == "Ijk_Call":
2329
+ a = first_successor.copy()
2330
+ a.ip = job.cfg_node.addr + job.cfg_node.size
2331
+ a.history.jumpkind = "Ijk_FakeRet"
2332
+ successors.append(a)
2333
+ return successors
2334
+
2335
+ def _try_resolving_indirect_jumps(self, sim_successors, cfg_node, func_addr, successors, exception_info, artifacts):
2336
+ """
2337
+ Resolve indirect jumps specified by sim_successors.addr.
2338
+
2339
+ :param SimSuccessors sim_successors: The SimSuccessors instance.
2340
+ :param CFGNode cfg_node: The CFGNode instance.
2341
+ :param int func_addr: Current function address.
2342
+ :param list successors: A list of successors.
2343
+ :param tuple exception_info: The sys.exc_info() of the exception or None if none occurred.
2344
+ :param artifacts: A container of collected information.
2345
+ :return: Resolved successors
2346
+ :rtype: list
2347
+ """
2348
+
2349
+ # Try to resolve indirect jumps with advanced backward slicing (if enabled)
2350
+ if sim_successors.sort == "IRSB" and self._is_indirect_jump(cfg_node, sim_successors):
2351
+ l.debug("IRSB %#x has an indirect jump as its default exit", cfg_node.addr)
2352
+
2353
+ # We need input states to perform backward slicing
2354
+ if self._advanced_backward_slicing and self._keep_state:
2355
+ # Optimization: make sure we only try to resolve an indirect jump if any of the following criteria holds
2356
+ # - It's a jump (Ijk_Boring), and its target is either fully symbolic, or its resolved target is within
2357
+ # the current binary
2358
+ # - It's a call (Ijk_Call), and its target is fully symbolic
2359
+ # TODO: This is very hackish, please refactor this part of code later
2360
+ should_resolve = True
2361
+ legit_successors = [
2362
+ suc for suc in successors if suc.history.jumpkind in ("Ijk_Boring", "Ijk_InvalICache", "Ijk_Call")
2363
+ ]
2364
+ if legit_successors:
2365
+ legit_successor = legit_successors[0]
2366
+ if legit_successor.ip.symbolic:
2367
+ if legit_successor.history.jumpkind != "Ijk_Call":
2368
+ should_resolve = False
2369
+ else:
2370
+ if legit_successor.history.jumpkind == "Ijk_Call":
2371
+ should_resolve = False
2372
+ else:
2373
+ concrete_target = legit_successor.solver.eval(legit_successor.ip)
2374
+ if (
2375
+ self.project.loader.find_object_containing(concrete_target)
2376
+ is not self.project.loader.main_object
2377
+ ):
2378
+ should_resolve = False
2379
+
2380
+ else:
2381
+ # No interesting successors... skip
2382
+ should_resolve = False
2383
+
2384
+ # TODO: Handle those successors
2385
+ if not should_resolve:
2386
+ l.debug("This might not be an indirect jump that has multiple targets. Skipped.")
2387
+ self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
2388
+
2389
+ else:
2390
+ more_successors = self._backward_slice_indirect(cfg_node, sim_successors, func_addr)
2391
+
2392
+ if more_successors:
2393
+ # Remove the symbolic successor
2394
+ # TODO: Now we are removing all symbolic successors. Is it possible
2395
+ # TODO: that there is more than one symbolic successor?
2396
+ all_successors = [suc for suc in successors if not suc.solver.symbolic(suc.ip)]
2397
+ # Insert new successors
2398
+ # We insert new successors in the beginning of all_successors list so that we don't break the
2399
+ # assumption that Ijk_FakeRet is always the last element in the list
2400
+ for suc_addr in more_successors:
2401
+ a = sim_successors.all_successors[0].copy()
2402
+ a.ip = suc_addr
2403
+ all_successors.insert(0, a)
2404
+
2405
+ l.debug("The indirect jump is successfully resolved.")
2406
+ self.kb.indirect_jumps.update_resolved_addrs(cfg_node.addr, more_successors)
2407
+
2408
+ else:
2409
+ l.debug("Failed to resolve the indirect jump.")
2410
+ self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
2411
+
2412
+ else:
2413
+ if not successors:
2414
+ l.debug("Cannot resolve the indirect jump without advanced backward slicing enabled: %s", cfg_node)
2415
+
2416
+ # Try to find more successors if we failed to resolve the indirect jump before
2417
+ if exception_info is None and (cfg_node.is_simprocedure or self._is_indirect_jump(cfg_node, sim_successors)):
2418
+ has_call_jumps = any(suc_state.history.jumpkind == "Ijk_Call" for suc_state in successors)
2419
+ if has_call_jumps:
2420
+ concrete_successors = [
2421
+ suc_state
2422
+ for suc_state in successors
2423
+ if suc_state.history.jumpkind != "Ijk_FakeRet" and not suc_state.solver.symbolic(suc_state.ip)
2424
+ ]
2425
+ else:
2426
+ concrete_successors = [
2427
+ suc_state for suc_state in successors if not suc_state.solver.symbolic(suc_state.ip)
2428
+ ]
2429
+ symbolic_successors = [suc_state for suc_state in successors if suc_state.solver.symbolic(suc_state.ip)]
2430
+
2431
+ resolved = not symbolic_successors
2432
+ if symbolic_successors:
2433
+ for suc in symbolic_successors:
2434
+ if o.SYMBOLIC in suc.options:
2435
+ targets = suc.solver.eval_upto(suc.ip, 32)
2436
+ if len(targets) < 32:
2437
+ all_successors = []
2438
+ resolved = True
2439
+ for t in targets:
2440
+ new_ex = suc.copy()
2441
+ new_ex.ip = claripy.BVV(t, suc.ip.size())
2442
+ all_successors.append(new_ex)
2443
+ else:
2444
+ break
2445
+
2446
+ if not resolved and (
2447
+ (symbolic_successors and not concrete_successors)
2448
+ or (not cfg_node.is_simprocedure and self._is_indirect_jump(cfg_node, sim_successors))
2449
+ ):
2450
+ l.debug("%s has an indirect jump. See what we can do about it.", cfg_node)
2451
+
2452
+ if sim_successors.sort == "SimProcedure" and sim_successors.artifacts["adds_exits"]:
2453
+ # Skip those SimProcedures that don't create new SimExits
2454
+ l.debug(
2455
+ "We got a SimProcedure %s in fastpath mode that creates new exits.", sim_successors.description
2456
+ )
2457
+ if self._enable_symbolic_back_traversal:
2458
+ successors = self._symbolically_back_traverse(sim_successors, artifacts, cfg_node)
2459
+ # mark jump as resolved if we got successors
2460
+ if successors:
2461
+ succ_addrs = [s.addr for s in successors]
2462
+ self.kb.indirect_jumps.update_resolved_addrs(cfg_node.addr, succ_addrs)
2463
+ else:
2464
+ self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
2465
+ l.debug("Got %d concrete exits in symbolic mode.", len(successors))
2466
+ else:
2467
+ self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
2468
+ # keep fake_rets
2469
+ successors = [s for s in successors if s.history.jumpkind == "Ijk_FakeRet"]
2470
+
2471
+ elif sim_successors.sort == "IRSB" and any(ex.history.jumpkind != "Ijk_Ret" for ex in successors):
2472
+ # We cannot properly handle Return as that requires us start execution from the caller...
2473
+ l.debug("Try traversal backwards in symbolic mode on %s.", cfg_node)
2474
+ if self._enable_symbolic_back_traversal:
2475
+ successors = self._symbolically_back_traverse(sim_successors, artifacts, cfg_node)
2476
+
2477
+ # Remove successors whose IP doesn't make sense
2478
+ successors = [
2479
+ suc for suc in successors if self._is_address_executable(suc.solver.eval_one(suc.ip))
2480
+ ]
2481
+
2482
+ # mark jump as resolved if we got successors
2483
+ if successors:
2484
+ succ_addrs = [s.addr for s in successors]
2485
+ self.kb.indirect_jumps.update_resolved_addrs(cfg_node.addr, succ_addrs)
2486
+ else:
2487
+ self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
2488
+ l.debug("Got %d concrete exits in symbolic mode", len(successors))
2489
+ else:
2490
+ self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
2491
+ successors = []
2492
+
2493
+ elif successors and all(ex.history.jumpkind == "Ijk_Ret" for ex in successors):
2494
+ l.debug("All exits are returns (Ijk_Ret). It will be handled by pending exits.")
2495
+
2496
+ else:
2497
+ l.debug("Cannot resolve this indirect jump: %s", cfg_node)
2498
+ self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
2499
+
2500
+ return successors
2501
+
2502
+ def _backward_slice_indirect(self, cfgnode, sim_successors, current_function_addr):
2503
+ """
2504
+ Try to resolve an indirect jump by slicing backwards
2505
+ """
2506
+ # TODO: make this a real indirect jump resolver under the new paradigm
2507
+
2508
+ irsb = sim_successors.artifacts["irsb"] # shorthand
2509
+
2510
+ l.debug("Resolving indirect jump at IRSB %s", irsb)
2511
+
2512
+ # Let's slice backwards from the end of this exit
2513
+ next_tmp = irsb.next.tmp
2514
+ stmt_id = next(
2515
+ i for i, s in enumerate(irsb.statements) if isinstance(s, pyvex.IRStmt.WrTmp) and s.tmp == next_tmp
2516
+ )
2517
+
2518
+ cdg = self.project.analyses[CDG].prep(fail_fast=self._fail_fast)(cfg=self)
2519
+ ddg = self.project.analyses[DDG].prep(fail_fast=self._fail_fast)(
2520
+ cfg=self, start=current_function_addr, call_depth=0
2521
+ )
2522
+
2523
+ bc = self.project.analyses[BackwardSlice].prep(fail_fast=self._fail_fast)(
2524
+ self, cdg, ddg, targets=[(cfgnode, stmt_id)], same_function=True
2525
+ )
2526
+ taint_graph = bc.taint_graph
2527
+ # Find the correct taint
2528
+ next_nodes = [cl for cl in taint_graph.nodes() if cl.block_addr == sim_successors.addr]
2529
+
2530
+ if not next_nodes:
2531
+ l.error("The target exit is not included in the slice. Something is wrong")
2532
+ return []
2533
+
2534
+ next_node = next_nodes[0]
2535
+
2536
+ # Get the weakly-connected subgraph that contains `next_node`
2537
+ all_subgraphs = (
2538
+ networkx.induced_subgraph(taint_graph, nodes) for nodes in networkx.weakly_connected_components(taint_graph)
2539
+ )
2540
+ starts = set()
2541
+ for subgraph in all_subgraphs:
2542
+ if next_node in subgraph:
2543
+ # Make sure there is no symbolic read...
2544
+ # FIXME: This is an over-approximation. We should try to limit the starts more
2545
+ nodes = [n for n in subgraph.nodes() if subgraph.in_degree(n) == 0]
2546
+ for n in nodes:
2547
+ starts.add(n.block_addr)
2548
+
2549
+ # Execute the slice
2550
+ successing_addresses = set()
2551
+ annotated_cfg = bc.annotated_cfg()
2552
+ for start in starts:
2553
+ l.debug("Start symbolic execution at 0x%x on program slice.", start)
2554
+ # Get the state from our CFG
2555
+ node = self.model.get_any_node(start)
2556
+ if node is None:
2557
+ # Well, we have to live with an empty state
2558
+ base_state = self.project.factory.blank_state(addr=start)
2559
+ else:
2560
+ base_state = node.input_state.copy()
2561
+ base_state.set_mode("symbolic")
2562
+ base_state.ip = start
2563
+
2564
+ # Clear all initial taints (register values, memory values, etc.)
2565
+ initial_nodes = [n for n in bc.taint_graph.nodes() if bc.taint_graph.in_degree(n) == 0]
2566
+ for cl in initial_nodes:
2567
+ # Iterate in all actions of this node, and pick corresponding actions
2568
+ cfg_nodes = self.model.get_all_nodes(cl.block_addr)
2569
+ for n in cfg_nodes:
2570
+ if not n.final_states:
2571
+ continue
2572
+ actions = [
2573
+ ac
2574
+ for ac in n.final_states[0].history.recent_actions
2575
+ # Normally it's enough to only use the first final state
2576
+ if ac.bbl_addr == cl.block_addr and ac.stmt_idx == cl.stmt_idx
2577
+ ]
2578
+ for ac in actions:
2579
+ if not hasattr(ac, "action"):
2580
+ continue
2581
+ if ac.action == "read":
2582
+ if ac.type == "mem":
2583
+ unconstrained_value = base_state.solver.Unconstrained(
2584
+ "unconstrained", ac.size.ast * 8
2585
+ )
2586
+ base_state.memory.store(
2587
+ ac.addr, unconstrained_value, endness=self.project.arch.memory_endness
2588
+ )
2589
+ elif ac.type == "reg":
2590
+ unconstrained_value = base_state.solver.Unconstrained(
2591
+ "unconstrained", ac.size.ast * 8
2592
+ )
2593
+ base_state.registers.store(
2594
+ ac.offset, unconstrained_value, endness=self.project.arch.register_endness
2595
+ )
2596
+
2597
+ # Clear the constraints!
2598
+ base_state.release_plugin("solver")
2599
+
2600
+ # For speed concerns, we are limiting the timeout for z3 solver to 5 seconds
2601
+ base_state.solver._solver.timeout = 5000
2602
+
2603
+ sc = self.project.factory.simulation_manager(base_state)
2604
+ sc.use_technique(Slicecutor(annotated_cfg))
2605
+ sc.use_technique(LoopSeer(bound=1))
2606
+ sc.run()
2607
+
2608
+ if sc.cut or sc.deadended:
2609
+ all_deadended_states = sc.cut + sc.deadended
2610
+ for s in all_deadended_states:
2611
+ if s.addr == sim_successors.addr:
2612
+ # We want to get its successors
2613
+ succs = s.step()
2614
+ for succ in succs.flat_successors:
2615
+ successing_addresses.add(succ.addr)
2616
+
2617
+ else:
2618
+ l.debug("Cannot determine the exit. You need some better ways to recover the exits :-(")
2619
+
2620
+ l.debug("Resolution is done, and we have %d new successors.", len(successing_addresses))
2621
+
2622
+ return list(successing_addresses)
2623
+
2624
+ def _symbolically_back_traverse(self, current_block, block_artifacts, cfg_node):
2625
+ """
2626
+ Symbolically executes from ancestor nodes (2-5 times removed) finding paths of execution through the given
2627
+ CFGNode.
2628
+
2629
+ :param SimSuccessors current_block: SimSuccessor with address to attempt to navigate to.
2630
+ :param dict block_artifacts: Container of IRSB data - specifically used for known persistent register values.
2631
+ :param CFGNode cfg_node: Current node interested around.
2632
+ :returns: Double-checked concrete successors.
2633
+ :rtype: List
2634
+ """
2635
+
2636
+ class RegisterProtector:
2637
+ """
2638
+ A class that prevent specific registers from being overwritten.
2639
+ """
2640
+
2641
+ def __init__(self, reg_offset, info_collection):
2642
+ """
2643
+ Class to overwrite registers.
2644
+
2645
+ :param int reg_offset: Register offset to overwrite from.
2646
+ :param dict info_collection: New register offsets to use (in container).
2647
+ """
2648
+ self._reg_offset = reg_offset
2649
+ self._info_collection = info_collection
2650
+
2651
+ def write_persistent_register(self, state_):
2652
+ """
2653
+ Writes over given registers from self._info_collection (taken from block_artifacts)
2654
+
2655
+ :param SimSuccessors state_: state to update registers for
2656
+ """
2657
+ if state_.inspect.address is None:
2658
+ l.error("state.inspect.address is None. It will be fixed by Yan later.")
2659
+ return
2660
+
2661
+ if state_.registers.load(self._reg_offset).symbolic:
2662
+ current_run = state_.inspect.address
2663
+ if current_run in self._info_collection and not state_.solver.symbolic(
2664
+ self._info_collection[current_run][self._reg_offset]
2665
+ ):
2666
+ l.debug(
2667
+ "Overwriting %s with %s",
2668
+ state_.registers.load(self._reg_offset),
2669
+ self._info_collection[current_run][self._reg_offset],
2670
+ )
2671
+ state_.registers.store(self._reg_offset, self._info_collection[current_run][self._reg_offset])
2672
+
2673
+ l.debug("Start back traversal from %s", current_block)
2674
+
2675
+ # Create a partial CFG first
2676
+ temp_cfg = networkx.DiGraph(self.graph)
2677
+ # Reverse it
2678
+ temp_cfg.reverse(copy=False)
2679
+
2680
+ path_length = 0
2681
+ concrete_exits = []
2682
+ if cfg_node not in temp_cfg.nodes():
2683
+ # TODO: Figure out why this is happening
2684
+ return concrete_exits
2685
+
2686
+ keep_running = True
2687
+ while not concrete_exits and path_length < 5 and keep_running:
2688
+ path_length += 1
2689
+ queue = [cfg_node]
2690
+ avoid = set()
2691
+ for _ in range(path_length):
2692
+ new_queue = []
2693
+ for n in queue:
2694
+ successors = list(temp_cfg.successors(n))
2695
+ for suc in successors:
2696
+ jk = temp_cfg.get_edge_data(n, suc)["jumpkind"]
2697
+ if jk != "Ijk_Ret":
2698
+ # We don't want to trace into libraries
2699
+ predecessors = list(temp_cfg.predecessors(suc))
2700
+ avoid |= {p.addr for p in predecessors if p is not n}
2701
+ new_queue.append(suc)
2702
+ queue = new_queue
2703
+
2704
+ if path_length <= 1:
2705
+ continue
2706
+
2707
+ for n in queue:
2708
+ # Start symbolic exploration from each block
2709
+ state = self.project.factory.blank_state(
2710
+ addr=n.addr,
2711
+ mode="symbolic",
2712
+ add_options={
2713
+ o.DO_RET_EMULATION,
2714
+ o.CONSERVATIVE_READ_STRATEGY,
2715
+ }
2716
+ | o.resilience,
2717
+ )
2718
+ # Avoid concretization of any symbolic read address that is over a certain limit
2719
+ # TODO: test case is needed for this option
2720
+
2721
+ # Set initial values of persistent regs
2722
+ if n.addr in block_artifacts:
2723
+ for reg in state.arch.persistent_regs:
2724
+ state.registers.store(reg, block_artifacts[n.addr][reg])
2725
+ for reg in state.arch.persistent_regs:
2726
+ reg_protector = RegisterProtector(reg, block_artifacts)
2727
+ state.inspect.add_breakpoint(
2728
+ "reg_write",
2729
+ BP(
2730
+ BP_AFTER,
2731
+ reg_write_offset=state.arch.registers[reg][0],
2732
+ action=reg_protector.write_persistent_register,
2733
+ ),
2734
+ )
2735
+ simgr = self.project.factory.simulation_manager(state)
2736
+ simgr.use_technique(LoopSeer(bound=10))
2737
+ simgr.use_technique(Explorer(find=current_block.addr, avoid=avoid))
2738
+ simgr.use_technique(LengthLimiter(path_length))
2739
+ simgr.run()
2740
+
2741
+ if simgr.found:
2742
+ simgr = self.project.factory.simulation_manager(simgr.one_found, save_unsat=True)
2743
+ simgr.step()
2744
+ if simgr.active or simgr.unsat:
2745
+ keep_running = False
2746
+ concrete_exits.extend(simgr.active)
2747
+ concrete_exits.extend(simgr.unsat)
2748
+ if keep_running:
2749
+ l.debug("Step back for one more run...")
2750
+
2751
+ # Make sure these successors are actually concrete
2752
+ # We just use the ip, persistent registers, and jumpkind to initialize the original unsat state
2753
+ # TODO: It works for jumptables, but not for calls. We should also handle changes in sp
2754
+ new_concrete_successors = []
2755
+ for c in concrete_exits:
2756
+ unsat_state = current_block.unsat_successors[0].copy()
2757
+ unsat_state.history.jumpkind = c.history.jumpkind
2758
+ for reg in [*unsat_state.arch.persistent_regs, "ip"]:
2759
+ unsat_state.registers.store(reg, c.registers.load(reg))
2760
+ new_concrete_successors.append(unsat_state)
2761
+
2762
+ return new_concrete_successors
2763
+
2764
+ def _get_symbolic_function_initial_state(self, function_addr, fastpath_mode_state=None):
2765
+ """
2766
+ Symbolically execute the first basic block of the specified function,
2767
+ then returns it. We prepares the state using the already existing
2768
+ state in fastpath mode (if available).
2769
+ :param function_addr: The function address
2770
+ :return: A symbolic state if succeeded, None otherwise
2771
+ """
2772
+ if function_addr is None:
2773
+ return None
2774
+
2775
+ if function_addr in self._symbolic_function_initial_state:
2776
+ return self._symbolic_function_initial_state[function_addr]
2777
+
2778
+ if fastpath_mode_state is not None:
2779
+ fastpath_state = fastpath_mode_state
2780
+ else:
2781
+ if function_addr in self._function_input_states:
2782
+ fastpath_state = self._function_input_states[function_addr]
2783
+ else:
2784
+ raise AngrCFGError("The impossible happened. Please report to Fish.")
2785
+
2786
+ symbolic_initial_state = self.project.factory.entry_state(mode="symbolic")
2787
+ if fastpath_state is not None:
2788
+ symbolic_initial_state = self.project.simos.prepare_call_state(
2789
+ fastpath_state, initial_state=symbolic_initial_state
2790
+ )
2791
+
2792
+ # Find number of instructions of start block
2793
+ func = self.project.kb.functions.get(function_addr)
2794
+ start_block = func._get_block(function_addr)
2795
+ num_instr = start_block.instructions - 1
2796
+
2797
+ symbolic_initial_state.ip = function_addr
2798
+ path = self.project.factory.path(symbolic_initial_state)
2799
+ try:
2800
+ sim_successors = self.project.factory.successors(path.state, num_inst=num_instr)
2801
+ except (SimError, AngrError):
2802
+ return None
2803
+
2804
+ # We execute all but the last instruction in this basic block, so we have a cleaner
2805
+ # state
2806
+ # Start execution!
2807
+ exits = sim_successors.flat_successors + sim_successors.unsat_successors
2808
+
2809
+ if exits:
2810
+ final_st = None
2811
+ for ex in exits:
2812
+ if ex.satisfiable():
2813
+ final_st = ex
2814
+ break
2815
+ else:
2816
+ final_st = None
2817
+
2818
+ self._symbolic_function_initial_state[function_addr] = final_st
2819
+
2820
+ return final_st
2821
+
2822
+ # Private methods - function hints
2823
+
2824
+ def _search_for_function_hints(self, successor_state):
2825
+ """
2826
+ Scan for constants that might be used as exit targets later, and add them into pending_exits.
2827
+
2828
+ :param SimState successor_state: A successing state.
2829
+ :return: A list of discovered code addresses.
2830
+ :rtype: list
2831
+ """
2832
+
2833
+ function_hints = []
2834
+
2835
+ for action in successor_state.history.recent_actions:
2836
+ if action.type == "reg" and action.offset == self.project.arch.ip_offset:
2837
+ # Skip all accesses to IP registers
2838
+ continue
2839
+ if action.type == "exit":
2840
+ # only consider read/write actions
2841
+ continue
2842
+
2843
+ # Enumerate actions
2844
+ if isinstance(action, SimActionData):
2845
+ data = action.data
2846
+ if data is not None:
2847
+ # TODO: Check if there is a proper way to tell whether this const falls in the range of code
2848
+ # TODO: segments
2849
+ # Now let's live with this big hack...
2850
+ try:
2851
+ const = successor_state.solver.eval_one(data.ast)
2852
+ except Exception: # pylint:disable=broad-exception-caught
2853
+ continue
2854
+
2855
+ if self._is_address_executable(const):
2856
+ if self._pending_function_hints is not None and const in self._pending_function_hints:
2857
+ continue
2858
+
2859
+ # target = const
2860
+ # tpl = (None, None, target)
2861
+ # st = self.project._simos.prepare_call_state(self.project.initial_state(mode='fastpath'),
2862
+ # initial_state=saved_state)
2863
+ # st = self.project.initial_state(mode='fastpath')
2864
+ # exits[tpl] = (st, None, None)
2865
+
2866
+ function_hints.append(const)
2867
+
2868
+ l.debug(
2869
+ "Got %d possible exits, including: %s", len(function_hints), ", ".join([f"0x{f:x}" for f in function_hints])
2870
+ )
2871
+
2872
+ return function_hints
2873
+
2874
+ # Private methods - creation of stuff (SimSuccessors, CFGNode, call-stack, etc.)
2875
+
2876
+ def _get_simsuccessors(self, addr, job, current_function_addr=None):
2877
+ """
2878
+ Create the SimSuccessors instance for a block.
2879
+
2880
+ :param int addr: Address of the block.
2881
+ :param CFGJob job: The CFG job instance with an input state inside.
2882
+ :param int current_function_addr: Address of the current function.
2883
+ :return: A SimSuccessors instance
2884
+ :rtype: SimSuccessors
2885
+ """
2886
+
2887
+ exception_info = None
2888
+ state = job.state
2889
+ saved_state = job.state # We don't have to make a copy here
2890
+
2891
+ # respect the basic block size from base graph
2892
+ block_size = None
2893
+ if self._base_graph is not None:
2894
+ for n in self._base_graph.nodes():
2895
+ if n.addr == addr:
2896
+ block_size = n.size
2897
+ break
2898
+
2899
+ try:
2900
+ sim_successors = None
2901
+
2902
+ if not self._keep_state:
2903
+ if self.project.is_hooked(addr):
2904
+ old_proc = self.project._sim_procedures[addr]
2905
+ is_continuation = old_proc.is_continuation
2906
+ elif self.project.simos.is_syscall_addr(addr):
2907
+ old_proc = self.project.simos.syscall_from_addr(addr)
2908
+ is_continuation = False # syscalls don't support continuation
2909
+ else:
2910
+ old_proc = None
2911
+ is_continuation = None
2912
+
2913
+ if old_proc is not None and not is_continuation and not old_proc.ADDS_EXITS and not old_proc.NO_RET:
2914
+ # DON'T CREATE USELESS SIMPROCEDURES if we don't care about the accuracy of states
2915
+ # When generating CFG, a SimProcedure will not be created as it is but be created as a
2916
+ # ReturnUnconstrained stub if it satisfies the following conditions:
2917
+ # - It doesn't add any new exits.
2918
+ # - It returns as normal.
2919
+ # In this way, we can speed up the CFG generation by quite a lot as we avoid simulating
2920
+ # those functions like read() and puts(), which has no impact on the overall control flow at all.
2921
+ #
2922
+ # Special notes about SimProcedure continuation: Any SimProcedure instance that is a continuation
2923
+ # will add new exits, otherwise the original SimProcedure wouldn't have been executed anyway. Hence
2924
+ # it's reasonable for us to always simulate a SimProcedure with continuation.
2925
+
2926
+ old_name = None
2927
+
2928
+ if old_proc.is_syscall:
2929
+ new_stub = SIM_PROCEDURES["stubs"]["syscall"]
2930
+ ret_to = state.regs.ip_at_syscall
2931
+ else:
2932
+ # normal SimProcedures
2933
+ new_stub = SIM_PROCEDURES["stubs"]["ReturnUnconstrained"]
2934
+ ret_to = None
2935
+
2936
+ old_name = old_proc.display_name
2937
+
2938
+ # instantiate the stub
2939
+ new_stub_inst = new_stub(display_name=old_name)
2940
+
2941
+ sim_successors = self.project.factory.procedure_engine.process(
2942
+ state,
2943
+ procedure=new_stub_inst,
2944
+ force_addr=addr,
2945
+ ret_to=ret_to,
2946
+ )
2947
+
2948
+ if sim_successors is None:
2949
+ jumpkind = state.history.jumpkind
2950
+ jumpkind = "Ijk_Boring" if jumpkind is None else jumpkind
2951
+ sim_successors = self.project.factory.successors(
2952
+ state, jumpkind=jumpkind, size=block_size, opt_level=self._iropt_level
2953
+ )
2954
+
2955
+ except (SimFastPathError, SimSolverModeError) as ex:
2956
+ if saved_state.mode == "fastpath":
2957
+ # Got a SimFastPathError or SimSolverModeError in FastPath mode.
2958
+ # We wanna switch to symbolic mode for current IRSB.
2959
+ l.debug("Switch to symbolic mode for address %#x", addr)
2960
+ # Make a copy of the current 'fastpath' state
2961
+
2962
+ l.debug("Symbolic jumps at basic block %#x.", addr)
2963
+
2964
+ new_state = None
2965
+ if addr != current_function_addr:
2966
+ new_state = self._get_symbolic_function_initial_state(current_function_addr)
2967
+
2968
+ if new_state is None:
2969
+ new_state = state.copy()
2970
+ new_state.set_mode("symbolic")
2971
+ new_state.options.add(o.DO_RET_EMULATION)
2972
+ # Remove bad constraints
2973
+ # FIXME: This is so hackish...
2974
+ preserved_constraints = [
2975
+ c for c in new_state.solver.constraints if c.op != "BoolV" or c.args[0] is not False
2976
+ ]
2977
+ new_solver = new_state.solver._solver.blank_copy()
2978
+ new_solver.add(preserved_constraints)
2979
+ new_state.solver._stored_solver = new_solver
2980
+
2981
+ # Swap them
2982
+ saved_state, job.state = job.state, new_state
2983
+ sim_successors, exception_info, _ = self._get_simsuccessors(addr, job)
2984
+
2985
+ else:
2986
+ exception_info = sys.exc_info()
2987
+ # Got a SimSolverModeError in symbolic mode. We are screwed.
2988
+ # Skip this IRSB
2989
+ l.debug("Caught a SimIRSBError %s. Don't panic, this is usually expected.", ex)
2990
+ inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
2991
+ sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
2992
+
2993
+ except SimIRSBError:
2994
+ exception_info = sys.exc_info()
2995
+ # It's a tragedy that we came across some instructions that VEX
2996
+ # does not support. I'll create a terminating stub there
2997
+ l.debug("Caught a SimIRSBError during CFG recovery. Creating a PathTerminator.", exc_info=True)
2998
+ inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
2999
+ sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
3000
+
3001
+ except claripy.ClaripyError:
3002
+ exception_info = sys.exc_info()
3003
+ l.debug("Caught a ClaripyError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
3004
+ # Generate a PathTerminator to terminate the current path
3005
+ inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
3006
+ sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
3007
+
3008
+ except SimError:
3009
+ exception_info = sys.exc_info()
3010
+ l.debug("Caught a SimError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
3011
+ # Generate a PathTerminator to terminate the current path
3012
+ inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
3013
+ sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
3014
+
3015
+ except AngrExitError:
3016
+ exception_info = sys.exc_info()
3017
+ l.debug("Caught a AngrExitError during CFG recovery. Don't panic, this is usually expected.", exc_info=True)
3018
+ # Generate a PathTerminator to terminate the current path
3019
+ inst = SIM_PROCEDURES["stubs"]["PathTerminator"]()
3020
+ sim_successors = ProcedureEngine(self.project).process(state, procedure=inst)
3021
+
3022
+ except AngrError:
3023
+ exception_info = sys.exc_info()
3024
+ section = self.project.loader.main_object.find_section_containing(addr)
3025
+ sec_name = "No section" if section is None else section.name
3026
+ # AngrError shouldn't really happen though
3027
+ l.debug("Caught an AngrError during CFG recovery at %#x (%s)", addr, sec_name, exc_info=True)
3028
+ # We might be on a wrong branch, and is likely to encounter the
3029
+ # "No bytes in memory xxx" exception
3030
+ # Just ignore it
3031
+ sim_successors = None
3032
+
3033
+ return sim_successors, exception_info, saved_state
3034
+
3035
+ def _create_new_call_stack(self, addr, all_jobs, job, exit_target, jumpkind):
3036
+ """
3037
+ Creates a new call stack, and according to the jumpkind performs appropriate actions.
3038
+
3039
+ :param int addr: Address to create at.
3040
+ :param Simsuccessors all_jobs: Jobs to get stack pointer from or return address.
3041
+ :param CFGJob job: CFGJob to copy current call stack from.
3042
+ :param int exit_target: Address of exit target.
3043
+ :param str jumpkind: The type of jump performed.
3044
+ :returns: New call stack for target block.
3045
+ :rtype: CallStack
3046
+ """
3047
+
3048
+ if self._is_call_jumpkind(jumpkind):
3049
+ new_call_stack = job.call_stack_copy()
3050
+ # Notice that in ARM, there are some freaking instructions
3051
+ # like
3052
+ # BLEQ <address>
3053
+ # It should give us three exits: Ijk_Call, Ijk_Boring, and
3054
+ # Ijk_Ret. The last exit is simulated.
3055
+ # Notice: We assume the last exit is the simulated one
3056
+ if len(all_jobs) > 1 and all_jobs[-1].history.jumpkind == "Ijk_FakeRet":
3057
+ se = all_jobs[-1].solver
3058
+ retn_target_addr = se.eval_one(all_jobs[-1].ip, default=0)
3059
+ sp = se.eval_one(all_jobs[-1].regs.sp, default=0)
3060
+
3061
+ new_call_stack = new_call_stack.call(addr, exit_target, retn_target=retn_target_addr, stack_pointer=sp)
3062
+
3063
+ elif jumpkind.startswith("Ijk_Sys") and len(all_jobs) == 1:
3064
+ # This is a syscall. It returns to the same address as itself (with a different jumpkind)
3065
+ retn_target_addr = exit_target
3066
+ se = all_jobs[0].solver
3067
+ sp = se.eval_one(all_jobs[0].regs.sp, default=0)
3068
+ new_call_stack = new_call_stack.call(addr, exit_target, retn_target=retn_target_addr, stack_pointer=sp)
3069
+
3070
+ else:
3071
+ # We don't have a fake return exit available, which means
3072
+ # this call doesn't return.
3073
+ new_call_stack = CallStack()
3074
+ se = all_jobs[-1].solver
3075
+ sp = se.eval_one(all_jobs[-1].regs.sp, default=0)
3076
+
3077
+ new_call_stack = new_call_stack.call(addr, exit_target, retn_target=None, stack_pointer=sp)
3078
+
3079
+ elif jumpkind == "Ijk_Ret":
3080
+ # Normal return
3081
+ new_call_stack = job.call_stack_copy()
3082
+ with contextlib.suppress(SimEmptyCallStackError):
3083
+ new_call_stack = new_call_stack.ret(exit_target)
3084
+
3085
+ se = all_jobs[-1].solver
3086
+ sp = se.eval_one(all_jobs[-1].regs.sp, default=0)
3087
+ old_sp = job.current_stack_pointer
3088
+
3089
+ # Calculate the delta of stack pointer
3090
+ if sp is not None and old_sp is not None:
3091
+ delta = sp - old_sp
3092
+ func_addr = job.func_addr
3093
+
3094
+ if self.kb.functions.function(func_addr) is None:
3095
+ # Create the function if it doesn't exist
3096
+ # FIXME: But hell, why doesn't it exist in the first place?
3097
+ l.error(
3098
+ "Function 0x%x doesn't exist in function manager although it should be there."
3099
+ "Look into this issue later.",
3100
+ func_addr,
3101
+ )
3102
+ self.kb.functions.function(func_addr, create=True)
3103
+
3104
+ # Set sp_delta of the function
3105
+ self.kb.functions.function(func_addr, create=True).sp_delta = delta
3106
+
3107
+ elif jumpkind == "Ijk_FakeRet":
3108
+ # The fake return...
3109
+ new_call_stack = job.call_stack
3110
+
3111
+ else:
3112
+ # although the jumpkind is not Ijk_Call, it may still jump to a new function... let's see
3113
+ if self.project.is_hooked(exit_target):
3114
+ hooker = self.project.hooked_by(exit_target)
3115
+ if hooker is not procedures.stubs.UserHook.UserHook:
3116
+ # if it's not a UserHook, it must be a function
3117
+ # Update the function address of the most recent call stack frame
3118
+ new_call_stack = job.call_stack_copy()
3119
+ new_call_stack.current_function_address = exit_target
3120
+
3121
+ else:
3122
+ # TODO: We need a way to mark if a user hook is a function or not
3123
+ # TODO: We can add a map in Project to store this information
3124
+ # For now we are just assuming they are not functions, which is mostly the case
3125
+ new_call_stack = job.call_stack
3126
+
3127
+ else:
3128
+ # Normal control flow transition
3129
+ new_call_stack = job.call_stack
3130
+
3131
+ return new_call_stack
3132
+
3133
+ def _create_cfgnode(self, sim_successors, call_stack, func_addr, block_id=None, depth=None, exception_info=None):
3134
+ """
3135
+ Create a context-sensitive CFGNode instance for a specific block.
3136
+
3137
+ :param SimSuccessors sim_successors: The SimSuccessors object.
3138
+ :param CallStack call_stack_suffix: The call stack.
3139
+ :param int func_addr: Address of the current function.
3140
+ :param BlockID block_id: The block ID of this CFGNode.
3141
+ :param int or None depth: Depth of this CFGNode.
3142
+ :return: A CFGNode instance.
3143
+ :rtype: CFGNode
3144
+ """
3145
+
3146
+ sa = sim_successors.artifacts # shorthand
3147
+
3148
+ # Determine if this is a SimProcedure, and further, if this is a syscall
3149
+ syscall = None
3150
+ is_syscall = False
3151
+ if sim_successors.sort == "SimProcedure":
3152
+ is_simprocedure = True
3153
+ if sa["is_syscall"] is True:
3154
+ is_syscall = True
3155
+ syscall = sim_successors.artifacts["procedure"]
3156
+ else:
3157
+ is_simprocedure = False
3158
+
3159
+ if is_simprocedure:
3160
+ simproc_name = sa["name"].split(".")[-1]
3161
+ if simproc_name == "ReturnUnconstrained" and "resolves" in sa and sa["resolves"] is not None:
3162
+ simproc_name = sa["resolves"]
3163
+
3164
+ no_ret = False
3165
+ if syscall is not None and sa["no_ret"]:
3166
+ no_ret = True
3167
+
3168
+ cfg_node = CFGENode(
3169
+ sim_successors.addr,
3170
+ None,
3171
+ self.model,
3172
+ callstack_key=call_stack.stack_suffix(self.context_sensitivity_level),
3173
+ input_state=None,
3174
+ simprocedure_name=simproc_name,
3175
+ syscall_name=syscall,
3176
+ no_ret=no_ret,
3177
+ is_syscall=is_syscall,
3178
+ function_address=sim_successors.addr,
3179
+ block_id=block_id,
3180
+ depth=depth,
3181
+ creation_failure_info=exception_info,
3182
+ thumb=(isinstance(self.project.arch, ArchARM) and sim_successors.addr & 1),
3183
+ )
3184
+
3185
+ else:
3186
+ cfg_node = CFGENode(
3187
+ sim_successors.addr,
3188
+ sa["irsb_size"],
3189
+ self.model,
3190
+ callstack_key=call_stack.stack_suffix(self.context_sensitivity_level),
3191
+ input_state=None,
3192
+ is_syscall=is_syscall,
3193
+ function_address=func_addr,
3194
+ block_id=block_id,
3195
+ depth=depth,
3196
+ irsb=sim_successors.artifacts["irsb"],
3197
+ creation_failure_info=exception_info,
3198
+ thumb=(isinstance(self.project.arch, ArchARM) and sim_successors.addr & 1),
3199
+ )
3200
+
3201
+ return cfg_node
3202
+
3203
+ # Private methods - loops and graph normalization
3204
+
3205
+ def _detect_loops(self, loop_callback=None):
3206
+ """
3207
+ Loop detection.
3208
+
3209
+ :param func loop_callback: A callback function for each detected loop backedge.
3210
+ :return: None
3211
+ """
3212
+
3213
+ loop_finder = self.project.analyses[LoopFinder].prep(kb=self.kb, fail_fast=self._fail_fast)(normalize=False)
3214
+
3215
+ if loop_callback is not None:
3216
+ graph_copy = networkx.DiGraph(self._graph)
3217
+
3218
+ loop: angr.analyses.loopfinder.Loop
3219
+ for loop in loop_finder.loops:
3220
+ loop_callback(graph_copy, loop)
3221
+
3222
+ self.model.graph = graph_copy
3223
+
3224
+ # Update loop backedges and graph
3225
+ self._loop_back_edges = list(itertools.chain.from_iterable(loop.continue_edges for loop in loop_finder.loops))
3226
+
3227
+ # Private methods - dominators and post-dominators
3228
+
3229
+ def _immediate_dominators(self, node, target_graph=None, reverse_graph=False):
3230
+ """
3231
+ Get all immediate dominators of sub graph from given node upwards.
3232
+
3233
+ :param str node: id of the node to navigate forwards from.
3234
+ :param networkx.classes.digraph.DiGraph target_graph: graph to analyse, default is self.graph.
3235
+ :param bool reverse_graph: Whether the target graph should be reversed before analysation.
3236
+
3237
+ :return: each node of graph as index values, with element as respective node's immediate dominator.
3238
+ :rtype: dict
3239
+ """
3240
+ if target_graph is None:
3241
+ target_graph = self.graph
3242
+
3243
+ if node not in target_graph:
3244
+ raise AngrCFGError(f"Target node {node} is not in graph.")
3245
+
3246
+ graph = networkx.DiGraph(target_graph)
3247
+ if reverse_graph:
3248
+ # Reverse the graph without deepcopy
3249
+ for n in target_graph.nodes():
3250
+ graph.add_node(n)
3251
+ for src, dst in target_graph.edges():
3252
+ graph.add_edge(dst, src)
3253
+
3254
+ idom = {node: node}
3255
+
3256
+ order = list(networkx.dfs_postorder_nodes(graph, node))
3257
+ dfn = {u: i for i, u in enumerate(order)}
3258
+ order.pop()
3259
+ order.reverse()
3260
+
3261
+ def intersect(u_, v_):
3262
+ """
3263
+ Finds the highest (in postorder valuing) point of intersection above two node arguments.
3264
+
3265
+ :param str u_: nx node id.
3266
+ :param str v_: nx node id.
3267
+ :return: intersection of paths.
3268
+ :rtype: str
3269
+ """
3270
+ while u_ != v_:
3271
+ while dfn[u_] < dfn[v_]:
3272
+ u_ = idom[u_]
3273
+ while dfn[u_] > dfn[v_]:
3274
+ v_ = idom[v_]
3275
+ return u_
3276
+
3277
+ changed = True
3278
+ while changed:
3279
+ changed = False
3280
+ for u in order:
3281
+ new_idom = reduce(intersect, (v for v in graph.pred[u] if v in idom))
3282
+ if u not in idom or idom[u] != new_idom:
3283
+ idom[u] = new_idom
3284
+ changed = True
3285
+
3286
+ return idom
3287
+
3288
+ #
3289
+ # Static private utility methods
3290
+ #
3291
+
3292
+ @staticmethod
3293
+ def _is_indirect_jump(_, sim_successors):
3294
+ """
3295
+ Determine if this SimIRSB has an indirect jump as its exit
3296
+ """
3297
+
3298
+ if sim_successors.artifacts["irsb_direct_next"]:
3299
+ # It's a direct jump
3300
+ return False
3301
+
3302
+ default_jumpkind = sim_successors.artifacts["irsb_default_jumpkind"]
3303
+
3304
+ # If false, it's something else, like a ret of a syscall... we don't care about it
3305
+ return not (default_jumpkind not in ("Ijk_Call", "Ijk_Boring", "Ijk_InvalICache"))
3306
+
3307
+ @staticmethod
3308
+ def _generate_block_id(call_stack_suffix, block_addr, is_syscall):
3309
+ if not is_syscall:
3310
+ return BlockID.new(block_addr, call_stack_suffix, "normal")
3311
+ return BlockID.new(block_addr, call_stack_suffix, "syscall")
3312
+
3313
+ @staticmethod
3314
+ def _block_id_repr(block_id):
3315
+ return repr(block_id)
3316
+
3317
+ @staticmethod
3318
+ def _block_id_callstack_key(block_id):
3319
+ return block_id.callsite_tuples
3320
+
3321
+ @staticmethod
3322
+ def _block_id_addr(block_id):
3323
+ return block_id.addr
3324
+
3325
+ @staticmethod
3326
+ def _block_id_current_func_addr(block_id):
3327
+ """
3328
+ If we don't have any information about the caller, we have no way to get the address of the current function.
3329
+
3330
+ :param BlockID block_id: The block ID.
3331
+ :return: The function address if there is one, or None if it's not possible to get.
3332
+ :rtype: int or None
3333
+ """
3334
+
3335
+ if block_id.callsite_tuples:
3336
+ return block_id.callsite_tuples[-1]
3337
+ return None
3338
+
3339
+ #
3340
+ # Other private utility methods
3341
+ #
3342
+
3343
+ @staticmethod
3344
+ def _is_call_jumpkind(jumpkind):
3345
+ return bool(jumpkind == "Ijk_Call" or jumpkind.startswith("Ijk_Sys_"))
3346
+
3347
+ def _push_unresolvable_run(self, block_address):
3348
+ """
3349
+ Adds this block to the list of unresolvable runs.
3350
+
3351
+ :param dict block_address: container of IRSB data from run.
3352
+ """
3353
+ self._unresolvable_runs.add(block_address)
3354
+
3355
+ def _is_address_executable(self, address):
3356
+ """
3357
+ Check if the specific address is in one of the executable ranges.
3358
+
3359
+ :param int address: The address
3360
+ :return: True if it's in an executable range, False otherwise
3361
+ """
3362
+
3363
+ return any(r[0] <= address < r[1] for r in self._executable_address_ranges)
3364
+
3365
+ def _update_thumb_addrs(self, simsuccessors, state):
3366
+ """
3367
+
3368
+ :return:
3369
+ """
3370
+
3371
+ # For ARM THUMB mode
3372
+ if simsuccessors.sort == "IRSB" and state.thumb:
3373
+ insn_addrs = simsuccessors.artifacts["insn_addrs"]
3374
+ self._thumb_addrs.update(insn_addrs)
3375
+ self._thumb_addrs.update(x + 1 for x in insn_addrs) # pylint:disable=bad-builtin
3376
+
3377
+ def _get_callsites(self, function_address):
3378
+ """
3379
+ Get where a specific function is called.
3380
+ :param function_address: Address of the target function
3381
+ :return: A list of CFGNodes whose exits include a call/jump to the given function
3382
+ """
3383
+
3384
+ all_predecessors = []
3385
+
3386
+ nodes = self.model.get_all_nodes(function_address)
3387
+ for n in nodes:
3388
+ predecessors = list(self.model.get_predecessors(n))
3389
+ all_predecessors.extend(predecessors)
3390
+
3391
+ return all_predecessors
3392
+
3393
+ def _get_nx_paths(self, begin, end):
3394
+ """
3395
+ Get the possible (networkx) simple paths between two nodes or addresses
3396
+ corresponding to nodes.
3397
+ Input: addresses or node instances
3398
+ Return: a list of lists of nodes representing paths.
3399
+ """
3400
+ if isinstance(begin, int) and isinstance(end, int):
3401
+ n_begin = self.model.get_any_node(begin)
3402
+ n_end = self.model.get_any_node(end)
3403
+
3404
+ elif isinstance(begin, CFGENode) and isinstance(end, CFGENode):
3405
+ n_begin = begin
3406
+ n_end = end
3407
+ else:
3408
+ raise AngrCFGError("from and to should be of the same type")
3409
+
3410
+ self.remove_fakerets()
3411
+ return networkx.all_shortest_paths(self.graph, n_begin, n_end)
3412
+
3413
+ def _quasi_topological_sort(self):
3414
+ """
3415
+ Perform a quasi-topological sort on an already constructed CFG graph (a networkx DiGraph)
3416
+
3417
+ :return: None
3418
+ """
3419
+
3420
+ # Clear the existing sorting result
3421
+ self._quasi_topological_order = {}
3422
+
3423
+ ctr = self._graph.number_of_nodes()
3424
+
3425
+ for ep in self._entry_points:
3426
+ # FIXME: This is not always correct. We'd better store CFGNodes in self._entry_points
3427
+ ep_node = self.model.get_any_node(ep)
3428
+
3429
+ if not ep_node:
3430
+ continue
3431
+
3432
+ for n in networkx.dfs_postorder_nodes(self._graph, source=ep_node):
3433
+ if n not in self._quasi_topological_order:
3434
+ self._quasi_topological_order[n] = ctr
3435
+ ctr -= 1
3436
+
3437
+ def _reset_state_mode(self, state, mode):
3438
+ """
3439
+ Reset the state mode to the given mode, and apply the custom state options specified with this analysis.
3440
+
3441
+ :param state: The state to work with.
3442
+ :param str mode: The state mode.
3443
+ :return: None
3444
+ """
3445
+
3446
+ state.set_mode(mode)
3447
+ state.options |= self._state_add_options
3448
+ state.options = state.options.difference(self._state_remove_options)
3449
+
3450
+
3451
+ AnalysesHub.register_default("CFGEmulated", CFGEmulated)