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,2954 @@
1
+ # pylint:disable=line-too-long,multiple-statements
2
+ from __future__ import annotations
3
+ from typing import TYPE_CHECKING, Any
4
+ import logging
5
+ from collections import defaultdict
6
+
7
+ import networkx
8
+ from sortedcontainers import SortedDict
9
+
10
+ import pyvex
11
+ from cle import (
12
+ ELF,
13
+ PE,
14
+ Blob,
15
+ PEStubs,
16
+ TLSObject,
17
+ MachO,
18
+ ExternObject,
19
+ KernelObject,
20
+ FunctionHintSource,
21
+ Hex,
22
+ Coff,
23
+ SRec,
24
+ XBE,
25
+ )
26
+ from cle.backends import NamedRegion
27
+ import archinfo
28
+ from archinfo.arch_soot import SootAddressDescriptor, SootMethodDescriptor
29
+ from archinfo.arch_arm import is_arm_arch, get_real_address_if_arm
30
+
31
+ from angr.knowledge_plugins.functions.function_manager import FunctionManager
32
+ from angr.knowledge_plugins.functions.function import Function
33
+ from angr.knowledge_plugins.cfg import IndirectJump, CFGNode, CFGENode, CFGModel # pylint:disable=unused-import
34
+ from angr.procedures.stubs.UnresolvableJumpTarget import UnresolvableJumpTarget
35
+ from angr.utils.constants import DEFAULT_STATEMENT
36
+ from angr.procedures.procedure_dict import SIM_PROCEDURES
37
+ from angr.errors import (
38
+ AngrCFGError,
39
+ SimTranslationError,
40
+ SimMemoryError,
41
+ SimIRSBError,
42
+ SimEngineError,
43
+ AngrUnsupportedSyscallError,
44
+ SimError,
45
+ )
46
+ from angr.codenode import HookNode, BlockNode
47
+ from angr.engines.vex.lifter import VEX_IRSB_MAX_SIZE, VEX_IRSB_MAX_INST
48
+ from angr.analyses import Analysis
49
+ from angr.analyses.stack_pointer_tracker import StackPointerTracker
50
+ from angr.utils.orderedset import OrderedSet
51
+ from .indirect_jump_resolvers.default_resolvers import default_indirect_jump_resolvers
52
+
53
+ if TYPE_CHECKING:
54
+ from angr.sim_state import SimState
55
+
56
+
57
+ l = logging.getLogger(name=__name__)
58
+
59
+
60
+ class CFGBase(Analysis):
61
+ """
62
+ The base class for control flow graphs.
63
+ """
64
+
65
+ tag: str | None = None
66
+ _cle_pseudo_objects = (ExternObject, KernelObject, TLSObject)
67
+
68
+ def __init__(
69
+ self,
70
+ sort,
71
+ context_sensitivity_level,
72
+ normalize=False,
73
+ binary=None,
74
+ objects=None,
75
+ regions=None,
76
+ exclude_sparse_regions=True,
77
+ skip_specific_regions=True,
78
+ force_segment=False,
79
+ base_state=None,
80
+ resolve_indirect_jumps=True,
81
+ indirect_jump_resolvers=None,
82
+ indirect_jump_target_limit=100000,
83
+ detect_tail_calls=False,
84
+ low_priority=False,
85
+ skip_unmapped_addrs=True,
86
+ sp_tracking_track_memory=True,
87
+ model=None,
88
+ ):
89
+ """
90
+ :param str sort: 'fast' or 'emulated'.
91
+ :param int context_sensitivity_level: The level of context-sensitivity of this CFG (see documentation for
92
+ further details). It ranges from 0 to infinity.
93
+ :param bool normalize: Whether the CFG as well as all Function graphs should be normalized.
94
+ :param cle.backends.Backend binary: The binary to recover CFG on. By default, the main binary is used.
95
+ :param objects: A list of objects to recover the CFG on. By default, it will recover
96
+ the CFG of all loaded objects.
97
+ :param iterable regions: A list of tuples in the form of (start address, end address)
98
+ describing memory regions that the CFG should cover.
99
+ :param bool force_segment: Force CFGFast to rely on binary segments instead of sections.
100
+ :param angr.SimState base_state: A state to use as a backer for all memory loads.
101
+ :param bool resolve_indirect_jumps: Whether to try to resolve indirect jumps.
102
+ This is necessary to resolve jump targets from jump tables, etc.
103
+ :param list indirect_jump_resolvers: A custom list of indirect jump resolvers.
104
+ If this list is None or empty, default indirect jump resolvers
105
+ specific to this architecture and binary types will be loaded.
106
+ :param int indirect_jump_target_limit: Maximum indirect jump targets to be recovered.
107
+ :param skip_unmapped_addrs: Ignore all branches into unmapped regions. True by default. You may
108
+ want to set it to False if you are analyzing manually patched
109
+ binaries or malware samples.
110
+ :param bool detect_tail_calls: Aggressive tail-call optimization detection. This option is only
111
+ respected in make_functions().
112
+ :param bool sp_tracking_track_memory: Whether or not to track memory writes if tracking the stack pointer.
113
+ This increases the accuracy of stack pointer tracking,
114
+ especially for architectures without a base pointer.
115
+ Only used if detect_tail_calls is enabled.
116
+ :param None or CFGModel model: The CFGModel instance to write to. A new CFGModel instance will be
117
+ created and registered with the knowledge base if `model` is None.
118
+
119
+ :return: None
120
+ """
121
+
122
+ self.sort = sort
123
+ self._context_sensitivity_level = context_sensitivity_level
124
+
125
+ # Sanity checks
126
+ if context_sensitivity_level < 0:
127
+ raise ValueError(f"Unsupported context sensitivity level {context_sensitivity_level}")
128
+
129
+ self._binary = binary if binary is not None else self.project.loader.main_object
130
+ self._force_segment = force_segment
131
+ self._base_state = base_state
132
+ self._detect_tail_calls = detect_tail_calls
133
+ self._low_priority = low_priority
134
+ self._skip_unmapped_addrs = skip_unmapped_addrs
135
+
136
+ # Initialization
137
+ self._edge_map = None
138
+ self._loop_back_edges = None
139
+ self._overlapped_loop_headers = None
140
+ self._thumb_addrs = set()
141
+ self._tail_calls = set()
142
+
143
+ # Store all the functions analyzed before the set is cleared
144
+ # Used for performance optimization
145
+ self._updated_nonreturning_functions: set[int | SootMethodDescriptor] | None = None
146
+
147
+ self._normalize = normalize
148
+
149
+ # Flag, whether to track memory writes in stack pointer tracking
150
+ self._sp_tracking_track_memory = sp_tracking_track_memory
151
+
152
+ # IndirectJump object that describe all indirect exits found in the binary
153
+ # stores as a map between addresses and IndirectJump objects
154
+ self.indirect_jumps: dict[int, IndirectJump] = {}
155
+ self._indirect_jumps_to_resolve = set()
156
+
157
+ # Indirect jump resolvers
158
+ self._indirect_jump_target_limit = indirect_jump_target_limit
159
+ self._resolve_indirect_jumps = resolve_indirect_jumps
160
+ self.timeless_indirect_jump_resolvers = []
161
+ self.indirect_jump_resolvers = []
162
+ if not indirect_jump_resolvers:
163
+ indirect_jump_resolvers = default_indirect_jump_resolvers(self._binary, self.project)
164
+ if self._resolve_indirect_jumps and indirect_jump_resolvers:
165
+ # split them into different groups for the sake of speed
166
+ for ijr in indirect_jump_resolvers:
167
+ if ijr.timeless:
168
+ self.timeless_indirect_jump_resolvers.append(ijr)
169
+ else:
170
+ self.indirect_jump_resolvers.append(ijr)
171
+
172
+ l.info(
173
+ "Loaded %d indirect jump resolvers (%d timeless, %d generic).",
174
+ len(self.timeless_indirect_jump_resolvers) + len(self.indirect_jump_resolvers),
175
+ len(self.timeless_indirect_jump_resolvers),
176
+ len(self.indirect_jump_resolvers),
177
+ )
178
+
179
+ # Get all executable memory regions
180
+ self._exec_mem_regions = self._executable_memory_regions(None, self._force_segment)
181
+ self._exec_mem_region_size = sum((end - start) for start, end in self._exec_mem_regions)
182
+
183
+ # initialize UnresolvableJumpTarget and UnresolvableCallTarget SimProcedure
184
+ # but we do not want to hook the same symbol multiple times
185
+ ut_jump_addr = self.project.loader.extern_object.get_pseudo_addr("UnresolvableJumpTarget")
186
+ if not self.project.is_hooked(ut_jump_addr):
187
+ self.project.hook(ut_jump_addr, SIM_PROCEDURES["stubs"]["UnresolvableJumpTarget"]())
188
+ self._unresolvable_jump_target_addr = ut_jump_addr
189
+ ut_call_addr = self.project.loader.extern_object.get_pseudo_addr("UnresolvableCallTarget")
190
+ if not self.project.is_hooked(ut_call_addr):
191
+ self.project.hook(ut_call_addr, SIM_PROCEDURES["stubs"]["UnresolvableCallTarget"]())
192
+ self._unresolvable_call_target_addr = ut_call_addr
193
+
194
+ # partially and fully analyzed functions
195
+ # this is implemented as a state machine: jobs (CFGJob instances) of each function are put into
196
+ # _jobs_to_analyze_per_function, which essentially makes the keys of this dict being all partially analyzed
197
+ # functions so far. And then when a function does not have any more job to analyze in the future, it will be
198
+ # put in to _completed_functions.
199
+
200
+ # a dict of mapping between function addresses and sets of jobs (include both future jobs and pending jobs)
201
+ # a set is used to speed up the job removal procedure
202
+ self._jobs_to_analyze_per_function = defaultdict(set)
203
+ # addresses of functions that have been completely recovered (i.e. all of its blocks are identified) so far
204
+ self._completed_functions = set()
205
+
206
+ # TODO: A segment tree to speed up CFG node lookups
207
+ self._node_lookup_index = None
208
+ self._node_lookup_index_warned = False
209
+
210
+ self._function_addresses_from_symbols = self._load_func_addrs_from_symbols()
211
+ self._function_addresses_from_eh_frame = self._load_func_addrs_from_eh_frame()
212
+
213
+ # Cache if an object has executable sections or not
214
+ self._object_to_executable_sections = {}
215
+ # Cache if an object has executable segments or not
216
+ self._object_to_executable_segments = {}
217
+
218
+ if model is not None:
219
+ self._model = model
220
+ else:
221
+ self._model: CFGModel = self.kb.cfgs.new_model(self.tag)
222
+
223
+ # necessary warnings
224
+ regions_not_specified = regions is None and binary is None and not objects
225
+ if regions_not_specified and self.project.loader._auto_load_libs and len(self.project.loader.all_objects) > 3:
226
+ l.warning(
227
+ '"auto_load_libs" is enabled. With libraries loaded in project, CFG will cover libraries, '
228
+ "which may take significantly more time than expected. You may reload the binary with "
229
+ '"auto_load_libs" disabled, or specify "regions" to limit the scope of CFG recovery.'
230
+ )
231
+
232
+ if regions is None:
233
+ if self._skip_unmapped_addrs:
234
+ regions = self._executable_memory_regions(objects=objects, force_segment=force_segment)
235
+ else:
236
+ if not objects:
237
+ objects = self.project.loader.all_objects
238
+ regions = self._executable_memory_regions(objects=objects, force_segment=force_segment)
239
+ if not regions:
240
+ # fall back to using min and max addresses of all objects
241
+ regions = [(obj.min_addr, obj.max_addr) for obj in objects]
242
+
243
+ for start, end in regions:
244
+ if end < start:
245
+ raise AngrCFGError("Invalid region bounds (end precedes start)")
246
+
247
+ # Block factory returns patched state by default, so ensure we are also analyzing the patched state
248
+ if self._base_state is None and self.project.kb.patches.values():
249
+ self._base_state = self.project.kb.patches.patched_entry_state
250
+
251
+ if exclude_sparse_regions:
252
+ regions = [r for r in regions if not self._is_region_extremely_sparse(*r, base_state=self._base_state)]
253
+
254
+ if skip_specific_regions:
255
+ if base_state is not None:
256
+ l.warning("You specified both base_state and skip_specific_regions. They may conflict with each other.")
257
+ regions = [r for r in regions if not self._should_skip_region(r[0])]
258
+
259
+ if not regions and self.project.arch.name != "Soot":
260
+ raise AngrCFGError(
261
+ "Regions are empty, or all regions are skipped. You may want to manually specify regions."
262
+ )
263
+
264
+ self._regions_size = sum((end - start) for start, end in regions)
265
+ self._regions: SortedDict = SortedDict(regions)
266
+
267
+ l.debug("CFG recovery covers %d regions:", len(self._regions))
268
+ for start, end in self._regions.items():
269
+ l.debug("... %#x - %#x", start, end)
270
+
271
+ def __contains__(self, cfg_node):
272
+ return cfg_node in self.graph
273
+
274
+ #
275
+ # Properties
276
+ #
277
+
278
+ @property
279
+ def _nodes(self):
280
+ return self._model._nodes
281
+
282
+ @property
283
+ def _nodes_by_addr(self):
284
+ return self._model._nodes_by_addr
285
+
286
+ @property
287
+ def model(self) -> CFGModel:
288
+ """
289
+ Get the CFGModel instance.
290
+ :return: The CFGModel instance that this analysis currently uses.
291
+ """
292
+ return self._model
293
+
294
+ @property
295
+ def normalized(self):
296
+ return self._model.normalized
297
+
298
+ @normalized.setter
299
+ def normalized(self, v):
300
+ self._model.normalized = v
301
+
302
+ @property
303
+ def context_sensitivity_level(self):
304
+ return self._context_sensitivity_level
305
+
306
+ @property
307
+ def functions(self):
308
+ """
309
+ A reference to the FunctionManager in the current knowledge base.
310
+
311
+ :return: FunctionManager with all functions
312
+ :rtype: angr.knowledge_plugins.FunctionManager
313
+ """
314
+ return self.kb.functions
315
+
316
+ #
317
+ # Methods
318
+ #
319
+
320
+ def _initialize_cfg(self):
321
+ """
322
+ Re-create the DiGraph
323
+ """
324
+
325
+ self._jobs_to_analyze_per_function = defaultdict(set)
326
+ self._completed_functions = set()
327
+
328
+ def _function_completed(self, func_addr: int):
329
+ pass
330
+
331
+ def _post_analysis(self):
332
+ if self._normalize:
333
+ if not self.normalized:
334
+ self.normalize()
335
+
336
+ # Call normalize() on each function
337
+ for f in self.kb.functions.values():
338
+ if not self.project.is_hooked(f.addr):
339
+ f.normalize()
340
+
341
+ # drop all propagation results that start with "cfg_intermediate"
342
+ self.kb.propagations.discard_by_prefix("cfg_intermediate")
343
+
344
+ def make_copy(self, copy_to):
345
+ """
346
+ Copy self attributes to the new object.
347
+
348
+ :param CFGBase copy_to: The target to copy to.
349
+ :return: None
350
+ """
351
+
352
+ for attr, value in self.__dict__.items():
353
+ if attr.startswith("__") and attr.endswith("__"):
354
+ continue
355
+ setattr(copy_to, attr, value)
356
+
357
+ # pylint: disable=no-self-use
358
+ def copy(self):
359
+ raise NotImplementedError
360
+
361
+ def output(self):
362
+ raise NotImplementedError
363
+
364
+ def generate_index(self):
365
+ """
366
+ Generate an index of all nodes in the graph in order to speed up get_any_node() with anyaddr=True.
367
+
368
+ :return: None
369
+ """
370
+
371
+ raise NotImplementedError("I'm too lazy to implement it right now")
372
+
373
+ def get_loop_back_edges(self):
374
+ return self._loop_back_edges
375
+
376
+ @property
377
+ def graph(self) -> networkx.DiGraph[CFGNode]:
378
+ raise NotImplementedError
379
+
380
+ def remove_edge(self, block_from, block_to):
381
+ if self.graph is None:
382
+ raise TypeError("self.graph does not exist.")
383
+
384
+ if block_from not in self.graph:
385
+ raise ValueError(f"{block_from!r} is not in CFG.")
386
+
387
+ if block_to not in self.graph:
388
+ raise ValueError(f"{block_to!r} is not in CFG.")
389
+
390
+ if block_to not in self.graph[block_from]:
391
+ raise ValueError(f"Edge {block_from!r}->{block_to!r} does not exist.")
392
+
393
+ self.graph.remove_edge(block_from, block_to)
394
+
395
+ def _merge_cfgnodes(self, cfgnode_0, cfgnode_1):
396
+ """
397
+ Merge two adjacent CFGNodes into one.
398
+
399
+ :param CFGNode cfgnode_0: The first CFGNode.
400
+ :param CFGNode cfgnode_1: The second CFGNode.
401
+ :return: None
402
+ """
403
+
404
+ assert cfgnode_0.addr + cfgnode_0.size == cfgnode_1.addr
405
+ new_node = cfgnode_0.merge(cfgnode_1)
406
+
407
+ # Update the graph and the nodes dict accordingly
408
+ self._model.remove_node(cfgnode_1.block_id, cfgnode_1)
409
+ self._model.remove_node(cfgnode_0.block_id, cfgnode_0)
410
+
411
+ in_edges = list(self.graph.in_edges(cfgnode_0, data=True))
412
+ out_edges = list(self.graph.out_edges(cfgnode_1, data=True))
413
+
414
+ self.graph.remove_node(cfgnode_0)
415
+ self.graph.remove_node(cfgnode_1)
416
+
417
+ self.graph.add_node(new_node)
418
+ for src, _, data in in_edges:
419
+ self.graph.add_edge(src, new_node, **data)
420
+ for _, dst, data in out_edges:
421
+ self.graph.add_edge(new_node, dst, **data)
422
+
423
+ # Put the new node into node dicts
424
+ self._model.add_node(new_node.block_id, new_node)
425
+
426
+ def _to_snippet(self, cfg_node=None, addr=None, size=None, thumb=False, jumpkind=None, base_state=None):
427
+ """
428
+ Convert a CFGNode instance to a CodeNode object.
429
+
430
+ :param angr.analyses.CFGNode cfg_node: The CFGNode instance.
431
+ :param int addr: Address of the node. Only used when `cfg_node` is None.
432
+ :param bool thumb: Whether this is in THUMB mode or not. Only used for ARM code and when `cfg_node` is None.
433
+ :param str or None jumpkind: Jumpkind of this node.
434
+ :param SimState or None base_state: The state where BlockNode should be created from.
435
+ :return: A converted CodeNode instance.
436
+ :rtype: CodeNode
437
+ """
438
+
439
+ if cfg_node is not None:
440
+ addr = cfg_node.addr
441
+ size = cfg_node.size
442
+ thumb = cfg_node.thumb
443
+
444
+ if addr is None:
445
+ raise ValueError("_to_snippet(): Either cfg_node or addr must be provided.")
446
+
447
+ if self.project.is_hooked(addr) and jumpkind != "Ijk_NoHook":
448
+ hooker = self.project._sim_procedures[addr]
449
+ size = hooker.kwargs.get("length", 0)
450
+ return HookNode(addr, size, type(hooker))
451
+
452
+ if cfg_node is not None:
453
+ return BlockNode(addr, size, thumb=thumb, bytestr=cfg_node.byte_string) # pylint: disable=no-member
454
+ return self.project.factory.snippet(addr, size=size, jumpkind=jumpkind, thumb=thumb, backup_state=base_state)
455
+
456
+ def is_thumb_addr(self, addr):
457
+ return addr in self._thumb_addrs
458
+
459
+ def _arm_thumb_filter_jump_successors(self, irsb, successors, get_ins_addr, get_exit_stmt_idx, get_jumpkind):
460
+ """
461
+ Filter successors for THUMB mode basic blocks, and remove those successors that won't be taken normally.
462
+
463
+ :param irsb: The IRSB object.
464
+ :param list successors: A list of successors.
465
+ :param func get_ins_addr: A callable that returns the source instruction address for a successor.
466
+ :param func get_exit_stmt_idx: A callable that returns the source statement ID for a successor.
467
+ :param func get_jumpkind: A callable that returns the jumpkind of a successor.
468
+ :return: A new list of successors after filtering.
469
+ :rtype: list
470
+ """
471
+
472
+ if not successors:
473
+ return []
474
+
475
+ if len(successors) == 1 and get_exit_stmt_idx(successors[0]) == DEFAULT_STATEMENT:
476
+ # only have a default exit. no need to filter
477
+ return successors
478
+
479
+ if irsb.instruction_addresses and all(
480
+ get_ins_addr(suc) == irsb.instruction_addresses[-1] for suc in successors
481
+ ):
482
+ # check if all exits are produced by the last instruction
483
+ # only takes the following jump kinds: Boring, FakeRet, Call, Syscall, Ret
484
+ allowed_jumpkinds = {"Ijk_Boring", "Ijk_FakeRet", "Ijk_Call", "Ijk_Ret"}
485
+ successors = [
486
+ suc
487
+ for suc in successors
488
+ if get_jumpkind(suc) in allowed_jumpkinds or get_jumpkind(suc).startswith("Ijk_Sys")
489
+ ]
490
+ if len(successors) == 1:
491
+ return successors
492
+
493
+ can_produce_exits = set() # addresses of instructions that can produce exits
494
+ bb = self._lift(irsb.addr, size=irsb.size, thumb=True)
495
+
496
+ # step A: filter exits using capstone (since it's faster than re-lifting the entire block to VEX)
497
+ THUMB_BRANCH_INSTRUCTIONS = {
498
+ "beq",
499
+ "bne",
500
+ "bcs",
501
+ "bhs",
502
+ "bcc",
503
+ "blo",
504
+ "bmi",
505
+ "bpl",
506
+ "bvs",
507
+ "bvc",
508
+ "bhi",
509
+ "bls",
510
+ "bge",
511
+ "blt",
512
+ "bgt",
513
+ "ble",
514
+ "cbz",
515
+ "cbnz",
516
+ }
517
+ for cs_insn in bb.capstone.insns:
518
+ if cs_insn.mnemonic.split(".")[0] in THUMB_BRANCH_INSTRUCTIONS:
519
+ can_produce_exits.add(cs_insn.address)
520
+
521
+ if all(
522
+ get_ins_addr(suc) in can_produce_exits or get_exit_stmt_idx(suc) == DEFAULT_STATEMENT for suc in successors
523
+ ):
524
+ # nothing will be filtered.
525
+ return successors
526
+
527
+ # step B: consider VEX statements
528
+ it_counter = 0
529
+ conc_temps = {}
530
+
531
+ for stmt in bb.vex.statements:
532
+ if stmt.tag == "Ist_IMark":
533
+ if it_counter > 0:
534
+ it_counter -= 1
535
+ can_produce_exits.add(stmt.addr + stmt.delta)
536
+ elif stmt.tag == "Ist_WrTmp":
537
+ val = stmt.data
538
+ if val.tag == "Iex_Const":
539
+ conc_temps[stmt.tmp] = val.con.value
540
+ elif stmt.tag == "Ist_Put" and stmt.offset == self.project.arch.registers["itstate"][0]:
541
+ val = stmt.data
542
+ if val.tag == "Iex_RdTmp":
543
+ if val.tmp in conc_temps:
544
+ # We found an IT instruction!!
545
+ # Determine how many instructions are conditional
546
+ it_counter = 0
547
+ itstate = conc_temps[val.tmp]
548
+ while itstate != 0:
549
+ it_counter += 1
550
+ itstate >>= 8
551
+ elif val.tag == "Iex_Const":
552
+ it_counter = 0
553
+ itstate = val.con.value
554
+ while itstate != 0:
555
+ it_counter += 1
556
+ itstate >>= 8
557
+
558
+ if it_counter != 0:
559
+ l.debug("Basic block ends before calculated IT block (%#x)", irsb.addr)
560
+
561
+ return [
562
+ suc
563
+ for suc in successors
564
+ if get_ins_addr(suc) in can_produce_exits or get_exit_stmt_idx(suc) == DEFAULT_STATEMENT
565
+ ]
566
+
567
+ # Methods for determining scanning scope
568
+
569
+ def _inside_regions(self, address: int | None) -> bool:
570
+ """
571
+ Check if the address is inside any existing region.
572
+
573
+ :param int address: Address to check.
574
+ :return: True if the address is within one of the memory regions, False otherwise.
575
+ """
576
+
577
+ try:
578
+ start_addr = next(self._regions.irange(maximum=address, reverse=True))
579
+ except StopIteration:
580
+ return False
581
+ else:
582
+ return address < self._regions[start_addr]
583
+
584
+ def _get_min_addr(self) -> int | None:
585
+ """
586
+ Get the minimum address out of all regions. We assume self._regions is sorted.
587
+
588
+ :return: The minimum address, or None if there is no such address.
589
+ """
590
+
591
+ if not self._regions:
592
+ if self.project.arch.name != "Soot":
593
+ l.error("self._regions is empty or not properly set.")
594
+ return None
595
+
596
+ return next(self._regions.irange())
597
+
598
+ def _next_address_in_regions(self, address: int | None) -> int | None:
599
+ """
600
+ Return the next immediate address that is inside any of the regions.
601
+
602
+ :param address: The address to start scanning.
603
+ :return: The next address that is inside one of the memory regions, or None if there is no such address.
604
+ """
605
+
606
+ if self._inside_regions(address):
607
+ return address
608
+
609
+ try:
610
+ return next(self._regions.irange(minimum=address, reverse=False))
611
+ except StopIteration:
612
+ return None
613
+
614
+ def _is_region_extremely_sparse(self, start: int, end: int, base_state: SimState | None = None) -> bool:
615
+ """
616
+ Check whether the given memory region is extremely sparse, i.e., all bytes are the same value.
617
+
618
+ :param start: The beginning of the region.
619
+ :param end: The end of the region (exclusive).
620
+ :param base_state: The base state (optional).
621
+ :return: True if the region is extremely sparse, False otherwise.
622
+ """
623
+
624
+ all_bytes = None
625
+
626
+ if base_state is not None:
627
+ all_bytes = base_state.memory.load(start, end - start)
628
+ try:
629
+ all_bytes = base_state.solver.eval(all_bytes, cast_to=bytes)
630
+ except SimError:
631
+ all_bytes = None
632
+
633
+ size = end - start
634
+
635
+ if all_bytes is None:
636
+ # load from the binary
637
+ all_bytes = self._fast_memory_load_bytes(start, size)
638
+
639
+ if all_bytes is None:
640
+ # failed to load bytes in this region. it might be because the region is not fully mapped (i.e., there are
641
+ # holes). we assume this region is good for analysis.
642
+ return False
643
+
644
+ if len(all_bytes) < size:
645
+ l.warning(
646
+ "_is_region_extremely_sparse: The given region %#x-%#x is not a continuous memory region in the "
647
+ "memory space. Only the first %d bytes (%#x-%#x) are processed.",
648
+ start,
649
+ end,
650
+ len(all_bytes),
651
+ start,
652
+ start + len(all_bytes),
653
+ )
654
+
655
+ the_byte_value = None
656
+ for b in all_bytes:
657
+ if the_byte_value is None:
658
+ the_byte_value = b
659
+ else:
660
+ if the_byte_value != b:
661
+ return False
662
+
663
+ return True
664
+
665
+ def _should_skip_region(self, region_start):
666
+ """
667
+ Some regions usually do not contain any executable code, but are still marked as executable. We should skip
668
+ those regions by default.
669
+
670
+ :param int region_start: Address of the beginning of the region.
671
+ :return: True/False
672
+ :rtype: bool
673
+ """
674
+
675
+ obj = self.project.loader.find_object_containing(region_start, membership_check=False)
676
+ if obj is None:
677
+ return False
678
+ if isinstance(obj, PE):
679
+ section = obj.find_section_containing(region_start)
680
+ if section is None:
681
+ return False
682
+ if section.name in {".textbss"}:
683
+ return True
684
+
685
+ return False
686
+
687
+ def _executable_memory_regions(self, objects=None, force_segment=False):
688
+ """
689
+ Get all executable memory regions from the binaries
690
+
691
+ :param objects: A collection of binary objects to collect regions from. If None, regions from all project
692
+ binary objects are used.
693
+ :param bool force_segment: Rely on binary segments instead of sections.
694
+ :return: A sorted list of tuples (beginning_address, end_address)
695
+ """
696
+
697
+ binaries = self.project.loader.all_objects if objects is None else objects
698
+
699
+ memory_regions = []
700
+
701
+ for b in binaries:
702
+ if not b.has_memory:
703
+ continue
704
+
705
+ if isinstance(b, ELF):
706
+ # If we have sections, we get result from sections
707
+ sections = []
708
+ if not force_segment and b.sections:
709
+ # Get all executable sections
710
+ for section in b.sections:
711
+ if section.is_executable:
712
+ max_mapped_addr = section.min_addr + min(section.memsize, section.filesize)
713
+ tpl = (section.min_addr, max_mapped_addr)
714
+ sections.append(tpl)
715
+ memory_regions += sections
716
+
717
+ segments = []
718
+ # Get all executable segments
719
+ for segment in b.segments:
720
+ if segment.is_executable:
721
+ max_mapped_addr = segment.min_addr + min(segment.memsize, segment.filesize)
722
+ tpl = (segment.min_addr, max_mapped_addr)
723
+ segments.append(tpl)
724
+ if sections and segments:
725
+ # are there executable segments with no sections inside?
726
+ for segment in segments:
727
+ for section in sections:
728
+ if segment[0] <= section[0] < segment[1]:
729
+ break
730
+ else:
731
+ memory_regions.append(segment)
732
+
733
+ elif isinstance(b, (Coff, PE)):
734
+ for section in b.sections:
735
+ if section.is_executable:
736
+ max_mapped_addr = section.min_addr + min(section.memsize, section.filesize)
737
+ tpl = (section.min_addr, max_mapped_addr)
738
+ memory_regions.append(tpl)
739
+
740
+ elif isinstance(b, XBE):
741
+ # some XBE files will mark the data sections as executable
742
+ for section in b.sections:
743
+ if (
744
+ section.is_executable
745
+ and not section.is_writable
746
+ and section.name not in {".data", ".rdata", ".rodata"}
747
+ ):
748
+ tpl = (section.min_addr, section.max_addr)
749
+ memory_regions.append(tpl)
750
+
751
+ elif isinstance(b, MachO):
752
+ if b.segments:
753
+ # Get all executable segments
754
+ for seg in b.segments:
755
+ if seg.is_executable:
756
+ # Take all sections from this segment (MachO style)
757
+ for section in seg.sections:
758
+ max_mapped_addr = section.min_addr + min(section.memsize, section.filesize)
759
+ tpl = (section.min_addr, max_mapped_addr)
760
+ memory_regions.append(tpl)
761
+
762
+ elif isinstance(b, (Hex, SRec)):
763
+ if b.regions:
764
+ for region_addr, region_size in b.regions:
765
+ memory_regions.append((region_addr, region_addr + region_size))
766
+
767
+ elif isinstance(b, Blob):
768
+ # a blob is entirely executable
769
+ tpl = (b.min_addr, b.max_addr + 1)
770
+ memory_regions.append(tpl)
771
+
772
+ elif isinstance(b, NamedRegion):
773
+ # NamedRegions have no content! Ignore
774
+ pass
775
+
776
+ elif isinstance(b, PEStubs):
777
+ # no code here
778
+ pass
779
+
780
+ elif isinstance(b, self._cle_pseudo_objects):
781
+ pass
782
+
783
+ elif hasattr(b, "sections") and b.sections:
784
+ sections = []
785
+ # Get all executable sections
786
+ for section in b.sections:
787
+ if section.is_executable:
788
+ max_mapped_addr = section.min_addr + min(section.memsize, section.filesize)
789
+ tpl = (section.min_addr, max_mapped_addr)
790
+ sections.append(tpl)
791
+ memory_regions += sections
792
+
793
+ elif hasattr(b, "segments") and b.segments:
794
+ segments = []
795
+ for segment in b.segments:
796
+ if segment.is_executable:
797
+ max_mapped_addr = segment.min_addr + min(segment.memsize, segment.filesize)
798
+ tpl = (segment.min_addr, max_mapped_addr)
799
+ segments.append(tpl)
800
+ memory_regions += segments
801
+
802
+ else:
803
+ l.warning('Unsupported object format "%s". Treat it as an executable.', b.__class__.__name__)
804
+
805
+ tpl = (b.min_addr, b.max_addr + 1)
806
+ memory_regions.append(tpl)
807
+
808
+ if not memory_regions:
809
+ memory_regions = [(start, start + len(backer)) for start, backer in self.project.loader.memory.backers()]
810
+
811
+ return sorted(memory_regions, key=lambda x: x[0])
812
+
813
+ def _addr_in_exec_memory_regions(self, addr):
814
+ """
815
+ Test if the address belongs to an executable memory region.
816
+
817
+ :param int addr: The address to test
818
+ :return: True if the address belongs to an exectubale memory region, False otherwise
819
+ :rtype: bool
820
+ """
821
+
822
+ return any(start <= addr < end for start, end in self._exec_mem_regions)
823
+
824
+ def _addrs_belong_to_same_section(self, addr_a, addr_b):
825
+ """
826
+ Test if two addresses belong to the same section.
827
+
828
+ :param int addr_a: The first address to test.
829
+ :param int addr_b: The second address to test.
830
+ :return: True if the two addresses belong to the same section or both of them do not belong to any
831
+ section, False otherwise.
832
+ :rtype: bool
833
+ """
834
+
835
+ obj = self.project.loader.find_object_containing(addr_a, membership_check=False)
836
+
837
+ if obj is None:
838
+ # test if addr_b also does not belong to any object
839
+ obj_b = self.project.loader.find_object_containing(addr_b, membership_check=False)
840
+ return obj_b is None
841
+
842
+ src_section = obj.find_section_containing(addr_a)
843
+ if src_section is None:
844
+ # test if addr_b also does not belong to any section
845
+ dst_section = obj.find_section_containing(addr_b)
846
+ if dst_section is None:
847
+ return self._addrs_belong_to_same_segment(addr_a, addr_b)
848
+ return False
849
+
850
+ return src_section.contains_addr(addr_b)
851
+
852
+ def _addrs_belong_to_same_segment(self, addr_a, addr_b):
853
+ """
854
+ Test if two addresses belong to the same segment.
855
+
856
+ :param int addr_a: The first address to test.
857
+ :param int addr_b: The second address to test.
858
+ :return: True if the two addresses belong to the same segment or both of them do not belong to any
859
+ section, False otherwise.
860
+ :rtype: bool
861
+ """
862
+
863
+ obj = self.project.loader.find_object_containing(addr_a, membership_check=False)
864
+
865
+ if obj is None:
866
+ # test if addr_b also does not belong to any object
867
+ obj_b = self.project.loader.find_object_containing(addr_b, membership_check=False)
868
+ return obj_b is None
869
+
870
+ src_segment = obj.find_segment_containing(addr_a)
871
+ if src_segment is None:
872
+ # test if addr_b also does not belong to any section
873
+ dst_segment = obj.find_segment_containing(addr_b)
874
+ return dst_segment is None
875
+
876
+ return src_segment.contains_addr(addr_b)
877
+
878
+ def _object_has_executable_sections(self, obj):
879
+ """
880
+ Check whether an object has at least one executable section.
881
+
882
+ :param cle.Backend obj: The object to test.
883
+ :return: None
884
+ """
885
+
886
+ if obj in self._object_to_executable_sections:
887
+ return self._object_to_executable_sections[obj]
888
+ r = any(sec.is_executable for sec in obj.sections)
889
+ self._object_to_executable_sections[obj] = r
890
+ return r
891
+
892
+ def _object_has_executable_segments(self, obj):
893
+ """
894
+ Check whether an object has at least one executable segment.
895
+
896
+ :param cle.Backend obj: The object to test.
897
+ :return: None
898
+ """
899
+
900
+ if obj in self._object_to_executable_segments:
901
+ return self._object_to_executable_segments[obj]
902
+ r = any(seg.is_executable for seg in obj.segments)
903
+ self._object_to_executable_segments[obj] = r
904
+ return r
905
+
906
+ def _addr_hooked_or_syscall(self, addr):
907
+ """
908
+ Check whether the address belongs to a hook or a syscall.
909
+
910
+ :param int addr: The address to check.
911
+ :return: True if the address is hooked or belongs to a syscall. False otherwise.
912
+ :rtype: bool
913
+ """
914
+
915
+ return self.project.is_hooked(addr) or self.project.simos.is_syscall_addr(addr)
916
+
917
+ def _fast_memory_load_byte(self, addr):
918
+ """
919
+ Perform a fast memory loading of a byte.
920
+
921
+ :param int addr: Address to read from.
922
+ :return: A char or None if the address does not exist.
923
+ :rtype: int or None
924
+ """
925
+
926
+ try:
927
+ return self.project.loader.memory[addr]
928
+ except KeyError:
929
+ return None
930
+
931
+ def _fast_memory_load_bytes(self, addr, length):
932
+ """
933
+ Perform a fast memory loading of some data.
934
+
935
+ :param int addr: Address to read from.
936
+ :param int length: Size of the string to load.
937
+ :return: A string or None if the address does not exist.
938
+ :rtype: bytes or None
939
+ """
940
+
941
+ try:
942
+ return self.project.loader.memory.load(addr, length)
943
+ except KeyError:
944
+ return None
945
+
946
+ def _fast_memory_load_pointer(self, addr, size=None) -> int | None:
947
+ """
948
+ Perform a fast memory loading of a pointer.
949
+
950
+ :param int addr: Address to read from.
951
+ :param int size: Size of the pointer. Default to machine-word size.
952
+ :return: A pointer or None if the address does not exist.
953
+ :rtype: int
954
+ """
955
+
956
+ try:
957
+ return self.project.loader.memory.unpack_word(addr, size=size)
958
+ except KeyError:
959
+ return None
960
+
961
+ def _load_func_addrs_from_symbols(self):
962
+ """
963
+ Get all possible function addresses that are specified by the symbols in the binary
964
+
965
+ :return: A set of addresses that are probably functions
966
+ :rtype: set
967
+ """
968
+
969
+ return {sym.rebased_addr for sym in self._binary.symbols if sym.is_function}
970
+
971
+ def _load_func_addrs_from_eh_frame(self):
972
+ """
973
+ Get possible function addresses from .eh_frame.
974
+
975
+ :return: A set of addresses that are probably functions.
976
+ :rtype: set
977
+ """
978
+
979
+ addrs = set()
980
+ if (isinstance(self._binary, ELF) and self._binary.has_dwarf_info) or isinstance(self._binary, PE):
981
+ for function_hint in self._binary.function_hints:
982
+ if function_hint.source == FunctionHintSource.EH_FRAME:
983
+ addrs.add(function_hint.addr)
984
+ return addrs
985
+
986
+ #
987
+ # Analyze function features
988
+ #
989
+
990
+ def _determine_function_returning(self, func, all_funcs_completed=False):
991
+ """
992
+ Determine if a function returns or not.
993
+
994
+ A function does not return if
995
+ a) it is a SimProcedure that has NO_RET being True,
996
+ or
997
+ b) it is completely recovered (i.e. every block of this function has been recovered, and no future block will
998
+ be added to it), and it does not have a ret or any equivalent instruction.
999
+
1000
+ A function returns if any of its block contains a ret instruction or any equivalence.
1001
+
1002
+ :param Function func: The function to work on.
1003
+ :param bool all_funcs_completed: Whether we treat all functions as completed functions or not.
1004
+ :return: True if the function returns, False if the function does not return, or None if it is
1005
+ not yet determinable with the information available at the moment.
1006
+ :rtype: bool or None
1007
+ """
1008
+
1009
+ if not self._inside_regions(func.addr):
1010
+ # we don't have a full view of this function. assume it returns
1011
+ return True
1012
+
1013
+ # If there is at least one return site, then this function is definitely returning
1014
+ if func.has_return:
1015
+ return True
1016
+
1017
+ # Let's first see if it's a known SimProcedure that does not return
1018
+ if self.project.is_hooked(func.addr):
1019
+ procedure = self.project.hooked_by(func.addr)
1020
+ else:
1021
+ try:
1022
+ procedure = self.project.simos.syscall_from_addr(func.addr, allow_unsupported=False)
1023
+ except AngrUnsupportedSyscallError:
1024
+ procedure = None
1025
+
1026
+ if procedure is not None and hasattr(procedure, "NO_RET"):
1027
+ return not procedure.NO_RET
1028
+
1029
+ # did we finish analyzing this function?
1030
+ if not all_funcs_completed and func.addr not in self._completed_functions:
1031
+ return None
1032
+
1033
+ if not func.block_addrs_set:
1034
+ # there is no block inside this function
1035
+ # it might happen if the function has been incorrectly identified as part of another function
1036
+ # the error will be corrected during post-processing. In fact at this moment we cannot say anything
1037
+ # about whether this function returns or not. We always assume it returns.
1038
+ return True
1039
+
1040
+ bail_out = False
1041
+
1042
+ # if this function has jump-out sites or ret-out sites, it returns as long as any of the target function
1043
+ # returns
1044
+ for goout_site, type_ in [(site, "jumpout") for site in func.jumpout_sites] + [
1045
+ (site, "retout") for site in func.retout_sites
1046
+ ]:
1047
+ # determine where it jumps/returns to
1048
+ goout_site_successors = goout_site.successors()
1049
+ # Filter out UnresolvableJumpTarget because those don't mean that we actually know where it jumps to
1050
+ known_successors = [
1051
+ n
1052
+ for n in goout_site_successors
1053
+ if not (isinstance(n, HookNode) and n.sim_procedure == UnresolvableJumpTarget)
1054
+ ]
1055
+
1056
+ if not known_successors:
1057
+ # not sure where it jumps to. bail out
1058
+ bail_out = True
1059
+ continue
1060
+
1061
+ # for ret-out sites, determine what function it calls
1062
+ if type_ == "retout":
1063
+ # see whether the function being called returns or not
1064
+ func_successors = [succ for succ in goout_site_successors if isinstance(succ, Function)]
1065
+ if func_successors and all(
1066
+ func_successor.returning in (None, False) for func_successor in func_successors
1067
+ ):
1068
+ # the returning of all possible function calls are undetermined, or they do not return
1069
+ # ignore this site
1070
+ continue
1071
+
1072
+ if type_ == "retout":
1073
+ goout_target = next((succ for succ in goout_site_successors if not isinstance(succ, Function)), None)
1074
+ else:
1075
+ goout_target = next((succ for succ in goout_site_successors), None)
1076
+ if goout_target is None:
1077
+ # there is no jumpout site, which is weird, but what can we do...
1078
+ continue
1079
+ if not self.kb.functions.contains_addr(goout_target.addr):
1080
+ # wait it does not jump to a function?
1081
+ bail_out = True
1082
+ continue
1083
+
1084
+ target_func = self.kb.functions[goout_target.addr]
1085
+ if target_func.returning is True:
1086
+ return True
1087
+ if target_func.returning is None:
1088
+ # the returning status of at least one of the target functions is not decided yet.
1089
+ bail_out = True
1090
+
1091
+ if bail_out:
1092
+ # We cannot determine at this point. bail out
1093
+ return None
1094
+
1095
+ # well this function does not return then
1096
+ return False
1097
+
1098
+ def _analyze_function_features(self, all_funcs_completed=False):
1099
+ """
1100
+ For each function in the function_manager, try to determine if it returns or not. A function does not return if
1101
+ it calls another function that is known to be not returning, and this function does not have other exits.
1102
+
1103
+ We might as well analyze other features of functions in the future.
1104
+
1105
+ :param bool all_funcs_completed: Ignore _completed_functions set and treat all functions as completed. This
1106
+ can be set to True after the entire CFG is built and _post_analysis() is
1107
+ called (at which point analysis on all functions must be completed).
1108
+ """
1109
+
1110
+ changes = {"functions_return": [], "functions_do_not_return": []}
1111
+
1112
+ if self._updated_nonreturning_functions is not None:
1113
+ all_func_addrs = self._updated_nonreturning_functions
1114
+
1115
+ # Convert addresses to objects
1116
+ all_functions = [
1117
+ self.kb.functions.get_by_addr(f) for f in all_func_addrs if self.kb.functions.contains_addr(f)
1118
+ ]
1119
+
1120
+ else:
1121
+ all_functions = list(self.kb.functions.values())
1122
+
1123
+ analyzed_functions = set()
1124
+ # short-hand
1125
+ functions: FunctionManager = self.kb.functions
1126
+
1127
+ while all_functions:
1128
+ func: Function = all_functions.pop(-1)
1129
+ analyzed_functions.add(func.addr)
1130
+
1131
+ if func.returning is not None:
1132
+ # It has been determined before. Skip it
1133
+ continue
1134
+
1135
+ returning = self._determine_function_returning(func, all_funcs_completed=all_funcs_completed)
1136
+
1137
+ if returning:
1138
+ func.returning = True
1139
+ changes["functions_return"].append(func)
1140
+ elif returning is False:
1141
+ func.returning = False
1142
+ changes["functions_do_not_return"].append(func)
1143
+
1144
+ if returning is not None and func.addr in functions.callgraph:
1145
+ # Add all callers of this function to all_functions list
1146
+ callers = functions.callgraph.predecessors(func.addr)
1147
+ for caller in callers:
1148
+ if caller in analyzed_functions:
1149
+ continue
1150
+ if functions.contains_addr(caller):
1151
+ all_functions.append(functions.get_by_addr(caller))
1152
+
1153
+ return changes
1154
+
1155
+ def _iteratively_analyze_function_features(self, all_funcs_completed=False):
1156
+ """
1157
+ Iteratively analyze function features until a fixed point is reached.
1158
+
1159
+ :return: the "changes" dict
1160
+ :rtype: dict
1161
+ """
1162
+
1163
+ changes = {"functions_do_not_return": set(), "functions_return": set()}
1164
+
1165
+ while True:
1166
+ new_changes = self._analyze_function_features(all_funcs_completed=all_funcs_completed)
1167
+
1168
+ changes["functions_do_not_return"] |= set(new_changes["functions_do_not_return"])
1169
+ changes["functions_return"] |= set(new_changes["functions_return"])
1170
+
1171
+ if not new_changes["functions_do_not_return"] and not new_changes["functions_return"]:
1172
+ # a fixed point is reached
1173
+ break
1174
+
1175
+ return changes
1176
+
1177
+ def normalize(self):
1178
+ """
1179
+ Normalize the CFG, making sure that there are no overlapping basic blocks.
1180
+
1181
+ Note that this method will not alter transition graphs of each function in self.kb.functions. You may call
1182
+ normalize() on each Function object to normalize their transition graphs.
1183
+
1184
+ :return: None
1185
+ """
1186
+
1187
+ graph = self.graph
1188
+
1189
+ smallest_nodes = {} # indexed by end address of the node
1190
+ end_addr_to_node = {} # a dictionary from node key to node *if* only one node exists for the key
1191
+ end_addr_to_nodes = defaultdict(list) # a dictionary from node key to nodes *if* more than one node exist
1192
+
1193
+ for n in graph.nodes():
1194
+ if n.is_simprocedure:
1195
+ continue
1196
+ end_addr = n.addr + n.size
1197
+ key = (end_addr, n.callstack_key)
1198
+ # add the new item
1199
+ if key not in end_addr_to_node:
1200
+ # this is the first node of this key
1201
+ end_addr_to_node[key] = n
1202
+ else:
1203
+ # this is the 2nd+ node of this key
1204
+ if key not in end_addr_to_nodes:
1205
+ end_addr_to_nodes[key].append(end_addr_to_node[key])
1206
+ end_addr_to_nodes[key].append(n)
1207
+
1208
+ # update smallest_nodes
1209
+ for key, node in end_addr_to_node.items():
1210
+ if key in end_addr_to_nodes:
1211
+ continue
1212
+ smallest_nodes[key] = node
1213
+ del end_addr_to_node # micro memory optimization
1214
+
1215
+ while end_addr_to_nodes:
1216
+ key_to_find = (None, None)
1217
+ for tpl in list(end_addr_to_nodes):
1218
+ x = end_addr_to_nodes[tpl]
1219
+ if len(x) <= 1:
1220
+ continue
1221
+ key_to_find = tpl
1222
+
1223
+ end_addr, callstack_key = key_to_find
1224
+ all_nodes = end_addr_to_nodes[key_to_find]
1225
+
1226
+ all_nodes = sorted(all_nodes, key=lambda node: node.addr, reverse=True)
1227
+ smallest_node = all_nodes[0] # take the one that has the highest address
1228
+ other_nodes = all_nodes[1:]
1229
+
1230
+ self._normalize_core(
1231
+ graph, callstack_key, smallest_node, other_nodes, smallest_nodes, end_addr_to_nodes
1232
+ )
1233
+
1234
+ del end_addr_to_nodes[key_to_find]
1235
+ # make sure the smallest node is stored in end_addresses
1236
+ smallest_nodes[key_to_find] = smallest_node
1237
+
1238
+ # corner case
1239
+ # sometimes two overlapping blocks may not end at the instruction. this might happen when one of the
1240
+ # blocks (the bigger one) hits the instruction count limit or bytes limit before reaching the end
1241
+ # address of the smaller block. in this case we manually pick up those blocks.
1242
+ if not end_addr_to_nodes:
1243
+ # find if there are still overlapping blocks
1244
+ sorted_smallest_nodes = defaultdict(list) # callstack_key is the key of this dict
1245
+ for k, node in smallest_nodes.items():
1246
+ _, callstack_key = k
1247
+ sorted_smallest_nodes[callstack_key].append(node)
1248
+ for k in sorted_smallest_nodes:
1249
+ sorted_smallest_nodes[k] = sorted(sorted_smallest_nodes[k], key=lambda node: node.addr)
1250
+
1251
+ for callstack_key, lst in sorted_smallest_nodes.items():
1252
+ lst_len = len(lst)
1253
+ for i, node in enumerate(lst):
1254
+ if i == lst_len - 1:
1255
+ break
1256
+ next_node = lst[i + 1]
1257
+ if node is not next_node and node.addr <= next_node.addr < node.addr + node.size:
1258
+ # umm, those nodes are overlapping, but they must have different end addresses
1259
+ nodekey_a = node.addr + node.size, callstack_key
1260
+ nodekey_b = next_node.addr + next_node.size, callstack_key
1261
+ if nodekey_a == nodekey_b:
1262
+ # error handling: this will only happen if we have completely overlapping nodes
1263
+ # caused by different jumps (one of the jumps is probably incorrect), which usually
1264
+ # indicates an error in CFG recovery. we print a warning and skip this node
1265
+ l.warning(
1266
+ "Found completely overlapping nodes %s. It usually indicates an error in CFG "
1267
+ "recovery. Skip.",
1268
+ node,
1269
+ )
1270
+ continue
1271
+
1272
+ if nodekey_a in smallest_nodes and nodekey_b in smallest_nodes:
1273
+ # misuse end_addresses_to_nodes
1274
+ key = node.addr + node.size, callstack_key
1275
+ if node not in end_addr_to_nodes[key]:
1276
+ end_addr_to_nodes[key].append(node)
1277
+ if next_node not in end_addr_to_nodes[key]:
1278
+ end_addr_to_nodes[key].append(next_node)
1279
+
1280
+ smallest_nodes.pop(nodekey_a, None)
1281
+ smallest_nodes.pop(nodekey_b, None)
1282
+
1283
+ self.normalized = True
1284
+
1285
+ def _normalize_core(
1286
+ self,
1287
+ graph: networkx.DiGraph[CFGNode],
1288
+ callstack_key,
1289
+ smallest_node,
1290
+ other_nodes,
1291
+ smallest_nodes,
1292
+ end_addr_to_nodes,
1293
+ ):
1294
+ # Break other nodes
1295
+ for n in other_nodes:
1296
+ new_size = get_real_address_if_arm(self.project.arch, smallest_node.addr) - get_real_address_if_arm(
1297
+ self.project.arch, n.addr
1298
+ )
1299
+ if new_size == 0:
1300
+ # This node has the same size as the smallest one. Don't touch it.
1301
+ continue
1302
+
1303
+ new_end_addr = n.addr + new_size
1304
+
1305
+ # Does it already exist?
1306
+ new_node = None
1307
+ key = (new_end_addr, n.callstack_key)
1308
+ # the logic below is a little convoluted. we check if key exists in either end_address_to_nodes or
1309
+ # smallest_nodes, since we don't always add the new node back to end_addresses_to_nodes dict - we only do so
1310
+ # when there are more than one node with that key.
1311
+ if key in end_addr_to_nodes:
1312
+ new_node = next((i for i in end_addr_to_nodes[key] if i.addr == n.addr), None)
1313
+ if new_node is None and key in smallest_nodes and smallest_nodes[key].addr == n.addr:
1314
+ new_node = smallest_nodes[key]
1315
+
1316
+ if new_node is None:
1317
+ # Create a new one
1318
+
1319
+ instruction_addrs = []
1320
+ for ins_addr in n.instruction_addrs:
1321
+ if n.addr <= ins_addr < n.addr + new_size:
1322
+ instruction_addrs.append(ins_addr)
1323
+ elif ins_addr == n.addr + new_size:
1324
+ break
1325
+ elif ins_addr > n.addr + new_size:
1326
+ # the immediate next instruction does not start right after the new node. this means we break
1327
+ # an existing instruction in the middle! we need to drop the last instruction address from
1328
+ # instruction_addrs.
1329
+ instruction_addrs.pop()
1330
+ break
1331
+ else:
1332
+ # should not happen if the instruction_addrs list is normal...
1333
+ break
1334
+
1335
+ if self.tag == "CFGFast":
1336
+ new_node = CFGNode(
1337
+ n.addr,
1338
+ new_size,
1339
+ self.model,
1340
+ function_address=n.function_address,
1341
+ block_id=n.block_id,
1342
+ instruction_addrs=instruction_addrs,
1343
+ thumb=n.thumb,
1344
+ )
1345
+ elif self.tag == "CFGEmulated":
1346
+ new_node = CFGENode(
1347
+ n.addr,
1348
+ new_size,
1349
+ self.model,
1350
+ callstack_key=callstack_key,
1351
+ function_address=n.function_address,
1352
+ block_id=n.block_id,
1353
+ instruction_addrs=instruction_addrs,
1354
+ thumb=n.thumb,
1355
+ )
1356
+ else:
1357
+ raise ValueError(f"Unknown tag {self.tag}.")
1358
+
1359
+ # Put the new node into end_addresses list
1360
+ if key in smallest_nodes:
1361
+ if smallest_nodes[key] not in end_addr_to_nodes[key]:
1362
+ end_addr_to_nodes[key].append(smallest_nodes[key])
1363
+ if new_node not in end_addr_to_nodes[key]:
1364
+ end_addr_to_nodes[key].append(new_node)
1365
+ else:
1366
+ smallest_nodes[key] = new_node
1367
+
1368
+ # Modify the CFG
1369
+ original_predecessors = list(graph.in_edges([n], data=True))
1370
+ original_successors = list(graph.out_edges([n], data=True))
1371
+
1372
+ if smallest_node not in graph:
1373
+ continue
1374
+
1375
+ for _s, d, data in original_successors:
1376
+ ins_addr = data.get("ins_addr", None) # ins_addr might be None for FakeRet edges
1377
+ if ins_addr is None and data.get("jumpkind", None) != "Ijk_FakeRet":
1378
+ l.warning(
1379
+ "Unexpected edge with ins_addr being None: %s -> %s, data = %s.",
1380
+ _s,
1381
+ d,
1382
+ str(data),
1383
+ )
1384
+ if ins_addr is not None and ins_addr < smallest_node.addr:
1385
+ continue
1386
+ if d not in graph[smallest_node]:
1387
+ if d is n:
1388
+ graph.add_edge(smallest_node, new_node, **data)
1389
+ else:
1390
+ graph.add_edge(smallest_node, d, **data)
1391
+
1392
+ for p, _, _ in original_predecessors:
1393
+ graph.remove_edge(p, n)
1394
+ if n in graph:
1395
+ graph.remove_node(n)
1396
+
1397
+ # Update nodes dict
1398
+ self._model.remove_node(n.block_id, n)
1399
+ self._model.add_node(n.block_id, new_node)
1400
+
1401
+ for p, _, data in original_predecessors:
1402
+ # Consider the following case: two basic blocks ending at the same position, where A is larger, and
1403
+ # B is smaller. Suppose there is an edge going from the end of A to A itself, and apparently there
1404
+ # is another edge from B to A as well. After splitting A into A' and B, we DO NOT want to add A back
1405
+ # in, otherwise there will be an edge from A to A`, while A should totally be got rid of in the new
1406
+ # graph.
1407
+ if p not in other_nodes:
1408
+ graph.add_edge(p, new_node, **data)
1409
+
1410
+ # We should find the correct successor
1411
+ new_successors = [i for i in [smallest_node, *other_nodes] if i.addr == smallest_node.addr]
1412
+ if new_successors:
1413
+ new_successor = new_successors[0]
1414
+ graph.add_edge(
1415
+ new_node,
1416
+ new_successor,
1417
+ jumpkind="Ijk_Boring",
1418
+ ins_addr=new_node.instruction_addrs[-1] if new_node.instruction_addrs else new_node.addr,
1419
+ )
1420
+ else:
1421
+ # We gotta create a new one
1422
+ l.error("normalize(): Please report it to Fish.")
1423
+
1424
+ # update the jump tables dict and the indirect jumps dict
1425
+ if smallest_node.addr not in self.model.jump_tables:
1426
+ for n in other_nodes:
1427
+ if n.addr in self.model.jump_tables:
1428
+ self.model.jump_tables[n.addr].addr = smallest_node.addr
1429
+ self.model.jump_tables[smallest_node.addr] = self.model.jump_tables[n.addr]
1430
+ break
1431
+ if smallest_node.addr not in self.indirect_jumps:
1432
+ for n in other_nodes:
1433
+ if n.addr in self.indirect_jumps:
1434
+ self.indirect_jumps[n.addr].addr = smallest_node.addr
1435
+ self.indirect_jumps[smallest_node.addr] = self.indirect_jumps[n.addr]
1436
+ break
1437
+ # deal with duplicated entries in self.jump_tables and self.indirect_jumps
1438
+ if smallest_node.addr in self.model.jump_tables:
1439
+ for n in other_nodes:
1440
+ if n.addr in self.model.jump_tables:
1441
+ del self.model.jump_tables[n.addr]
1442
+ if smallest_node.addr in self.indirect_jumps:
1443
+ for n in other_nodes:
1444
+ if n.addr in self.indirect_jumps:
1445
+ del self.indirect_jumps[n.addr]
1446
+
1447
+ #
1448
+ # Job management
1449
+ #
1450
+
1451
+ def _register_analysis_job(self, func_addr, job):
1452
+ """
1453
+ Register an analysis job of a function to job manager. This allows us to track whether we have finished
1454
+ analyzing/recovering a function or not.
1455
+
1456
+ :param int func_addr: Address of the function that this job belongs to.
1457
+ :param job: The job to register. Note that it does not necessarily be the a CFGJob instance. There
1458
+ can be PendingJob or PendingJob or other instances, too.
1459
+ :return: None
1460
+ """
1461
+
1462
+ self._jobs_to_analyze_per_function[func_addr].add(job)
1463
+
1464
+ def _deregister_analysis_job(self, func_addr, job):
1465
+ """
1466
+ Deregister/Remove an analysis job of a function from job manager.
1467
+
1468
+ :param int func_addr: Address of the function that this job belongs to.
1469
+ :param job: The job to deregister.
1470
+ :return: None
1471
+ """
1472
+
1473
+ self._jobs_to_analyze_per_function[func_addr].discard(job)
1474
+
1475
+ def _get_finished_functions(self):
1476
+ """
1477
+ Obtain all functions of which we have finished analyzing. As _jobs_to_analyze_per_function is a defaultdict(),
1478
+ if a function address shows up in it with an empty job list, we consider we have exhausted all jobs of this
1479
+ function (both current jobs and pending jobs), thus the analysis of this function is done.
1480
+
1481
+ :return: a list of function addresses of that we have finished analysis.
1482
+ :rtype: list
1483
+ """
1484
+
1485
+ finished_func_addrs = []
1486
+ for func_addr, all_jobs in self._jobs_to_analyze_per_function.items():
1487
+ if not all_jobs:
1488
+ # great! we have finished analyzing this function!
1489
+ finished_func_addrs.append(func_addr)
1490
+
1491
+ return finished_func_addrs
1492
+
1493
+ def _cleanup_analysis_jobs(self, finished_func_addrs=None):
1494
+ """
1495
+ From job manager, remove all functions of which we have finished analysis.
1496
+
1497
+ :param list or None finished_func_addrs: A list of addresses of functions of which we have finished analysis.
1498
+ A new list of function addresses will be obtained by calling
1499
+ _get_finished_functions() if this parameter is None.
1500
+ :return: None
1501
+ """
1502
+
1503
+ if finished_func_addrs is None:
1504
+ finished_func_addrs = self._get_finished_functions()
1505
+
1506
+ for func_addr in finished_func_addrs:
1507
+ if func_addr in self._jobs_to_analyze_per_function:
1508
+ del self._jobs_to_analyze_per_function[func_addr]
1509
+
1510
+ def _make_completed_functions(self):
1511
+ """
1512
+ Fill in self._completed_functions list and clean up job manager.
1513
+
1514
+ :return: None
1515
+ """
1516
+
1517
+ finished = self._get_finished_functions()
1518
+ for func_addr in finished:
1519
+ if func_addr not in self._completed_functions:
1520
+ self._function_completed(func_addr)
1521
+ self._completed_functions.add(func_addr)
1522
+ self._cleanup_analysis_jobs(finished_func_addrs=finished)
1523
+
1524
+ #
1525
+ # Function identification and such
1526
+ #
1527
+
1528
+ def mark_function_alignments(self):
1529
+ """
1530
+ Find all potential function alignments and mark them.
1531
+
1532
+ Note that it is not always correct to simply remove them, because these functions may not be actual alignments
1533
+ but part of an actual function, and is incorrectly marked as an individual function because of failures in
1534
+ resolving indirect jumps. An example is in the test binary ``x86_64/dir_gcc_-O0`` 0x40541d (indirect jump at
1535
+ 0x4051b0). If the indirect jump cannot be correctly resolved, removing function 0x40541d will cause a missing
1536
+ label failure in reassembler.
1537
+
1538
+ :return: None
1539
+ """
1540
+
1541
+ # This function requires Capstone engine support
1542
+ if not self.project.arch.capstone_support:
1543
+ return
1544
+
1545
+ for func_addr in self.kb.functions:
1546
+ function = self.kb.functions[func_addr]
1547
+ if function.is_simprocedure or function.is_syscall:
1548
+ continue
1549
+ if len(function.block_addrs_set) == 1:
1550
+ block = next((b for b in function.blocks), None)
1551
+ if block is None:
1552
+ continue
1553
+ if self._is_noop_block(self.project.arch, block) or all(
1554
+ self._is_noop_insn(insn) for insn in block.capstone.insns
1555
+ ):
1556
+ # all nops. mark this function as a function alignment
1557
+ l.debug("Function chunk %#x is probably used as a function alignment (all nops).", func_addr)
1558
+ self.kb.functions[func_addr].is_alignment = True
1559
+ continue
1560
+ node = function.get_node(block.addr)
1561
+ assert node is not None
1562
+ successors = list(function.graph.successors(node))
1563
+ if len(successors) == 1 and successors[0].addr == node.addr:
1564
+ # self loop. mark this function as a function alignment
1565
+ l.debug("Function chunk %#x is probably used as a function alignment (self-loop).", func_addr)
1566
+ self.kb.functions[func_addr].is_alignment = True
1567
+ continue
1568
+
1569
+ def make_functions(self):
1570
+ """
1571
+ Revisit the entire control flow graph, create Function instances accordingly, and correctly put blocks into
1572
+ each function.
1573
+
1574
+ Although Function objects are created during the CFG recovery, they are neither sound nor accurate. With a
1575
+ pre-constructed CFG, this method rebuilds all functions bearing the following rules:
1576
+
1577
+ - A block may only belong to one function.
1578
+ - Small functions lying inside the startpoint and the endpoint of another function will be merged with the
1579
+ other function
1580
+ - Tail call optimizations are detected.
1581
+ - PLT stubs are aligned by 16.
1582
+
1583
+ :return: None
1584
+ """
1585
+
1586
+ # TODO: Is it required that PLT stubs are always aligned by 16? If so, on what architectures and platforms is it
1587
+ # TODO: enforced?
1588
+
1589
+ tmp_functions = self.kb.functions
1590
+
1591
+ for function in tmp_functions.values():
1592
+ function.mark_nonreturning_calls_endpoints()
1593
+ if function.returning is False:
1594
+ # remove all FakeRet edges that are related to this function
1595
+ func_node = self.model.get_any_node(function.addr, force_fastpath=True)
1596
+ if func_node is not None:
1597
+ callsite_nodes = [
1598
+ src
1599
+ for src, _, data in self.graph.in_edges(func_node, data=True)
1600
+ if data.get("jumpkind", None) == "Ijk_Call"
1601
+ ]
1602
+ for callsite_node in callsite_nodes:
1603
+ for _, dst, data in list(self.graph.out_edges(callsite_node, data=True)):
1604
+ if data.get("jumpkind", None) == "Ijk_FakeRet":
1605
+ self.graph.remove_edge(callsite_node, dst)
1606
+
1607
+ # Clear old functions dict by creating a new function manager
1608
+ self.kb.functions = FunctionManager(self.kb)
1609
+
1610
+ blockaddr_to_function = {}
1611
+ traversed_cfg_nodes = set()
1612
+
1613
+ function_nodes = set()
1614
+
1615
+ # Find nodes for beginnings of all functions
1616
+ for _, dst, data in self.graph.edges(data=True):
1617
+ jumpkind = data.get("jumpkind", "")
1618
+ if jumpkind == "Ijk_Call" or jumpkind.startswith("Ijk_Sys"):
1619
+ function_nodes.add(dst)
1620
+
1621
+ entry_node = self.model.get_any_node(self._binary.entry, force_fastpath=True)
1622
+ if entry_node is not None:
1623
+ function_nodes.add(entry_node)
1624
+
1625
+ # aggressively remove and merge functions
1626
+ # For any function, if there is a call to it, it won't be removed
1627
+ called_function_addrs = {n.addr for n in function_nodes}
1628
+ # Any function addresses that appear as symbols won't be removed
1629
+ predetermined_function_addrs = called_function_addrs | self._function_addresses_from_symbols
1630
+
1631
+ removed_functions_a = self._process_irrational_functions(
1632
+ tmp_functions, predetermined_function_addrs, blockaddr_to_function
1633
+ )
1634
+ removed_functions_b, adjusted_cfgnodes = self._process_irrational_function_starts(
1635
+ tmp_functions, predetermined_function_addrs, blockaddr_to_function
1636
+ )
1637
+ self._process_jump_table_targeted_functions(
1638
+ tmp_functions,
1639
+ predetermined_function_addrs,
1640
+ blockaddr_to_function,
1641
+ )
1642
+ removed_functions = removed_functions_a | removed_functions_b
1643
+
1644
+ # Remove all nodes that are adjusted
1645
+ function_nodes.difference_update(adjusted_cfgnodes)
1646
+ for n in self.graph.nodes():
1647
+ if n.addr in tmp_functions or n.addr in removed_functions:
1648
+ function_nodes.add(n)
1649
+
1650
+ # traverse the graph starting from each node, not following call edges
1651
+ # it's important that we traverse all functions in order so that we have a greater chance to come across
1652
+ # rational functions before its irrational counterparts (e.g. due to failed jump table resolution)
1653
+
1654
+ min_stage_2_progress = 50.0
1655
+ max_stage_2_progress = 90.0
1656
+ nodes_count = len(function_nodes)
1657
+ for i, fn in enumerate(sorted(function_nodes, key=lambda n: n.addr)):
1658
+ if self._low_priority:
1659
+ self._release_gil(i, 800, 0.000001)
1660
+
1661
+ if self._show_progressbar or self._progress_callback:
1662
+ progress = min_stage_2_progress + (max_stage_2_progress - min_stage_2_progress) * (
1663
+ i * 1.0 / nodes_count
1664
+ )
1665
+ self._update_progress(progress)
1666
+
1667
+ self._graph_bfs_custom(
1668
+ self.graph,
1669
+ [fn],
1670
+ self._graph_traversal_handler,
1671
+ blockaddr_to_function,
1672
+ tmp_functions,
1673
+ traversed_cfg_nodes,
1674
+ )
1675
+
1676
+ # Don't forget those small function chunks that are not called by anything.
1677
+ # There might be references to them from data, or simply references that we cannot find via static analysis
1678
+
1679
+ secondary_function_nodes = set()
1680
+ # add all function chunks ("functions" that are not called from anywhere)
1681
+ for func_addr in tmp_functions:
1682
+ node = self.model.get_any_node(func_addr, force_fastpath=True)
1683
+ if node is None:
1684
+ continue
1685
+ if node.addr not in blockaddr_to_function:
1686
+ secondary_function_nodes.add(node)
1687
+
1688
+ missing_cfg_nodes = set(self.graph.nodes()) - traversed_cfg_nodes
1689
+ missing_cfg_nodes = {node for node in missing_cfg_nodes if node.function_address is not None}
1690
+ if missing_cfg_nodes:
1691
+ l.debug("%d CFGNodes are missing in the first traversal.", len(missing_cfg_nodes))
1692
+ secondary_function_nodes |= missing_cfg_nodes
1693
+
1694
+ min_stage_3_progress = 90.0
1695
+ max_stage_3_progress = 99.9
1696
+
1697
+ nodes_count = len(secondary_function_nodes)
1698
+ for i, fn in enumerate(sorted(secondary_function_nodes, key=lambda n: n.addr)):
1699
+ if self._show_progressbar or self._progress_callback:
1700
+ progress = min_stage_3_progress + (max_stage_3_progress - min_stage_3_progress) * (
1701
+ i * 1.0 / nodes_count
1702
+ )
1703
+ self._update_progress(progress)
1704
+
1705
+ self._graph_bfs_custom(
1706
+ self.graph,
1707
+ [fn],
1708
+ self._graph_traversal_handler,
1709
+ blockaddr_to_function,
1710
+ tmp_functions,
1711
+ traversed_cfg_nodes,
1712
+ )
1713
+
1714
+ to_remove = set()
1715
+
1716
+ # Remove all stubs after PLT entries
1717
+ if not is_arm_arch(self.project.arch):
1718
+ to_remove |= self._remove_dummy_plt_stubs(self.kb.functions)
1719
+
1720
+ # remove empty functions
1721
+ for func in self.kb.functions.values():
1722
+ if func.startpoint is None:
1723
+ to_remove.add(func.addr)
1724
+
1725
+ for addr in to_remove:
1726
+ del self.kb.functions[addr]
1727
+
1728
+ # Update CFGNode.function_address
1729
+ for node in self._nodes.values():
1730
+ if node.addr in blockaddr_to_function:
1731
+ node.function_address = blockaddr_to_function[node.addr].addr
1732
+
1733
+ # Update function.info
1734
+ for func in self.kb.functions.values():
1735
+ if func.addr in tmp_functions:
1736
+ func.info = tmp_functions[func.addr].info
1737
+
1738
+ def _remove_dummy_plt_stubs(self, functions):
1739
+ def _is_function_a_plt_stub(arch_, func):
1740
+ if len(func.block_addrs_set) != 1:
1741
+ # multiple blocks? no idea what this is...
1742
+ return False
1743
+ block = next(func.blocks)
1744
+ if self._is_noop_block(arch_, block):
1745
+ # alignments
1746
+ return False
1747
+
1748
+ # TODO: We may want to add support for filtering dummy PLT stubs for other architectures, but I haven't
1749
+ # TODO: seen any need for those.
1750
+ return not (
1751
+ arch_.name in {"X86", "AMD64"}
1752
+ and len(block.vex.instruction_addresses) == 2
1753
+ and block.vex.jumpkind == "Ijk_Boring"
1754
+ )
1755
+
1756
+ to_remove = set()
1757
+
1758
+ met_plts = False
1759
+ non_plt_funcs = 0
1760
+ sorted_func_addrs = sorted(functions.keys())
1761
+ arch = self.project.arch
1762
+
1763
+ # we assume all PLT entries are all located at the same region. the moment we come across the end of it, we
1764
+ # stop looping.
1765
+ for fn_addr in sorted_func_addrs:
1766
+ fn = functions.get_by_addr(fn_addr)
1767
+ addr = fn.addr - (fn.addr % 16)
1768
+ if (
1769
+ addr != fn.addr
1770
+ and addr in functions
1771
+ and functions[addr].is_plt
1772
+ and not _is_function_a_plt_stub(arch, fn)
1773
+ ):
1774
+ to_remove.add(fn.addr)
1775
+ continue
1776
+
1777
+ if fn.is_plt:
1778
+ met_plts = True
1779
+ non_plt_funcs = 0
1780
+ if met_plts and not fn.is_plt:
1781
+ non_plt_funcs += 1
1782
+ if non_plt_funcs >= 2:
1783
+ break
1784
+
1785
+ return to_remove
1786
+
1787
+ def _process_irrational_functions(self, functions, predetermined_function_addrs, blockaddr_to_function):
1788
+ """
1789
+ When force_complete_scan is enabled, for unresolveable indirect jumps, angr will find jump targets and mark
1790
+ them as individual functions. For example, usually the following pattern is seen:
1791
+
1792
+ sub_0x400010:
1793
+ push ebp
1794
+ mov esp, ebp
1795
+ ...
1796
+ cmp eax, 10
1797
+ ja end
1798
+ mov eax, jumptable[eax]
1799
+ jmp eax
1800
+
1801
+ sub_0x400080:
1802
+ # do something here
1803
+ jmp end
1804
+
1805
+ end (0x400e00):
1806
+ pop ebp
1807
+ ret
1808
+
1809
+ In the example above, `process_irrational_functions` will remove function 0x400080, and merge it with function
1810
+ 0x400010.
1811
+
1812
+ :param angr.knowledge_plugins.FunctionManager functions: all functions that angr recovers, including those ones
1813
+ that are misidentified as functions.
1814
+ :param dict blockaddr_to_function: A mapping between block addresses and Function instances.
1815
+ :return: A set of addresses of all removed functions
1816
+ :rtype: set
1817
+ """
1818
+
1819
+ functions_to_remove = {}
1820
+
1821
+ all_func_addrs = sorted(set(functions.keys()))
1822
+
1823
+ for func_pos, (func_addr, function) in enumerate(functions.items()):
1824
+ if func_addr in functions_to_remove:
1825
+ continue
1826
+
1827
+ # check all blocks and see if any block ends with an indirect jump and is not resolved
1828
+ has_unresolved_jumps = False
1829
+ # the functions to merge with must be locating between the unresolved basic block address and the endpoint
1830
+ # of the current function
1831
+ max_unresolved_jump_addr = 0
1832
+ for block_addr in function.block_addrs_set:
1833
+ if (
1834
+ block_addr in self.indirect_jumps
1835
+ and self.indirect_jumps[block_addr].jumpkind == "Ijk_Boring"
1836
+ and not self.indirect_jumps[block_addr].resolved_targets
1837
+ ):
1838
+ # it's not resolved
1839
+ # we should also make sure it's a jump, not a call
1840
+ has_unresolved_jumps = True
1841
+ max_unresolved_jump_addr = max(max_unresolved_jump_addr, block_addr)
1842
+
1843
+ if not has_unresolved_jumps:
1844
+ continue
1845
+
1846
+ if function.startpoint is None:
1847
+ continue
1848
+
1849
+ startpoint_addr = function.startpoint.addr
1850
+ if not function.endpoints:
1851
+ # Function should have at least one endpoint
1852
+ continue
1853
+ endpoint_addr = max(a.addr for a in function.endpoints)
1854
+ the_endpoint = next(a for a in function.endpoints if a.addr == endpoint_addr)
1855
+ endpoint_addr += the_endpoint.size
1856
+
1857
+ # sanity check: startpoint of the function should be greater than its endpoint
1858
+ if startpoint_addr >= endpoint_addr:
1859
+ continue
1860
+ if max_unresolved_jump_addr <= startpoint_addr or max_unresolved_jump_addr >= endpoint_addr:
1861
+ continue
1862
+
1863
+ # scan forward from the endpoint to include any function-tail jumps
1864
+ # Here is an example:
1865
+ # loc_8049562:
1866
+ # mov eax, ebp
1867
+ # add esp, 3ch
1868
+ # ...
1869
+ # ret
1870
+ # loc_804956c:
1871
+ # mov ebp, 3
1872
+ # jmp loc_8049562
1873
+ # loc_8049573:
1874
+ # mov ebp, 4
1875
+ # jmp loc_8049562
1876
+ #
1877
+ last_addr = endpoint_addr
1878
+ while True:
1879
+ try:
1880
+ # do not follow hooked addresses (such as SimProcedures)
1881
+ if self.project.is_hooked(last_addr):
1882
+ break
1883
+
1884
+ next_block = self._lift(last_addr)
1885
+ next_block_irsb = next_block.vex_nostmt
1886
+ if next_block_irsb.jumpkind not in ("Ijk_Boring", "Ijk_InvalICache"):
1887
+ break
1888
+ if not isinstance(next_block_irsb.next, pyvex.IRExpr.Const):
1889
+ break
1890
+ suc_addr = next_block_irsb.next.con.value
1891
+ if (
1892
+ max(startpoint_addr, the_endpoint.addr - 0x40)
1893
+ <= suc_addr
1894
+ < the_endpoint.addr + the_endpoint.size
1895
+ ):
1896
+ # increment the endpoint_addr
1897
+ endpoint_addr = next_block.addr + next_block.size
1898
+ else:
1899
+ break
1900
+
1901
+ last_addr = next_block.addr + next_block.size
1902
+
1903
+ except (SimTranslationError, SimMemoryError, SimIRSBError, SimEngineError):
1904
+ break
1905
+
1906
+ # find all functions that are between [ startpoint, endpoint ]
1907
+
1908
+ should_merge = True
1909
+ functions_to_merge = set()
1910
+ i = func_pos + 1
1911
+ while i < len(all_func_addrs) and all_func_addrs[i] < endpoint_addr:
1912
+ f_addr = all_func_addrs[i]
1913
+ i += 1
1914
+ f = functions[f_addr]
1915
+ if f_addr == func_addr:
1916
+ continue
1917
+ if max_unresolved_jump_addr < f_addr < endpoint_addr and all(
1918
+ max_unresolved_jump_addr < b_addr < endpoint_addr for b_addr in f.block_addrs
1919
+ ):
1920
+ if f_addr in functions_to_remove:
1921
+ # this function has already been merged with other functions before... it cannot be merged with
1922
+ # this function anymore
1923
+ should_merge = False
1924
+ break
1925
+ if f_addr in predetermined_function_addrs:
1926
+ # this function is a legit one. it shouldn't be removed/merged
1927
+ should_merge = False
1928
+ break
1929
+ functions_to_merge.add(f_addr)
1930
+
1931
+ if not should_merge:
1932
+ # we shouldn't merge...
1933
+ continue
1934
+
1935
+ for f_addr in functions_to_merge:
1936
+ functions_to_remove[f_addr] = func_addr
1937
+
1938
+ # merge all functions
1939
+ for to_remove, merge_with in functions_to_remove.items():
1940
+ func_merge_with = self._addr_to_function(merge_with, blockaddr_to_function, functions)
1941
+
1942
+ for block_addr in functions[to_remove].block_addrs:
1943
+ blockaddr_to_function[block_addr] = func_merge_with
1944
+
1945
+ del functions[to_remove]
1946
+
1947
+ return set(functions_to_remove.keys())
1948
+
1949
+ def _process_irrational_function_starts(self, functions, predetermined_function_addrs, blockaddr_to_function):
1950
+ """
1951
+ Functions that are identified via function prologues can be starting after the actual beginning of the function.
1952
+ For example, the following function (with an incorrect start) might exist after a CFG recovery:
1953
+
1954
+ sub_8049f70:
1955
+ push esi
1956
+
1957
+ sub_8049f71:
1958
+ sub esp, 0A8h
1959
+ mov esi, [esp+0ACh+arg_0]
1960
+ mov [esp+0ACh+var_88], 0
1961
+
1962
+ If the following conditions are met, we will remove the second function and merge it into the first function:
1963
+ - The second function is not called by other code.
1964
+ - The first function has only one non-empty jumpout site (e.g., the first function contains more than just nops
1965
+ and jumps), which points to the second function.
1966
+
1967
+ :param FunctionManager functions: All functions that angr recovers.
1968
+ :return: A set of addresses of all removed functions.
1969
+ :rtype: set
1970
+ """
1971
+
1972
+ addrs = sorted(
1973
+ k for k in functions if not self.project.is_hooked(k) and not self.project.simos.is_syscall_addr(k)
1974
+ )
1975
+ functions_to_remove = set()
1976
+ adjusted_cfgnodes = set()
1977
+
1978
+ for addr_0, addr_1 in zip(addrs[:-1], addrs[1:]):
1979
+ if addr_1 in predetermined_function_addrs:
1980
+ continue
1981
+ if addr_0 in functions_to_remove:
1982
+ continue
1983
+
1984
+ func_0 = functions[addr_0]
1985
+
1986
+ if len(func_0.block_addrs_set) >= 1:
1987
+ if len(func_0.jumpout_sites) != 1:
1988
+ continue
1989
+ block_node = func_0.jumpout_sites[0]
1990
+ if block_node is None:
1991
+ continue
1992
+ if block_node.size == 0:
1993
+ # skip empty blocks (that are usually caused by lifting failures)
1994
+ continue
1995
+ block = func_0.get_block(block_node.addr, block_node.size)
1996
+ # Skip alignment blocks
1997
+ if self._is_noop_block(self.project.arch, block):
1998
+ continue
1999
+ if block.vex_nostmt.jumpkind not in ("Ijk_Boring", "Ijk_InvalICache"):
2000
+ continue
2001
+ if all(isinstance(stmt, pyvex.stmt.IMark) for stmt in block.vex.statements):
2002
+ # the first block is empty
2003
+ continue
2004
+
2005
+ # does the first block transition to the next function?
2006
+ transition_found = False
2007
+ out_edges = list(func_0.transition_graph.out_edges(block_node, data=True))
2008
+ for _, dst_node, data in out_edges:
2009
+ if (
2010
+ dst_node.addr == addr_1
2011
+ and data.get("type", None) == "transition"
2012
+ and data.get("outside", False) is True
2013
+ ):
2014
+ transition_found = True
2015
+ break
2016
+
2017
+ if not transition_found:
2018
+ continue
2019
+
2020
+ cfgnode_0 = self.model.get_any_node(block_node.addr, force_fastpath=True)
2021
+ cfgnode_1 = self.model.get_any_node(addr_1, force_fastpath=True)
2022
+
2023
+ if cfgnode_0 is None or cfgnode_1 is None:
2024
+ continue
2025
+
2026
+ # who's jumping to or calling cfgnode_1?
2027
+ cfgnode_1_preds = self.model.get_predecessors_and_jumpkinds(cfgnode_1, excluding_fakeret=True)
2028
+ func_1 = functions[addr_1]
2029
+ abort = False
2030
+ for pred, jumpkind in cfgnode_1_preds:
2031
+ if pred.addr in func_0.block_addrs_set and jumpkind == "Ijk_Boring":
2032
+ # this is the transition from function 0
2033
+ continue
2034
+ if pred.addr in func_1.block_addrs_set:
2035
+ # this is a transition from function 1 itself
2036
+ continue
2037
+ # found an unexpected edge. give up
2038
+ abort = True
2039
+ break
2040
+ if abort:
2041
+ continue
2042
+
2043
+ # Merge functions addr_0 and addr_1
2044
+ l.debug("Merging function %#x into %#x.", addr_1, addr_0)
2045
+
2046
+ cfgnode_1_merged = False
2047
+ # we only merge two CFG nodes if the first one does not end with a branch instruction and there are no
2048
+ # other predecessors to CFG node addr_1
2049
+ if len(func_0.block_addrs_set) == 1 and len(out_edges) == 1 and len(cfgnode_1_preds) <= 1:
2050
+ outedge_src, outedge_dst, outedge_data = out_edges[0]
2051
+ if (
2052
+ outedge_src.addr == cfgnode_0.addr
2053
+ and outedge_src.size == cfgnode_0.size
2054
+ and outedge_dst.addr == cfgnode_1.addr
2055
+ and cfgnode_0.addr + cfgnode_0.size == cfgnode_1.addr
2056
+ and outedge_data.get("type", None) == "transition"
2057
+ and outedge_data.get("stmt_idx", None) == DEFAULT_STATEMENT
2058
+ ):
2059
+ cfgnode_1_merged = True
2060
+ self._merge_cfgnodes(cfgnode_0, cfgnode_1)
2061
+ adjusted_cfgnodes.add(cfgnode_0)
2062
+ adjusted_cfgnodes.add(cfgnode_1)
2063
+
2064
+ # Merge the two functions
2065
+ func_1 = functions[addr_1]
2066
+ for block_addr in func_1.block_addrs:
2067
+ if block_addr == addr_1 and cfgnode_1_merged:
2068
+ # Skip addr_1 (since it has been merged to the preceding block)
2069
+ continue
2070
+ merge_with = self._addr_to_function(addr_0, blockaddr_to_function, functions)
2071
+ blockaddr_to_function[block_addr] = merge_with
2072
+
2073
+ functions_to_remove.add(addr_1)
2074
+
2075
+ for to_remove in functions_to_remove:
2076
+ del functions[to_remove]
2077
+
2078
+ return functions_to_remove, adjusted_cfgnodes
2079
+
2080
+ def _process_jump_table_targeted_functions(
2081
+ self, functions, predetermined_function_addrs, blockaddr_to_function
2082
+ ) -> set[int]:
2083
+ """
2084
+ Sometimes compilers will optimize "cold" code regions, make them separate functions, mark them as cold, which
2085
+ conflicts with how angr handles jumps to these functions (because they weren't functions to start with). Here
2086
+ is an example (in function version_etc_arn() from gllib)::
2087
+
2088
+ switch (n_authors) {
2089
+ case 0:
2090
+ abort();
2091
+ case 1:
2092
+ ...
2093
+ }
2094
+
2095
+ GCC may decide to move the `abort();` block under case 0 into a separate function (usually named
2096
+ "version_etc_arn_cold") and mark it as "cold." When loading function hints from eh frame is enabled, this
2097
+ function will be identified, and the recovered switch-case structure will have a jump to a function. It's
2098
+ usually not a problem until we need to decompile this function, where (at least for now) angr decompiler
2099
+ requires all switch-case entry blocks must belong to the same function.
2100
+
2101
+ The temporary solution is identifying functions that (a) have no call predecessors, and (b) are used as
2102
+ jump targets for identified jump tables. Remove these functions so that they can be treated as part of the
2103
+ source function where the corresponding jump table belongs.
2104
+ """
2105
+
2106
+ jumptable_entries: set[int] = set()
2107
+ for jt in self.model.jump_tables.values():
2108
+ assert jt.jumptable_entries is not None
2109
+ jumptable_entries |= set(jt.jumptable_entries)
2110
+
2111
+ if not jumptable_entries:
2112
+ return set()
2113
+
2114
+ functions_to_remove = set()
2115
+
2116
+ for func_addr in functions:
2117
+ if func_addr in predetermined_function_addrs:
2118
+ continue
2119
+ if func_addr in jumptable_entries:
2120
+ # is there any call edge pointing to it?
2121
+ func_node = self.model.get_any_node(func_addr, force_fastpath=True)
2122
+ if func_node is not None:
2123
+ in_edges = self.graph.in_edges(func_node, data=True)
2124
+ has_transition_pred = None
2125
+ has_non_transition_pred = None
2126
+ for _, _, data in in_edges:
2127
+ if data.get("jumpkind", None) == "Ijk_Boring":
2128
+ has_transition_pred = True
2129
+ else:
2130
+ has_non_transition_pred = True
2131
+ if has_transition_pred is True and not has_non_transition_pred:
2132
+ # all predecessors are transition-only
2133
+ # remove this function
2134
+ functions_to_remove.add(func_addr)
2135
+
2136
+ for to_remove in functions_to_remove:
2137
+ del functions[to_remove]
2138
+ if to_remove in blockaddr_to_function:
2139
+ del blockaddr_to_function[to_remove]
2140
+
2141
+ return functions_to_remove
2142
+
2143
+ def _addr_to_function(self, addr, blockaddr_to_function, known_functions):
2144
+ """
2145
+ Convert an address to a Function object, and store the mapping in a dict. If the block is known to be part of a
2146
+ function, just return that function.
2147
+
2148
+ :param int addr: Address to convert
2149
+ :param dict blockaddr_to_function: A mapping between block addresses to Function instances.
2150
+ :param angr.knowledge_plugins.FunctionManager known_functions: Recovered functions.
2151
+ :return: a Function object
2152
+ :rtype: angr.knowledge.Function
2153
+ """
2154
+
2155
+ if addr in blockaddr_to_function:
2156
+ f = blockaddr_to_function[addr]
2157
+ else:
2158
+ is_syscall = self.project.simos.is_syscall_addr(addr)
2159
+
2160
+ n = self.model.get_any_node(addr, is_syscall=is_syscall, force_fastpath=True)
2161
+ node = addr if n is None else self._to_snippet(n)
2162
+
2163
+ if isinstance(addr, SootAddressDescriptor):
2164
+ addr = addr.method
2165
+
2166
+ self.kb.functions._add_node(addr, node, syscall=is_syscall)
2167
+ f = self.kb.functions.function(addr=addr)
2168
+ assert f is not None
2169
+
2170
+ # copy over existing metadata
2171
+ if known_functions.contains_addr(addr):
2172
+ kf = known_functions.get_by_addr(addr)
2173
+ f.is_plt = kf.is_plt
2174
+
2175
+ blockaddr_to_function[addr] = f
2176
+
2177
+ function_is_returning = False
2178
+ if addr in known_functions and known_functions.function(addr).returning:
2179
+ f.returning = True
2180
+ function_is_returning = True
2181
+
2182
+ if not function_is_returning and self._updated_nonreturning_functions is not None:
2183
+ # We will rerun function feature analysis on this function later. Add it to
2184
+ # self._updated_nonreturning_functions so it can be picked up by function feature analysis later.
2185
+ self._updated_nonreturning_functions.add(addr)
2186
+
2187
+ return f
2188
+
2189
+ def _is_tail_call_optimization(
2190
+ self,
2191
+ g: networkx.DiGraph[CFGNode],
2192
+ src_addr,
2193
+ dst_addr,
2194
+ src_function,
2195
+ all_edges: list[tuple[CFGNode, CFGNode, Any]],
2196
+ known_functions,
2197
+ blockaddr_to_function,
2198
+ ):
2199
+ """
2200
+ If source and destination belong to the same function, and the following criteria apply:
2201
+ - source node has only one default exit
2202
+ - destination is not one of the known functions
2203
+ - destination does not belong to another function, or destination belongs to the same function that
2204
+ source belongs to
2205
+ - at the end of the block, the SP offset is 0
2206
+ - for all other edges that are pointing to the destination node, their source nodes must only have one default
2207
+ exit, too
2208
+
2209
+ :return: True if it is a tail-call optimization. False otherwise.
2210
+ :rtype: bool
2211
+ """
2212
+
2213
+ def _has_more_than_one_exit(node_):
2214
+ # Do not consider FakeRets as counting as multiple exits here.
2215
+ out_edges = [e for e in g.out_edges(node_) if g.get_edge_data(*e)["jumpkind"] != "Ijk_FakeRet"]
2216
+ return len(out_edges) > 1
2217
+
2218
+ if len(all_edges) == 1 and dst_addr != src_addr:
2219
+ the_edge = next(iter(all_edges))
2220
+ _, dst, data = the_edge
2221
+ if data.get("stmt_idx", None) != DEFAULT_STATEMENT:
2222
+ return False
2223
+
2224
+ # relift the source node to make sure it's not a fall-through target
2225
+ full_src_node = self.project.factory.block(src_addr)
2226
+ if full_src_node.size >= VEX_IRSB_MAX_SIZE or full_src_node.instructions >= VEX_IRSB_MAX_INST:
2227
+ # we are probably hitting the max-block limit in VEX
2228
+ return False
2229
+ if full_src_node.addr <= dst_addr < full_src_node.addr + full_src_node.size:
2230
+ return False
2231
+
2232
+ dst_in_edges = g.in_edges(dst, data=True)
2233
+ if len(dst_in_edges) > 1:
2234
+ # there are other edges going to the destination node. check all edges to make sure all source nodes
2235
+ # only have one default exit
2236
+ if any(data.get("stmt_idx", None) != DEFAULT_STATEMENT for _, _, data in dst_in_edges):
2237
+ # some nodes are jumping to the destination node via non-default edges. skip.
2238
+ return False
2239
+ if any(_has_more_than_one_exit(src_) for src_, _, _ in dst_in_edges):
2240
+ # at least one source node has more than just the default exit. skip.
2241
+ return False
2242
+
2243
+ candidate = False
2244
+ if dst_addr in known_functions:
2245
+ # dst_addr cannot be the same as src_function.addr. Pass
2246
+ pass
2247
+ elif dst_addr in blockaddr_to_function:
2248
+ # it seems that we already know where this function should belong to. Pass.
2249
+ dst_func = blockaddr_to_function[dst_addr]
2250
+ if dst_func is src_function:
2251
+ # they belong to the same function right now, but they'd better not
2252
+ candidate = True
2253
+ # treat it as a tail-call optimization
2254
+ else:
2255
+ # we don't know where it belongs to
2256
+ # treat it as a tail-call optimization
2257
+ candidate = True
2258
+
2259
+ if candidate:
2260
+ # we have two strategies; for small functions, we run SPTracker on the entire function and see if the
2261
+ # stack pointer changes or not; for large functions, we simply detect how far away we jump as well as
2262
+ # if there are any other functions identified between the source and the destination.
2263
+ if len(src_function.block_addrs_set) <= 10:
2264
+ regs = {self.project.arch.sp_offset}
2265
+ if hasattr(self.project.arch, "bp_offset") and self.project.arch.bp_offset is not None:
2266
+ regs.add(self.project.arch.bp_offset)
2267
+ sptracker = self.project.analyses[StackPointerTracker].prep()(
2268
+ src_function, regs, track_memory=self._sp_tracking_track_memory
2269
+ )
2270
+ sp_delta = sptracker.offset_after_block(src_addr, self.project.arch.sp_offset)
2271
+ if sp_delta == 0:
2272
+ return True
2273
+ else:
2274
+ # large function; to speed things up, we don't track sp
2275
+ minaddr, maxaddr = None, None
2276
+ if dst_addr - src_addr >= 0x100:
2277
+ minaddr = src_addr
2278
+ maxaddr = dst_addr
2279
+ elif dst_addr < src_addr:
2280
+ # jumping back; is it jumping beyond the function header?
2281
+ src_func = blockaddr_to_function[src_addr]
2282
+ if dst_addr < src_func.addr and src_func.addr - dst_addr >= 0x100:
2283
+ minaddr = dst_addr
2284
+ maxaddr = src_func.addr
2285
+
2286
+ if minaddr is not None and maxaddr is not None:
2287
+ # are there other function in between?
2288
+ funcaddrs_in_between = list(
2289
+ known_functions._function_map.irange(minimum=minaddr + 1, maximum=maxaddr - 1)
2290
+ )
2291
+ funcs_in_between = [known_functions.get_by_addr(a) for a in funcaddrs_in_between]
2292
+ funcs_in_between = [func for func in funcs_in_between if not func.is_alignment]
2293
+ if len(funcs_in_between) >= 3:
2294
+ return True
2295
+
2296
+ return False
2297
+
2298
+ def _graph_bfs_custom(self, g, starts, callback, blockaddr_to_function, known_functions, traversed_cfg_nodes=None):
2299
+ """
2300
+ A customized control flow graph BFS implementation with the following rules:
2301
+ - Call edges are not followed.
2302
+ - Syscall edges are not followed.
2303
+
2304
+ :param networkx.DiGraph g: The graph.
2305
+ :param list starts: A collection of beginning nodes to start graph traversal.
2306
+ :param func callback: Callback function for each edge and node.
2307
+ :param dict blockaddr_to_function: A mapping between block addresses to Function instances.
2308
+ :param angr.knowledge_plugins.FunctionManager known_functions: Already recovered functions.
2309
+ :param set traversed_cfg_nodes: A set of CFGNodes that are traversed before.
2310
+ :return: None
2311
+ """
2312
+
2313
+ stack = OrderedSet(starts)
2314
+ traversed = set() if traversed_cfg_nodes is None else traversed_cfg_nodes
2315
+
2316
+ while stack:
2317
+ n: CFGNode = stack.pop(last=False)
2318
+
2319
+ if n in traversed:
2320
+ continue
2321
+
2322
+ traversed.add(n)
2323
+
2324
+ if n.has_return:
2325
+ callback(g, n, None, {"jumpkind": "Ijk_Ret"}, blockaddr_to_function, known_functions, None)
2326
+ # NOTE: A block that has_return CAN have successors that aren't the return.
2327
+ # This is particularly the case for ARM conditional instructions. Yes, conditional rets are a thing.
2328
+
2329
+ if g.out_degree(n) == 0:
2330
+ # it's a single node
2331
+ callback(g, n, None, None, blockaddr_to_function, known_functions, None)
2332
+
2333
+ else:
2334
+ all_out_edges = g.out_edges(n, data=True)
2335
+ for src, dst, data in all_out_edges:
2336
+ callback(g, src, dst, data, blockaddr_to_function, known_functions, all_out_edges)
2337
+
2338
+ jumpkind = data.get("jumpkind", "")
2339
+ if (not (jumpkind in ("Ijk_Call", "Ijk_Ret") or jumpkind.startswith("Ijk_Sys"))) and (
2340
+ dst not in stack and dst not in traversed
2341
+ ):
2342
+ stack.add(dst)
2343
+
2344
+ def _graph_traversal_handler(self, g, src, dst, data, blockaddr_to_function, known_functions, all_edges):
2345
+ """
2346
+ Graph traversal handler. It takes in a node or an edge, and create new functions or add nodes to existing
2347
+ functions accordingly. Oh, it also create edges on the transition map of functions.
2348
+
2349
+ :param g: The control flow graph that is currently being traversed.
2350
+ :param CFGNode src: Beginning of the edge, or a single node when dst is None.
2351
+ :param CFGNode dst: Destination of the edge. For processing a single node, `dst` is None.
2352
+ :param dict data: Edge data in the CFG. 'jumpkind' should be there if it's not None.
2353
+ :param dict blockaddr_to_function: A mapping between block addresses to Function instances.
2354
+ :param angr.knowledge_plugins.FunctionManager known_functions: Already recovered functions.
2355
+ :param list or None all_edges: All edges going out from src.
2356
+ :return: None
2357
+ """
2358
+
2359
+ src_addr = src.addr
2360
+ src_function = self._addr_to_function(src_addr, blockaddr_to_function, known_functions)
2361
+
2362
+ if src_addr not in src_function.block_addrs_set:
2363
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2364
+ node = src_addr if n is None else self._to_snippet(n)
2365
+ self.kb.functions._add_node(src_function.addr, node)
2366
+
2367
+ if data is None:
2368
+ # it's a single node only
2369
+ return
2370
+
2371
+ jumpkind = data["jumpkind"]
2372
+
2373
+ if jumpkind == "Ijk_Ret":
2374
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2375
+ from_node = src_addr if n is None else self._to_snippet(n)
2376
+ self.kb.functions._add_return_from(src_function.addr, from_node, None)
2377
+
2378
+ if dst is None:
2379
+ return
2380
+
2381
+ dst_addr = dst.addr
2382
+
2383
+ # get instruction address and statement index
2384
+ ins_addr = data.get("ins_addr", None)
2385
+ stmt_idx = data.get("stmt_idx", None)
2386
+
2387
+ if jumpkind == "Ijk_Call" or jumpkind.startswith("Ijk_Sys"):
2388
+ is_syscall = jumpkind.startswith("Ijk_Sys")
2389
+
2390
+ # It must be calling a function
2391
+ dst_function = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2392
+
2393
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2394
+ if n is None:
2395
+ src_snippet = self._to_snippet(addr=src_addr, base_state=self._base_state)
2396
+ else:
2397
+ src_snippet = self._to_snippet(cfg_node=n)
2398
+
2399
+ # HACK: FIXME: We need a better way of representing unresolved calls and whether they return.
2400
+ # For now, assume UnresolvedTarget returns if we're calling to it
2401
+
2402
+ # If the function doesn't return, don't add a fakeret!
2403
+ if not all_edges or (dst_function.returning is False and dst_function.name != "UnresolvableCallTarget"):
2404
+ fakeret_node = None
2405
+ else:
2406
+ fakeret_node = self._one_fakeret_node(all_edges)
2407
+
2408
+ if isinstance(dst_addr, SootAddressDescriptor):
2409
+ dst_addr = dst_addr.method
2410
+
2411
+ # determining the returning target
2412
+ return_to_outside = False
2413
+ returning_snippet = None
2414
+ if dst_function.returning and fakeret_node is not None:
2415
+ returning_target = src.addr + src.size
2416
+ if returning_target not in blockaddr_to_function:
2417
+ if returning_target not in known_functions:
2418
+ blockaddr_to_function[returning_target] = src_function
2419
+ else:
2420
+ self._addr_to_function(returning_target, blockaddr_to_function, known_functions)
2421
+
2422
+ return_to_outside = blockaddr_to_function[returning_target] is not src_function
2423
+
2424
+ n = self.model.get_any_node(returning_target, force_fastpath=True)
2425
+ if n is None:
2426
+ try:
2427
+ returning_snippet = self._to_snippet(addr=returning_target, base_state=self._base_state)
2428
+ except SimEngineError:
2429
+ # it may not exist
2430
+ returning_snippet = None
2431
+ else:
2432
+ returning_snippet = self._to_snippet(cfg_node=n)
2433
+
2434
+ self.kb.functions._add_call_to(
2435
+ src_function.addr,
2436
+ src_snippet,
2437
+ dst_addr,
2438
+ retn_node=returning_snippet,
2439
+ syscall=is_syscall,
2440
+ ins_addr=ins_addr,
2441
+ stmt_idx=stmt_idx,
2442
+ return_to_outside=return_to_outside,
2443
+ )
2444
+
2445
+ if returning_snippet is not None:
2446
+ self.kb.functions._add_fakeret_to(
2447
+ src_function.addr, src_snippet, returning_snippet, confirmed=True, to_outside=return_to_outside
2448
+ )
2449
+
2450
+ elif jumpkind in ("Ijk_Boring", "Ijk_InvalICache", "Ijk_Exception"):
2451
+ # convert src_addr and dst_addr to CodeNodes
2452
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2453
+ src_node = src_addr if n is None else self._to_snippet(cfg_node=n)
2454
+
2455
+ n = self.model.get_any_node(dst_addr, force_fastpath=True)
2456
+ dst_node = dst_addr if n is None else self._to_snippet(cfg_node=n)
2457
+
2458
+ if self._skip_unmapped_addrs:
2459
+ # pre-check: if source and destination do not belong to the same section, it must be jumping to another
2460
+ # function
2461
+ belong_to_same_section = self._addrs_belong_to_same_section(src_addr, dst_addr)
2462
+ if not belong_to_same_section:
2463
+ _ = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2464
+
2465
+ if self._detect_tail_calls and self._is_tail_call_optimization(
2466
+ g, src_addr, dst_addr, src_function, all_edges, known_functions, blockaddr_to_function
2467
+ ):
2468
+ l.debug("Possible tail-call optimization detected at function %#x.", dst_addr)
2469
+ # it's (probably) a tail-call optimization. we should make the destination node a new function
2470
+ # instead.
2471
+ blockaddr_to_function.pop(dst_addr, None)
2472
+ _ = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2473
+ self.kb.functions._add_outside_transition_to(
2474
+ src_function.addr, src_node, dst_node, to_function_addr=dst_addr
2475
+ )
2476
+ self._tail_calls.add(dst_addr)
2477
+
2478
+ # is it a jump to another function?
2479
+ if isinstance(dst_addr, SootAddressDescriptor):
2480
+ is_known_function_addr = dst_addr.method in known_functions and dst_addr.method.addr == dst_addr
2481
+ else:
2482
+ is_known_function_addr = dst_addr in known_functions
2483
+
2484
+ if (is_known_function_addr and dst_addr != src_function.addr) or (
2485
+ dst_addr in blockaddr_to_function and blockaddr_to_function[dst_addr] is not src_function
2486
+ ):
2487
+ # yes it is
2488
+ dst_function_addr = (
2489
+ blockaddr_to_function[dst_addr].addr if dst_addr in blockaddr_to_function else dst_addr
2490
+ )
2491
+
2492
+ self.kb.functions._add_outside_transition_to(
2493
+ src_function.addr,
2494
+ src_node,
2495
+ dst_node,
2496
+ ins_addr=ins_addr,
2497
+ stmt_idx=stmt_idx,
2498
+ to_function_addr=dst_function_addr,
2499
+ is_exception=jumpkind == "Ijk_Exception",
2500
+ )
2501
+
2502
+ _ = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2503
+ else:
2504
+ # no it's not
2505
+ # add the transition code
2506
+
2507
+ if dst_addr not in blockaddr_to_function:
2508
+ blockaddr_to_function[dst_addr] = src_function
2509
+
2510
+ self.kb.functions._add_transition_to(
2511
+ src_function.addr,
2512
+ src_node,
2513
+ dst_node,
2514
+ ins_addr=ins_addr,
2515
+ stmt_idx=stmt_idx,
2516
+ is_exception=jumpkind == "Ijk_Exception",
2517
+ )
2518
+
2519
+ elif jumpkind == "Ijk_FakeRet":
2520
+ # convert src_addr and dst_addr to CodeNodes
2521
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2522
+ src_node = src_addr if n is None else self._to_snippet(n)
2523
+
2524
+ n = self.model.get_any_node(dst_addr, force_fastpath=True)
2525
+ dst_node = dst_addr if n is None else self._to_snippet(n)
2526
+
2527
+ if dst_addr not in blockaddr_to_function:
2528
+ if isinstance(dst_addr, SootAddressDescriptor):
2529
+ if dst_addr.method not in known_functions:
2530
+ blockaddr_to_function[dst_addr] = src_function
2531
+ target_function = src_function
2532
+ else:
2533
+ target_function = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2534
+ else:
2535
+ if dst_addr not in known_functions:
2536
+ blockaddr_to_function[dst_addr] = src_function
2537
+ target_function = src_function
2538
+ else:
2539
+ target_function = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2540
+ else:
2541
+ target_function = blockaddr_to_function[dst_addr]
2542
+
2543
+ # Figure out if the function called (not the function returned to) returns.
2544
+ # We may have determined that this does not happen, since the time this path
2545
+ # was scheduled for exploration
2546
+ called_function = None
2547
+ called_function_addr = None
2548
+ # Try to find the call that this fakeret goes with
2549
+ for _, d, e in all_edges:
2550
+ if e["jumpkind"] == "Ijk_Call" and d.addr in blockaddr_to_function:
2551
+ called_function = blockaddr_to_function[d.addr]
2552
+ called_function_addr = d.addr
2553
+ break
2554
+ # We may have since figured out that the called function doesn't ret.
2555
+ # It's important to assume that all unresolved targets do return
2556
+ if called_function is not None and called_function.returning is False:
2557
+ return
2558
+
2559
+ to_outside = target_function is not src_function
2560
+
2561
+ confirmed = called_function is None or called_function.returning is True
2562
+ self.kb.functions._add_fakeret_to(
2563
+ src_function.addr,
2564
+ src_node,
2565
+ dst_node,
2566
+ confirmed=confirmed,
2567
+ to_outside=to_outside,
2568
+ to_function_addr=called_function_addr,
2569
+ )
2570
+
2571
+ else:
2572
+ l.debug("Ignored jumpkind %s", jumpkind)
2573
+
2574
+ #
2575
+ # Other functions
2576
+ #
2577
+
2578
+ @staticmethod
2579
+ def _is_noop_jump_block(block) -> bool:
2580
+ """
2581
+ Check if the block does nothing but jumping to a constant address.
2582
+
2583
+ :param block: The block instance. We assume the block is already optimized.
2584
+ :return: True if the entire block is a jump to a constant address, False otherwise.
2585
+ """
2586
+
2587
+ vex = block.vex
2588
+ if vex.jumpkind != "Ijk_Boring":
2589
+ return False
2590
+ if isinstance(vex.next, pyvex.expr.Const):
2591
+ return all(isinstance(stmt, pyvex.stmt.IMark) for stmt in vex.statements)
2592
+ if isinstance(vex.next, pyvex.expr.RdTmp):
2593
+ next_tmp = vex.next.tmp
2594
+ return all(
2595
+ isinstance(stmt, pyvex.stmt.IMark)
2596
+ or (
2597
+ isinstance(stmt, pyvex.stmt.WrTmp)
2598
+ and stmt.tmp == next_tmp
2599
+ and isinstance(stmt.data, pyvex.expr.Load)
2600
+ and isinstance(stmt.data.addr, pyvex.expr.Const)
2601
+ )
2602
+ for stmt in vex.statements
2603
+ )
2604
+ return False
2605
+
2606
+ @staticmethod
2607
+ def _is_noop_block(arch: archinfo.Arch, block) -> bool:
2608
+ """
2609
+ Check if the block is a no-op block by checking VEX statements.
2610
+
2611
+ :param arch: An architecture descriptor.
2612
+ :param block: The VEX block instance.
2613
+ :return: True if the entire block is a single-byte or multi-byte nop instruction, False otherwise.
2614
+ """
2615
+
2616
+ if arch.name == "X86" or arch.name == "AMD64":
2617
+ block_bytes_set = set(block.bytes)
2618
+ if block_bytes_set == {0x90}:
2619
+ return True
2620
+ if block_bytes_set == {0xCC}:
2621
+ # technically this is not a no-op, but for our purposes we can settle for now
2622
+ return True
2623
+ elif arch.name == "MIPS32":
2624
+ if arch.memory_endness == "Iend_BE":
2625
+ MIPS32_BE_NOOPS = {
2626
+ b"\x00\x20\x08\x25", # move $at, $at
2627
+ }
2628
+ insns = {block.bytes[i : i + 4] for i in range(0, block.size, 4)}
2629
+ if MIPS32_BE_NOOPS.issuperset(insns):
2630
+ return True
2631
+
2632
+ elif is_arm_arch(arch):
2633
+ if block.addr & 1 == 0:
2634
+ # ARM mode
2635
+ if arch.memory_endness == archinfo.Endness.LE:
2636
+ ARM_NOOPS = {
2637
+ b"\x00\x00\x00\x00", # andeq r0, r0, r0
2638
+ b"\x00\x00\xa0\xe1", # mov r0, r0
2639
+ }
2640
+ else: # if arch.memory_endness == archinfo.Endness.BE:
2641
+ ARM_NOOPS = {
2642
+ b"\x00\x00\x00\x00", # andeq r0, r0, r0
2643
+ b"\xe1\xa0\x00\x00", # mov r0, r0
2644
+ }
2645
+ insns = {block.bytes[i : i + 4] for i in range(0, block.size, 4)}
2646
+ if ARM_NOOPS.issuperset(insns):
2647
+ return True
2648
+
2649
+ else:
2650
+ # THUMB mode, 2-byte instructions
2651
+ if arch.memory_endness == archinfo.Endness.LE:
2652
+ THUMB_NOOPS = {
2653
+ b"\xc0\x46", # mov r8, r8
2654
+ b"\xb0\x00", # add sp, #0
2655
+ b"\x00\xbf", # nop
2656
+ }
2657
+ else:
2658
+ THUMB_NOOPS = {
2659
+ b"\x46\xc0", # mov r8, r8
2660
+ b"\x00\xb0", # add sp, #0
2661
+ b"\xbf\x00", # nop
2662
+ }
2663
+ insns = {block.bytes[i : i + 2] for i in range(0, block.size, 2)}
2664
+ if THUMB_NOOPS.issuperset(insns):
2665
+ return True
2666
+
2667
+ return block.vex_nostmt.is_noop_block
2668
+
2669
+ @staticmethod
2670
+ def _is_noop_insn(insn):
2671
+ """
2672
+ Check if the instruction does nothing.
2673
+
2674
+ :param insn: The capstone insn object.
2675
+ :return: True if the instruction does no-op, False otherwise.
2676
+ """
2677
+
2678
+ insn_name = insn.mnemonic
2679
+
2680
+ if insn_name == "nop":
2681
+ # nops
2682
+ return True
2683
+ if insn_name == "lea":
2684
+ # lea reg, [reg + 0]
2685
+ op0, op1 = insn.operands
2686
+ # reg and mem
2687
+ if op0.type == 1 and op1.type == 3 and op0.reg == op1.mem.base and op1.mem.index == 0 and op1.mem.disp == 0:
2688
+ return True
2689
+ elif insn_name == "mov":
2690
+ if len(insn.operands) > 2:
2691
+ # mov reg_a, imm1, shift imm2
2692
+ # This is not a NOP
2693
+ return False
2694
+ # mov reg_a, reg_a
2695
+ op0, op1 = insn.operands
2696
+ # reg and reg
2697
+ if op0.type == 1 and op1.type == 1 and op0.reg == op1.reg:
2698
+ return True
2699
+ elif insn_name in {"ud0", "ud1", "ud2"}:
2700
+ return True
2701
+
2702
+ # add more types of no-op instructions here :-)
2703
+
2704
+ return False
2705
+
2706
+ @classmethod
2707
+ def _get_nop_length(cls, insns):
2708
+ """
2709
+ Calculate the total size of leading nop instructions.
2710
+
2711
+ :param insns: A list of capstone insn objects.
2712
+ :return: Number of bytes of leading nop instructions.
2713
+ :rtype: int
2714
+ """
2715
+
2716
+ nop_length = 0
2717
+
2718
+ if insns and cls._is_noop_insn(insns[0]):
2719
+ # see where those nop instructions terminate
2720
+ for insn in insns:
2721
+ if cls._is_noop_insn(insn):
2722
+ nop_length += insn.size
2723
+ else:
2724
+ break
2725
+
2726
+ return nop_length
2727
+
2728
+ @staticmethod
2729
+ def _one_fakeret_node(all_edges):
2730
+ """
2731
+ Pick the first Ijk_FakeRet edge from all_edges, and return the destination node.
2732
+
2733
+ :param list all_edges: A list of networkx.Graph edges with data.
2734
+ :return: The first FakeRet node, or None if nothing is found.
2735
+ :rtype: CFGNode or None
2736
+ """
2737
+
2738
+ for _, dst, data in all_edges:
2739
+ if data.get("jumpkind", None) == "Ijk_FakeRet":
2740
+ return dst
2741
+ return None
2742
+
2743
+ def _lift(self, addr, *args, opt_level=1, cross_insn_opt=False, **kwargs):
2744
+ """
2745
+ Lift a basic block of code. Will use the base state as a source of bytes if possible.
2746
+ """
2747
+ if "backup_state" not in kwargs:
2748
+ kwargs["backup_state"] = self._base_state
2749
+ return self.project.factory.block(addr, *args, opt_level=opt_level, cross_insn_opt=cross_insn_opt, **kwargs)
2750
+
2751
+ #
2752
+ # Indirect jumps processing
2753
+ #
2754
+
2755
+ def _resolve_indirect_jump_timelessly(self, addr, block, func_addr, jumpkind):
2756
+ """
2757
+ Attempt to quickly resolve an indirect jump.
2758
+
2759
+ :param int addr: Basic block address of this indirect jump.
2760
+ :param block: The basic block. The type is determined by the backend being used. It's pyvex.IRSB if
2761
+ pyvex is used as the backend.
2762
+ :param int func_addr: Address of the function that this indirect jump belongs to.
2763
+ :param str jumpkind: The jumpkind.
2764
+ :return: A tuple of a boolean indicating whether the resolution is successful or not, and a list
2765
+ of resolved targets (ints).
2766
+ :rtype: tuple
2767
+ """
2768
+
2769
+ # pre-check: if re-lifting the block with full optimization (cross-instruction-optimization enabled) gives us
2770
+ # a constant next expression, we don't need to resolve it
2771
+ try:
2772
+ relifted = self.project.factory.block(block.addr, size=block.size, opt_level=1, cross_insn_opt=True).vex
2773
+ except SimError:
2774
+ return False, []
2775
+ if not relifted.jumpkind.startswith("Ijk_Sys") and isinstance(relifted.next, pyvex.IRExpr.Const):
2776
+ # yes!
2777
+ return True, [relifted.next.con.value]
2778
+
2779
+ if block.statements is None:
2780
+ # make sure there are statements
2781
+ block = self.project.factory.block(block.addr, size=block.size).vex
2782
+
2783
+ for res in self.timeless_indirect_jump_resolvers:
2784
+ if res.filter(self, addr, func_addr, block, jumpkind):
2785
+ r, resolved_targets = res.resolve(self, addr, func_addr, block, jumpkind)
2786
+ if r:
2787
+ return True, resolved_targets
2788
+ return False, []
2789
+
2790
+ def _indirect_jump_resolved(self, jump, jump_addr, resolved_by, targets):
2791
+ """
2792
+ Called when an indirect jump is successfully resolved.
2793
+
2794
+ :param IndirectJump jump: The resolved indirect jump, or None if an IndirectJump instance is
2795
+ not available.
2796
+ :param int jump_addr: Address of the resolved indirect jump.
2797
+ :param IndirectJumpResolver resolved_by: The resolver used to resolve this indirect jump.
2798
+ :param list targets: List of indirect jump targets.
2799
+ :param CFGJob job: The job at the start of the block containing the indirect jump.
2800
+
2801
+ :return: None
2802
+ """
2803
+
2804
+ addr = jump.addr if jump is not None else jump_addr
2805
+ l.debug(
2806
+ "The indirect jump at %#x is successfully resolved by %s. It has %d targets.",
2807
+ addr,
2808
+ resolved_by,
2809
+ len(targets),
2810
+ )
2811
+ self.kb.indirect_jumps.update_resolved_addrs(addr, targets)
2812
+
2813
+ def _indirect_jump_unresolved(self, jump):
2814
+ """
2815
+ Called when we cannot resolve an indirect jump.
2816
+
2817
+ :param IndirectJump jump: The unresolved indirect jump.
2818
+
2819
+ :return: None
2820
+ """
2821
+
2822
+ l.debug("Failed to resolve the indirect jump at %#x.", jump.addr)
2823
+ # tell KnowledgeBase that it's not resolved
2824
+ # TODO: self.kb._unresolved_indirect_jumps is not processed during normalization. Fix it.
2825
+ self.kb.unresolved_indirect_jumps.add(jump.addr)
2826
+
2827
+ def _indirect_jump_encountered(
2828
+ self,
2829
+ addr: int,
2830
+ cfg_node: CFGNode,
2831
+ irsb: pyvex.IRSB,
2832
+ func_addr: int,
2833
+ stmt_idx: int = DEFAULT_STATEMENT,
2834
+ ) -> tuple[bool, set[int], IndirectJump | None]:
2835
+ """
2836
+ Called when we encounter an indirect jump. We will try to resolve this indirect jump using timeless (fast)
2837
+ indirect jump resolvers. If it cannot be resolved, we will see if this indirect jump has been resolved before.
2838
+
2839
+ :param addr: Address of the block containing the indirect jump.
2840
+ :param cfg_node: The CFGNode instance of the block that contains the indirect jump.
2841
+ :param irsb: The IRSB instance of the block that contains the indirect jump. It must be lifted with
2842
+ cross-instruction optimization disabled (cross_insn_opt=True when opt_level=1, or
2843
+ opt_level=0).
2844
+ :param func_addr: Address of the current function.
2845
+ :param stmt_idx: ID of the source statement.
2846
+
2847
+ :return: A 3-tuple of (whether it is resolved or not, all resolved targets, an IndirectJump object
2848
+ if there is one or None otherwise)
2849
+ """
2850
+
2851
+ jumpkind = irsb.jumpkind
2852
+ l.debug("IRSB %#x has an indirect jump (%s) as its default exit.", addr, jumpkind)
2853
+
2854
+ # try resolving it fast
2855
+ resolved, resolved_targets = self._resolve_indirect_jump_timelessly(addr, irsb, func_addr, jumpkind)
2856
+ if resolved:
2857
+ l.debug(
2858
+ "Indirect jump at block %#x is resolved by a timeless indirect jump resolver. %d targets found.",
2859
+ addr,
2860
+ len(resolved_targets),
2861
+ )
2862
+ return True, set(resolved_targets), None
2863
+
2864
+ l.debug("Indirect jump at block %#x cannot be resolved by a timeless indirect jump resolver.", addr)
2865
+
2866
+ # Add it to our set. Will process it later if user allows.
2867
+ # Create an IndirectJump instance
2868
+ if addr not in self.indirect_jumps:
2869
+ if self.project.arch.branch_delay_slot:
2870
+ if len(cfg_node.instruction_addrs) < 2:
2871
+ # sanity check
2872
+ # decoding failed when decoding the second instruction (or even the first instruction)
2873
+ return False, set(), None
2874
+ ins_addr = cfg_node.instruction_addrs[-2]
2875
+ elif cfg_node.instruction_addrs:
2876
+ ins_addr = cfg_node.instruction_addrs[-1]
2877
+ else:
2878
+ # fallback
2879
+ ins_addr = addr
2880
+ assert jumpkind is not None
2881
+ ij = IndirectJump(addr, ins_addr, func_addr, jumpkind, stmt_idx, resolved_targets=[])
2882
+ self.indirect_jumps[addr] = ij
2883
+ resolved = False
2884
+ else:
2885
+ ij: IndirectJump = self.indirect_jumps[addr]
2886
+ resolved = len(ij.resolved_targets) > 0
2887
+
2888
+ return resolved, ij.resolved_targets, ij
2889
+
2890
+ def _process_unresolved_indirect_jumps(self):
2891
+ """
2892
+ Resolve all unresolved indirect jumps found in previous scanning.
2893
+
2894
+ Currently we support resolving the following types of indirect jumps:
2895
+ - Ijk_Call: indirect calls where the function address is passed in from a proceeding basic block
2896
+ - Ijk_Boring: jump tables
2897
+ - For an up-to-date list, see analyses/cfg/indirect_jump_resolvers
2898
+
2899
+ :return: A set of concrete indirect jump targets (ints).
2900
+ :rtype: set
2901
+ """
2902
+
2903
+ l.info("%d indirect jumps to resolve.", len(self._indirect_jumps_to_resolve))
2904
+
2905
+ all_targets = set()
2906
+ idx: int
2907
+ jump: IndirectJump
2908
+ for idx, jump in enumerate(self._indirect_jumps_to_resolve):
2909
+ if self._low_priority:
2910
+ self._release_gil(idx, 50, 0.000001)
2911
+ all_targets |= self._process_one_indirect_jump(jump)
2912
+
2913
+ self._indirect_jumps_to_resolve.clear()
2914
+
2915
+ return all_targets
2916
+
2917
+ def _process_one_indirect_jump(self, jump: IndirectJump, func_graph_complete: bool = True) -> set:
2918
+ """
2919
+ Resolve a given indirect jump.
2920
+
2921
+ :param jump: The IndirectJump instance.
2922
+ :param func_graph_complete: True if the function graph is complete at this point (except for this indirect jump
2923
+ and all nodes that it dominates). Indirect jump resolvers may use the current
2924
+ function graph to perform sanity checks. CFGEmulated sets func_graph_complete to
2925
+ False while CFGFast sets it to True (because in CFGFast, indirect jumps are always
2926
+ resolved after direct jump jobs are processed).
2927
+ :return: A set of resolved indirect jump targets (ints).
2928
+ """
2929
+
2930
+ resolved = False
2931
+ resolved_by = None
2932
+ targets = None
2933
+
2934
+ block = self._lift(jump.addr)
2935
+
2936
+ for resolver in self.indirect_jump_resolvers:
2937
+ resolver.base_state = self._base_state
2938
+
2939
+ if not resolver.filter(self, jump.addr, jump.func_addr, block, jump.jumpkind):
2940
+ continue
2941
+
2942
+ resolved, targets = resolver.resolve(
2943
+ self, jump.addr, jump.func_addr, block, jump.jumpkind, func_graph_complete=func_graph_complete
2944
+ )
2945
+ if resolved:
2946
+ resolved_by = resolver
2947
+ break
2948
+
2949
+ if resolved:
2950
+ self._indirect_jump_resolved(jump, jump.addr, resolved_by, targets)
2951
+ else:
2952
+ self._indirect_jump_unresolved(jump)
2953
+
2954
+ return set() if targets is None else set(targets)