angr 9.2.156__cp310-cp310-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of angr might be problematic. Click here for more details.

Files changed (1393) hide show
  1. angr/__init__.py +363 -0
  2. angr/__main__.py +152 -0
  3. angr/analyses/__init__.py +113 -0
  4. angr/analyses/analysis.py +407 -0
  5. angr/analyses/backward_slice.py +686 -0
  6. angr/analyses/binary_optimizer.py +670 -0
  7. angr/analyses/bindiff.py +1512 -0
  8. angr/analyses/boyscout.py +76 -0
  9. angr/analyses/callee_cleanup_finder.py +74 -0
  10. angr/analyses/calling_convention/__init__.py +6 -0
  11. angr/analyses/calling_convention/calling_convention.py +1092 -0
  12. angr/analyses/calling_convention/fact_collector.py +636 -0
  13. angr/analyses/calling_convention/utils.py +60 -0
  14. angr/analyses/cdg.py +189 -0
  15. angr/analyses/cfg/__init__.py +23 -0
  16. angr/analyses/cfg/cfb.py +428 -0
  17. angr/analyses/cfg/cfg.py +74 -0
  18. angr/analyses/cfg/cfg_arch_options.py +95 -0
  19. angr/analyses/cfg/cfg_base.py +2886 -0
  20. angr/analyses/cfg/cfg_emulated.py +3447 -0
  21. angr/analyses/cfg/cfg_fast.py +5273 -0
  22. angr/analyses/cfg/cfg_fast_soot.py +662 -0
  23. angr/analyses/cfg/cfg_job_base.py +203 -0
  24. angr/analyses/cfg/indirect_jump_resolvers/__init__.py +28 -0
  25. angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
  26. angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
  27. angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +149 -0
  28. angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +186 -0
  29. angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
  30. angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +76 -0
  31. angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2367 -0
  32. angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
  33. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
  34. angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
  35. angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
  36. angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
  37. angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
  38. angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
  39. angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
  40. angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
  41. angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
  42. angr/analyses/cfg_slice_to_sink/graph.py +87 -0
  43. angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
  44. angr/analyses/class_identifier.py +63 -0
  45. angr/analyses/code_tagging.py +123 -0
  46. angr/analyses/codecave.py +77 -0
  47. angr/analyses/complete_calling_conventions.py +461 -0
  48. angr/analyses/congruency_check.py +377 -0
  49. angr/analyses/data_dep/__init__.py +16 -0
  50. angr/analyses/data_dep/data_dependency_analysis.py +595 -0
  51. angr/analyses/data_dep/dep_nodes.py +171 -0
  52. angr/analyses/data_dep/sim_act_location.py +49 -0
  53. angr/analyses/datagraph_meta.py +105 -0
  54. angr/analyses/ddg.py +1670 -0
  55. angr/analyses/decompiler/__init__.py +41 -0
  56. angr/analyses/decompiler/ail_simplifier.py +1872 -0
  57. angr/analyses/decompiler/ailgraph_walker.py +49 -0
  58. angr/analyses/decompiler/block_io_finder.py +302 -0
  59. angr/analyses/decompiler/block_similarity.py +196 -0
  60. angr/analyses/decompiler/block_simplifier.py +371 -0
  61. angr/analyses/decompiler/callsite_maker.py +555 -0
  62. angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
  63. angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +580 -0
  64. angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +20 -0
  65. angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +313 -0
  66. angr/analyses/decompiler/clinic.py +3222 -0
  67. angr/analyses/decompiler/condition_processor.py +1245 -0
  68. angr/analyses/decompiler/counters/__init__.py +16 -0
  69. angr/analyses/decompiler/counters/boolean_counter.py +27 -0
  70. angr/analyses/decompiler/counters/call_counter.py +47 -0
  71. angr/analyses/decompiler/counters/expression_counters.py +77 -0
  72. angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
  73. angr/analyses/decompiler/decompilation_cache.py +46 -0
  74. angr/analyses/decompiler/decompilation_options.py +275 -0
  75. angr/analyses/decompiler/decompiler.py +692 -0
  76. angr/analyses/decompiler/dephication/__init__.py +6 -0
  77. angr/analyses/decompiler/dephication/dephication_base.py +89 -0
  78. angr/analyses/decompiler/dephication/graph_dephication.py +63 -0
  79. angr/analyses/decompiler/dephication/graph_rewriting.py +116 -0
  80. angr/analyses/decompiler/dephication/graph_vvar_mapping.py +326 -0
  81. angr/analyses/decompiler/dephication/rewriting_engine.py +504 -0
  82. angr/analyses/decompiler/dephication/seqnode_dephication.py +134 -0
  83. angr/analyses/decompiler/empty_node_remover.py +212 -0
  84. angr/analyses/decompiler/expression_narrower.py +287 -0
  85. angr/analyses/decompiler/goto_manager.py +112 -0
  86. angr/analyses/decompiler/graph_region.py +398 -0
  87. angr/analyses/decompiler/jump_target_collector.py +37 -0
  88. angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
  89. angr/analyses/decompiler/label_collector.py +32 -0
  90. angr/analyses/decompiler/optimization_passes/__init__.py +151 -0
  91. angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
  92. angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
  93. angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
  94. angr/analyses/decompiler/optimization_passes/condition_constprop.py +219 -0
  95. angr/analyses/decompiler/optimization_passes/const_derefs.py +266 -0
  96. angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
  97. angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
  98. angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
  99. angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
  100. angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
  101. angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
  102. angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
  103. angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1218 -0
  104. angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
  105. angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
  106. angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
  107. angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +165 -0
  108. angr/analyses/decompiler/optimization_passes/engine_base.py +500 -0
  109. angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +135 -0
  110. angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
  111. angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +615 -0
  112. angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
  113. angr/analyses/decompiler/optimization_passes/ite_region_converter.py +335 -0
  114. angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +922 -0
  115. angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
  116. angr/analyses/decompiler/optimization_passes/optimization_pass.py +659 -0
  117. angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +221 -0
  118. angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
  119. angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
  120. angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +640 -0
  121. angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
  122. angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +235 -0
  123. angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
  124. angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +149 -0
  125. angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
  126. angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
  127. angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +421 -0
  128. angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
  129. angr/analyses/decompiler/peephole_optimizations/__init__.py +127 -0
  130. angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
  131. angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
  132. angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
  133. angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
  134. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
  135. angr/analyses/decompiler/peephole_optimizations/a_sub_a_div_const_mul_const.py +57 -0
  136. angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
  137. angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
  138. angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
  139. angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
  140. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
  141. angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
  142. angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
  143. angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
  144. angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
  145. angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +115 -0
  146. angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
  147. angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
  148. angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
  149. angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +189 -0
  150. angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
  151. angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
  152. angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
  153. angr/analyses/decompiler/peephole_optimizations/eager_eval.py +372 -0
  154. angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
  155. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +160 -0
  156. angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +109 -0
  157. angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +170 -0
  158. angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
  159. angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
  160. angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
  161. angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
  162. angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
  163. angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
  164. angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +116 -0
  165. angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +247 -0
  166. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
  167. angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
  168. angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
  169. angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
  170. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
  171. angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +44 -0
  172. angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
  173. angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
  174. angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
  175. angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
  176. angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
  177. angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +112 -0
  178. angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
  179. angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
  180. angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +53 -0
  181. angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
  182. angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
  183. angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
  184. angr/analyses/decompiler/presets/__init__.py +20 -0
  185. angr/analyses/decompiler/presets/basic.py +32 -0
  186. angr/analyses/decompiler/presets/fast.py +58 -0
  187. angr/analyses/decompiler/presets/full.py +68 -0
  188. angr/analyses/decompiler/presets/preset.py +37 -0
  189. angr/analyses/decompiler/redundant_label_remover.py +134 -0
  190. angr/analyses/decompiler/region_identifier.py +1218 -0
  191. angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
  192. angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
  193. angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
  194. angr/analyses/decompiler/region_simplifiers/expr_folding.py +789 -0
  195. angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
  196. angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
  197. angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
  198. angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
  199. angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
  200. angr/analyses/decompiler/region_simplifiers/region_simplifier.py +234 -0
  201. angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
  202. angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
  203. angr/analyses/decompiler/region_walker.py +24 -0
  204. angr/analyses/decompiler/return_maker.py +72 -0
  205. angr/analyses/decompiler/seq_to_blocks.py +20 -0
  206. angr/analyses/decompiler/sequence_walker.py +257 -0
  207. angr/analyses/decompiler/ssailification/__init__.py +4 -0
  208. angr/analyses/decompiler/ssailification/rewriting.py +379 -0
  209. angr/analyses/decompiler/ssailification/rewriting_engine.py +1053 -0
  210. angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
  211. angr/analyses/decompiler/ssailification/ssailification.py +276 -0
  212. angr/analyses/decompiler/ssailification/traversal.py +124 -0
  213. angr/analyses/decompiler/ssailification/traversal_engine.py +297 -0
  214. angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
  215. angr/analyses/decompiler/stack_item.py +36 -0
  216. angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
  217. angr/analyses/decompiler/structured_codegen/base.py +132 -0
  218. angr/analyses/decompiler/structured_codegen/c.py +4069 -0
  219. angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
  220. angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
  221. angr/analyses/decompiler/structuring/__init__.py +30 -0
  222. angr/analyses/decompiler/structuring/dream.py +1217 -0
  223. angr/analyses/decompiler/structuring/phoenix.py +2999 -0
  224. angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
  225. angr/analyses/decompiler/structuring/sailr.py +112 -0
  226. angr/analyses/decompiler/structuring/structurer_base.py +1067 -0
  227. angr/analyses/decompiler/structuring/structurer_nodes.py +438 -0
  228. angr/analyses/decompiler/utils.py +1106 -0
  229. angr/analyses/deobfuscator/__init__.py +18 -0
  230. angr/analyses/deobfuscator/api_obf_finder.py +325 -0
  231. angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +51 -0
  232. angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
  233. angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
  234. angr/analyses/deobfuscator/string_obf_finder.py +861 -0
  235. angr/analyses/deobfuscator/string_obf_opt_passes.py +133 -0
  236. angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
  237. angr/analyses/disassembly.py +1301 -0
  238. angr/analyses/disassembly_utils.py +101 -0
  239. angr/analyses/dominance_frontier.py +57 -0
  240. angr/analyses/fcp/__init__.py +4 -0
  241. angr/analyses/fcp/fcp.py +426 -0
  242. angr/analyses/find_objects_static.py +205 -0
  243. angr/analyses/flirt/__init__.py +47 -0
  244. angr/analyses/flirt/consts.py +160 -0
  245. angr/analyses/flirt/flirt.py +244 -0
  246. angr/analyses/flirt/flirt_function.py +20 -0
  247. angr/analyses/flirt/flirt_matcher.py +351 -0
  248. angr/analyses/flirt/flirt_module.py +32 -0
  249. angr/analyses/flirt/flirt_node.py +23 -0
  250. angr/analyses/flirt/flirt_sig.py +356 -0
  251. angr/analyses/flirt/flirt_utils.py +31 -0
  252. angr/analyses/forward_analysis/__init__.py +12 -0
  253. angr/analyses/forward_analysis/forward_analysis.py +530 -0
  254. angr/analyses/forward_analysis/job_info.py +64 -0
  255. angr/analyses/forward_analysis/visitors/__init__.py +14 -0
  256. angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
  257. angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
  258. angr/analyses/forward_analysis/visitors/graph.py +242 -0
  259. angr/analyses/forward_analysis/visitors/loop.py +29 -0
  260. angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
  261. angr/analyses/identifier/__init__.py +5 -0
  262. angr/analyses/identifier/custom_callable.py +137 -0
  263. angr/analyses/identifier/errors.py +10 -0
  264. angr/analyses/identifier/func.py +60 -0
  265. angr/analyses/identifier/functions/__init__.py +37 -0
  266. angr/analyses/identifier/functions/atoi.py +73 -0
  267. angr/analyses/identifier/functions/based_atoi.py +125 -0
  268. angr/analyses/identifier/functions/fdprintf.py +123 -0
  269. angr/analyses/identifier/functions/free.py +64 -0
  270. angr/analyses/identifier/functions/int2str.py +287 -0
  271. angr/analyses/identifier/functions/malloc.py +111 -0
  272. angr/analyses/identifier/functions/memcmp.py +67 -0
  273. angr/analyses/identifier/functions/memcpy.py +89 -0
  274. angr/analyses/identifier/functions/memset.py +43 -0
  275. angr/analyses/identifier/functions/printf.py +123 -0
  276. angr/analyses/identifier/functions/recv_until.py +312 -0
  277. angr/analyses/identifier/functions/skip_calloc.py +73 -0
  278. angr/analyses/identifier/functions/skip_realloc.py +97 -0
  279. angr/analyses/identifier/functions/skip_recv_n.py +105 -0
  280. angr/analyses/identifier/functions/snprintf.py +112 -0
  281. angr/analyses/identifier/functions/sprintf.py +116 -0
  282. angr/analyses/identifier/functions/strcasecmp.py +33 -0
  283. angr/analyses/identifier/functions/strcmp.py +113 -0
  284. angr/analyses/identifier/functions/strcpy.py +43 -0
  285. angr/analyses/identifier/functions/strlen.py +27 -0
  286. angr/analyses/identifier/functions/strncmp.py +104 -0
  287. angr/analyses/identifier/functions/strncpy.py +65 -0
  288. angr/analyses/identifier/functions/strtol.py +89 -0
  289. angr/analyses/identifier/identify.py +825 -0
  290. angr/analyses/identifier/runner.py +360 -0
  291. angr/analyses/init_finder.py +289 -0
  292. angr/analyses/loop_analysis.py +349 -0
  293. angr/analyses/loopfinder.py +171 -0
  294. angr/analyses/patchfinder.py +137 -0
  295. angr/analyses/pathfinder.py +282 -0
  296. angr/analyses/propagator/__init__.py +5 -0
  297. angr/analyses/propagator/engine_base.py +62 -0
  298. angr/analyses/propagator/engine_vex.py +297 -0
  299. angr/analyses/propagator/propagator.py +361 -0
  300. angr/analyses/propagator/top_checker_mixin.py +218 -0
  301. angr/analyses/propagator/values.py +117 -0
  302. angr/analyses/propagator/vex_vars.py +68 -0
  303. angr/analyses/proximity_graph.py +444 -0
  304. angr/analyses/reaching_definitions/__init__.py +67 -0
  305. angr/analyses/reaching_definitions/call_trace.py +73 -0
  306. angr/analyses/reaching_definitions/dep_graph.py +433 -0
  307. angr/analyses/reaching_definitions/engine_ail.py +1130 -0
  308. angr/analyses/reaching_definitions/engine_vex.py +1127 -0
  309. angr/analyses/reaching_definitions/external_codeloc.py +0 -0
  310. angr/analyses/reaching_definitions/function_handler.py +637 -0
  311. angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
  312. angr/analyses/reaching_definitions/function_handler_library/stdio.py +268 -0
  313. angr/analyses/reaching_definitions/function_handler_library/stdlib.py +189 -0
  314. angr/analyses/reaching_definitions/function_handler_library/string.py +147 -0
  315. angr/analyses/reaching_definitions/function_handler_library/unistd.py +44 -0
  316. angr/analyses/reaching_definitions/heap_allocator.py +70 -0
  317. angr/analyses/reaching_definitions/rd_initializer.py +237 -0
  318. angr/analyses/reaching_definitions/rd_state.py +579 -0
  319. angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
  320. angr/analyses/reaching_definitions/subject.py +65 -0
  321. angr/analyses/reassembler.py +2900 -0
  322. angr/analyses/s_liveness.py +203 -0
  323. angr/analyses/s_propagator.py +544 -0
  324. angr/analyses/s_reaching_definitions/__init__.py +12 -0
  325. angr/analyses/s_reaching_definitions/s_rda_model.py +135 -0
  326. angr/analyses/s_reaching_definitions/s_rda_view.py +315 -0
  327. angr/analyses/s_reaching_definitions/s_reaching_definitions.py +174 -0
  328. angr/analyses/smc.py +161 -0
  329. angr/analyses/soot_class_hierarchy.py +273 -0
  330. angr/analyses/stack_pointer_tracker.py +957 -0
  331. angr/analyses/static_hooker.py +53 -0
  332. angr/analyses/typehoon/__init__.py +5 -0
  333. angr/analyses/typehoon/dfa.py +118 -0
  334. angr/analyses/typehoon/lifter.py +122 -0
  335. angr/analyses/typehoon/simple_solver.py +1450 -0
  336. angr/analyses/typehoon/translator.py +279 -0
  337. angr/analyses/typehoon/typeconsts.py +336 -0
  338. angr/analyses/typehoon/typehoon.py +305 -0
  339. angr/analyses/typehoon/typevars.py +578 -0
  340. angr/analyses/typehoon/variance.py +11 -0
  341. angr/analyses/unpacker/__init__.py +6 -0
  342. angr/analyses/unpacker/obfuscation_detector.py +103 -0
  343. angr/analyses/unpacker/packing_detector.py +138 -0
  344. angr/analyses/variable_recovery/__init__.py +9 -0
  345. angr/analyses/variable_recovery/annotations.py +58 -0
  346. angr/analyses/variable_recovery/engine_ail.py +891 -0
  347. angr/analyses/variable_recovery/engine_base.py +1185 -0
  348. angr/analyses/variable_recovery/engine_vex.py +593 -0
  349. angr/analyses/variable_recovery/irsb_scanner.py +143 -0
  350. angr/analyses/variable_recovery/variable_recovery.py +573 -0
  351. angr/analyses/variable_recovery/variable_recovery_base.py +461 -0
  352. angr/analyses/variable_recovery/variable_recovery_fast.py +652 -0
  353. angr/analyses/veritesting.py +626 -0
  354. angr/analyses/vfg.py +1898 -0
  355. angr/analyses/vsa_ddg.py +420 -0
  356. angr/analyses/vtable.py +92 -0
  357. angr/analyses/xrefs.py +286 -0
  358. angr/angrdb/__init__.py +14 -0
  359. angr/angrdb/db.py +206 -0
  360. angr/angrdb/models.py +184 -0
  361. angr/angrdb/serializers/__init__.py +10 -0
  362. angr/angrdb/serializers/cfg_model.py +41 -0
  363. angr/angrdb/serializers/comments.py +60 -0
  364. angr/angrdb/serializers/funcs.py +61 -0
  365. angr/angrdb/serializers/kb.py +111 -0
  366. angr/angrdb/serializers/labels.py +59 -0
  367. angr/angrdb/serializers/loader.py +165 -0
  368. angr/angrdb/serializers/structured_code.py +125 -0
  369. angr/angrdb/serializers/variables.py +58 -0
  370. angr/angrdb/serializers/xrefs.py +48 -0
  371. angr/annocfg.py +317 -0
  372. angr/blade.py +426 -0
  373. angr/block.py +509 -0
  374. angr/callable.py +168 -0
  375. angr/calling_conventions.py +2580 -0
  376. angr/code_location.py +163 -0
  377. angr/codenode.py +145 -0
  378. angr/concretization_strategies/__init__.py +32 -0
  379. angr/concretization_strategies/any.py +17 -0
  380. angr/concretization_strategies/any_named.py +35 -0
  381. angr/concretization_strategies/base.py +81 -0
  382. angr/concretization_strategies/controlled_data.py +58 -0
  383. angr/concretization_strategies/eval.py +19 -0
  384. angr/concretization_strategies/logging.py +35 -0
  385. angr/concretization_strategies/max.py +25 -0
  386. angr/concretization_strategies/nonzero.py +16 -0
  387. angr/concretization_strategies/nonzero_range.py +22 -0
  388. angr/concretization_strategies/norepeats.py +37 -0
  389. angr/concretization_strategies/norepeats_range.py +37 -0
  390. angr/concretization_strategies/range.py +19 -0
  391. angr/concretization_strategies/signed_add.py +31 -0
  392. angr/concretization_strategies/single.py +15 -0
  393. angr/concretization_strategies/solutions.py +20 -0
  394. angr/concretization_strategies/unlimited_range.py +17 -0
  395. angr/distributed/__init__.py +9 -0
  396. angr/distributed/server.py +197 -0
  397. angr/distributed/worker.py +185 -0
  398. angr/engines/__init__.py +67 -0
  399. angr/engines/engine.py +29 -0
  400. angr/engines/failure.py +27 -0
  401. angr/engines/hook.py +68 -0
  402. angr/engines/light/__init__.py +23 -0
  403. angr/engines/light/data.py +681 -0
  404. angr/engines/light/engine.py +1285 -0
  405. angr/engines/pcode/__init__.py +9 -0
  406. angr/engines/pcode/behavior.py +997 -0
  407. angr/engines/pcode/cc.py +128 -0
  408. angr/engines/pcode/emulate.py +443 -0
  409. angr/engines/pcode/engine.py +242 -0
  410. angr/engines/pcode/lifter.py +1428 -0
  411. angr/engines/procedure.py +70 -0
  412. angr/engines/soot/__init__.py +5 -0
  413. angr/engines/soot/engine.py +410 -0
  414. angr/engines/soot/exceptions.py +17 -0
  415. angr/engines/soot/expressions/__init__.py +87 -0
  416. angr/engines/soot/expressions/arrayref.py +22 -0
  417. angr/engines/soot/expressions/base.py +21 -0
  418. angr/engines/soot/expressions/binop.py +28 -0
  419. angr/engines/soot/expressions/cast.py +22 -0
  420. angr/engines/soot/expressions/condition.py +35 -0
  421. angr/engines/soot/expressions/constants.py +47 -0
  422. angr/engines/soot/expressions/instanceOf.py +15 -0
  423. angr/engines/soot/expressions/instancefieldref.py +8 -0
  424. angr/engines/soot/expressions/invoke.py +114 -0
  425. angr/engines/soot/expressions/length.py +8 -0
  426. angr/engines/soot/expressions/local.py +8 -0
  427. angr/engines/soot/expressions/new.py +16 -0
  428. angr/engines/soot/expressions/newArray.py +54 -0
  429. angr/engines/soot/expressions/newMultiArray.py +86 -0
  430. angr/engines/soot/expressions/paramref.py +8 -0
  431. angr/engines/soot/expressions/phi.py +30 -0
  432. angr/engines/soot/expressions/staticfieldref.py +8 -0
  433. angr/engines/soot/expressions/thisref.py +7 -0
  434. angr/engines/soot/expressions/unsupported.py +7 -0
  435. angr/engines/soot/field_dispatcher.py +46 -0
  436. angr/engines/soot/method_dispatcher.py +46 -0
  437. angr/engines/soot/statements/__init__.py +44 -0
  438. angr/engines/soot/statements/assign.py +30 -0
  439. angr/engines/soot/statements/base.py +79 -0
  440. angr/engines/soot/statements/goto.py +14 -0
  441. angr/engines/soot/statements/identity.py +15 -0
  442. angr/engines/soot/statements/if_.py +19 -0
  443. angr/engines/soot/statements/invoke.py +12 -0
  444. angr/engines/soot/statements/return_.py +20 -0
  445. angr/engines/soot/statements/switch.py +41 -0
  446. angr/engines/soot/statements/throw.py +15 -0
  447. angr/engines/soot/values/__init__.py +38 -0
  448. angr/engines/soot/values/arrayref.py +122 -0
  449. angr/engines/soot/values/base.py +7 -0
  450. angr/engines/soot/values/constants.py +18 -0
  451. angr/engines/soot/values/instancefieldref.py +44 -0
  452. angr/engines/soot/values/local.py +18 -0
  453. angr/engines/soot/values/paramref.py +18 -0
  454. angr/engines/soot/values/staticfieldref.py +38 -0
  455. angr/engines/soot/values/strref.py +38 -0
  456. angr/engines/soot/values/thisref.py +149 -0
  457. angr/engines/successors.py +654 -0
  458. angr/engines/syscall.py +51 -0
  459. angr/engines/unicorn.py +490 -0
  460. angr/engines/vex/__init__.py +20 -0
  461. angr/engines/vex/claripy/__init__.py +5 -0
  462. angr/engines/vex/claripy/ccall.py +2097 -0
  463. angr/engines/vex/claripy/datalayer.py +141 -0
  464. angr/engines/vex/claripy/irop.py +1276 -0
  465. angr/engines/vex/heavy/__init__.py +16 -0
  466. angr/engines/vex/heavy/actions.py +231 -0
  467. angr/engines/vex/heavy/concretizers.py +403 -0
  468. angr/engines/vex/heavy/dirty.py +466 -0
  469. angr/engines/vex/heavy/heavy.py +370 -0
  470. angr/engines/vex/heavy/inspect.py +52 -0
  471. angr/engines/vex/heavy/resilience.py +85 -0
  472. angr/engines/vex/heavy/super_fastpath.py +34 -0
  473. angr/engines/vex/lifter.py +420 -0
  474. angr/engines/vex/light/__init__.py +11 -0
  475. angr/engines/vex/light/light.py +551 -0
  476. angr/engines/vex/light/resilience.py +74 -0
  477. angr/engines/vex/light/slicing.py +52 -0
  478. angr/errors.py +609 -0
  479. angr/exploration_techniques/__init__.py +53 -0
  480. angr/exploration_techniques/base.py +126 -0
  481. angr/exploration_techniques/bucketizer.py +94 -0
  482. angr/exploration_techniques/common.py +56 -0
  483. angr/exploration_techniques/dfs.py +37 -0
  484. angr/exploration_techniques/director.py +520 -0
  485. angr/exploration_techniques/driller_core.py +100 -0
  486. angr/exploration_techniques/explorer.py +152 -0
  487. angr/exploration_techniques/lengthlimiter.py +22 -0
  488. angr/exploration_techniques/local_loop_seer.py +65 -0
  489. angr/exploration_techniques/loop_seer.py +236 -0
  490. angr/exploration_techniques/manual_mergepoint.py +82 -0
  491. angr/exploration_techniques/memory_watcher.py +43 -0
  492. angr/exploration_techniques/oppologist.py +92 -0
  493. angr/exploration_techniques/slicecutor.py +118 -0
  494. angr/exploration_techniques/spiller.py +280 -0
  495. angr/exploration_techniques/spiller_db.py +27 -0
  496. angr/exploration_techniques/stochastic.py +56 -0
  497. angr/exploration_techniques/stub_stasher.py +19 -0
  498. angr/exploration_techniques/suggestions.py +159 -0
  499. angr/exploration_techniques/tech_builder.py +49 -0
  500. angr/exploration_techniques/threading.py +69 -0
  501. angr/exploration_techniques/timeout.py +34 -0
  502. angr/exploration_techniques/tracer.py +1098 -0
  503. angr/exploration_techniques/unique.py +106 -0
  504. angr/exploration_techniques/veritesting.py +37 -0
  505. angr/factory.py +404 -0
  506. angr/flirt/__init__.py +97 -0
  507. angr/flirt/build_sig.py +305 -0
  508. angr/graph_utils.py +0 -0
  509. angr/keyed_region.py +525 -0
  510. angr/knowledge_base.py +143 -0
  511. angr/knowledge_plugins/__init__.py +43 -0
  512. angr/knowledge_plugins/callsite_prototypes.py +53 -0
  513. angr/knowledge_plugins/cfg/__init__.py +18 -0
  514. angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
  515. angr/knowledge_plugins/cfg/cfg_model.py +1045 -0
  516. angr/knowledge_plugins/cfg/cfg_node.py +536 -0
  517. angr/knowledge_plugins/cfg/indirect_jump.py +65 -0
  518. angr/knowledge_plugins/cfg/memory_data.py +156 -0
  519. angr/knowledge_plugins/comments.py +16 -0
  520. angr/knowledge_plugins/custom_strings.py +38 -0
  521. angr/knowledge_plugins/data.py +22 -0
  522. angr/knowledge_plugins/debug_variables.py +216 -0
  523. angr/knowledge_plugins/functions/__init__.py +9 -0
  524. angr/knowledge_plugins/functions/function.py +1772 -0
  525. angr/knowledge_plugins/functions/function_manager.py +526 -0
  526. angr/knowledge_plugins/functions/function_parser.py +299 -0
  527. angr/knowledge_plugins/functions/soot_function.py +128 -0
  528. angr/knowledge_plugins/indirect_jumps.py +35 -0
  529. angr/knowledge_plugins/key_definitions/__init__.py +17 -0
  530. angr/knowledge_plugins/key_definitions/atoms.py +374 -0
  531. angr/knowledge_plugins/key_definitions/constants.py +29 -0
  532. angr/knowledge_plugins/key_definitions/definition.py +214 -0
  533. angr/knowledge_plugins/key_definitions/environment.py +96 -0
  534. angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
  535. angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
  536. angr/knowledge_plugins/key_definitions/live_definitions.py +1010 -0
  537. angr/knowledge_plugins/key_definitions/liveness.py +165 -0
  538. angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
  539. angr/knowledge_plugins/key_definitions/tag.py +78 -0
  540. angr/knowledge_plugins/key_definitions/undefined.py +70 -0
  541. angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
  542. angr/knowledge_plugins/key_definitions/uses.py +178 -0
  543. angr/knowledge_plugins/labels.py +110 -0
  544. angr/knowledge_plugins/obfuscations.py +37 -0
  545. angr/knowledge_plugins/patches.py +126 -0
  546. angr/knowledge_plugins/plugin.py +24 -0
  547. angr/knowledge_plugins/propagations/__init__.py +10 -0
  548. angr/knowledge_plugins/propagations/prop_value.py +191 -0
  549. angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
  550. angr/knowledge_plugins/propagations/propagation_model.py +73 -0
  551. angr/knowledge_plugins/propagations/states.py +552 -0
  552. angr/knowledge_plugins/structured_code.py +63 -0
  553. angr/knowledge_plugins/types.py +88 -0
  554. angr/knowledge_plugins/variables/__init__.py +8 -0
  555. angr/knowledge_plugins/variables/variable_access.py +113 -0
  556. angr/knowledge_plugins/variables/variable_manager.py +1368 -0
  557. angr/knowledge_plugins/xrefs/__init__.py +12 -0
  558. angr/knowledge_plugins/xrefs/xref.py +150 -0
  559. angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
  560. angr/knowledge_plugins/xrefs/xref_types.py +16 -0
  561. angr/lib/angr_native.dylib +0 -0
  562. angr/misc/__init__.py +19 -0
  563. angr/misc/ansi.py +47 -0
  564. angr/misc/autoimport.py +90 -0
  565. angr/misc/bug_report.py +117 -0
  566. angr/misc/hookset.py +106 -0
  567. angr/misc/loggers.py +130 -0
  568. angr/misc/picklable_lock.py +46 -0
  569. angr/misc/plugins.py +289 -0
  570. angr/misc/telemetry.py +54 -0
  571. angr/misc/testing.py +24 -0
  572. angr/misc/ux.py +31 -0
  573. angr/procedures/__init__.py +12 -0
  574. angr/procedures/advapi32/__init__.py +0 -0
  575. angr/procedures/cgc/__init__.py +3 -0
  576. angr/procedures/cgc/_terminate.py +11 -0
  577. angr/procedures/cgc/allocate.py +75 -0
  578. angr/procedures/cgc/deallocate.py +67 -0
  579. angr/procedures/cgc/fdwait.py +65 -0
  580. angr/procedures/cgc/random.py +67 -0
  581. angr/procedures/cgc/receive.py +93 -0
  582. angr/procedures/cgc/transmit.py +65 -0
  583. angr/procedures/definitions/__init__.py +779 -0
  584. angr/procedures/definitions/cgc.py +20 -0
  585. angr/procedures/definitions/glibc.py +8372 -0
  586. angr/procedures/definitions/gnulib.py +32 -0
  587. angr/procedures/definitions/libstdcpp.py +21 -0
  588. angr/procedures/definitions/linux_kernel.py +6171 -0
  589. angr/procedures/definitions/linux_loader.py +7 -0
  590. angr/procedures/definitions/msvcr.py +16 -0
  591. angr/procedures/definitions/parse_syscalls_from_local_system.py +50 -0
  592. angr/procedures/definitions/parse_win32json.py +2553 -0
  593. angr/procedures/definitions/types_stl.py +22 -0
  594. angr/procedures/definitions/types_win32.py +34482 -0
  595. angr/procedures/definitions/wdk_api-ms-win-dx-d3dkmt-l1-1-4.py +30 -0
  596. angr/procedures/definitions/wdk_api-ms-win-dx-d3dkmt-l1-1-6.py +26 -0
  597. angr/procedures/definitions/wdk_clfs.py +140 -0
  598. angr/procedures/definitions/wdk_fltmgr.py +556 -0
  599. angr/procedures/definitions/wdk_fwpkclnt.py +30 -0
  600. angr/procedures/definitions/wdk_fwpuclnt.py +316 -0
  601. angr/procedures/definitions/wdk_gdi32.py +366 -0
  602. angr/procedures/definitions/wdk_hal.py +78 -0
  603. angr/procedures/definitions/wdk_ksecdd.py +62 -0
  604. angr/procedures/definitions/wdk_ndis.py +238 -0
  605. angr/procedures/definitions/wdk_ntoskrnl.py +3451 -0
  606. angr/procedures/definitions/wdk_offreg.py +72 -0
  607. angr/procedures/definitions/wdk_pshed.py +36 -0
  608. angr/procedures/definitions/wdk_secur32.py +40 -0
  609. angr/procedures/definitions/wdk_vhfum.py +34 -0
  610. angr/procedures/definitions/win32_aclui.py +30 -0
  611. angr/procedures/definitions/win32_activeds.py +68 -0
  612. angr/procedures/definitions/win32_advapi32.py +1684 -0
  613. angr/procedures/definitions/win32_advpack.py +124 -0
  614. angr/procedures/definitions/win32_amsi.py +38 -0
  615. angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-1.py +44 -0
  616. angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-3.py +34 -0
  617. angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-6.py +26 -0
  618. angr/procedures/definitions/win32_api-ms-win-core-apiquery-l2-1-0.py +26 -0
  619. angr/procedures/definitions/win32_api-ms-win-core-backgroundtask-l1-1-0.py +26 -0
  620. angr/procedures/definitions/win32_api-ms-win-core-comm-l1-1-1.py +26 -0
  621. angr/procedures/definitions/win32_api-ms-win-core-comm-l1-1-2.py +26 -0
  622. angr/procedures/definitions/win32_api-ms-win-core-enclave-l1-1-1.py +30 -0
  623. angr/procedures/definitions/win32_api-ms-win-core-errorhandling-l1-1-3.py +26 -0
  624. angr/procedures/definitions/win32_api-ms-win-core-featurestaging-l1-1-0.py +34 -0
  625. angr/procedures/definitions/win32_api-ms-win-core-featurestaging-l1-1-1.py +26 -0
  626. angr/procedures/definitions/win32_api-ms-win-core-file-fromapp-l1-1-0.py +46 -0
  627. angr/procedures/definitions/win32_api-ms-win-core-handle-l1-1-0.py +26 -0
  628. angr/procedures/definitions/win32_api-ms-win-core-ioring-l1-1-0.py +48 -0
  629. angr/procedures/definitions/win32_api-ms-win-core-marshal-l1-1-0.py +32 -0
  630. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-3.py +32 -0
  631. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-4.py +26 -0
  632. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-5.py +30 -0
  633. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-6.py +32 -0
  634. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-7.py +28 -0
  635. angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-8.py +30 -0
  636. angr/procedures/definitions/win32_api-ms-win-core-path-l1-1-0.py +68 -0
  637. angr/procedures/definitions/win32_api-ms-win-core-psm-appnotify-l1-1-0.py +28 -0
  638. angr/procedures/definitions/win32_api-ms-win-core-psm-appnotify-l1-1-1.py +28 -0
  639. angr/procedures/definitions/win32_api-ms-win-core-realtime-l1-1-1.py +30 -0
  640. angr/procedures/definitions/win32_api-ms-win-core-realtime-l1-1-2.py +30 -0
  641. angr/procedures/definitions/win32_api-ms-win-core-slapi-l1-1-0.py +26 -0
  642. angr/procedures/definitions/win32_api-ms-win-core-state-helpers-l1-1-0.py +26 -0
  643. angr/procedures/definitions/win32_api-ms-win-core-synch-l1-2-0.py +30 -0
  644. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-0.py +26 -0
  645. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-3.py +28 -0
  646. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-4.py +28 -0
  647. angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-6.py +26 -0
  648. angr/procedures/definitions/win32_api-ms-win-core-util-l1-1-1.py +28 -0
  649. angr/procedures/definitions/win32_api-ms-win-core-winrt-error-l1-1-0.py +44 -0
  650. angr/procedures/definitions/win32_api-ms-win-core-winrt-error-l1-1-1.py +38 -0
  651. angr/procedures/definitions/win32_api-ms-win-core-winrt-l1-1-0.py +40 -0
  652. angr/procedures/definitions/win32_api-ms-win-core-winrt-registration-l1-1-0.py +24 -0
  653. angr/procedures/definitions/win32_api-ms-win-core-winrt-robuffer-l1-1-0.py +24 -0
  654. angr/procedures/definitions/win32_api-ms-win-core-winrt-roparameterizediid-l1-1-0.py +28 -0
  655. angr/procedures/definitions/win32_api-ms-win-core-winrt-string-l1-1-0.py +76 -0
  656. angr/procedures/definitions/win32_api-ms-win-core-winrt-string-l1-1-1.py +24 -0
  657. angr/procedures/definitions/win32_api-ms-win-core-wow64-l1-1-1.py +30 -0
  658. angr/procedures/definitions/win32_api-ms-win-devices-query-l1-1-0.py +42 -0
  659. angr/procedures/definitions/win32_api-ms-win-devices-query-l1-1-1.py +34 -0
  660. angr/procedures/definitions/win32_api-ms-win-dx-d3dkmt-l1-1-0.py +26 -0
  661. angr/procedures/definitions/win32_api-ms-win-gaming-deviceinformation-l1-1-0.py +26 -0
  662. angr/procedures/definitions/win32_api-ms-win-gaming-expandedresources-l1-1-0.py +30 -0
  663. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-0.py +38 -0
  664. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-1.py +28 -0
  665. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-2.py +38 -0
  666. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-3.py +28 -0
  667. angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-4.py +40 -0
  668. angr/procedures/definitions/win32_api-ms-win-mm-misc-l1-1-1.py +26 -0
  669. angr/procedures/definitions/win32_api-ms-win-net-isolation-l1-1-0.py +40 -0
  670. angr/procedures/definitions/win32_api-ms-win-security-base-l1-2-2.py +26 -0
  671. angr/procedures/definitions/win32_api-ms-win-security-isolatedcontainer-l1-1-0.py +26 -0
  672. angr/procedures/definitions/win32_api-ms-win-security-isolatedcontainer-l1-1-1.py +26 -0
  673. angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-3.py +26 -0
  674. angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-4.py +26 -0
  675. angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-5.py +28 -0
  676. angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-0.py +30 -0
  677. angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-1.py +36 -0
  678. angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-2.py +26 -0
  679. angr/procedures/definitions/win32_api-ms-win-shcore-stream-winrt-l1-1-0.py +28 -0
  680. angr/procedures/definitions/win32_api-ms-win-wsl-api-l1-1-0.py +38 -0
  681. angr/procedures/definitions/win32_apphelp.py +26 -0
  682. angr/procedures/definitions/win32_authz.py +90 -0
  683. angr/procedures/definitions/win32_avicap32.py +32 -0
  684. angr/procedures/definitions/win32_avifil32.py +144 -0
  685. angr/procedures/definitions/win32_avrt.py +52 -0
  686. angr/procedures/definitions/win32_bcp47mrm.py +28 -0
  687. angr/procedures/definitions/win32_bcrypt.py +130 -0
  688. angr/procedures/definitions/win32_bcryptprimitives.py +28 -0
  689. angr/procedures/definitions/win32_bluetoothapis.py +106 -0
  690. angr/procedures/definitions/win32_bthprops.py +34 -0
  691. angr/procedures/definitions/win32_bthprops_cpl.py +36 -0
  692. angr/procedures/definitions/win32_cabinet.py +68 -0
  693. angr/procedures/definitions/win32_certadm.py +60 -0
  694. angr/procedures/definitions/win32_certpoleng.py +40 -0
  695. angr/procedures/definitions/win32_cfgmgr32.py +502 -0
  696. angr/procedures/definitions/win32_chakra.py +198 -0
  697. angr/procedures/definitions/win32_cldapi.py +96 -0
  698. angr/procedures/definitions/win32_clfsw32.py +142 -0
  699. angr/procedures/definitions/win32_clusapi.py +584 -0
  700. angr/procedures/definitions/win32_comctl32.py +254 -0
  701. angr/procedures/definitions/win32_comdlg32.py +66 -0
  702. angr/procedures/definitions/win32_compstui.py +32 -0
  703. angr/procedures/definitions/win32_computecore.py +132 -0
  704. angr/procedures/definitions/win32_computenetwork.py +110 -0
  705. angr/procedures/definitions/win32_computestorage.py +48 -0
  706. angr/procedures/definitions/win32_comsvcs.py +38 -0
  707. angr/procedures/definitions/win32_coremessaging.py +24 -0
  708. angr/procedures/definitions/win32_credui.py +62 -0
  709. angr/procedures/definitions/win32_crypt32.py +482 -0
  710. angr/procedures/definitions/win32_cryptnet.py +34 -0
  711. angr/procedures/definitions/win32_cryptui.py +44 -0
  712. angr/procedures/definitions/win32_cryptxml.py +62 -0
  713. angr/procedures/definitions/win32_cscapi.py +32 -0
  714. angr/procedures/definitions/win32_d2d1.py +50 -0
  715. angr/procedures/definitions/win32_d3d10.py +78 -0
  716. angr/procedures/definitions/win32_d3d10_1.py +28 -0
  717. angr/procedures/definitions/win32_d3d11.py +30 -0
  718. angr/procedures/definitions/win32_d3d12.py +40 -0
  719. angr/procedures/definitions/win32_d3d9.py +46 -0
  720. angr/procedures/definitions/win32_d3dcompiler_47.py +76 -0
  721. angr/procedures/definitions/win32_d3dcsx.py +42 -0
  722. angr/procedures/definitions/win32_davclnt.py +60 -0
  723. angr/procedures/definitions/win32_dbgeng.py +32 -0
  724. angr/procedures/definitions/win32_dbghelp.py +462 -0
  725. angr/procedures/definitions/win32_dbgmodel.py +26 -0
  726. angr/procedures/definitions/win32_dciman32.py +64 -0
  727. angr/procedures/definitions/win32_dcomp.py +48 -0
  728. angr/procedures/definitions/win32_ddraw.py +38 -0
  729. angr/procedures/definitions/win32_deviceaccess.py +26 -0
  730. angr/procedures/definitions/win32_dflayout.py +26 -0
  731. angr/procedures/definitions/win32_dhcpcsvc.py +54 -0
  732. angr/procedures/definitions/win32_dhcpcsvc6.py +36 -0
  733. angr/procedures/definitions/win32_dhcpsapi.py +416 -0
  734. angr/procedures/definitions/win32_diagnosticdataquery.py +94 -0
  735. angr/procedures/definitions/win32_dinput8.py +26 -0
  736. angr/procedures/definitions/win32_directml.py +28 -0
  737. angr/procedures/definitions/win32_dmprocessxmlfiltered.py +26 -0
  738. angr/procedures/definitions/win32_dnsapi.py +152 -0
  739. angr/procedures/definitions/win32_drt.py +56 -0
  740. angr/procedures/definitions/win32_drtprov.py +42 -0
  741. angr/procedures/definitions/win32_drttransport.py +28 -0
  742. angr/procedures/definitions/win32_dsound.py +44 -0
  743. angr/procedures/definitions/win32_dsparse.py +62 -0
  744. angr/procedures/definitions/win32_dsprop.py +38 -0
  745. angr/procedures/definitions/win32_dssec.py +32 -0
  746. angr/procedures/definitions/win32_dsuiext.py +32 -0
  747. angr/procedures/definitions/win32_dwmapi.py +86 -0
  748. angr/procedures/definitions/win32_dwrite.py +26 -0
  749. angr/procedures/definitions/win32_dxcompiler.py +28 -0
  750. angr/procedures/definitions/win32_dxcore.py +26 -0
  751. angr/procedures/definitions/win32_dxgi.py +36 -0
  752. angr/procedures/definitions/win32_dxva2.py +100 -0
  753. angr/procedures/definitions/win32_eappcfg.py +52 -0
  754. angr/procedures/definitions/win32_eappprxy.py +60 -0
  755. angr/procedures/definitions/win32_efswrt.py +28 -0
  756. angr/procedures/definitions/win32_elscore.py +34 -0
  757. angr/procedures/definitions/win32_esent.py +482 -0
  758. angr/procedures/definitions/win32_evr.py +38 -0
  759. angr/procedures/definitions/win32_faultrep.py +32 -0
  760. angr/procedures/definitions/win32_fhsvcctl.py +38 -0
  761. angr/procedures/definitions/win32_firewallapi.py +30 -0
  762. angr/procedures/definitions/win32_fltlib.py +80 -0
  763. angr/procedures/definitions/win32_fontsub.py +28 -0
  764. angr/procedures/definitions/win32_forceinline.py +30 -0
  765. angr/procedures/definitions/win32_fwpuclnt.py +408 -0
  766. angr/procedures/definitions/win32_fxsutility.py +28 -0
  767. angr/procedures/definitions/win32_gdi32.py +886 -0
  768. angr/procedures/definitions/win32_gdiplus.py +1282 -0
  769. angr/procedures/definitions/win32_glu32.py +128 -0
  770. angr/procedures/definitions/win32_gpedit.py +36 -0
  771. angr/procedures/definitions/win32_hhctrl_ocx.py +28 -0
  772. angr/procedures/definitions/win32_hid.py +114 -0
  773. angr/procedures/definitions/win32_hlink.py +80 -0
  774. angr/procedures/definitions/win32_hrtfapo.py +26 -0
  775. angr/procedures/definitions/win32_httpapi.py +110 -0
  776. angr/procedures/definitions/win32_icm32.py +66 -0
  777. angr/procedures/definitions/win32_icmui.py +28 -0
  778. angr/procedures/definitions/win32_icu.py +2074 -0
  779. angr/procedures/definitions/win32_ieframe.py +82 -0
  780. angr/procedures/definitions/win32_imagehlp.py +76 -0
  781. angr/procedures/definitions/win32_imgutil.py +42 -0
  782. angr/procedures/definitions/win32_imm32.py +188 -0
  783. angr/procedures/definitions/win32_infocardapi.py +58 -0
  784. angr/procedures/definitions/win32_inkobjcore.py +78 -0
  785. angr/procedures/definitions/win32_iphlpapi.py +426 -0
  786. angr/procedures/definitions/win32_iscsidsc.py +182 -0
  787. angr/procedures/definitions/win32_isolatedwindowsenvironmentutils.py +28 -0
  788. angr/procedures/definitions/win32_kernel32.py +3185 -0
  789. angr/procedures/definitions/win32_kernelbase.py +36 -0
  790. angr/procedures/definitions/win32_keycredmgr.py +32 -0
  791. angr/procedures/definitions/win32_ksproxy_ax.py +36 -0
  792. angr/procedures/definitions/win32_ksuser.py +40 -0
  793. angr/procedures/definitions/win32_ktmw32.py +102 -0
  794. angr/procedures/definitions/win32_licenseprotection.py +28 -0
  795. angr/procedures/definitions/win32_loadperf.py +48 -0
  796. angr/procedures/definitions/win32_magnification.py +62 -0
  797. angr/procedures/definitions/win32_mapi32.py +156 -0
  798. angr/procedures/definitions/win32_mdmlocalmanagement.py +30 -0
  799. angr/procedures/definitions/win32_mdmregistration.py +54 -0
  800. angr/procedures/definitions/win32_mf.py +148 -0
  801. angr/procedures/definitions/win32_mfcore.py +28 -0
  802. angr/procedures/definitions/win32_mfplat.py +314 -0
  803. angr/procedures/definitions/win32_mfplay.py +26 -0
  804. angr/procedures/definitions/win32_mfreadwrite.py +34 -0
  805. angr/procedures/definitions/win32_mfsensorgroup.py +44 -0
  806. angr/procedures/definitions/win32_mfsrcsnk.py +28 -0
  807. angr/procedures/definitions/win32_mgmtapi.py +42 -0
  808. angr/procedures/definitions/win32_mi.py +26 -0
  809. angr/procedures/definitions/win32_mmdevapi.py +26 -0
  810. angr/procedures/definitions/win32_mpr.py +118 -0
  811. angr/procedures/definitions/win32_mprapi.py +248 -0
  812. angr/procedures/definitions/win32_mqrt.py +92 -0
  813. angr/procedures/definitions/win32_mrmsupport.py +78 -0
  814. angr/procedures/definitions/win32_msacm32.py +108 -0
  815. angr/procedures/definitions/win32_msajapi.py +1118 -0
  816. angr/procedures/definitions/win32_mscms.py +182 -0
  817. angr/procedures/definitions/win32_mscoree.py +78 -0
  818. angr/procedures/definitions/win32_msctfmonitor.py +30 -0
  819. angr/procedures/definitions/win32_msdelta.py +56 -0
  820. angr/procedures/definitions/win32_msdmo.py +46 -0
  821. angr/procedures/definitions/win32_msdrm.py +192 -0
  822. angr/procedures/definitions/win32_msi.py +552 -0
  823. angr/procedures/definitions/win32_msimg32.py +30 -0
  824. angr/procedures/definitions/win32_mspatcha.py +56 -0
  825. angr/procedures/definitions/win32_mspatchc.py +42 -0
  826. angr/procedures/definitions/win32_msports.py +38 -0
  827. angr/procedures/definitions/win32_msrating.py +62 -0
  828. angr/procedures/definitions/win32_mssign32.py +44 -0
  829. angr/procedures/definitions/win32_mstask.py +28 -0
  830. angr/procedures/definitions/win32_msvfw32.py +110 -0
  831. angr/procedures/definitions/win32_mswsock.py +56 -0
  832. angr/procedures/definitions/win32_mtxdm.py +26 -0
  833. angr/procedures/definitions/win32_ncrypt.py +102 -0
  834. angr/procedures/definitions/win32_ndfapi.py +56 -0
  835. angr/procedures/definitions/win32_netapi32.py +436 -0
  836. angr/procedures/definitions/win32_netsh.py +40 -0
  837. angr/procedures/definitions/win32_netshell.py +28 -0
  838. angr/procedures/definitions/win32_newdev.py +46 -0
  839. angr/procedures/definitions/win32_ninput.py +84 -0
  840. angr/procedures/definitions/win32_normaliz.py +28 -0
  841. angr/procedures/definitions/win32_ntdll.py +171 -0
  842. angr/procedures/definitions/win32_ntdllk.py +26 -0
  843. angr/procedures/definitions/win32_ntdsapi.py +186 -0
  844. angr/procedures/definitions/win32_ntlanman.py +44 -0
  845. angr/procedures/definitions/win32_odbc32.py +392 -0
  846. angr/procedures/definitions/win32_odbcbcp.py +78 -0
  847. angr/procedures/definitions/win32_ole32.py +658 -0
  848. angr/procedures/definitions/win32_oleacc.py +58 -0
  849. angr/procedures/definitions/win32_oleaut32.py +834 -0
  850. angr/procedures/definitions/win32_oledlg.py +70 -0
  851. angr/procedures/definitions/win32_ondemandconnroutehelper.py +34 -0
  852. angr/procedures/definitions/win32_opengl32.py +734 -0
  853. angr/procedures/definitions/win32_opmxbox.py +30 -0
  854. angr/procedures/definitions/win32_p2p.py +240 -0
  855. angr/procedures/definitions/win32_p2pgraph.py +98 -0
  856. angr/procedures/definitions/win32_pdh.py +220 -0
  857. angr/procedures/definitions/win32_peerdist.py +80 -0
  858. angr/procedures/definitions/win32_powrprof.py +192 -0
  859. angr/procedures/definitions/win32_prntvpt.py +46 -0
  860. angr/procedures/definitions/win32_projectedfslib.py +62 -0
  861. angr/procedures/definitions/win32_propsys.py +460 -0
  862. angr/procedures/definitions/win32_psapi.py +78 -0
  863. angr/procedures/definitions/win32_quartz.py +28 -0
  864. angr/procedures/definitions/win32_query.py +32 -0
  865. angr/procedures/definitions/win32_qwave.py +46 -0
  866. angr/procedures/definitions/win32_rasapi32.py +192 -0
  867. angr/procedures/definitions/win32_rasdlg.py +36 -0
  868. angr/procedures/definitions/win32_resutils.py +264 -0
  869. angr/procedures/definitions/win32_rometadata.py +24 -0
  870. angr/procedures/definitions/win32_rpcns4.py +146 -0
  871. angr/procedures/definitions/win32_rpcproxy.py +32 -0
  872. angr/procedures/definitions/win32_rpcrt4.py +918 -0
  873. angr/procedures/definitions/win32_rstrtmgr.py +46 -0
  874. angr/procedures/definitions/win32_rtm.py +176 -0
  875. angr/procedures/definitions/win32_rtutils.py +106 -0
  876. angr/procedures/definitions/win32_rtworkq.py +90 -0
  877. angr/procedures/definitions/win32_sas.py +26 -0
  878. angr/procedures/definitions/win32_scarddlg.py +34 -0
  879. angr/procedures/definitions/win32_schannel.py +42 -0
  880. angr/procedures/definitions/win32_sechost.py +28 -0
  881. angr/procedures/definitions/win32_secur32.py +202 -0
  882. angr/procedures/definitions/win32_sensapi.py +30 -0
  883. angr/procedures/definitions/win32_sensorsutilsv2.py +104 -0
  884. angr/procedures/definitions/win32_setupapi.py +692 -0
  885. angr/procedures/definitions/win32_sfc.py +36 -0
  886. angr/procedures/definitions/win32_shdocvw.py +30 -0
  887. angr/procedures/definitions/win32_shell32.py +512 -0
  888. angr/procedures/definitions/win32_shlwapi.py +744 -0
  889. angr/procedures/definitions/win32_slc.py +88 -0
  890. angr/procedures/definitions/win32_slcext.py +32 -0
  891. angr/procedures/definitions/win32_slwga.py +26 -0
  892. angr/procedures/definitions/win32_snmpapi.py +76 -0
  893. angr/procedures/definitions/win32_spoolss.py +76 -0
  894. angr/procedures/definitions/win32_srclient.py +26 -0
  895. angr/procedures/definitions/win32_srpapi.py +46 -0
  896. angr/procedures/definitions/win32_sspicli.py +38 -0
  897. angr/procedures/definitions/win32_sti.py +26 -0
  898. angr/procedures/definitions/win32_t2embed.py +52 -0
  899. angr/procedures/definitions/win32_tapi32.py +522 -0
  900. angr/procedures/definitions/win32_tbs.py +52 -0
  901. angr/procedures/definitions/win32_tdh.py +78 -0
  902. angr/procedures/definitions/win32_tokenbinding.py +44 -0
  903. angr/procedures/definitions/win32_traffic.py +64 -0
  904. angr/procedures/definitions/win32_txfw32.py +42 -0
  905. angr/procedures/definitions/win32_ualapi.py +32 -0
  906. angr/procedures/definitions/win32_uiautomationcore.py +220 -0
  907. angr/procedures/definitions/win32_urlmon.py +178 -0
  908. angr/procedures/definitions/win32_user32.py +1551 -0
  909. angr/procedures/definitions/win32_userenv.py +112 -0
  910. angr/procedures/definitions/win32_usp10.py +104 -0
  911. angr/procedures/definitions/win32_uxtheme.py +178 -0
  912. angr/procedures/definitions/win32_verifier.py +26 -0
  913. angr/procedures/definitions/win32_version.py +52 -0
  914. angr/procedures/definitions/win32_vertdll.py +38 -0
  915. angr/procedures/definitions/win32_virtdisk.py +82 -0
  916. angr/procedures/definitions/win32_vmdevicehost.py +50 -0
  917. angr/procedures/definitions/win32_vmsavedstatedumpprovider.py +110 -0
  918. angr/procedures/definitions/win32_vssapi.py +26 -0
  919. angr/procedures/definitions/win32_wcmapi.py +34 -0
  920. angr/procedures/definitions/win32_wdsbp.py +38 -0
  921. angr/procedures/definitions/win32_wdsclientapi.py +98 -0
  922. angr/procedures/definitions/win32_wdsmc.py +36 -0
  923. angr/procedures/definitions/win32_wdspxe.py +86 -0
  924. angr/procedures/definitions/win32_wdstptc.py +50 -0
  925. angr/procedures/definitions/win32_webauthn.py +50 -0
  926. angr/procedures/definitions/win32_webservices.py +410 -0
  927. angr/procedures/definitions/win32_websocket.py +50 -0
  928. angr/procedures/definitions/win32_wecapi.py +54 -0
  929. angr/procedures/definitions/win32_wer.py +66 -0
  930. angr/procedures/definitions/win32_wevtapi.py +94 -0
  931. angr/procedures/definitions/win32_winbio.py +132 -0
  932. angr/procedures/definitions/win32_windows_ai_machinelearning.py +26 -0
  933. angr/procedures/definitions/win32_windows_data_pdf.py +24 -0
  934. angr/procedures/definitions/win32_windows_media_mediacontrol.py +40 -0
  935. angr/procedures/definitions/win32_windows_networking.py +26 -0
  936. angr/procedures/definitions/win32_windows_ui_xaml.py +28 -0
  937. angr/procedures/definitions/win32_windowscodecs.py +42 -0
  938. angr/procedures/definitions/win32_winfax.py +136 -0
  939. angr/procedures/definitions/win32_winhttp.py +136 -0
  940. angr/procedures/definitions/win32_winhvemulation.py +32 -0
  941. angr/procedures/definitions/win32_winhvplatform.py +156 -0
  942. angr/procedures/definitions/win32_wininet.py +616 -0
  943. angr/procedures/definitions/win32_winml.py +26 -0
  944. angr/procedures/definitions/win32_winmm.py +376 -0
  945. angr/procedures/definitions/win32_winscard.py +164 -0
  946. angr/procedures/definitions/win32_winspool.py +364 -0
  947. angr/procedures/definitions/win32_winspool_drv.py +368 -0
  948. angr/procedures/definitions/win32_wintrust.py +144 -0
  949. angr/procedures/definitions/win32_winusb.py +92 -0
  950. angr/procedures/definitions/win32_wlanapi.py +144 -0
  951. angr/procedures/definitions/win32_wlanui.py +26 -0
  952. angr/procedures/definitions/win32_wldap32.py +510 -0
  953. angr/procedures/definitions/win32_wldp.py +42 -0
  954. angr/procedures/definitions/win32_wmvcore.py +46 -0
  955. angr/procedures/definitions/win32_wnvapi.py +28 -0
  956. angr/procedures/definitions/win32_wofutil.py +46 -0
  957. angr/procedures/definitions/win32_ws2_32.py +344 -0
  958. angr/procedures/definitions/win32_wscapi.py +36 -0
  959. angr/procedures/definitions/win32_wsclient.py +30 -0
  960. angr/procedures/definitions/win32_wsdapi.py +88 -0
  961. angr/procedures/definitions/win32_wsmsvc.py +90 -0
  962. angr/procedures/definitions/win32_wsnmp32.py +122 -0
  963. angr/procedures/definitions/win32_wtsapi32.py +150 -0
  964. angr/procedures/definitions/win32_xaudio2_8.py +32 -0
  965. angr/procedures/definitions/win32_xinput1_4.py +38 -0
  966. angr/procedures/definitions/win32_xinputuap.py +36 -0
  967. angr/procedures/definitions/win32_xmllite.py +36 -0
  968. angr/procedures/definitions/win32_xolehlp.py +32 -0
  969. angr/procedures/definitions/win32_xpsprint.py +28 -0
  970. angr/procedures/glibc/__ctype_b_loc.py +21 -0
  971. angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
  972. angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
  973. angr/procedures/glibc/__errno_location.py +7 -0
  974. angr/procedures/glibc/__init__.py +3 -0
  975. angr/procedures/glibc/__libc_init.py +37 -0
  976. angr/procedures/glibc/__libc_start_main.py +301 -0
  977. angr/procedures/glibc/dynamic_loading.py +20 -0
  978. angr/procedures/glibc/scanf.py +11 -0
  979. angr/procedures/glibc/sscanf.py +6 -0
  980. angr/procedures/gnulib/__init__.py +3 -0
  981. angr/procedures/gnulib/xalloc_die.py +14 -0
  982. angr/procedures/gnulib/xstrtol_fatal.py +14 -0
  983. angr/procedures/java/__init__.py +42 -0
  984. angr/procedures/java/unconstrained.py +65 -0
  985. angr/procedures/java_io/__init__.py +0 -0
  986. angr/procedures/java_io/read.py +12 -0
  987. angr/procedures/java_io/write.py +17 -0
  988. angr/procedures/java_jni/__init__.py +482 -0
  989. angr/procedures/java_jni/array_operations.py +312 -0
  990. angr/procedures/java_jni/class_and_interface_operations.py +31 -0
  991. angr/procedures/java_jni/field_access.py +173 -0
  992. angr/procedures/java_jni/global_and_local_refs.py +57 -0
  993. angr/procedures/java_jni/method_calls.py +365 -0
  994. angr/procedures/java_jni/not_implemented.py +26 -0
  995. angr/procedures/java_jni/object_operations.py +94 -0
  996. angr/procedures/java_jni/string_operations.py +87 -0
  997. angr/procedures/java_jni/version_information.py +12 -0
  998. angr/procedures/java_lang/__init__.py +0 -0
  999. angr/procedures/java_lang/character.py +30 -0
  1000. angr/procedures/java_lang/double.py +24 -0
  1001. angr/procedures/java_lang/exit.py +13 -0
  1002. angr/procedures/java_lang/getsimplename.py +18 -0
  1003. angr/procedures/java_lang/integer.py +43 -0
  1004. angr/procedures/java_lang/load_library.py +9 -0
  1005. angr/procedures/java_lang/math.py +15 -0
  1006. angr/procedures/java_lang/string.py +78 -0
  1007. angr/procedures/java_lang/stringbuilder.py +44 -0
  1008. angr/procedures/java_lang/system.py +18 -0
  1009. angr/procedures/java_util/__init__.py +0 -0
  1010. angr/procedures/java_util/collection.py +35 -0
  1011. angr/procedures/java_util/iterator.py +46 -0
  1012. angr/procedures/java_util/list.py +99 -0
  1013. angr/procedures/java_util/map.py +131 -0
  1014. angr/procedures/java_util/random.py +14 -0
  1015. angr/procedures/java_util/scanner_nextline.py +23 -0
  1016. angr/procedures/libc/__init__.py +3 -0
  1017. angr/procedures/libc/abort.py +9 -0
  1018. angr/procedures/libc/access.py +13 -0
  1019. angr/procedures/libc/atoi.py +14 -0
  1020. angr/procedures/libc/atol.py +13 -0
  1021. angr/procedures/libc/calloc.py +8 -0
  1022. angr/procedures/libc/closelog.py +10 -0
  1023. angr/procedures/libc/err.py +14 -0
  1024. angr/procedures/libc/error.py +54 -0
  1025. angr/procedures/libc/exit.py +11 -0
  1026. angr/procedures/libc/fclose.py +19 -0
  1027. angr/procedures/libc/feof.py +21 -0
  1028. angr/procedures/libc/fflush.py +16 -0
  1029. angr/procedures/libc/fgetc.py +27 -0
  1030. angr/procedures/libc/fgets.py +68 -0
  1031. angr/procedures/libc/fopen.py +63 -0
  1032. angr/procedures/libc/fprintf.py +25 -0
  1033. angr/procedures/libc/fputc.py +23 -0
  1034. angr/procedures/libc/fputs.py +24 -0
  1035. angr/procedures/libc/fread.py +24 -0
  1036. angr/procedures/libc/free.py +9 -0
  1037. angr/procedures/libc/fscanf.py +20 -0
  1038. angr/procedures/libc/fseek.py +34 -0
  1039. angr/procedures/libc/ftell.py +22 -0
  1040. angr/procedures/libc/fwrite.py +19 -0
  1041. angr/procedures/libc/getchar.py +13 -0
  1042. angr/procedures/libc/getdelim.py +99 -0
  1043. angr/procedures/libc/getegid.py +8 -0
  1044. angr/procedures/libc/geteuid.py +8 -0
  1045. angr/procedures/libc/getgid.py +8 -0
  1046. angr/procedures/libc/gets.py +68 -0
  1047. angr/procedures/libc/getuid.py +8 -0
  1048. angr/procedures/libc/malloc.py +12 -0
  1049. angr/procedures/libc/memcmp.py +69 -0
  1050. angr/procedures/libc/memcpy.py +38 -0
  1051. angr/procedures/libc/memset.py +72 -0
  1052. angr/procedures/libc/openlog.py +10 -0
  1053. angr/procedures/libc/perror.py +13 -0
  1054. angr/procedures/libc/printf.py +34 -0
  1055. angr/procedures/libc/putchar.py +13 -0
  1056. angr/procedures/libc/puts.py +19 -0
  1057. angr/procedures/libc/rand.py +8 -0
  1058. angr/procedures/libc/realloc.py +8 -0
  1059. angr/procedures/libc/rewind.py +12 -0
  1060. angr/procedures/libc/scanf.py +20 -0
  1061. angr/procedures/libc/setbuf.py +9 -0
  1062. angr/procedures/libc/setvbuf.py +7 -0
  1063. angr/procedures/libc/snprintf.py +36 -0
  1064. angr/procedures/libc/sprintf.py +25 -0
  1065. angr/procedures/libc/srand.py +7 -0
  1066. angr/procedures/libc/sscanf.py +13 -0
  1067. angr/procedures/libc/stpcpy.py +18 -0
  1068. angr/procedures/libc/strcat.py +14 -0
  1069. angr/procedures/libc/strchr.py +48 -0
  1070. angr/procedures/libc/strcmp.py +31 -0
  1071. angr/procedures/libc/strcpy.py +13 -0
  1072. angr/procedures/libc/strlen.py +114 -0
  1073. angr/procedures/libc/strncat.py +19 -0
  1074. angr/procedures/libc/strncmp.py +183 -0
  1075. angr/procedures/libc/strncpy.py +22 -0
  1076. angr/procedures/libc/strnlen.py +13 -0
  1077. angr/procedures/libc/strstr.py +101 -0
  1078. angr/procedures/libc/strtol.py +261 -0
  1079. angr/procedures/libc/strtoul.py +9 -0
  1080. angr/procedures/libc/system.py +13 -0
  1081. angr/procedures/libc/time.py +9 -0
  1082. angr/procedures/libc/tmpnam.py +20 -0
  1083. angr/procedures/libc/tolower.py +10 -0
  1084. angr/procedures/libc/toupper.py +10 -0
  1085. angr/procedures/libc/ungetc.py +20 -0
  1086. angr/procedures/libc/vsnprintf.py +17 -0
  1087. angr/procedures/libc/wchar.py +16 -0
  1088. angr/procedures/libstdcpp/__init__.py +0 -0
  1089. angr/procedures/libstdcpp/_unwind_resume.py +11 -0
  1090. angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
  1091. angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
  1092. angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
  1093. angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
  1094. angr/procedures/libstdcpp/std__terminate.py +13 -0
  1095. angr/procedures/linux_kernel/__init__.py +3 -0
  1096. angr/procedures/linux_kernel/access.py +18 -0
  1097. angr/procedures/linux_kernel/arch_prctl.py +34 -0
  1098. angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
  1099. angr/procedures/linux_kernel/brk.py +18 -0
  1100. angr/procedures/linux_kernel/cwd.py +28 -0
  1101. angr/procedures/linux_kernel/fstat.py +138 -0
  1102. angr/procedures/linux_kernel/fstat64.py +170 -0
  1103. angr/procedures/linux_kernel/futex.py +17 -0
  1104. angr/procedures/linux_kernel/getegid.py +17 -0
  1105. angr/procedures/linux_kernel/geteuid.py +17 -0
  1106. angr/procedures/linux_kernel/getgid.py +17 -0
  1107. angr/procedures/linux_kernel/getpid.py +14 -0
  1108. angr/procedures/linux_kernel/getrlimit.py +24 -0
  1109. angr/procedures/linux_kernel/gettid.py +9 -0
  1110. angr/procedures/linux_kernel/getuid.py +17 -0
  1111. angr/procedures/linux_kernel/iovec.py +47 -0
  1112. angr/procedures/linux_kernel/lseek.py +42 -0
  1113. angr/procedures/linux_kernel/mmap.py +16 -0
  1114. angr/procedures/linux_kernel/mprotect.py +42 -0
  1115. angr/procedures/linux_kernel/munmap.py +8 -0
  1116. angr/procedures/linux_kernel/openat.py +26 -0
  1117. angr/procedures/linux_kernel/set_tid_address.py +8 -0
  1118. angr/procedures/linux_kernel/sigaction.py +19 -0
  1119. angr/procedures/linux_kernel/sigprocmask.py +23 -0
  1120. angr/procedures/linux_kernel/stat.py +23 -0
  1121. angr/procedures/linux_kernel/sysinfo.py +59 -0
  1122. angr/procedures/linux_kernel/tgkill.py +10 -0
  1123. angr/procedures/linux_kernel/time.py +34 -0
  1124. angr/procedures/linux_kernel/uid.py +30 -0
  1125. angr/procedures/linux_kernel/uname.py +29 -0
  1126. angr/procedures/linux_kernel/unlink.py +22 -0
  1127. angr/procedures/linux_kernel/vsyscall.py +16 -0
  1128. angr/procedures/linux_loader/__init__.py +3 -0
  1129. angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
  1130. angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
  1131. angr/procedures/linux_loader/sim_loader.py +54 -0
  1132. angr/procedures/linux_loader/tls.py +40 -0
  1133. angr/procedures/msvcr/__getmainargs.py +16 -0
  1134. angr/procedures/msvcr/__init__.py +4 -0
  1135. angr/procedures/msvcr/_initterm.py +38 -0
  1136. angr/procedures/msvcr/fmode.py +31 -0
  1137. angr/procedures/ntdll/__init__.py +0 -0
  1138. angr/procedures/ntdll/exceptions.py +60 -0
  1139. angr/procedures/posix/__init__.py +3 -0
  1140. angr/procedures/posix/accept.py +29 -0
  1141. angr/procedures/posix/bind.py +13 -0
  1142. angr/procedures/posix/bzero.py +9 -0
  1143. angr/procedures/posix/chroot.py +27 -0
  1144. angr/procedures/posix/close.py +9 -0
  1145. angr/procedures/posix/closedir.py +7 -0
  1146. angr/procedures/posix/dup.py +56 -0
  1147. angr/procedures/posix/fcntl.py +10 -0
  1148. angr/procedures/posix/fdopen.py +76 -0
  1149. angr/procedures/posix/fileno.py +18 -0
  1150. angr/procedures/posix/fork.py +13 -0
  1151. angr/procedures/posix/getenv.py +35 -0
  1152. angr/procedures/posix/gethostbyname.py +43 -0
  1153. angr/procedures/posix/getpass.py +19 -0
  1154. angr/procedures/posix/getsockopt.py +11 -0
  1155. angr/procedures/posix/htonl.py +11 -0
  1156. angr/procedures/posix/htons.py +11 -0
  1157. angr/procedures/posix/inet_ntoa.py +59 -0
  1158. angr/procedures/posix/listen.py +13 -0
  1159. angr/procedures/posix/mmap.py +144 -0
  1160. angr/procedures/posix/open.py +18 -0
  1161. angr/procedures/posix/opendir.py +10 -0
  1162. angr/procedures/posix/poll.py +55 -0
  1163. angr/procedures/posix/pread64.py +46 -0
  1164. angr/procedures/posix/pthread.py +87 -0
  1165. angr/procedures/posix/pwrite64.py +46 -0
  1166. angr/procedures/posix/read.py +13 -0
  1167. angr/procedures/posix/readdir.py +62 -0
  1168. angr/procedures/posix/recv.py +13 -0
  1169. angr/procedures/posix/recvfrom.py +13 -0
  1170. angr/procedures/posix/select.py +48 -0
  1171. angr/procedures/posix/send.py +23 -0
  1172. angr/procedures/posix/setsockopt.py +9 -0
  1173. angr/procedures/posix/sigaction.py +23 -0
  1174. angr/procedures/posix/sim_time.py +48 -0
  1175. angr/procedures/posix/sleep.py +8 -0
  1176. angr/procedures/posix/socket.py +18 -0
  1177. angr/procedures/posix/strcasecmp.py +26 -0
  1178. angr/procedures/posix/strdup.py +18 -0
  1179. angr/procedures/posix/strtok_r.py +64 -0
  1180. angr/procedures/posix/syslog.py +15 -0
  1181. angr/procedures/posix/tz.py +9 -0
  1182. angr/procedures/posix/unlink.py +11 -0
  1183. angr/procedures/posix/usleep.py +8 -0
  1184. angr/procedures/posix/write.py +13 -0
  1185. angr/procedures/procedure_dict.py +50 -0
  1186. angr/procedures/stubs/CallReturn.py +13 -0
  1187. angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
  1188. angr/procedures/stubs/Nop.py +7 -0
  1189. angr/procedures/stubs/PathTerminator.py +9 -0
  1190. angr/procedures/stubs/Redirect.py +18 -0
  1191. angr/procedures/stubs/ReturnChar.py +11 -0
  1192. angr/procedures/stubs/ReturnUnconstrained.py +24 -0
  1193. angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
  1194. angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
  1195. angr/procedures/stubs/UserHook.py +18 -0
  1196. angr/procedures/stubs/__init__.py +3 -0
  1197. angr/procedures/stubs/b64_decode.py +15 -0
  1198. angr/procedures/stubs/caller.py +14 -0
  1199. angr/procedures/stubs/crazy_scanf.py +20 -0
  1200. angr/procedures/stubs/format_parser.py +669 -0
  1201. angr/procedures/stubs/syscall_stub.py +24 -0
  1202. angr/procedures/testing/__init__.py +3 -0
  1203. angr/procedures/testing/manyargs.py +9 -0
  1204. angr/procedures/testing/retreg.py +8 -0
  1205. angr/procedures/tracer/__init__.py +4 -0
  1206. angr/procedures/tracer/random.py +9 -0
  1207. angr/procedures/tracer/receive.py +23 -0
  1208. angr/procedures/tracer/transmit.py +26 -0
  1209. angr/procedures/uclibc/__init__.py +3 -0
  1210. angr/procedures/uclibc/__uClibc_main.py +10 -0
  1211. angr/procedures/win32/EncodePointer.py +7 -0
  1212. angr/procedures/win32/ExitProcess.py +9 -0
  1213. angr/procedures/win32/GetCommandLine.py +12 -0
  1214. angr/procedures/win32/GetCurrentProcessId.py +7 -0
  1215. angr/procedures/win32/GetCurrentThreadId.py +7 -0
  1216. angr/procedures/win32/GetLastInputInfo.py +40 -0
  1217. angr/procedures/win32/GetModuleHandle.py +29 -0
  1218. angr/procedures/win32/GetProcessAffinityMask.py +37 -0
  1219. angr/procedures/win32/InterlockedExchange.py +15 -0
  1220. angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
  1221. angr/procedures/win32/VirtualAlloc.py +114 -0
  1222. angr/procedures/win32/VirtualProtect.py +60 -0
  1223. angr/procedures/win32/__init__.py +3 -0
  1224. angr/procedures/win32/critical_section.py +12 -0
  1225. angr/procedures/win32/dynamic_loading.py +104 -0
  1226. angr/procedures/win32/file_handles.py +47 -0
  1227. angr/procedures/win32/gethostbyname.py +12 -0
  1228. angr/procedures/win32/heap.py +45 -0
  1229. angr/procedures/win32/is_bad_ptr.py +26 -0
  1230. angr/procedures/win32/local_storage.py +88 -0
  1231. angr/procedures/win32/mutex.py +11 -0
  1232. angr/procedures/win32/sim_time.py +135 -0
  1233. angr/procedures/win32/system_paths.py +35 -0
  1234. angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
  1235. angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
  1236. angr/procedures/win32_kernel/__fastfail.py +15 -0
  1237. angr/procedures/win32_kernel/__init__.py +3 -0
  1238. angr/procedures/win_user32/__init__.py +0 -0
  1239. angr/procedures/win_user32/chars.py +15 -0
  1240. angr/procedures/win_user32/keyboard.py +14 -0
  1241. angr/procedures/win_user32/messagebox.py +49 -0
  1242. angr/project.py +837 -0
  1243. angr/protos/__init__.py +19 -0
  1244. angr/protos/cfg_pb2.py +31 -0
  1245. angr/protos/function_pb2.py +27 -0
  1246. angr/protos/primitives_pb2.py +52 -0
  1247. angr/protos/variables_pb2.py +44 -0
  1248. angr/protos/xrefs_pb2.py +25 -0
  1249. angr/py.typed +1 -0
  1250. angr/rustylib.cpython-310-darwin.so +0 -0
  1251. angr/rustylib.pyi +165 -0
  1252. angr/serializable.py +66 -0
  1253. angr/sim_manager.py +971 -0
  1254. angr/sim_options.py +438 -0
  1255. angr/sim_procedure.py +606 -0
  1256. angr/sim_state.py +901 -0
  1257. angr/sim_state_options.py +403 -0
  1258. angr/sim_type.py +3679 -0
  1259. angr/sim_variable.py +434 -0
  1260. angr/simos/__init__.py +47 -0
  1261. angr/simos/cgc.py +153 -0
  1262. angr/simos/javavm.py +458 -0
  1263. angr/simos/linux.py +509 -0
  1264. angr/simos/simos.py +444 -0
  1265. angr/simos/snimmuc_nxp.py +149 -0
  1266. angr/simos/userland.py +163 -0
  1267. angr/simos/windows.py +601 -0
  1268. angr/simos/xbox.py +32 -0
  1269. angr/slicer.py +352 -0
  1270. angr/state_hierarchy.py +262 -0
  1271. angr/state_plugins/__init__.py +84 -0
  1272. angr/state_plugins/callstack.py +398 -0
  1273. angr/state_plugins/cgc.py +155 -0
  1274. angr/state_plugins/debug_variables.py +192 -0
  1275. angr/state_plugins/filesystem.py +463 -0
  1276. angr/state_plugins/gdb.py +148 -0
  1277. angr/state_plugins/globals.py +65 -0
  1278. angr/state_plugins/heap/__init__.py +15 -0
  1279. angr/state_plugins/heap/heap_base.py +128 -0
  1280. angr/state_plugins/heap/heap_brk.py +136 -0
  1281. angr/state_plugins/heap/heap_freelist.py +213 -0
  1282. angr/state_plugins/heap/heap_libc.py +46 -0
  1283. angr/state_plugins/heap/heap_ptmalloc.py +620 -0
  1284. angr/state_plugins/heap/utils.py +22 -0
  1285. angr/state_plugins/history.py +548 -0
  1286. angr/state_plugins/inspect.py +375 -0
  1287. angr/state_plugins/javavm_classloader.py +134 -0
  1288. angr/state_plugins/jni_references.py +95 -0
  1289. angr/state_plugins/libc.py +1263 -0
  1290. angr/state_plugins/light_registers.py +168 -0
  1291. angr/state_plugins/log.py +84 -0
  1292. angr/state_plugins/loop_data.py +92 -0
  1293. angr/state_plugins/plugin.py +170 -0
  1294. angr/state_plugins/posix.py +703 -0
  1295. angr/state_plugins/preconstrainer.py +196 -0
  1296. angr/state_plugins/scratch.py +173 -0
  1297. angr/state_plugins/sim_action.py +326 -0
  1298. angr/state_plugins/sim_action_object.py +271 -0
  1299. angr/state_plugins/sim_event.py +59 -0
  1300. angr/state_plugins/solver.py +1127 -0
  1301. angr/state_plugins/symbolizer.py +291 -0
  1302. angr/state_plugins/trace_additions.py +738 -0
  1303. angr/state_plugins/uc_manager.py +94 -0
  1304. angr/state_plugins/unicorn_engine.py +1886 -0
  1305. angr/state_plugins/view.py +340 -0
  1306. angr/storage/__init__.py +15 -0
  1307. angr/storage/file.py +1210 -0
  1308. angr/storage/memory_mixins/__init__.py +317 -0
  1309. angr/storage/memory_mixins/actions_mixin.py +72 -0
  1310. angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
  1311. angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
  1312. angr/storage/memory_mixins/clouseau_mixin.py +137 -0
  1313. angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
  1314. angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
  1315. angr/storage/memory_mixins/default_filler_mixin.py +144 -0
  1316. angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
  1317. angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
  1318. angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
  1319. angr/storage/memory_mixins/keyvalue_memory_mixin.py +42 -0
  1320. angr/storage/memory_mixins/label_merger_mixin.py +31 -0
  1321. angr/storage/memory_mixins/memory_mixin.py +174 -0
  1322. angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
  1323. angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
  1324. angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
  1325. angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
  1326. angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
  1327. angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
  1328. angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
  1329. angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
  1330. angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
  1331. angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
  1332. angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
  1333. angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
  1334. angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
  1335. angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
  1336. angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
  1337. angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
  1338. angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +503 -0
  1339. angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
  1340. angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
  1341. angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
  1342. angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
  1343. angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
  1344. angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
  1345. angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
  1346. angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
  1347. angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
  1348. angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +441 -0
  1349. angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
  1350. angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
  1351. angr/storage/memory_mixins/simplification_mixin.py +15 -0
  1352. angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
  1353. angr/storage/memory_mixins/slotted_memory.py +140 -0
  1354. angr/storage/memory_mixins/smart_find_mixin.py +161 -0
  1355. angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
  1356. angr/storage/memory_mixins/top_merger_mixin.py +25 -0
  1357. angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
  1358. angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
  1359. angr/storage/memory_object.py +195 -0
  1360. angr/tablespecs.py +91 -0
  1361. angr/utils/__init__.py +46 -0
  1362. angr/utils/ail.py +70 -0
  1363. angr/utils/algo.py +34 -0
  1364. angr/utils/bits.py +46 -0
  1365. angr/utils/constants.py +9 -0
  1366. angr/utils/cowdict.py +63 -0
  1367. angr/utils/cpp.py +17 -0
  1368. angr/utils/doms.py +149 -0
  1369. angr/utils/dynamic_dictlist.py +89 -0
  1370. angr/utils/endness.py +18 -0
  1371. angr/utils/enums_conv.py +97 -0
  1372. angr/utils/env.py +12 -0
  1373. angr/utils/formatting.py +128 -0
  1374. angr/utils/funcid.py +159 -0
  1375. angr/utils/graph.py +898 -0
  1376. angr/utils/lazy_import.py +13 -0
  1377. angr/utils/library.py +211 -0
  1378. angr/utils/loader.py +55 -0
  1379. angr/utils/mp.py +66 -0
  1380. angr/utils/orderedset.py +74 -0
  1381. angr/utils/ssa/__init__.py +395 -0
  1382. angr/utils/ssa/tmp_uses_collector.py +23 -0
  1383. angr/utils/ssa/vvar_uses_collector.py +37 -0
  1384. angr/utils/tagged_interval_map.py +112 -0
  1385. angr/utils/timing.py +74 -0
  1386. angr/utils/types.py +151 -0
  1387. angr/vaults.py +367 -0
  1388. angr-9.2.156.dist-info/METADATA +112 -0
  1389. angr-9.2.156.dist-info/RECORD +1393 -0
  1390. angr-9.2.156.dist-info/WHEEL +5 -0
  1391. angr-9.2.156.dist-info/entry_points.txt +2 -0
  1392. angr-9.2.156.dist-info/licenses/LICENSE +27 -0
  1393. angr-9.2.156.dist-info/top_level.txt +1 -0
@@ -0,0 +1,2886 @@
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 ELF, PE, Blob, TLSObject, MachO, ExternObject, KernelObject, FunctionHintSource, Hex, Coff, SRec, XBE
12
+ from cle.backends import NamedRegion
13
+ import archinfo
14
+ from archinfo.arch_soot import SootAddressDescriptor, SootMethodDescriptor
15
+ from archinfo.arch_arm import is_arm_arch, get_real_address_if_arm
16
+
17
+ from angr.knowledge_plugins.functions.function_manager import FunctionManager
18
+ from angr.knowledge_plugins.functions.function import Function
19
+ from angr.knowledge_plugins.cfg import IndirectJump, CFGNode, CFGENode, CFGModel # pylint:disable=unused-import
20
+ from angr.procedures.stubs.UnresolvableJumpTarget import UnresolvableJumpTarget
21
+ from angr.utils.constants import DEFAULT_STATEMENT
22
+ from angr.procedures.procedure_dict import SIM_PROCEDURES
23
+ from angr.errors import (
24
+ AngrCFGError,
25
+ SimTranslationError,
26
+ SimMemoryError,
27
+ SimIRSBError,
28
+ SimEngineError,
29
+ AngrUnsupportedSyscallError,
30
+ SimError,
31
+ )
32
+ from angr.codenode import HookNode, BlockNode
33
+ from angr.engines.vex.lifter import VEX_IRSB_MAX_SIZE, VEX_IRSB_MAX_INST
34
+ from angr.analyses import Analysis
35
+ from angr.analyses.stack_pointer_tracker import StackPointerTracker
36
+ from angr.utils.orderedset import OrderedSet
37
+ from .indirect_jump_resolvers.default_resolvers import default_indirect_jump_resolvers
38
+
39
+ if TYPE_CHECKING:
40
+ from angr.sim_state import SimState
41
+
42
+
43
+ l = logging.getLogger(name=__name__)
44
+
45
+
46
+ class CFGBase(Analysis):
47
+ """
48
+ The base class for control flow graphs.
49
+ """
50
+
51
+ tag: str | None = None
52
+ _cle_pseudo_objects = (ExternObject, KernelObject, TLSObject)
53
+
54
+ def __init__(
55
+ self,
56
+ sort,
57
+ context_sensitivity_level,
58
+ normalize=False,
59
+ binary=None,
60
+ objects=None,
61
+ regions=None,
62
+ exclude_sparse_regions=True,
63
+ skip_specific_regions=True,
64
+ force_segment=False,
65
+ base_state=None,
66
+ resolve_indirect_jumps=True,
67
+ indirect_jump_resolvers=None,
68
+ indirect_jump_target_limit=100000,
69
+ detect_tail_calls=False,
70
+ low_priority=False,
71
+ skip_unmapped_addrs=True,
72
+ sp_tracking_track_memory=True,
73
+ model=None,
74
+ ):
75
+ """
76
+ :param str sort: 'fast' or 'emulated'.
77
+ :param int context_sensitivity_level: The level of context-sensitivity of this CFG (see documentation for
78
+ further details). It ranges from 0 to infinity.
79
+ :param bool normalize: Whether the CFG as well as all Function graphs should be normalized.
80
+ :param cle.backends.Backend binary: The binary to recover CFG on. By default, the main binary is used.
81
+ :param objects: A list of objects to recover the CFG on. By default, it will recover
82
+ the CFG of all loaded objects.
83
+ :param iterable regions: A list of tuples in the form of (start address, end address)
84
+ describing memory regions that the CFG should cover.
85
+ :param bool force_segment: Force CFGFast to rely on binary segments instead of sections.
86
+ :param angr.SimState base_state: A state to use as a backer for all memory loads.
87
+ :param bool resolve_indirect_jumps: Whether to try to resolve indirect jumps.
88
+ This is necessary to resolve jump targets from jump tables, etc.
89
+ :param list indirect_jump_resolvers: A custom list of indirect jump resolvers.
90
+ If this list is None or empty, default indirect jump resolvers
91
+ specific to this architecture and binary types will be loaded.
92
+ :param int indirect_jump_target_limit: Maximum indirect jump targets to be recovered.
93
+ :param skip_unmapped_addrs: Ignore all branches into unmapped regions. True by default. You may
94
+ want to set it to False if you are analyzing manually patched
95
+ binaries or malware samples.
96
+ :param bool detect_tail_calls: Aggressive tail-call optimization detection. This option is only
97
+ respected in make_functions().
98
+ :param bool sp_tracking_track_memory: Whether or not to track memory writes if tracking the stack pointer.
99
+ This increases the accuracy of stack pointer tracking,
100
+ especially for architectures without a base pointer.
101
+ Only used if detect_tail_calls is enabled.
102
+ :param None or CFGModel model: The CFGModel instance to write to. A new CFGModel instance will be
103
+ created and registered with the knowledge base if `model` is None.
104
+
105
+ :return: None
106
+ """
107
+
108
+ self.sort = sort
109
+ self._context_sensitivity_level = context_sensitivity_level
110
+
111
+ # Sanity checks
112
+ if context_sensitivity_level < 0:
113
+ raise ValueError(f"Unsupported context sensitivity level {context_sensitivity_level}")
114
+
115
+ self._binary = binary if binary is not None else self.project.loader.main_object
116
+ self._force_segment = force_segment
117
+ self._base_state = base_state
118
+ self._detect_tail_calls = detect_tail_calls
119
+ self._low_priority = low_priority
120
+ self._skip_unmapped_addrs = skip_unmapped_addrs
121
+
122
+ # Initialization
123
+ self._edge_map = None
124
+ self._loop_back_edges = None
125
+ self._overlapped_loop_headers = None
126
+ self._thumb_addrs = set()
127
+ self._tail_calls = set()
128
+
129
+ # Store all the functions analyzed before the set is cleared
130
+ # Used for performance optimization
131
+ self._updated_nonreturning_functions: set[int | SootMethodDescriptor] | None = None
132
+
133
+ self._normalize = normalize
134
+
135
+ # Flag, whether to track memory writes in stack pointer tracking
136
+ self._sp_tracking_track_memory = sp_tracking_track_memory
137
+
138
+ # IndirectJump object that describe all indirect exits found in the binary
139
+ # stores as a map between addresses and IndirectJump objects
140
+ self.indirect_jumps: dict[int, IndirectJump] = {}
141
+ self._indirect_jumps_to_resolve = set()
142
+
143
+ # Indirect jump resolvers
144
+ self._indirect_jump_target_limit = indirect_jump_target_limit
145
+ self._resolve_indirect_jumps = resolve_indirect_jumps
146
+ self.timeless_indirect_jump_resolvers = []
147
+ self.indirect_jump_resolvers = []
148
+ if not indirect_jump_resolvers:
149
+ indirect_jump_resolvers = default_indirect_jump_resolvers(self._binary, self.project)
150
+ if self._resolve_indirect_jumps and indirect_jump_resolvers:
151
+ # split them into different groups for the sake of speed
152
+ for ijr in indirect_jump_resolvers:
153
+ if ijr.timeless:
154
+ self.timeless_indirect_jump_resolvers.append(ijr)
155
+ else:
156
+ self.indirect_jump_resolvers.append(ijr)
157
+
158
+ l.info(
159
+ "Loaded %d indirect jump resolvers (%d timeless, %d generic).",
160
+ len(self.timeless_indirect_jump_resolvers) + len(self.indirect_jump_resolvers),
161
+ len(self.timeless_indirect_jump_resolvers),
162
+ len(self.indirect_jump_resolvers),
163
+ )
164
+
165
+ # Get all executable memory regions
166
+ self._exec_mem_regions = self._executable_memory_regions(None, self._force_segment)
167
+ self._exec_mem_region_size = sum((end - start) for start, end in self._exec_mem_regions)
168
+
169
+ # initialize UnresolvableJumpTarget and UnresolvableCallTarget SimProcedure
170
+ # but we do not want to hook the same symbol multiple times
171
+ ut_jump_addr = self.project.loader.extern_object.get_pseudo_addr("UnresolvableJumpTarget")
172
+ if not self.project.is_hooked(ut_jump_addr):
173
+ self.project.hook(ut_jump_addr, SIM_PROCEDURES["stubs"]["UnresolvableJumpTarget"]())
174
+ self._unresolvable_jump_target_addr = ut_jump_addr
175
+ ut_call_addr = self.project.loader.extern_object.get_pseudo_addr("UnresolvableCallTarget")
176
+ if not self.project.is_hooked(ut_call_addr):
177
+ self.project.hook(ut_call_addr, SIM_PROCEDURES["stubs"]["UnresolvableCallTarget"]())
178
+ self._unresolvable_call_target_addr = ut_call_addr
179
+
180
+ # partially and fully analyzed functions
181
+ # this is implemented as a state machine: jobs (CFGJob instances) of each function are put into
182
+ # _jobs_to_analyze_per_function, which essentially makes the keys of this dict being all partially analyzed
183
+ # functions so far. And then when a function does not have any more job to analyze in the future, it will be
184
+ # put in to _completed_functions.
185
+
186
+ # a dict of mapping between function addresses and sets of jobs (include both future jobs and pending jobs)
187
+ # a set is used to speed up the job removal procedure
188
+ self._jobs_to_analyze_per_function = defaultdict(set)
189
+ # addresses of functions that have been completely recovered (i.e. all of its blocks are identified) so far
190
+ self._completed_functions = set()
191
+
192
+ # TODO: A segment tree to speed up CFG node lookups
193
+ self._node_lookup_index = None
194
+ self._node_lookup_index_warned = False
195
+
196
+ self._function_addresses_from_symbols = self._load_func_addrs_from_symbols()
197
+ self._function_addresses_from_eh_frame = self._load_func_addrs_from_eh_frame()
198
+
199
+ # Cache if an object has executable sections or not
200
+ self._object_to_executable_sections = {}
201
+ # Cache if an object has executable segments or not
202
+ self._object_to_executable_segments = {}
203
+
204
+ if model is not None:
205
+ self._model = model
206
+ else:
207
+ self._model: CFGModel = self.kb.cfgs.new_model(self.tag)
208
+
209
+ # necessary warnings
210
+ regions_not_specified = regions is None and binary is None and not objects
211
+ if regions_not_specified and self.project.loader._auto_load_libs and len(self.project.loader.all_objects) > 3:
212
+ l.warning(
213
+ '"auto_load_libs" is enabled. With libraries loaded in project, CFG will cover libraries, '
214
+ "which may take significantly more time than expected. You may reload the binary with "
215
+ '"auto_load_libs" disabled, or specify "regions" to limit the scope of CFG recovery.'
216
+ )
217
+
218
+ if regions is None:
219
+ if self._skip_unmapped_addrs:
220
+ regions = self._executable_memory_regions(objects=objects, force_segment=force_segment)
221
+ else:
222
+ if not objects:
223
+ objects = self.project.loader.all_objects
224
+ regions = [(obj.min_addr, obj.max_addr) for obj in objects]
225
+
226
+ for start, end in regions:
227
+ if end < start:
228
+ raise AngrCFGError("Invalid region bounds (end precedes start)")
229
+
230
+ # Block factory returns patched state by default, so ensure we are also analyzing the patched state
231
+ if self._base_state is None and self.project.kb.patches.values():
232
+ self._base_state = self.project.kb.patches.patched_entry_state
233
+
234
+ if exclude_sparse_regions:
235
+ regions = [r for r in regions if not self._is_region_extremely_sparse(*r, base_state=self._base_state)]
236
+
237
+ if skip_specific_regions:
238
+ if base_state is not None:
239
+ l.warning("You specified both base_state and skip_specific_regions. They may conflict with each other.")
240
+ regions = [r for r in regions if not self._should_skip_region(r[0])]
241
+
242
+ if not regions and self.project.arch.name != "Soot":
243
+ raise AngrCFGError(
244
+ "Regions are empty, or all regions are skipped. You may want to manually specify regions."
245
+ )
246
+
247
+ self._regions_size = sum((end - start) for start, end in regions)
248
+ self._regions: SortedDict = SortedDict(regions)
249
+
250
+ l.debug("CFG recovery covers %d regions:", len(self._regions))
251
+ for start, end in self._regions.items():
252
+ l.debug("... %#x - %#x", start, end)
253
+
254
+ def __contains__(self, cfg_node):
255
+ return cfg_node in self.graph
256
+
257
+ #
258
+ # Properties
259
+ #
260
+
261
+ @property
262
+ def _nodes(self):
263
+ return self._model._nodes
264
+
265
+ @property
266
+ def _nodes_by_addr(self):
267
+ return self._model._nodes_by_addr
268
+
269
+ @property
270
+ def model(self) -> CFGModel:
271
+ """
272
+ Get the CFGModel instance.
273
+ :return: The CFGModel instance that this analysis currently uses.
274
+ """
275
+ return self._model
276
+
277
+ @property
278
+ def normalized(self):
279
+ return self._model.normalized
280
+
281
+ @normalized.setter
282
+ def normalized(self, v):
283
+ self._model.normalized = v
284
+
285
+ @property
286
+ def context_sensitivity_level(self):
287
+ return self._context_sensitivity_level
288
+
289
+ @property
290
+ def functions(self):
291
+ """
292
+ A reference to the FunctionManager in the current knowledge base.
293
+
294
+ :return: FunctionManager with all functions
295
+ :rtype: angr.knowledge_plugins.FunctionManager
296
+ """
297
+ return self.kb.functions
298
+
299
+ #
300
+ # Methods
301
+ #
302
+
303
+ def _initialize_cfg(self):
304
+ """
305
+ Re-create the DiGraph
306
+ """
307
+
308
+ self._jobs_to_analyze_per_function = defaultdict(set)
309
+ self._completed_functions = set()
310
+
311
+ def _function_completed(self, func_addr: int):
312
+ pass
313
+
314
+ def _post_analysis(self):
315
+ if self._normalize:
316
+ if not self.normalized:
317
+ self.normalize()
318
+
319
+ # Call normalize() on each function
320
+ for f in self.kb.functions.values():
321
+ if not self.project.is_hooked(f.addr):
322
+ f.normalize()
323
+
324
+ # drop all propagation results that start with "cfg_intermediate"
325
+ self.kb.propagations.discard_by_prefix("cfg_intermediate")
326
+
327
+ def make_copy(self, copy_to):
328
+ """
329
+ Copy self attributes to the new object.
330
+
331
+ :param CFGBase copy_to: The target to copy to.
332
+ :return: None
333
+ """
334
+
335
+ for attr, value in self.__dict__.items():
336
+ if attr.startswith("__") and attr.endswith("__"):
337
+ continue
338
+ setattr(copy_to, attr, value)
339
+
340
+ # pylint: disable=no-self-use
341
+ def copy(self):
342
+ raise NotImplementedError
343
+
344
+ def output(self):
345
+ raise NotImplementedError
346
+
347
+ def generate_index(self):
348
+ """
349
+ Generate an index of all nodes in the graph in order to speed up get_any_node() with anyaddr=True.
350
+
351
+ :return: None
352
+ """
353
+
354
+ raise NotImplementedError("I'm too lazy to implement it right now")
355
+
356
+ def get_loop_back_edges(self):
357
+ return self._loop_back_edges
358
+
359
+ @property
360
+ def graph(self) -> networkx.DiGraph[CFGNode]:
361
+ raise NotImplementedError
362
+
363
+ def remove_edge(self, block_from, block_to):
364
+ if self.graph is None:
365
+ raise TypeError("self.graph does not exist.")
366
+
367
+ if block_from not in self.graph:
368
+ raise ValueError(f"{block_from!r} is not in CFG.")
369
+
370
+ if block_to not in self.graph:
371
+ raise ValueError(f"{block_to!r} is not in CFG.")
372
+
373
+ if block_to not in self.graph[block_from]:
374
+ raise ValueError(f"Edge {block_from!r}->{block_to!r} does not exist.")
375
+
376
+ self.graph.remove_edge(block_from, block_to)
377
+
378
+ def _merge_cfgnodes(self, cfgnode_0, cfgnode_1):
379
+ """
380
+ Merge two adjacent CFGNodes into one.
381
+
382
+ :param CFGNode cfgnode_0: The first CFGNode.
383
+ :param CFGNode cfgnode_1: The second CFGNode.
384
+ :return: None
385
+ """
386
+
387
+ assert cfgnode_0.addr + cfgnode_0.size == cfgnode_1.addr
388
+ new_node = cfgnode_0.merge(cfgnode_1)
389
+
390
+ # Update the graph and the nodes dict accordingly
391
+ self._model.remove_node(cfgnode_1.block_id, cfgnode_1)
392
+ self._model.remove_node(cfgnode_0.block_id, cfgnode_0)
393
+
394
+ in_edges = list(self.graph.in_edges(cfgnode_0, data=True))
395
+ out_edges = list(self.graph.out_edges(cfgnode_1, data=True))
396
+
397
+ self.graph.remove_node(cfgnode_0)
398
+ self.graph.remove_node(cfgnode_1)
399
+
400
+ self.graph.add_node(new_node)
401
+ for src, _, data in in_edges:
402
+ self.graph.add_edge(src, new_node, **data)
403
+ for _, dst, data in out_edges:
404
+ self.graph.add_edge(new_node, dst, **data)
405
+
406
+ # Put the new node into node dicts
407
+ self._model.add_node(new_node.block_id, new_node)
408
+
409
+ def _to_snippet(self, cfg_node=None, addr=None, size=None, thumb=False, jumpkind=None, base_state=None):
410
+ """
411
+ Convert a CFGNode instance to a CodeNode object.
412
+
413
+ :param angr.analyses.CFGNode cfg_node: The CFGNode instance.
414
+ :param int addr: Address of the node. Only used when `cfg_node` is None.
415
+ :param bool thumb: Whether this is in THUMB mode or not. Only used for ARM code and when `cfg_node` is None.
416
+ :param str or None jumpkind: Jumpkind of this node.
417
+ :param SimState or None base_state: The state where BlockNode should be created from.
418
+ :return: A converted CodeNode instance.
419
+ :rtype: CodeNode
420
+ """
421
+
422
+ if cfg_node is not None:
423
+ addr = cfg_node.addr
424
+ size = cfg_node.size
425
+ thumb = cfg_node.thumb
426
+
427
+ if addr is None:
428
+ raise ValueError("_to_snippet(): Either cfg_node or addr must be provided.")
429
+
430
+ if self.project.is_hooked(addr) and jumpkind != "Ijk_NoHook":
431
+ hooker = self.project._sim_procedures[addr]
432
+ size = hooker.kwargs.get("length", 0)
433
+ return HookNode(addr, size, type(hooker))
434
+
435
+ if cfg_node is not None:
436
+ return BlockNode(addr, size, thumb=thumb, bytestr=cfg_node.byte_string) # pylint: disable=no-member
437
+ return self.project.factory.snippet(addr, size=size, jumpkind=jumpkind, thumb=thumb, backup_state=base_state)
438
+
439
+ def is_thumb_addr(self, addr):
440
+ return addr in self._thumb_addrs
441
+
442
+ def _arm_thumb_filter_jump_successors(self, irsb, successors, get_ins_addr, get_exit_stmt_idx, get_jumpkind):
443
+ """
444
+ Filter successors for THUMB mode basic blocks, and remove those successors that won't be taken normally.
445
+
446
+ :param irsb: The IRSB object.
447
+ :param list successors: A list of successors.
448
+ :param func get_ins_addr: A callable that returns the source instruction address for a successor.
449
+ :param func get_exit_stmt_idx: A callable that returns the source statement ID for a successor.
450
+ :param func get_jumpkind: A callable that returns the jumpkind of a successor.
451
+ :return: A new list of successors after filtering.
452
+ :rtype: list
453
+ """
454
+
455
+ if not successors:
456
+ return []
457
+
458
+ if len(successors) == 1 and get_exit_stmt_idx(successors[0]) == DEFAULT_STATEMENT:
459
+ # only have a default exit. no need to filter
460
+ return successors
461
+
462
+ if irsb.instruction_addresses and all(
463
+ get_ins_addr(suc) == irsb.instruction_addresses[-1] for suc in successors
464
+ ):
465
+ # check if all exits are produced by the last instruction
466
+ # only takes the following jump kinds: Boring, FakeRet, Call, Syscall, Ret
467
+ allowed_jumpkinds = {"Ijk_Boring", "Ijk_FakeRet", "Ijk_Call", "Ijk_Ret"}
468
+ successors = [
469
+ suc
470
+ for suc in successors
471
+ if get_jumpkind(suc) in allowed_jumpkinds or get_jumpkind(suc).startswith("Ijk_Sys")
472
+ ]
473
+ if len(successors) == 1:
474
+ return successors
475
+
476
+ can_produce_exits = set() # addresses of instructions that can produce exits
477
+ bb = self._lift(irsb.addr, size=irsb.size, thumb=True)
478
+
479
+ # step A: filter exits using capstone (since it's faster than re-lifting the entire block to VEX)
480
+ THUMB_BRANCH_INSTRUCTIONS = {
481
+ "beq",
482
+ "bne",
483
+ "bcs",
484
+ "bhs",
485
+ "bcc",
486
+ "blo",
487
+ "bmi",
488
+ "bpl",
489
+ "bvs",
490
+ "bvc",
491
+ "bhi",
492
+ "bls",
493
+ "bge",
494
+ "blt",
495
+ "bgt",
496
+ "ble",
497
+ "cbz",
498
+ "cbnz",
499
+ }
500
+ for cs_insn in bb.capstone.insns:
501
+ if cs_insn.mnemonic.split(".")[0] in THUMB_BRANCH_INSTRUCTIONS:
502
+ can_produce_exits.add(cs_insn.address)
503
+
504
+ if all(
505
+ get_ins_addr(suc) in can_produce_exits or get_exit_stmt_idx(suc) == DEFAULT_STATEMENT for suc in successors
506
+ ):
507
+ # nothing will be filtered.
508
+ return successors
509
+
510
+ # step B: consider VEX statements
511
+ it_counter = 0
512
+ conc_temps = {}
513
+
514
+ for stmt in bb.vex.statements:
515
+ if stmt.tag == "Ist_IMark":
516
+ if it_counter > 0:
517
+ it_counter -= 1
518
+ can_produce_exits.add(stmt.addr + stmt.delta)
519
+ elif stmt.tag == "Ist_WrTmp":
520
+ val = stmt.data
521
+ if val.tag == "Iex_Const":
522
+ conc_temps[stmt.tmp] = val.con.value
523
+ elif stmt.tag == "Ist_Put" and stmt.offset == self.project.arch.registers["itstate"][0]:
524
+ val = stmt.data
525
+ if val.tag == "Iex_RdTmp":
526
+ if val.tmp in conc_temps:
527
+ # We found an IT instruction!!
528
+ # Determine how many instructions are conditional
529
+ it_counter = 0
530
+ itstate = conc_temps[val.tmp]
531
+ while itstate != 0:
532
+ it_counter += 1
533
+ itstate >>= 8
534
+ elif val.tag == "Iex_Const":
535
+ it_counter = 0
536
+ itstate = val.con.value
537
+ while itstate != 0:
538
+ it_counter += 1
539
+ itstate >>= 8
540
+
541
+ if it_counter != 0:
542
+ l.debug("Basic block ends before calculated IT block (%#x)", irsb.addr)
543
+
544
+ return [
545
+ suc
546
+ for suc in successors
547
+ if get_ins_addr(suc) in can_produce_exits or get_exit_stmt_idx(suc) == DEFAULT_STATEMENT
548
+ ]
549
+
550
+ # Methods for determining scanning scope
551
+
552
+ def _inside_regions(self, address: int | None) -> bool:
553
+ """
554
+ Check if the address is inside any existing region.
555
+
556
+ :param int address: Address to check.
557
+ :return: True if the address is within one of the memory regions, False otherwise.
558
+ """
559
+
560
+ try:
561
+ start_addr = next(self._regions.irange(maximum=address, reverse=True))
562
+ except StopIteration:
563
+ return False
564
+ else:
565
+ return address < self._regions[start_addr]
566
+
567
+ def _get_min_addr(self) -> int | None:
568
+ """
569
+ Get the minimum address out of all regions. We assume self._regions is sorted.
570
+
571
+ :return: The minimum address, or None if there is no such address.
572
+ """
573
+
574
+ if not self._regions:
575
+ if self.project.arch.name != "Soot":
576
+ l.error("self._regions is empty or not properly set.")
577
+ return None
578
+
579
+ return next(self._regions.irange())
580
+
581
+ def _next_address_in_regions(self, address: int | None) -> int | None:
582
+ """
583
+ Return the next immediate address that is inside any of the regions.
584
+
585
+ :param address: The address to start scanning.
586
+ :return: The next address that is inside one of the memory regions, or None if there is no such address.
587
+ """
588
+
589
+ if self._inside_regions(address):
590
+ return address
591
+
592
+ try:
593
+ return next(self._regions.irange(minimum=address, reverse=False))
594
+ except StopIteration:
595
+ return None
596
+
597
+ def _is_region_extremely_sparse(self, start: int, end: int, base_state: SimState | None = None) -> bool:
598
+ """
599
+ Check whether the given memory region is extremely sparse, i.e., all bytes are the same value.
600
+
601
+ :param start: The beginning of the region.
602
+ :param end: The end of the region (exclusive).
603
+ :param base_state: The base state (optional).
604
+ :return: True if the region is extremely sparse, False otherwise.
605
+ """
606
+
607
+ all_bytes = None
608
+
609
+ if base_state is not None:
610
+ all_bytes = base_state.memory.load(start, end - start)
611
+ try:
612
+ all_bytes = base_state.solver.eval(all_bytes, cast_to=bytes)
613
+ except SimError:
614
+ all_bytes = None
615
+
616
+ size = end - start
617
+
618
+ if all_bytes is None:
619
+ # load from the binary
620
+ all_bytes = self._fast_memory_load_bytes(start, size)
621
+
622
+ if all_bytes is None:
623
+ # failed to load bytes in this region. it might be because the region is not fully mapped (i.e., there are
624
+ # holes). we assume this region is good for analysis.
625
+ return False
626
+
627
+ if len(all_bytes) < size:
628
+ l.warning(
629
+ "_is_region_extremely_sparse: The given region %#x-%#x is not a continuous memory region in the "
630
+ "memory space. Only the first %d bytes (%#x-%#x) are processed.",
631
+ start,
632
+ end,
633
+ len(all_bytes),
634
+ start,
635
+ start + len(all_bytes),
636
+ )
637
+
638
+ the_byte_value = None
639
+ for b in all_bytes:
640
+ if the_byte_value is None:
641
+ the_byte_value = b
642
+ else:
643
+ if the_byte_value != b:
644
+ return False
645
+
646
+ return True
647
+
648
+ def _should_skip_region(self, region_start):
649
+ """
650
+ Some regions usually do not contain any executable code, but are still marked as executable. We should skip
651
+ those regions by default.
652
+
653
+ :param int region_start: Address of the beginning of the region.
654
+ :return: True/False
655
+ :rtype: bool
656
+ """
657
+
658
+ obj = self.project.loader.find_object_containing(region_start, membership_check=False)
659
+ if obj is None:
660
+ return False
661
+ if isinstance(obj, PE):
662
+ section = obj.find_section_containing(region_start)
663
+ if section is None:
664
+ return False
665
+ if section.name in {".textbss"}:
666
+ return True
667
+
668
+ return False
669
+
670
+ def _executable_memory_regions(self, objects=None, force_segment=False):
671
+ """
672
+ Get all executable memory regions from the binaries
673
+
674
+ :param objects: A collection of binary objects to collect regions from. If None, regions from all project
675
+ binary objects are used.
676
+ :param bool force_segment: Rely on binary segments instead of sections.
677
+ :return: A sorted list of tuples (beginning_address, end_address)
678
+ """
679
+
680
+ binaries = self.project.loader.all_objects if objects is None else objects
681
+
682
+ memory_regions = []
683
+
684
+ for b in binaries:
685
+ if not b.has_memory:
686
+ continue
687
+
688
+ if isinstance(b, ELF):
689
+ # If we have sections, we get result from sections
690
+ sections = []
691
+ if not force_segment and b.sections:
692
+ # Get all executable sections
693
+ for section in b.sections:
694
+ if section.is_executable:
695
+ max_mapped_addr = section.min_addr + min(section.memsize, section.filesize)
696
+ tpl = (section.min_addr, max_mapped_addr)
697
+ sections.append(tpl)
698
+ memory_regions += sections
699
+
700
+ segments = []
701
+ # Get all executable segments
702
+ for segment in b.segments:
703
+ if segment.is_executable:
704
+ max_mapped_addr = segment.min_addr + min(segment.memsize, segment.filesize)
705
+ tpl = (segment.min_addr, max_mapped_addr)
706
+ segments.append(tpl)
707
+ if sections and segments:
708
+ # are there executable segments with no sections inside?
709
+ for segment in segments:
710
+ for section in sections:
711
+ if segment[0] <= section[0] < segment[1]:
712
+ break
713
+ else:
714
+ memory_regions.append(segment)
715
+
716
+ elif isinstance(b, (Coff, PE)):
717
+ for section in b.sections:
718
+ if section.is_executable:
719
+ max_mapped_addr = section.min_addr + min(section.memsize, section.filesize)
720
+ tpl = (section.min_addr, max_mapped_addr)
721
+ memory_regions.append(tpl)
722
+
723
+ elif isinstance(b, XBE):
724
+ # some XBE files will mark the data sections as executable
725
+ for section in b.sections:
726
+ if (
727
+ section.is_executable
728
+ and not section.is_writable
729
+ and section.name not in {".data", ".rdata", ".rodata"}
730
+ ):
731
+ tpl = (section.min_addr, section.max_addr)
732
+ memory_regions.append(tpl)
733
+
734
+ elif isinstance(b, MachO):
735
+ if b.segments:
736
+ # Get all executable segments
737
+ for seg in b.segments:
738
+ if seg.is_executable:
739
+ # Take all sections from this segment (MachO style)
740
+ for section in seg.sections:
741
+ max_mapped_addr = section.min_addr + min(section.memsize, section.filesize)
742
+ tpl = (section.min_addr, max_mapped_addr)
743
+ memory_regions.append(tpl)
744
+
745
+ elif isinstance(b, (Hex, SRec)):
746
+ if b.regions:
747
+ for region_addr, region_size in b.regions:
748
+ memory_regions.append((region_addr, region_addr + region_size))
749
+
750
+ elif isinstance(b, Blob):
751
+ # a blob is entirely executable
752
+ tpl = (b.min_addr, b.max_addr + 1)
753
+ memory_regions.append(tpl)
754
+
755
+ elif isinstance(b, NamedRegion):
756
+ # NamedRegions have no content! Ignore
757
+ pass
758
+
759
+ elif isinstance(b, self._cle_pseudo_objects):
760
+ pass
761
+
762
+ else:
763
+ l.warning('Unsupported object format "%s". Treat it as an executable.', b.__class__.__name__)
764
+
765
+ tpl = (b.min_addr, b.max_addr + 1)
766
+ memory_regions.append(tpl)
767
+
768
+ if not memory_regions:
769
+ memory_regions = [(start, start + len(backer)) for start, backer in self.project.loader.memory.backers()]
770
+
771
+ return sorted(memory_regions, key=lambda x: x[0])
772
+
773
+ def _addr_in_exec_memory_regions(self, addr):
774
+ """
775
+ Test if the address belongs to an executable memory region.
776
+
777
+ :param int addr: The address to test
778
+ :return: True if the address belongs to an exectubale memory region, False otherwise
779
+ :rtype: bool
780
+ """
781
+
782
+ return any(start <= addr < end for start, end in self._exec_mem_regions)
783
+
784
+ def _addrs_belong_to_same_section(self, addr_a, addr_b):
785
+ """
786
+ Test if two addresses belong to the same section.
787
+
788
+ :param int addr_a: The first address to test.
789
+ :param int addr_b: The second address to test.
790
+ :return: True if the two addresses belong to the same section or both of them do not belong to any
791
+ section, False otherwise.
792
+ :rtype: bool
793
+ """
794
+
795
+ obj = self.project.loader.find_object_containing(addr_a, membership_check=False)
796
+
797
+ if obj is None:
798
+ # test if addr_b also does not belong to any object
799
+ obj_b = self.project.loader.find_object_containing(addr_b, membership_check=False)
800
+ return obj_b is None
801
+
802
+ src_section = obj.find_section_containing(addr_a)
803
+ if src_section is None:
804
+ # test if addr_b also does not belong to any section
805
+ dst_section = obj.find_section_containing(addr_b)
806
+ if dst_section is None:
807
+ return self._addrs_belong_to_same_segment(addr_a, addr_b)
808
+ return False
809
+
810
+ return src_section.contains_addr(addr_b)
811
+
812
+ def _addrs_belong_to_same_segment(self, addr_a, addr_b):
813
+ """
814
+ Test if two addresses belong to the same segment.
815
+
816
+ :param int addr_a: The first address to test.
817
+ :param int addr_b: The second address to test.
818
+ :return: True if the two addresses belong to the same segment or both of them do not belong to any
819
+ section, False otherwise.
820
+ :rtype: bool
821
+ """
822
+
823
+ obj = self.project.loader.find_object_containing(addr_a, membership_check=False)
824
+
825
+ if obj is None:
826
+ # test if addr_b also does not belong to any object
827
+ obj_b = self.project.loader.find_object_containing(addr_b, membership_check=False)
828
+ return obj_b is None
829
+
830
+ src_segment = obj.find_segment_containing(addr_a)
831
+ if src_segment is None:
832
+ # test if addr_b also does not belong to any section
833
+ dst_segment = obj.find_segment_containing(addr_b)
834
+ return dst_segment is None
835
+
836
+ return src_segment.contains_addr(addr_b)
837
+
838
+ def _object_has_executable_sections(self, obj):
839
+ """
840
+ Check whether an object has at least one executable section.
841
+
842
+ :param cle.Backend obj: The object to test.
843
+ :return: None
844
+ """
845
+
846
+ if obj in self._object_to_executable_sections:
847
+ return self._object_to_executable_sections[obj]
848
+ r = any(sec.is_executable for sec in obj.sections)
849
+ self._object_to_executable_sections[obj] = r
850
+ return r
851
+
852
+ def _object_has_executable_segments(self, obj):
853
+ """
854
+ Check whether an object has at least one executable segment.
855
+
856
+ :param cle.Backend obj: The object to test.
857
+ :return: None
858
+ """
859
+
860
+ if obj in self._object_to_executable_segments:
861
+ return self._object_to_executable_segments[obj]
862
+ r = any(seg.is_executable for seg in obj.segments)
863
+ self._object_to_executable_segments[obj] = r
864
+ return r
865
+
866
+ def _addr_hooked_or_syscall(self, addr):
867
+ """
868
+ Check whether the address belongs to a hook or a syscall.
869
+
870
+ :param int addr: The address to check.
871
+ :return: True if the address is hooked or belongs to a syscall. False otherwise.
872
+ :rtype: bool
873
+ """
874
+
875
+ return self.project.is_hooked(addr) or self.project.simos.is_syscall_addr(addr)
876
+
877
+ def _fast_memory_load_byte(self, addr):
878
+ """
879
+ Perform a fast memory loading of a byte.
880
+
881
+ :param int addr: Address to read from.
882
+ :return: A char or None if the address does not exist.
883
+ :rtype: int or None
884
+ """
885
+
886
+ try:
887
+ return self.project.loader.memory[addr]
888
+ except KeyError:
889
+ return None
890
+
891
+ def _fast_memory_load_bytes(self, addr, length):
892
+ """
893
+ Perform a fast memory loading of some data.
894
+
895
+ :param int addr: Address to read from.
896
+ :param int length: Size of the string to load.
897
+ :return: A string or None if the address does not exist.
898
+ :rtype: bytes or None
899
+ """
900
+
901
+ try:
902
+ return self.project.loader.memory.load(addr, length)
903
+ except KeyError:
904
+ return None
905
+
906
+ def _fast_memory_load_pointer(self, addr, size=None):
907
+ """
908
+ Perform a fast memory loading of a pointer.
909
+
910
+ :param int addr: Address to read from.
911
+ :param int size: Size of the pointer. Default to machine-word size.
912
+ :return: A pointer or None if the address does not exist.
913
+ :rtype: int
914
+ """
915
+
916
+ try:
917
+ return self.project.loader.memory.unpack_word(addr, size=size)
918
+ except KeyError:
919
+ return None
920
+
921
+ def _load_func_addrs_from_symbols(self):
922
+ """
923
+ Get all possible function addresses that are specified by the symbols in the binary
924
+
925
+ :return: A set of addresses that are probably functions
926
+ :rtype: set
927
+ """
928
+
929
+ return {sym.rebased_addr for sym in self._binary.symbols if sym.is_function}
930
+
931
+ def _load_func_addrs_from_eh_frame(self):
932
+ """
933
+ Get possible function addresses from .eh_frame.
934
+
935
+ :return: A set of addresses that are probably functions.
936
+ :rtype: set
937
+ """
938
+
939
+ addrs = set()
940
+ if isinstance(self._binary, ELF) and self._binary.has_dwarf_info:
941
+ for function_hint in self._binary.function_hints:
942
+ if function_hint.source == FunctionHintSource.EH_FRAME:
943
+ addrs.add(function_hint.addr)
944
+ return addrs
945
+
946
+ #
947
+ # Analyze function features
948
+ #
949
+
950
+ def _determine_function_returning(self, func, all_funcs_completed=False):
951
+ """
952
+ Determine if a function returns or not.
953
+
954
+ A function does not return if
955
+ a) it is a SimProcedure that has NO_RET being True,
956
+ or
957
+ b) it is completely recovered (i.e. every block of this function has been recovered, and no future block will
958
+ be added to it), and it does not have a ret or any equivalent instruction.
959
+
960
+ A function returns if any of its block contains a ret instruction or any equivalence.
961
+
962
+ :param Function func: The function to work on.
963
+ :param bool all_funcs_completed: Whether we treat all functions as completed functions or not.
964
+ :return: True if the function returns, False if the function does not return, or None if it is
965
+ not yet determinable with the information available at the moment.
966
+ :rtype: bool or None
967
+ """
968
+
969
+ if not self._inside_regions(func.addr):
970
+ # we don't have a full view of this function. assume it returns
971
+ return True
972
+
973
+ # If there is at least one return site, then this function is definitely returning
974
+ if func.has_return:
975
+ return True
976
+
977
+ # Let's first see if it's a known SimProcedure that does not return
978
+ if self.project.is_hooked(func.addr):
979
+ procedure = self.project.hooked_by(func.addr)
980
+ else:
981
+ try:
982
+ procedure = self.project.simos.syscall_from_addr(func.addr, allow_unsupported=False)
983
+ except AngrUnsupportedSyscallError:
984
+ procedure = None
985
+
986
+ if procedure is not None and hasattr(procedure, "NO_RET"):
987
+ return not procedure.NO_RET
988
+
989
+ # did we finish analyzing this function?
990
+ if not all_funcs_completed and func.addr not in self._completed_functions:
991
+ return None
992
+
993
+ if not func.block_addrs_set:
994
+ # there is no block inside this function
995
+ # it might happen if the function has been incorrectly identified as part of another function
996
+ # the error will be corrected during post-processing. In fact at this moment we cannot say anything
997
+ # about whether this function returns or not. We always assume it returns.
998
+ return True
999
+
1000
+ bail_out = False
1001
+
1002
+ # if this function has jump-out sites or ret-out sites, it returns as long as any of the target function
1003
+ # returns
1004
+ for goout_site, type_ in [(site, "jumpout") for site in func.jumpout_sites] + [
1005
+ (site, "retout") for site in func.retout_sites
1006
+ ]:
1007
+ # determine where it jumps/returns to
1008
+ goout_site_successors = goout_site.successors()
1009
+ # Filter out UnresolvableJumpTarget because those don't mean that we actually know where it jumps to
1010
+ known_successors = [
1011
+ n
1012
+ for n in goout_site_successors
1013
+ if not (isinstance(n, HookNode) and n.sim_procedure == UnresolvableJumpTarget)
1014
+ ]
1015
+
1016
+ if not known_successors:
1017
+ # not sure where it jumps to. bail out
1018
+ bail_out = True
1019
+ continue
1020
+
1021
+ # for ret-out sites, determine what function it calls
1022
+ if type_ == "retout":
1023
+ # see whether the function being called returns or not
1024
+ func_successors = [succ for succ in goout_site_successors if isinstance(succ, Function)]
1025
+ if func_successors and all(
1026
+ func_successor.returning in (None, False) for func_successor in func_successors
1027
+ ):
1028
+ # the returning of all possible function calls are undetermined, or they do not return
1029
+ # ignore this site
1030
+ continue
1031
+
1032
+ if type_ == "retout":
1033
+ goout_target = next((succ for succ in goout_site_successors if not isinstance(succ, Function)), None)
1034
+ else:
1035
+ goout_target = next((succ for succ in goout_site_successors), None)
1036
+ if goout_target is None:
1037
+ # there is no jumpout site, which is weird, but what can we do...
1038
+ continue
1039
+ if not self.kb.functions.contains_addr(goout_target.addr):
1040
+ # wait it does not jump to a function?
1041
+ bail_out = True
1042
+ continue
1043
+
1044
+ target_func = self.kb.functions[goout_target.addr]
1045
+ if target_func.returning is True:
1046
+ return True
1047
+ if target_func.returning is None:
1048
+ # the returning status of at least one of the target functions is not decided yet.
1049
+ bail_out = True
1050
+
1051
+ if bail_out:
1052
+ # We cannot determine at this point. bail out
1053
+ return None
1054
+
1055
+ # well this function does not return then
1056
+ return False
1057
+
1058
+ def _analyze_function_features(self, all_funcs_completed=False):
1059
+ """
1060
+ For each function in the function_manager, try to determine if it returns or not. A function does not return if
1061
+ it calls another function that is known to be not returning, and this function does not have other exits.
1062
+
1063
+ We might as well analyze other features of functions in the future.
1064
+
1065
+ :param bool all_funcs_completed: Ignore _completed_functions set and treat all functions as completed. This
1066
+ can be set to True after the entire CFG is built and _post_analysis() is
1067
+ called (at which point analysis on all functions must be completed).
1068
+ """
1069
+
1070
+ changes = {"functions_return": [], "functions_do_not_return": []}
1071
+
1072
+ if self._updated_nonreturning_functions is not None:
1073
+ all_func_addrs = self._updated_nonreturning_functions
1074
+
1075
+ # Convert addresses to objects
1076
+ all_functions = [
1077
+ self.kb.functions.get_by_addr(f) for f in all_func_addrs if self.kb.functions.contains_addr(f)
1078
+ ]
1079
+
1080
+ else:
1081
+ all_functions = list(self.kb.functions.values())
1082
+
1083
+ analyzed_functions = set()
1084
+ # short-hand
1085
+ functions: FunctionManager = self.kb.functions
1086
+
1087
+ while all_functions:
1088
+ func: Function = all_functions.pop(-1)
1089
+ analyzed_functions.add(func.addr)
1090
+
1091
+ if func.returning is not None:
1092
+ # It has been determined before. Skip it
1093
+ continue
1094
+
1095
+ returning = self._determine_function_returning(func, all_funcs_completed=all_funcs_completed)
1096
+
1097
+ if returning:
1098
+ func.returning = True
1099
+ changes["functions_return"].append(func)
1100
+ elif returning is False:
1101
+ func.returning = False
1102
+ changes["functions_do_not_return"].append(func)
1103
+
1104
+ if returning is not None and func.addr in functions.callgraph:
1105
+ # Add all callers of this function to all_functions list
1106
+ callers = functions.callgraph.predecessors(func.addr)
1107
+ for caller in callers:
1108
+ if caller in analyzed_functions:
1109
+ continue
1110
+ if functions.contains_addr(caller):
1111
+ all_functions.append(functions.get_by_addr(caller))
1112
+
1113
+ return changes
1114
+
1115
+ def _iteratively_analyze_function_features(self, all_funcs_completed=False):
1116
+ """
1117
+ Iteratively analyze function features until a fixed point is reached.
1118
+
1119
+ :return: the "changes" dict
1120
+ :rtype: dict
1121
+ """
1122
+
1123
+ changes = {"functions_do_not_return": set(), "functions_return": set()}
1124
+
1125
+ while True:
1126
+ new_changes = self._analyze_function_features(all_funcs_completed=all_funcs_completed)
1127
+
1128
+ changes["functions_do_not_return"] |= set(new_changes["functions_do_not_return"])
1129
+ changes["functions_return"] |= set(new_changes["functions_return"])
1130
+
1131
+ if not new_changes["functions_do_not_return"] and not new_changes["functions_return"]:
1132
+ # a fixed point is reached
1133
+ break
1134
+
1135
+ return changes
1136
+
1137
+ def normalize(self):
1138
+ """
1139
+ Normalize the CFG, making sure that there are no overlapping basic blocks.
1140
+
1141
+ Note that this method will not alter transition graphs of each function in self.kb.functions. You may call
1142
+ normalize() on each Function object to normalize their transition graphs.
1143
+
1144
+ :return: None
1145
+ """
1146
+
1147
+ graph = self.graph
1148
+
1149
+ smallest_nodes = {} # indexed by end address of the node
1150
+ end_addresses_to_nodes = defaultdict(set)
1151
+
1152
+ for n in graph.nodes():
1153
+ if n.is_simprocedure:
1154
+ continue
1155
+ end_addr = n.addr + n.size
1156
+ key = (end_addr, n.callstack_key)
1157
+ # add the new item
1158
+ end_addresses_to_nodes[key].add(n)
1159
+
1160
+ for key in list(end_addresses_to_nodes.keys()):
1161
+ if len(end_addresses_to_nodes[key]) == 1:
1162
+ smallest_nodes[key] = next(iter(end_addresses_to_nodes[key]))
1163
+ del end_addresses_to_nodes[key]
1164
+
1165
+ while end_addresses_to_nodes:
1166
+ key_to_find = (None, None)
1167
+ for tpl, x in end_addresses_to_nodes.items():
1168
+ if len(x) > 1:
1169
+ key_to_find = tpl
1170
+ break
1171
+
1172
+ end_addr, callstack_key = key_to_find
1173
+ all_nodes = end_addresses_to_nodes[key_to_find]
1174
+
1175
+ all_nodes = sorted(all_nodes, key=lambda node: node.addr, reverse=True)
1176
+ smallest_node = all_nodes[0] # take the one that has the highest address
1177
+ other_nodes = all_nodes[1:]
1178
+
1179
+ self._normalize_core(
1180
+ graph, callstack_key, smallest_node, other_nodes, smallest_nodes, end_addresses_to_nodes
1181
+ )
1182
+
1183
+ del end_addresses_to_nodes[key_to_find]
1184
+ # make sure the smallest node is stored in end_addresses
1185
+ smallest_nodes[key_to_find] = smallest_node
1186
+
1187
+ # corner case
1188
+ # sometimes two overlapping blocks may not be ending at the instruction. this might happen when one of the
1189
+ # blocks (the bigger one) hits the instruction count limit or bytes limit before reaching the end address
1190
+ # of the smaller block. in this case we manually pick up those blocks.
1191
+ if not end_addresses_to_nodes:
1192
+ # find if there are still overlapping blocks
1193
+ sorted_smallest_nodes = defaultdict(list) # callstack_key is the key of this dict
1194
+ for k, node in smallest_nodes.items():
1195
+ _, callstack_key = k
1196
+ sorted_smallest_nodes[callstack_key].append(node)
1197
+ for k in sorted_smallest_nodes:
1198
+ sorted_smallest_nodes[k] = sorted(sorted_smallest_nodes[k], key=lambda node: node.addr)
1199
+
1200
+ for callstack_key, lst in sorted_smallest_nodes.items():
1201
+ lst_len = len(lst)
1202
+ for i, node in enumerate(lst):
1203
+ if i == lst_len - 1:
1204
+ break
1205
+ next_node = lst[i + 1]
1206
+ if node is not next_node and node.addr <= next_node.addr < node.addr + node.size:
1207
+ # umm, those nodes are overlapping, but they must have different end addresses
1208
+ nodekey_a = node.addr + node.size, callstack_key
1209
+ nodekey_b = next_node.addr + next_node.size, callstack_key
1210
+ if nodekey_a == nodekey_b:
1211
+ # error handling: this will only happen if we have completely overlapping nodes
1212
+ # caused by different jumps (one of the jumps is probably incorrect), which usually
1213
+ # indicates an error in CFG recovery. we print a warning and skip this node
1214
+ l.warning(
1215
+ "Found completely overlapping nodes %s. It usually indicates an error in CFG "
1216
+ "recovery. Skip.",
1217
+ node,
1218
+ )
1219
+ continue
1220
+
1221
+ if nodekey_a in smallest_nodes and nodekey_b in smallest_nodes:
1222
+ # misuse end_addresses_to_nodes
1223
+ end_addresses_to_nodes[(node.addr + node.size, callstack_key)].add(node)
1224
+ end_addresses_to_nodes[(node.addr + node.size, callstack_key)].add(next_node)
1225
+
1226
+ smallest_nodes.pop(nodekey_a, None)
1227
+ smallest_nodes.pop(nodekey_b, None)
1228
+
1229
+ self.normalized = True
1230
+
1231
+ def _normalize_core(
1232
+ self,
1233
+ graph: networkx.DiGraph[CFGNode],
1234
+ callstack_key,
1235
+ smallest_node,
1236
+ other_nodes,
1237
+ smallest_nodes,
1238
+ end_addresses_to_nodes,
1239
+ ):
1240
+ # Break other nodes
1241
+ for n in other_nodes:
1242
+ new_size = get_real_address_if_arm(self.project.arch, smallest_node.addr) - get_real_address_if_arm(
1243
+ self.project.arch, n.addr
1244
+ )
1245
+ if new_size == 0:
1246
+ # This node has the same size as the smallest one. Don't touch it.
1247
+ continue
1248
+
1249
+ new_end_addr = n.addr + new_size
1250
+
1251
+ # Does it already exist?
1252
+ new_node = None
1253
+ key = (new_end_addr, n.callstack_key)
1254
+ # the logic below is a little convoluted. we check if key exists in either end_address_to_nodes or
1255
+ # smallest_nodes, since we don't always add the new node back to end_addresses_to_nodes dict - we only do so
1256
+ # when there are more than one node with that key.
1257
+ if key in end_addresses_to_nodes:
1258
+ new_node = next((i for i in end_addresses_to_nodes[key] if i.addr == n.addr), None)
1259
+ if new_node is None and key in smallest_nodes and smallest_nodes[key].addr == n.addr:
1260
+ new_node = smallest_nodes[key]
1261
+
1262
+ if new_node is None:
1263
+ # Create a new one
1264
+
1265
+ instruction_addrs = []
1266
+ for ins_addr in n.instruction_addrs:
1267
+ if n.addr <= ins_addr < n.addr + new_size:
1268
+ instruction_addrs.append(ins_addr)
1269
+ elif ins_addr == n.addr + new_size:
1270
+ break
1271
+ elif ins_addr > n.addr + new_size:
1272
+ # the immediate next instruction does not start right after the new node. this means we break
1273
+ # an existing instruction in the middle! we need to drop the last instruction address from
1274
+ # instruction_addrs.
1275
+ instruction_addrs.pop()
1276
+ break
1277
+ else:
1278
+ # should not happen if the instruction_addrs list is normal...
1279
+ break
1280
+
1281
+ if self.tag == "CFGFast":
1282
+ new_node = CFGNode(
1283
+ n.addr,
1284
+ new_size,
1285
+ self.model,
1286
+ function_address=n.function_address,
1287
+ block_id=n.block_id,
1288
+ instruction_addrs=instruction_addrs,
1289
+ thumb=n.thumb,
1290
+ )
1291
+ elif self.tag == "CFGEmulated":
1292
+ new_node = CFGENode(
1293
+ n.addr,
1294
+ new_size,
1295
+ self.model,
1296
+ callstack_key=callstack_key,
1297
+ function_address=n.function_address,
1298
+ block_id=n.block_id,
1299
+ instruction_addrs=instruction_addrs,
1300
+ thumb=n.thumb,
1301
+ )
1302
+ else:
1303
+ raise ValueError(f"Unknown tag {self.tag}.")
1304
+
1305
+ # Put the new node into end_addresses list
1306
+ if key in smallest_nodes:
1307
+ end_addresses_to_nodes[key].add(smallest_nodes[key])
1308
+ end_addresses_to_nodes[key].add(new_node)
1309
+ else:
1310
+ smallest_nodes[key] = new_node
1311
+
1312
+ # Modify the CFG
1313
+ original_predecessors = list(graph.in_edges([n], data=True))
1314
+ original_successors = list(graph.out_edges([n], data=True))
1315
+
1316
+ if smallest_node not in graph:
1317
+ continue
1318
+
1319
+ for _s, d, data in original_successors:
1320
+ ins_addr = data.get("ins_addr", None) # ins_addr might be None for FakeRet edges
1321
+ if ins_addr is None and data.get("jumpkind", None) != "Ijk_FakeRet":
1322
+ l.warning(
1323
+ "Unexpected edge with ins_addr being None: %s -> %s, data = %s.",
1324
+ _s,
1325
+ d,
1326
+ str(data),
1327
+ )
1328
+ if ins_addr is not None and ins_addr < smallest_node.addr:
1329
+ continue
1330
+ if d not in graph[smallest_node]:
1331
+ if d is n:
1332
+ graph.add_edge(smallest_node, new_node, **data)
1333
+ else:
1334
+ graph.add_edge(smallest_node, d, **data)
1335
+
1336
+ for p, _, _ in original_predecessors:
1337
+ graph.remove_edge(p, n)
1338
+ if n in graph:
1339
+ graph.remove_node(n)
1340
+
1341
+ # Update nodes dict
1342
+ self._model.remove_node(n.block_id, n)
1343
+ self._model.add_node(n.block_id, new_node)
1344
+
1345
+ for p, _, data in original_predecessors:
1346
+ # Consider the following case: two basic blocks ending at the same position, where A is larger, and
1347
+ # B is smaller. Suppose there is an edge going from the end of A to A itself, and apparently there
1348
+ # is another edge from B to A as well. After splitting A into A' and B, we DO NOT want to add A back
1349
+ # in, otherwise there will be an edge from A to A`, while A should totally be got rid of in the new
1350
+ # graph.
1351
+ if p not in other_nodes:
1352
+ graph.add_edge(p, new_node, **data)
1353
+
1354
+ # We should find the correct successor
1355
+ new_successors = [i for i in [smallest_node, *other_nodes] if i.addr == smallest_node.addr]
1356
+ if new_successors:
1357
+ new_successor = new_successors[0]
1358
+ graph.add_edge(
1359
+ new_node,
1360
+ new_successor,
1361
+ jumpkind="Ijk_Boring",
1362
+ ins_addr=new_node.instruction_addrs[-1] if new_node.instruction_addrs else new_node.addr,
1363
+ )
1364
+ else:
1365
+ # We gotta create a new one
1366
+ l.error("normalize(): Please report it to Fish.")
1367
+
1368
+ # update the jump tables dict and the indirect jumps dict
1369
+ if smallest_node.addr not in self.model.jump_tables:
1370
+ for n in other_nodes:
1371
+ if n.addr in self.model.jump_tables:
1372
+ self.model.jump_tables[n.addr].addr = smallest_node.addr
1373
+ self.model.jump_tables[smallest_node.addr] = self.model.jump_tables[n.addr]
1374
+ break
1375
+ if smallest_node.addr not in self.indirect_jumps:
1376
+ for n in other_nodes:
1377
+ if n.addr in self.indirect_jumps:
1378
+ self.indirect_jumps[n.addr].addr = smallest_node.addr
1379
+ self.indirect_jumps[smallest_node.addr] = self.indirect_jumps[n.addr]
1380
+ break
1381
+ # deal with duplicated entries in self.jump_tables and self.indirect_jumps
1382
+ if smallest_node.addr in self.model.jump_tables:
1383
+ for n in other_nodes:
1384
+ if n.addr in self.model.jump_tables:
1385
+ del self.model.jump_tables[n.addr]
1386
+ if smallest_node.addr in self.indirect_jumps:
1387
+ for n in other_nodes:
1388
+ if n.addr in self.indirect_jumps:
1389
+ del self.indirect_jumps[n.addr]
1390
+
1391
+ #
1392
+ # Job management
1393
+ #
1394
+
1395
+ def _register_analysis_job(self, func_addr, job):
1396
+ """
1397
+ Register an analysis job of a function to job manager. This allows us to track whether we have finished
1398
+ analyzing/recovering a function or not.
1399
+
1400
+ :param int func_addr: Address of the function that this job belongs to.
1401
+ :param job: The job to register. Note that it does not necessarily be the a CFGJob instance. There
1402
+ can be PendingJob or PendingJob or other instances, too.
1403
+ :return: None
1404
+ """
1405
+
1406
+ self._jobs_to_analyze_per_function[func_addr].add(job)
1407
+
1408
+ def _deregister_analysis_job(self, func_addr, job):
1409
+ """
1410
+ Deregister/Remove an analysis job of a function from job manager.
1411
+
1412
+ :param int func_addr: Address of the function that this job belongs to.
1413
+ :param job: The job to deregister.
1414
+ :return: None
1415
+ """
1416
+
1417
+ self._jobs_to_analyze_per_function[func_addr].discard(job)
1418
+
1419
+ def _get_finished_functions(self):
1420
+ """
1421
+ Obtain all functions of which we have finished analyzing. As _jobs_to_analyze_per_function is a defaultdict(),
1422
+ if a function address shows up in it with an empty job list, we consider we have exhausted all jobs of this
1423
+ function (both current jobs and pending jobs), thus the analysis of this function is done.
1424
+
1425
+ :return: a list of function addresses of that we have finished analysis.
1426
+ :rtype: list
1427
+ """
1428
+
1429
+ finished_func_addrs = []
1430
+ for func_addr, all_jobs in self._jobs_to_analyze_per_function.items():
1431
+ if not all_jobs:
1432
+ # great! we have finished analyzing this function!
1433
+ finished_func_addrs.append(func_addr)
1434
+
1435
+ return finished_func_addrs
1436
+
1437
+ def _cleanup_analysis_jobs(self, finished_func_addrs=None):
1438
+ """
1439
+ From job manager, remove all functions of which we have finished analysis.
1440
+
1441
+ :param list or None finished_func_addrs: A list of addresses of functions of which we have finished analysis.
1442
+ A new list of function addresses will be obtained by calling
1443
+ _get_finished_functions() if this parameter is None.
1444
+ :return: None
1445
+ """
1446
+
1447
+ if finished_func_addrs is None:
1448
+ finished_func_addrs = self._get_finished_functions()
1449
+
1450
+ for func_addr in finished_func_addrs:
1451
+ if func_addr in self._jobs_to_analyze_per_function:
1452
+ del self._jobs_to_analyze_per_function[func_addr]
1453
+
1454
+ def _make_completed_functions(self):
1455
+ """
1456
+ Fill in self._completed_functions list and clean up job manager.
1457
+
1458
+ :return: None
1459
+ """
1460
+
1461
+ finished = self._get_finished_functions()
1462
+ for func_addr in finished:
1463
+ if func_addr not in self._completed_functions:
1464
+ self._function_completed(func_addr)
1465
+ self._completed_functions.add(func_addr)
1466
+ self._cleanup_analysis_jobs(finished_func_addrs=finished)
1467
+
1468
+ #
1469
+ # Function identification and such
1470
+ #
1471
+
1472
+ def mark_function_alignments(self):
1473
+ """
1474
+ Find all potential function alignments and mark them.
1475
+
1476
+ Note that it is not always correct to simply remove them, because these functions may not be actual alignments
1477
+ but part of an actual function, and is incorrectly marked as an individual function because of failures in
1478
+ resolving indirect jumps. An example is in the test binary ``x86_64/dir_gcc_-O0`` 0x40541d (indirect jump at
1479
+ 0x4051b0). If the indirect jump cannot be correctly resolved, removing function 0x40541d will cause a missing
1480
+ label failure in reassembler.
1481
+
1482
+ :return: None
1483
+ """
1484
+
1485
+ # This function requires Capstone engine support
1486
+ if not self.project.arch.capstone_support:
1487
+ return
1488
+
1489
+ for func_addr in self.kb.functions:
1490
+ function = self.kb.functions[func_addr]
1491
+ if function.is_simprocedure or function.is_syscall:
1492
+ continue
1493
+ if len(function.block_addrs_set) == 1:
1494
+ block = next((b for b in function.blocks), None)
1495
+ if block is None:
1496
+ continue
1497
+ if self._is_noop_block(self.project.arch, block) or all(
1498
+ self._is_noop_insn(insn) for insn in block.capstone.insns
1499
+ ):
1500
+ # all nops. mark this function as a function alignment
1501
+ l.debug("Function chunk %#x is probably used as a function alignment (all nops).", func_addr)
1502
+ self.kb.functions[func_addr].is_alignment = True
1503
+ continue
1504
+ node = function.get_node(block.addr)
1505
+ assert node is not None
1506
+ successors = list(function.graph.successors(node))
1507
+ if len(successors) == 1 and successors[0].addr == node.addr:
1508
+ # self loop. mark this function as a function alignment
1509
+ l.debug("Function chunk %#x is probably used as a function alignment (self-loop).", func_addr)
1510
+ self.kb.functions[func_addr].is_alignment = True
1511
+ continue
1512
+
1513
+ def make_functions(self):
1514
+ """
1515
+ Revisit the entire control flow graph, create Function instances accordingly, and correctly put blocks into
1516
+ each function.
1517
+
1518
+ Although Function objects are created during the CFG recovery, they are neither sound nor accurate. With a
1519
+ pre-constructed CFG, this method rebuilds all functions bearing the following rules:
1520
+
1521
+ - A block may only belong to one function.
1522
+ - Small functions lying inside the startpoint and the endpoint of another function will be merged with the
1523
+ other function
1524
+ - Tail call optimizations are detected.
1525
+ - PLT stubs are aligned by 16.
1526
+
1527
+ :return: None
1528
+ """
1529
+
1530
+ # TODO: Is it required that PLT stubs are always aligned by 16? If so, on what architectures and platforms is it
1531
+ # TODO: enforced?
1532
+
1533
+ tmp_functions = self.kb.functions
1534
+
1535
+ for function in tmp_functions.values():
1536
+ function.mark_nonreturning_calls_endpoints()
1537
+ if function.returning is False:
1538
+ # remove all FakeRet edges that are related to this function
1539
+ func_node = self.model.get_any_node(function.addr, force_fastpath=True)
1540
+ if func_node is not None:
1541
+ callsite_nodes = [
1542
+ src
1543
+ for src, _, data in self.graph.in_edges(func_node, data=True)
1544
+ if data.get("jumpkind", None) == "Ijk_Call"
1545
+ ]
1546
+ for callsite_node in callsite_nodes:
1547
+ for _, dst, data in list(self.graph.out_edges(callsite_node, data=True)):
1548
+ if data.get("jumpkind", None) == "Ijk_FakeRet":
1549
+ self.graph.remove_edge(callsite_node, dst)
1550
+
1551
+ # Clear old functions dict by creating a new function manager
1552
+ self.kb.functions = FunctionManager(self.kb)
1553
+
1554
+ blockaddr_to_function = {}
1555
+ traversed_cfg_nodes = set()
1556
+
1557
+ function_nodes = set()
1558
+
1559
+ # Find nodes for beginnings of all functions
1560
+ for _, dst, data in self.graph.edges(data=True):
1561
+ jumpkind = data.get("jumpkind", "")
1562
+ if jumpkind == "Ijk_Call" or jumpkind.startswith("Ijk_Sys"):
1563
+ function_nodes.add(dst)
1564
+
1565
+ entry_node = self.model.get_any_node(self._binary.entry, force_fastpath=True)
1566
+ if entry_node is not None:
1567
+ function_nodes.add(entry_node)
1568
+
1569
+ # aggressively remove and merge functions
1570
+ # For any function, if there is a call to it, it won't be removed
1571
+ called_function_addrs = {n.addr for n in function_nodes}
1572
+ # Any function addresses that appear as symbols won't be removed
1573
+ predetermined_function_addrs = called_function_addrs | self._function_addresses_from_symbols
1574
+
1575
+ removed_functions_a = self._process_irrational_functions(
1576
+ tmp_functions, predetermined_function_addrs, blockaddr_to_function
1577
+ )
1578
+ removed_functions_b, adjusted_cfgnodes = self._process_irrational_function_starts(
1579
+ tmp_functions, predetermined_function_addrs, blockaddr_to_function
1580
+ )
1581
+ self._process_jump_table_targeted_functions(
1582
+ tmp_functions,
1583
+ predetermined_function_addrs,
1584
+ blockaddr_to_function,
1585
+ )
1586
+ removed_functions = removed_functions_a | removed_functions_b
1587
+
1588
+ # Remove all nodes that are adjusted
1589
+ function_nodes.difference_update(adjusted_cfgnodes)
1590
+ for n in self.graph.nodes():
1591
+ if n.addr in tmp_functions or n.addr in removed_functions:
1592
+ function_nodes.add(n)
1593
+
1594
+ # traverse the graph starting from each node, not following call edges
1595
+ # it's important that we traverse all functions in order so that we have a greater chance to come across
1596
+ # rational functions before its irrational counterparts (e.g. due to failed jump table resolution)
1597
+
1598
+ min_stage_2_progress = 50.0
1599
+ max_stage_2_progress = 90.0
1600
+ nodes_count = len(function_nodes)
1601
+ for i, fn in enumerate(sorted(function_nodes, key=lambda n: n.addr)):
1602
+ if self._low_priority:
1603
+ self._release_gil(i, 800, 0.000001)
1604
+
1605
+ if self._show_progressbar or self._progress_callback:
1606
+ progress = min_stage_2_progress + (max_stage_2_progress - min_stage_2_progress) * (
1607
+ i * 1.0 / nodes_count
1608
+ )
1609
+ self._update_progress(progress)
1610
+
1611
+ self._graph_bfs_custom(
1612
+ self.graph,
1613
+ [fn],
1614
+ self._graph_traversal_handler,
1615
+ blockaddr_to_function,
1616
+ tmp_functions,
1617
+ traversed_cfg_nodes,
1618
+ )
1619
+
1620
+ # Don't forget those small function chunks that are not called by anything.
1621
+ # There might be references to them from data, or simply references that we cannot find via static analysis
1622
+
1623
+ secondary_function_nodes = set()
1624
+ # add all function chunks ("functions" that are not called from anywhere)
1625
+ for func_addr in tmp_functions:
1626
+ node = self.model.get_any_node(func_addr, force_fastpath=True)
1627
+ if node is None:
1628
+ continue
1629
+ if node.addr not in blockaddr_to_function:
1630
+ secondary_function_nodes.add(node)
1631
+
1632
+ missing_cfg_nodes = set(self.graph.nodes()) - traversed_cfg_nodes
1633
+ missing_cfg_nodes = {node for node in missing_cfg_nodes if node.function_address is not None}
1634
+ if missing_cfg_nodes:
1635
+ l.debug("%d CFGNodes are missing in the first traversal.", len(missing_cfg_nodes))
1636
+ secondary_function_nodes |= missing_cfg_nodes
1637
+
1638
+ min_stage_3_progress = 90.0
1639
+ max_stage_3_progress = 99.9
1640
+
1641
+ nodes_count = len(secondary_function_nodes)
1642
+ for i, fn in enumerate(sorted(secondary_function_nodes, key=lambda n: n.addr)):
1643
+ if self._show_progressbar or self._progress_callback:
1644
+ progress = min_stage_3_progress + (max_stage_3_progress - min_stage_3_progress) * (
1645
+ i * 1.0 / nodes_count
1646
+ )
1647
+ self._update_progress(progress)
1648
+
1649
+ self._graph_bfs_custom(
1650
+ self.graph,
1651
+ [fn],
1652
+ self._graph_traversal_handler,
1653
+ blockaddr_to_function,
1654
+ tmp_functions,
1655
+ traversed_cfg_nodes,
1656
+ )
1657
+
1658
+ to_remove = set()
1659
+
1660
+ # Remove all stubs after PLT entries
1661
+ if not is_arm_arch(self.project.arch):
1662
+ to_remove |= self._remove_dummy_plt_stubs(self.kb.functions)
1663
+
1664
+ # remove empty functions
1665
+ for func in self.kb.functions.values():
1666
+ if func.startpoint is None:
1667
+ to_remove.add(func.addr)
1668
+
1669
+ for addr in to_remove:
1670
+ del self.kb.functions[addr]
1671
+
1672
+ # Update CFGNode.function_address
1673
+ for node in self._nodes.values():
1674
+ if node.addr in blockaddr_to_function:
1675
+ node.function_address = blockaddr_to_function[node.addr].addr
1676
+
1677
+ # Update function.info
1678
+ for func in self.kb.functions.values():
1679
+ if func.addr in tmp_functions:
1680
+ func.info = tmp_functions[func.addr].info
1681
+
1682
+ def _remove_dummy_plt_stubs(self, functions):
1683
+ def _is_function_a_plt_stub(arch_, func):
1684
+ if len(func.block_addrs_set) != 1:
1685
+ # multiple blocks? no idea what this is...
1686
+ return False
1687
+ block = next(func.blocks)
1688
+ if self._is_noop_block(arch_, block):
1689
+ # alignments
1690
+ return False
1691
+
1692
+ # TODO: We may want to add support for filtering dummy PLT stubs for other architectures, but I haven't
1693
+ # TODO: seen any need for those.
1694
+ return not (
1695
+ arch_.name in {"X86", "AMD64"}
1696
+ and len(block.vex.instruction_addresses) == 2
1697
+ and block.vex.jumpkind == "Ijk_Boring"
1698
+ )
1699
+
1700
+ to_remove = set()
1701
+
1702
+ met_plts = False
1703
+ non_plt_funcs = 0
1704
+ sorted_func_addrs = sorted(functions.keys())
1705
+ arch = self.project.arch
1706
+
1707
+ # we assume all PLT entries are all located at the same region. the moment we come across the end of it, we
1708
+ # stop looping.
1709
+ for fn_addr in sorted_func_addrs:
1710
+ fn = functions.get_by_addr(fn_addr)
1711
+ addr = fn.addr - (fn.addr % 16)
1712
+ if (
1713
+ addr != fn.addr
1714
+ and addr in functions
1715
+ and functions[addr].is_plt
1716
+ and not _is_function_a_plt_stub(arch, fn)
1717
+ ):
1718
+ to_remove.add(fn.addr)
1719
+ continue
1720
+
1721
+ if fn.is_plt:
1722
+ met_plts = True
1723
+ non_plt_funcs = 0
1724
+ if met_plts and not fn.is_plt:
1725
+ non_plt_funcs += 1
1726
+ if non_plt_funcs >= 2:
1727
+ break
1728
+
1729
+ return to_remove
1730
+
1731
+ def _process_irrational_functions(self, functions, predetermined_function_addrs, blockaddr_to_function):
1732
+ """
1733
+ When force_complete_scan is enabled, for unresolveable indirect jumps, angr will find jump targets and mark
1734
+ them as individual functions. For example, usually the following pattern is seen:
1735
+
1736
+ sub_0x400010:
1737
+ push ebp
1738
+ mov esp, ebp
1739
+ ...
1740
+ cmp eax, 10
1741
+ ja end
1742
+ mov eax, jumptable[eax]
1743
+ jmp eax
1744
+
1745
+ sub_0x400080:
1746
+ # do something here
1747
+ jmp end
1748
+
1749
+ end (0x400e00):
1750
+ pop ebp
1751
+ ret
1752
+
1753
+ In the example above, `process_irrational_functions` will remove function 0x400080, and merge it with function
1754
+ 0x400010.
1755
+
1756
+ :param angr.knowledge_plugins.FunctionManager functions: all functions that angr recovers, including those ones
1757
+ that are misidentified as functions.
1758
+ :param dict blockaddr_to_function: A mapping between block addresses and Function instances.
1759
+ :return: A set of addresses of all removed functions
1760
+ :rtype: set
1761
+ """
1762
+
1763
+ functions_to_remove = {}
1764
+
1765
+ all_func_addrs = sorted(set(functions.keys()))
1766
+
1767
+ for func_pos, (func_addr, function) in enumerate(functions.items()):
1768
+ if func_addr in functions_to_remove:
1769
+ continue
1770
+
1771
+ # check all blocks and see if any block ends with an indirect jump and is not resolved
1772
+ has_unresolved_jumps = False
1773
+ # the functions to merge with must be locating between the unresolved basic block address and the endpoint
1774
+ # of the current function
1775
+ max_unresolved_jump_addr = 0
1776
+ for block_addr in function.block_addrs_set:
1777
+ if (
1778
+ block_addr in self.indirect_jumps
1779
+ and self.indirect_jumps[block_addr].jumpkind == "Ijk_Boring"
1780
+ and not self.indirect_jumps[block_addr].resolved_targets
1781
+ ):
1782
+ # it's not resolved
1783
+ # we should also make sure it's a jump, not a call
1784
+ has_unresolved_jumps = True
1785
+ max_unresolved_jump_addr = max(max_unresolved_jump_addr, block_addr)
1786
+
1787
+ if not has_unresolved_jumps:
1788
+ continue
1789
+
1790
+ if function.startpoint is None:
1791
+ continue
1792
+
1793
+ startpoint_addr = function.startpoint.addr
1794
+ if not function.endpoints:
1795
+ # Function should have at least one endpoint
1796
+ continue
1797
+ endpoint_addr = max(a.addr for a in function.endpoints)
1798
+ the_endpoint = next(a for a in function.endpoints if a.addr == endpoint_addr)
1799
+ endpoint_addr += the_endpoint.size
1800
+
1801
+ # sanity check: startpoint of the function should be greater than its endpoint
1802
+ if startpoint_addr >= endpoint_addr:
1803
+ continue
1804
+ if max_unresolved_jump_addr <= startpoint_addr or max_unresolved_jump_addr >= endpoint_addr:
1805
+ continue
1806
+
1807
+ # scan forward from the endpoint to include any function-tail jumps
1808
+ # Here is an example:
1809
+ # loc_8049562:
1810
+ # mov eax, ebp
1811
+ # add esp, 3ch
1812
+ # ...
1813
+ # ret
1814
+ # loc_804956c:
1815
+ # mov ebp, 3
1816
+ # jmp loc_8049562
1817
+ # loc_8049573:
1818
+ # mov ebp, 4
1819
+ # jmp loc_8049562
1820
+ #
1821
+ last_addr = endpoint_addr
1822
+ while True:
1823
+ try:
1824
+ # do not follow hooked addresses (such as SimProcedures)
1825
+ if self.project.is_hooked(last_addr):
1826
+ break
1827
+
1828
+ next_block = self._lift(last_addr)
1829
+ next_block_irsb = next_block.vex_nostmt
1830
+ if next_block_irsb.jumpkind not in ("Ijk_Boring", "Ijk_InvalICache"):
1831
+ break
1832
+ if not isinstance(next_block_irsb.next, pyvex.IRExpr.Const):
1833
+ break
1834
+ suc_addr = next_block_irsb.next.con.value
1835
+ if (
1836
+ max(startpoint_addr, the_endpoint.addr - 0x40)
1837
+ <= suc_addr
1838
+ < the_endpoint.addr + the_endpoint.size
1839
+ ):
1840
+ # increment the endpoint_addr
1841
+ endpoint_addr = next_block.addr + next_block.size
1842
+ else:
1843
+ break
1844
+
1845
+ last_addr = next_block.addr + next_block.size
1846
+
1847
+ except (SimTranslationError, SimMemoryError, SimIRSBError, SimEngineError):
1848
+ break
1849
+
1850
+ # find all functions that are between [ startpoint, endpoint ]
1851
+
1852
+ should_merge = True
1853
+ functions_to_merge = set()
1854
+ i = func_pos + 1
1855
+ while i < len(all_func_addrs):
1856
+ f_addr = all_func_addrs[i]
1857
+ i += 1
1858
+ f = functions[f_addr]
1859
+ if f_addr == func_addr:
1860
+ continue
1861
+ if max_unresolved_jump_addr < f_addr < endpoint_addr and all(
1862
+ max_unresolved_jump_addr < b_addr < endpoint_addr for b_addr in f.block_addrs
1863
+ ):
1864
+ if f_addr in functions_to_remove:
1865
+ # this function has already been merged with other functions before... it cannot be merged with
1866
+ # this function anymore
1867
+ should_merge = False
1868
+ break
1869
+ if f_addr in predetermined_function_addrs:
1870
+ # this function is a legit one. it shouldn't be removed/merged
1871
+ should_merge = False
1872
+ break
1873
+ functions_to_merge.add(f_addr)
1874
+
1875
+ if not should_merge:
1876
+ # we shouldn't merge...
1877
+ continue
1878
+
1879
+ for f_addr in functions_to_merge:
1880
+ functions_to_remove[f_addr] = func_addr
1881
+
1882
+ # merge all functions
1883
+ for to_remove, merge_with in functions_to_remove.items():
1884
+ func_merge_with = self._addr_to_function(merge_with, blockaddr_to_function, functions)
1885
+
1886
+ for block_addr in functions[to_remove].block_addrs:
1887
+ blockaddr_to_function[block_addr] = func_merge_with
1888
+
1889
+ del functions[to_remove]
1890
+
1891
+ return set(functions_to_remove.keys())
1892
+
1893
+ def _process_irrational_function_starts(self, functions, predetermined_function_addrs, blockaddr_to_function):
1894
+ """
1895
+ Functions that are identified via function prologues can be starting after the actual beginning of the function.
1896
+ For example, the following function (with an incorrect start) might exist after a CFG recovery:
1897
+
1898
+ sub_8049f70:
1899
+ push esi
1900
+
1901
+ sub_8049f71:
1902
+ sub esp, 0A8h
1903
+ mov esi, [esp+0ACh+arg_0]
1904
+ mov [esp+0ACh+var_88], 0
1905
+
1906
+ If the following conditions are met, we will remove the second function and merge it into the first function:
1907
+ - The second function is not called by other code.
1908
+ - The first function has only one jumpout site, which points to the second function.
1909
+
1910
+ :param FunctionManager functions: All functions that angr recovers.
1911
+ :return: A set of addresses of all removed functions.
1912
+ :rtype: set
1913
+ """
1914
+
1915
+ addrs = sorted(
1916
+ k for k in functions if not self.project.is_hooked(k) and not self.project.simos.is_syscall_addr(k)
1917
+ )
1918
+ functions_to_remove = set()
1919
+ adjusted_cfgnodes = set()
1920
+
1921
+ for addr_0, addr_1 in zip(addrs[:-1], addrs[1:]):
1922
+ if addr_1 in predetermined_function_addrs:
1923
+ continue
1924
+ if addr_0 in functions_to_remove:
1925
+ continue
1926
+
1927
+ func_0 = functions[addr_0]
1928
+
1929
+ if len(func_0.block_addrs_set) >= 1:
1930
+ if len(func_0.jumpout_sites) != 1:
1931
+ continue
1932
+ block_node = func_0.jumpout_sites[0]
1933
+ if block_node is None:
1934
+ continue
1935
+ if block_node.size == 0:
1936
+ # skip empty blocks (that are usually caused by lifting failures)
1937
+ continue
1938
+ block = func_0.get_block(block_node.addr, block_node.size)
1939
+ if block.vex.jumpkind not in ("Ijk_Boring", "Ijk_InvalICache"):
1940
+ continue
1941
+ # Skip alignment blocks
1942
+ if self._is_noop_block(self.project.arch, block):
1943
+ continue
1944
+
1945
+ # does the first block transition to the next function?
1946
+ transition_found = False
1947
+ out_edges = list(func_0.transition_graph.out_edges(block_node, data=True))
1948
+ for _, dst_node, data in out_edges:
1949
+ if (
1950
+ dst_node.addr == addr_1
1951
+ and data.get("type", None) == "transition"
1952
+ and data.get("outside", False) is True
1953
+ ):
1954
+ transition_found = True
1955
+ break
1956
+
1957
+ if not transition_found:
1958
+ continue
1959
+
1960
+ cfgnode_0 = self.model.get_any_node(block_node.addr, force_fastpath=True)
1961
+ cfgnode_1 = self.model.get_any_node(addr_1, force_fastpath=True)
1962
+
1963
+ if cfgnode_0 is None or cfgnode_1 is None:
1964
+ continue
1965
+
1966
+ # who's jumping to or calling cfgnode_1?
1967
+ cfgnode_1_preds = self.model.get_predecessors_and_jumpkinds(cfgnode_1, excluding_fakeret=True)
1968
+ func_1 = functions[addr_1]
1969
+ abort = False
1970
+ for pred, jumpkind in cfgnode_1_preds:
1971
+ if pred.addr in func_0.block_addrs_set and jumpkind == "Ijk_Boring":
1972
+ # this is the transition from function 0
1973
+ continue
1974
+ if pred.addr in func_1.block_addrs_set:
1975
+ # this is a transition from function 1 itself
1976
+ continue
1977
+ # found an unexpected edge. give up
1978
+ abort = True
1979
+ break
1980
+ if abort:
1981
+ continue
1982
+
1983
+ # Merge block addr_0 and block addr_1
1984
+ l.debug("Merging function %#x into %#x.", addr_1, addr_0)
1985
+
1986
+ cfgnode_1_merged = False
1987
+ # we only merge two CFG nodes if the first one does not end with a branch instruction
1988
+ if (
1989
+ len(func_0.block_addrs_set) == 1
1990
+ and len(out_edges) == 1
1991
+ and out_edges[0][0].addr == cfgnode_0.addr
1992
+ and out_edges[0][0].size == cfgnode_0.size
1993
+ and self.project.factory.block(cfgnode_0.addr, strict_block_end=True).size > cfgnode_0.size
1994
+ ):
1995
+ cfgnode_1_merged = True
1996
+ self._merge_cfgnodes(cfgnode_0, cfgnode_1)
1997
+ adjusted_cfgnodes.add(cfgnode_0)
1998
+ adjusted_cfgnodes.add(cfgnode_1)
1999
+
2000
+ # Merge it
2001
+ func_1 = functions[addr_1]
2002
+ for block_addr in func_1.block_addrs:
2003
+ if block_addr == addr_1 and cfgnode_1_merged:
2004
+ # Skip addr_1 (since it has been merged to the preceding block)
2005
+ continue
2006
+ merge_with = self._addr_to_function(addr_0, blockaddr_to_function, functions)
2007
+ blockaddr_to_function[block_addr] = merge_with
2008
+
2009
+ functions_to_remove.add(addr_1)
2010
+
2011
+ for to_remove in functions_to_remove:
2012
+ del functions[to_remove]
2013
+
2014
+ return functions_to_remove, adjusted_cfgnodes
2015
+
2016
+ def _process_jump_table_targeted_functions(
2017
+ self, functions, predetermined_function_addrs, blockaddr_to_function
2018
+ ) -> set[int]:
2019
+ """
2020
+ Sometimes compilers will optimize "cold" code regions, make them separate functions, mark them as cold, which
2021
+ conflicts with how angr handles jumps to these functions (because they weren't functions to start with). Here
2022
+ is an example (in function version_etc_arn() from gllib)::
2023
+
2024
+ switch (n_authors) {
2025
+ case 0:
2026
+ abort();
2027
+ case 1:
2028
+ ...
2029
+ }
2030
+
2031
+ GCC may decide to move the `abort();` block under case 0 into a separate function (usually named
2032
+ "version_etc_arn_cold") and mark it as "cold." When loading function hints from eh frame is enabled, this
2033
+ function will be identified, and the recovered switch-case structure will have a jump to a function. It's
2034
+ usually not a problem until we need to decompile this function, where (at least for now) angr decompiler
2035
+ requires all switch-case entry blocks must belong to the same function.
2036
+
2037
+ The temporary solution is identifying functions that (a) have no call predecessors, and (b) are used as
2038
+ jump targets for identified jump tables. Remove these functions so that they can be treated as part of the
2039
+ source function where the corresponding jump table belongs.
2040
+ """
2041
+
2042
+ jumptable_entries: set[int] = set()
2043
+ for jt in self.model.jump_tables.values():
2044
+ assert jt.jumptable_entries is not None
2045
+ jumptable_entries |= set(jt.jumptable_entries)
2046
+
2047
+ if not jumptable_entries:
2048
+ return set()
2049
+
2050
+ functions_to_remove = set()
2051
+
2052
+ for func_addr in functions:
2053
+ if func_addr in predetermined_function_addrs:
2054
+ continue
2055
+ if func_addr in jumptable_entries:
2056
+ # is there any call edge pointing to it?
2057
+ func_node = self.model.get_any_node(func_addr, force_fastpath=True)
2058
+ if func_node is not None:
2059
+ in_edges = self.graph.in_edges(func_node, data=True)
2060
+ has_transition_pred = None
2061
+ has_non_transition_pred = None
2062
+ for _, _, data in in_edges:
2063
+ if data.get("jumpkind", None) == "Ijk_Boring":
2064
+ has_transition_pred = True
2065
+ else:
2066
+ has_non_transition_pred = True
2067
+ if has_transition_pred is True and not has_non_transition_pred:
2068
+ # all predecessors are transition-only
2069
+ # remove this function
2070
+ functions_to_remove.add(func_addr)
2071
+
2072
+ for to_remove in functions_to_remove:
2073
+ del functions[to_remove]
2074
+ if to_remove in blockaddr_to_function:
2075
+ del blockaddr_to_function[to_remove]
2076
+
2077
+ return functions_to_remove
2078
+
2079
+ def _addr_to_function(self, addr, blockaddr_to_function, known_functions):
2080
+ """
2081
+ Convert an address to a Function object, and store the mapping in a dict. If the block is known to be part of a
2082
+ function, just return that function.
2083
+
2084
+ :param int addr: Address to convert
2085
+ :param dict blockaddr_to_function: A mapping between block addresses to Function instances.
2086
+ :param angr.knowledge_plugins.FunctionManager known_functions: Recovered functions.
2087
+ :return: a Function object
2088
+ :rtype: angr.knowledge.Function
2089
+ """
2090
+
2091
+ if addr in blockaddr_to_function:
2092
+ f = blockaddr_to_function[addr]
2093
+ else:
2094
+ is_syscall = self.project.simos.is_syscall_addr(addr)
2095
+
2096
+ n = self.model.get_any_node(addr, is_syscall=is_syscall, force_fastpath=True)
2097
+ node = addr if n is None else self._to_snippet(n)
2098
+
2099
+ if isinstance(addr, SootAddressDescriptor):
2100
+ addr = addr.method
2101
+
2102
+ self.kb.functions._add_node(addr, node, syscall=is_syscall)
2103
+ f = self.kb.functions.function(addr=addr)
2104
+ assert f is not None
2105
+
2106
+ # copy over existing metadata
2107
+ if known_functions.contains_addr(addr):
2108
+ kf = known_functions.get_by_addr(addr)
2109
+ f.is_plt = kf.is_plt
2110
+
2111
+ blockaddr_to_function[addr] = f
2112
+
2113
+ function_is_returning = False
2114
+ if addr in known_functions and known_functions.function(addr).returning:
2115
+ f.returning = True
2116
+ function_is_returning = True
2117
+
2118
+ if not function_is_returning and self._updated_nonreturning_functions is not None:
2119
+ # We will rerun function feature analysis on this function later. Add it to
2120
+ # self._updated_nonreturning_functions so it can be picked up by function feature analysis later.
2121
+ self._updated_nonreturning_functions.add(addr)
2122
+
2123
+ return f
2124
+
2125
+ def _is_tail_call_optimization(
2126
+ self,
2127
+ g: networkx.DiGraph[CFGNode],
2128
+ src_addr,
2129
+ dst_addr,
2130
+ src_function,
2131
+ all_edges: list[tuple[CFGNode, CFGNode, Any]],
2132
+ known_functions,
2133
+ blockaddr_to_function,
2134
+ ):
2135
+ """
2136
+ If source and destination belong to the same function, and the following criteria apply:
2137
+ - source node has only one default exit
2138
+ - destination is not one of the known functions
2139
+ - destination does not belong to another function, or destination belongs to the same function that
2140
+ source belongs to
2141
+ - at the end of the block, the SP offset is 0
2142
+ - for all other edges that are pointing to the destination node, their source nodes must only have one default
2143
+ exit, too
2144
+
2145
+ :return: True if it is a tail-call optimization. False otherwise.
2146
+ :rtype: bool
2147
+ """
2148
+
2149
+ def _has_more_than_one_exit(node_):
2150
+ # Do not consider FakeRets as counting as multiple exits here.
2151
+ out_edges = [e for e in g.out_edges(node_) if g.get_edge_data(*e)["jumpkind"] != "Ijk_FakeRet"]
2152
+ return len(out_edges) > 1
2153
+
2154
+ if len(all_edges) == 1 and dst_addr != src_addr:
2155
+ the_edge = next(iter(all_edges))
2156
+ _, dst, data = the_edge
2157
+ if data.get("stmt_idx", None) != DEFAULT_STATEMENT:
2158
+ return False
2159
+
2160
+ # relift the source node to make sure it's not a fall-through target
2161
+ full_src_node = self.project.factory.block(src_addr)
2162
+ if full_src_node.size >= VEX_IRSB_MAX_SIZE or full_src_node.instructions >= VEX_IRSB_MAX_INST:
2163
+ # we are probably hitting the max-block limit in VEX
2164
+ return False
2165
+ if full_src_node.addr <= dst_addr < full_src_node.addr + full_src_node.size:
2166
+ return False
2167
+
2168
+ dst_in_edges = g.in_edges(dst, data=True)
2169
+ if len(dst_in_edges) > 1:
2170
+ # there are other edges going to the destination node. check all edges to make sure all source nodes
2171
+ # only have one default exit
2172
+ if any(data.get("stmt_idx", None) != DEFAULT_STATEMENT for _, _, data in dst_in_edges):
2173
+ # some nodes are jumping to the destination node via non-default edges. skip.
2174
+ return False
2175
+ if any(_has_more_than_one_exit(src_) for src_, _, _ in dst_in_edges):
2176
+ # at least one source node has more than just the default exit. skip.
2177
+ return False
2178
+
2179
+ candidate = False
2180
+ if dst_addr in known_functions:
2181
+ # dst_addr cannot be the same as src_function.addr. Pass
2182
+ pass
2183
+ elif dst_addr in blockaddr_to_function:
2184
+ # it seems that we already know where this function should belong to. Pass.
2185
+ dst_func = blockaddr_to_function[dst_addr]
2186
+ if dst_func is src_function:
2187
+ # they belong to the same function right now, but they'd better not
2188
+ candidate = True
2189
+ # treat it as a tail-call optimization
2190
+ else:
2191
+ # we don't know where it belongs to
2192
+ # treat it as a tail-call optimization
2193
+ candidate = True
2194
+
2195
+ if candidate:
2196
+ # we have two strategies; for small functions, we run SPTracker on the entire function and see if the
2197
+ # stack pointer changes or not; for large functions, we simply detect how far away we jump as well as
2198
+ # if there are any other functions identified between the source and the destination.
2199
+ if len(src_function.block_addrs_set) <= 10:
2200
+ regs = {self.project.arch.sp_offset}
2201
+ if hasattr(self.project.arch, "bp_offset") and self.project.arch.bp_offset is not None:
2202
+ regs.add(self.project.arch.bp_offset)
2203
+ sptracker = self.project.analyses[StackPointerTracker].prep()(
2204
+ src_function, regs, track_memory=self._sp_tracking_track_memory
2205
+ )
2206
+ sp_delta = sptracker.offset_after_block(src_addr, self.project.arch.sp_offset)
2207
+ if sp_delta == 0:
2208
+ return True
2209
+ else:
2210
+ # large function; to speed things up, we don't track sp
2211
+ minaddr, maxaddr = None, None
2212
+ if dst_addr - src_addr >= 0x100:
2213
+ minaddr = src_addr
2214
+ maxaddr = dst_addr
2215
+ elif dst_addr < src_addr:
2216
+ # jumping back; is it jumping beyond the function header?
2217
+ src_func = blockaddr_to_function[src_addr]
2218
+ if dst_addr < src_func.addr and src_func.addr - dst_addr >= 0x100:
2219
+ minaddr = dst_addr
2220
+ maxaddr = src_func.addr
2221
+
2222
+ if minaddr is not None and maxaddr is not None:
2223
+ # are there other function in between?
2224
+ funcaddrs_in_between = list(
2225
+ known_functions._function_map.irange(minimum=minaddr + 1, maximum=maxaddr - 1)
2226
+ )
2227
+ funcs_in_between = [known_functions.get_by_addr(a) for a in funcaddrs_in_between]
2228
+ funcs_in_between = [func for func in funcs_in_between if not func.is_alignment]
2229
+ if len(funcs_in_between) >= 3:
2230
+ return True
2231
+
2232
+ return False
2233
+
2234
+ def _graph_bfs_custom(self, g, starts, callback, blockaddr_to_function, known_functions, traversed_cfg_nodes=None):
2235
+ """
2236
+ A customized control flow graph BFS implementation with the following rules:
2237
+ - Call edges are not followed.
2238
+ - Syscall edges are not followed.
2239
+
2240
+ :param networkx.DiGraph g: The graph.
2241
+ :param list starts: A collection of beginning nodes to start graph traversal.
2242
+ :param func callback: Callback function for each edge and node.
2243
+ :param dict blockaddr_to_function: A mapping between block addresses to Function instances.
2244
+ :param angr.knowledge_plugins.FunctionManager known_functions: Already recovered functions.
2245
+ :param set traversed_cfg_nodes: A set of CFGNodes that are traversed before.
2246
+ :return: None
2247
+ """
2248
+
2249
+ stack = OrderedSet(starts)
2250
+ traversed = set() if traversed_cfg_nodes is None else traversed_cfg_nodes
2251
+
2252
+ while stack:
2253
+ n: CFGNode = stack.pop(last=False)
2254
+
2255
+ if n in traversed:
2256
+ continue
2257
+
2258
+ traversed.add(n)
2259
+
2260
+ if n.has_return:
2261
+ callback(g, n, None, {"jumpkind": "Ijk_Ret"}, blockaddr_to_function, known_functions, None)
2262
+ # NOTE: A block that has_return CAN have successors that aren't the return.
2263
+ # This is particularly the case for ARM conditional instructions. Yes, conditional rets are a thing.
2264
+
2265
+ if g.out_degree(n) == 0:
2266
+ # it's a single node
2267
+ callback(g, n, None, None, blockaddr_to_function, known_functions, None)
2268
+
2269
+ else:
2270
+ all_out_edges = g.out_edges(n, data=True)
2271
+ for src, dst, data in all_out_edges:
2272
+ callback(g, src, dst, data, blockaddr_to_function, known_functions, all_out_edges)
2273
+
2274
+ jumpkind = data.get("jumpkind", "")
2275
+ if (not (jumpkind in ("Ijk_Call", "Ijk_Ret") or jumpkind.startswith("Ijk_Sys"))) and (
2276
+ dst not in stack and dst not in traversed
2277
+ ):
2278
+ stack.add(dst)
2279
+
2280
+ def _graph_traversal_handler(self, g, src, dst, data, blockaddr_to_function, known_functions, all_edges):
2281
+ """
2282
+ Graph traversal handler. It takes in a node or an edge, and create new functions or add nodes to existing
2283
+ functions accordingly. Oh, it also create edges on the transition map of functions.
2284
+
2285
+ :param g: The control flow graph that is currently being traversed.
2286
+ :param CFGNode src: Beginning of the edge, or a single node when dst is None.
2287
+ :param CFGNode dst: Destination of the edge. For processing a single node, `dst` is None.
2288
+ :param dict data: Edge data in the CFG. 'jumpkind' should be there if it's not None.
2289
+ :param dict blockaddr_to_function: A mapping between block addresses to Function instances.
2290
+ :param angr.knowledge_plugins.FunctionManager known_functions: Already recovered functions.
2291
+ :param list or None all_edges: All edges going out from src.
2292
+ :return: None
2293
+ """
2294
+
2295
+ src_addr = src.addr
2296
+ src_function = self._addr_to_function(src_addr, blockaddr_to_function, known_functions)
2297
+
2298
+ if src_addr not in src_function.block_addrs_set:
2299
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2300
+ node = src_addr if n is None else self._to_snippet(n)
2301
+ self.kb.functions._add_node(src_function.addr, node)
2302
+
2303
+ if data is None:
2304
+ # it's a single node only
2305
+ return
2306
+
2307
+ jumpkind = data["jumpkind"]
2308
+
2309
+ if jumpkind == "Ijk_Ret":
2310
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2311
+ from_node = src_addr if n is None else self._to_snippet(n)
2312
+ self.kb.functions._add_return_from(src_function.addr, from_node, None)
2313
+
2314
+ if dst is None:
2315
+ return
2316
+
2317
+ dst_addr = dst.addr
2318
+
2319
+ # get instruction address and statement index
2320
+ ins_addr = data.get("ins_addr", None)
2321
+ stmt_idx = data.get("stmt_idx", None)
2322
+
2323
+ if jumpkind == "Ijk_Call" or jumpkind.startswith("Ijk_Sys"):
2324
+ is_syscall = jumpkind.startswith("Ijk_Sys")
2325
+
2326
+ # It must be calling a function
2327
+ dst_function = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2328
+
2329
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2330
+ if n is None:
2331
+ src_snippet = self._to_snippet(addr=src_addr, base_state=self._base_state)
2332
+ else:
2333
+ src_snippet = self._to_snippet(cfg_node=n)
2334
+
2335
+ # HACK: FIXME: We need a better way of representing unresolved calls and whether they return.
2336
+ # For now, assume UnresolvedTarget returns if we're calling to it
2337
+
2338
+ # If the function doesn't return, don't add a fakeret!
2339
+ if not all_edges or (dst_function.returning is False and dst_function.name != "UnresolvableCallTarget"):
2340
+ fakeret_node = None
2341
+ else:
2342
+ fakeret_node = self._one_fakeret_node(all_edges)
2343
+
2344
+ if isinstance(dst_addr, SootAddressDescriptor):
2345
+ dst_addr = dst_addr.method
2346
+
2347
+ # determining the returning target
2348
+ return_to_outside = False
2349
+ returning_snippet = None
2350
+ if dst_function.returning and fakeret_node is not None:
2351
+ returning_target = src.addr + src.size
2352
+ if returning_target not in blockaddr_to_function:
2353
+ if returning_target not in known_functions:
2354
+ blockaddr_to_function[returning_target] = src_function
2355
+ else:
2356
+ self._addr_to_function(returning_target, blockaddr_to_function, known_functions)
2357
+
2358
+ return_to_outside = blockaddr_to_function[returning_target] is not src_function
2359
+
2360
+ n = self.model.get_any_node(returning_target, force_fastpath=True)
2361
+ if n is None:
2362
+ try:
2363
+ returning_snippet = self._to_snippet(addr=returning_target, base_state=self._base_state)
2364
+ except SimEngineError:
2365
+ # it may not exist
2366
+ returning_snippet = None
2367
+ else:
2368
+ returning_snippet = self._to_snippet(cfg_node=n)
2369
+
2370
+ self.kb.functions._add_call_to(
2371
+ src_function.addr,
2372
+ src_snippet,
2373
+ dst_addr,
2374
+ retn_node=returning_snippet,
2375
+ syscall=is_syscall,
2376
+ ins_addr=ins_addr,
2377
+ stmt_idx=stmt_idx,
2378
+ return_to_outside=return_to_outside,
2379
+ )
2380
+
2381
+ if returning_snippet is not None:
2382
+ self.kb.functions._add_fakeret_to(
2383
+ src_function.addr, src_snippet, returning_snippet, confirmed=True, to_outside=return_to_outside
2384
+ )
2385
+
2386
+ elif jumpkind in ("Ijk_Boring", "Ijk_InvalICache", "Ijk_Exception"):
2387
+ # convert src_addr and dst_addr to CodeNodes
2388
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2389
+ src_node = src_addr if n is None else self._to_snippet(cfg_node=n)
2390
+
2391
+ n = self.model.get_any_node(dst_addr, force_fastpath=True)
2392
+ dst_node = dst_addr if n is None else self._to_snippet(cfg_node=n)
2393
+
2394
+ if self._skip_unmapped_addrs:
2395
+ # pre-check: if source and destination do not belong to the same section, it must be jumping to another
2396
+ # function
2397
+ belong_to_same_section = self._addrs_belong_to_same_section(src_addr, dst_addr)
2398
+ if not belong_to_same_section:
2399
+ _ = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2400
+
2401
+ if self._detect_tail_calls and self._is_tail_call_optimization(
2402
+ g, src_addr, dst_addr, src_function, all_edges, known_functions, blockaddr_to_function
2403
+ ):
2404
+ l.debug("Possible tail-call optimization detected at function %#x.", dst_addr)
2405
+ # it's (probably) a tail-call optimization. we should make the destination node a new function
2406
+ # instead.
2407
+ blockaddr_to_function.pop(dst_addr, None)
2408
+ _ = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2409
+ self.kb.functions._add_outside_transition_to(
2410
+ src_function.addr, src_node, dst_node, to_function_addr=dst_addr
2411
+ )
2412
+ self._tail_calls.add(dst_addr)
2413
+
2414
+ # is it a jump to another function?
2415
+ if isinstance(dst_addr, SootAddressDescriptor):
2416
+ is_known_function_addr = dst_addr.method in known_functions and dst_addr.method.addr == dst_addr
2417
+ else:
2418
+ is_known_function_addr = dst_addr in known_functions
2419
+
2420
+ if (is_known_function_addr and dst_addr != src_function.addr) or (
2421
+ dst_addr in blockaddr_to_function and blockaddr_to_function[dst_addr] is not src_function
2422
+ ):
2423
+ # yes it is
2424
+ dst_function_addr = (
2425
+ blockaddr_to_function[dst_addr].addr if dst_addr in blockaddr_to_function else dst_addr
2426
+ )
2427
+
2428
+ self.kb.functions._add_outside_transition_to(
2429
+ src_function.addr,
2430
+ src_node,
2431
+ dst_node,
2432
+ ins_addr=ins_addr,
2433
+ stmt_idx=stmt_idx,
2434
+ to_function_addr=dst_function_addr,
2435
+ is_exception=jumpkind == "Ijk_Exception",
2436
+ )
2437
+
2438
+ _ = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2439
+ else:
2440
+ # no it's not
2441
+ # add the transition code
2442
+
2443
+ if dst_addr not in blockaddr_to_function:
2444
+ blockaddr_to_function[dst_addr] = src_function
2445
+
2446
+ self.kb.functions._add_transition_to(
2447
+ src_function.addr,
2448
+ src_node,
2449
+ dst_node,
2450
+ ins_addr=ins_addr,
2451
+ stmt_idx=stmt_idx,
2452
+ is_exception=jumpkind == "Ijk_Exception",
2453
+ )
2454
+
2455
+ elif jumpkind == "Ijk_FakeRet":
2456
+ # convert src_addr and dst_addr to CodeNodes
2457
+ n = self.model.get_any_node(src_addr, force_fastpath=True)
2458
+ src_node = src_addr if n is None else self._to_snippet(n)
2459
+
2460
+ n = self.model.get_any_node(dst_addr, force_fastpath=True)
2461
+ dst_node = dst_addr if n is None else self._to_snippet(n)
2462
+
2463
+ if dst_addr not in blockaddr_to_function:
2464
+ if isinstance(dst_addr, SootAddressDescriptor):
2465
+ if dst_addr.method not in known_functions:
2466
+ blockaddr_to_function[dst_addr] = src_function
2467
+ target_function = src_function
2468
+ else:
2469
+ target_function = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2470
+ else:
2471
+ if dst_addr not in known_functions:
2472
+ blockaddr_to_function[dst_addr] = src_function
2473
+ target_function = src_function
2474
+ else:
2475
+ target_function = self._addr_to_function(dst_addr, blockaddr_to_function, known_functions)
2476
+ else:
2477
+ target_function = blockaddr_to_function[dst_addr]
2478
+
2479
+ # Figure out if the function called (not the function returned to) returns.
2480
+ # We may have determined that this does not happen, since the time this path
2481
+ # was scheduled for exploration
2482
+ called_function = None
2483
+ called_function_addr = None
2484
+ # Try to find the call that this fakeret goes with
2485
+ for _, d, e in all_edges:
2486
+ if e["jumpkind"] == "Ijk_Call" and d.addr in blockaddr_to_function:
2487
+ called_function = blockaddr_to_function[d.addr]
2488
+ called_function_addr = d.addr
2489
+ break
2490
+ # We may have since figured out that the called function doesn't ret.
2491
+ # It's important to assume that all unresolved targets do return
2492
+ if called_function is not None and called_function.returning is False:
2493
+ return
2494
+
2495
+ to_outside = target_function is not src_function
2496
+
2497
+ confirmed = called_function is None or called_function.returning is True
2498
+ self.kb.functions._add_fakeret_to(
2499
+ src_function.addr,
2500
+ src_node,
2501
+ dst_node,
2502
+ confirmed=confirmed,
2503
+ to_outside=to_outside,
2504
+ to_function_addr=called_function_addr,
2505
+ )
2506
+
2507
+ else:
2508
+ l.debug("Ignored jumpkind %s", jumpkind)
2509
+
2510
+ #
2511
+ # Other functions
2512
+ #
2513
+
2514
+ @staticmethod
2515
+ def _is_noop_jump_block(block) -> bool:
2516
+ """
2517
+ Check if the block does nothing but jumping to a constant address.
2518
+
2519
+ :param block: The block instance. We assume the block is already optimized.
2520
+ :return: True if the entire block is a jump to a constant address, False otherwise.
2521
+ """
2522
+
2523
+ vex = block.vex
2524
+ if vex.jumpkind != "Ijk_Boring":
2525
+ return False
2526
+ if isinstance(vex.next, pyvex.expr.Const):
2527
+ return all(isinstance(stmt, pyvex.stmt.IMark) for stmt in vex.statements)
2528
+ if isinstance(vex.next, pyvex.expr.RdTmp):
2529
+ next_tmp = vex.next.tmp
2530
+ return all(
2531
+ isinstance(stmt, pyvex.stmt.IMark)
2532
+ or (
2533
+ isinstance(stmt, pyvex.stmt.WrTmp)
2534
+ and stmt.tmp == next_tmp
2535
+ and isinstance(stmt.data, pyvex.expr.Load)
2536
+ and isinstance(stmt.data.addr, pyvex.expr.Const)
2537
+ )
2538
+ for stmt in vex.statements
2539
+ )
2540
+ return False
2541
+
2542
+ @staticmethod
2543
+ def _is_noop_block(arch: archinfo.Arch, block) -> bool:
2544
+ """
2545
+ Check if the block is a no-op block by checking VEX statements.
2546
+
2547
+ :param arch: An architecture descriptor.
2548
+ :param block: The VEX block instance.
2549
+ :return: True if the entire block is a single-byte or multi-byte nop instruction, False otherwise.
2550
+ """
2551
+
2552
+ if arch.name == "X86" or arch.name == "AMD64":
2553
+ if set(block.bytes) == {0x90}:
2554
+ return True
2555
+ elif arch.name == "MIPS32":
2556
+ if arch.memory_endness == "Iend_BE":
2557
+ MIPS32_BE_NOOPS = {
2558
+ b"\x00\x20\x08\x25", # move $at, $at
2559
+ }
2560
+ insns = {block.bytes[i : i + 4] for i in range(0, block.size, 4)}
2561
+ if MIPS32_BE_NOOPS.issuperset(insns):
2562
+ return True
2563
+
2564
+ elif is_arm_arch(arch):
2565
+ if block.addr & 1 == 0:
2566
+ # ARM mode
2567
+ if arch.memory_endness == archinfo.Endness.LE:
2568
+ ARM_NOOPS = {
2569
+ b"\x00\x00\x00\x00", # andeq r0, r0, r0
2570
+ b"\x00\x00\xa0\xe1", # mov r0, r0
2571
+ }
2572
+ else: # if arch.memory_endness == archinfo.Endness.BE:
2573
+ ARM_NOOPS = {
2574
+ b"\x00\x00\x00\x00", # andeq r0, r0, r0
2575
+ b"\xe1\xa0\x00\x00", # mov r0, r0
2576
+ }
2577
+ insns = {block.bytes[i : i + 4] for i in range(0, block.size, 4)}
2578
+ if ARM_NOOPS.issuperset(insns):
2579
+ return True
2580
+
2581
+ else:
2582
+ # THUMB mode, 2-byte instructions
2583
+ if arch.memory_endness == archinfo.Endness.LE:
2584
+ THUMB_NOOPS = {
2585
+ b"\xc0\x46", # mov r8, r8
2586
+ b"\xb0\x00", # add sp, #0
2587
+ b"\x00\xbf", # nop
2588
+ }
2589
+ else:
2590
+ THUMB_NOOPS = {
2591
+ b"\x46\xc0", # mov r8, r8
2592
+ b"\x00\xb0", # add sp, #0
2593
+ b"\xbf\x00", # nop
2594
+ }
2595
+ insns = {block.bytes[i : i + 2] for i in range(0, block.size, 2)}
2596
+ if THUMB_NOOPS.issuperset(insns):
2597
+ return True
2598
+
2599
+ return block.vex_nostmt.is_noop_block
2600
+
2601
+ @staticmethod
2602
+ def _is_noop_insn(insn):
2603
+ """
2604
+ Check if the instruction does nothing.
2605
+
2606
+ :param insn: The capstone insn object.
2607
+ :return: True if the instruction does no-op, False otherwise.
2608
+ """
2609
+
2610
+ insn_name = insn.mnemonic
2611
+
2612
+ if insn_name == "nop":
2613
+ # nops
2614
+ return True
2615
+ if insn_name == "lea":
2616
+ # lea reg, [reg + 0]
2617
+ op0, op1 = insn.operands
2618
+ # reg and mem
2619
+ if op0.type == 1 and op1.type == 3 and op0.reg == op1.mem.base and op1.mem.index == 0 and op1.mem.disp == 0:
2620
+ return True
2621
+ elif insn_name == "mov":
2622
+ if len(insn.operands) > 2:
2623
+ # mov reg_a, imm1, shift imm2
2624
+ # This is not a NOP
2625
+ return False
2626
+ # mov reg_a, reg_a
2627
+ op0, op1 = insn.operands
2628
+ # reg and reg
2629
+ if op0.type == 1 and op1.type == 1 and op0.reg == op1.reg:
2630
+ return True
2631
+ elif insn_name in {"ud0", "ud1", "ud2"}:
2632
+ return True
2633
+
2634
+ # add more types of no-op instructions here :-)
2635
+
2636
+ return False
2637
+
2638
+ @classmethod
2639
+ def _get_nop_length(cls, insns):
2640
+ """
2641
+ Calculate the total size of leading nop instructions.
2642
+
2643
+ :param insns: A list of capstone insn objects.
2644
+ :return: Number of bytes of leading nop instructions.
2645
+ :rtype: int
2646
+ """
2647
+
2648
+ nop_length = 0
2649
+
2650
+ if insns and cls._is_noop_insn(insns[0]):
2651
+ # see where those nop instructions terminate
2652
+ for insn in insns:
2653
+ if cls._is_noop_insn(insn):
2654
+ nop_length += insn.size
2655
+ else:
2656
+ break
2657
+
2658
+ return nop_length
2659
+
2660
+ @staticmethod
2661
+ def _one_fakeret_node(all_edges):
2662
+ """
2663
+ Pick the first Ijk_FakeRet edge from all_edges, and return the destination node.
2664
+
2665
+ :param list all_edges: A list of networkx.Graph edges with data.
2666
+ :return: The first FakeRet node, or None if nothing is found.
2667
+ :rtype: CFGNode or None
2668
+ """
2669
+
2670
+ for _, dst, data in all_edges:
2671
+ if data.get("jumpkind", None) == "Ijk_FakeRet":
2672
+ return dst
2673
+ return None
2674
+
2675
+ def _lift(self, addr, *args, opt_level=1, cross_insn_opt=False, **kwargs):
2676
+ """
2677
+ Lift a basic block of code. Will use the base state as a source of bytes if possible.
2678
+ """
2679
+ if "backup_state" not in kwargs:
2680
+ kwargs["backup_state"] = self._base_state
2681
+ return self.project.factory.block(addr, *args, opt_level=opt_level, cross_insn_opt=cross_insn_opt, **kwargs)
2682
+
2683
+ #
2684
+ # Indirect jumps processing
2685
+ #
2686
+
2687
+ def _resolve_indirect_jump_timelessly(self, addr, block, func_addr, jumpkind):
2688
+ """
2689
+ Attempt to quickly resolve an indirect jump.
2690
+
2691
+ :param int addr: Basic block address of this indirect jump.
2692
+ :param block: The basic block. The type is determined by the backend being used. It's pyvex.IRSB if
2693
+ pyvex is used as the backend.
2694
+ :param int func_addr: Address of the function that this indirect jump belongs to.
2695
+ :param str jumpkind: The jumpkind.
2696
+ :return: A tuple of a boolean indicating whether the resolution is successful or not, and a list
2697
+ of resolved targets (ints).
2698
+ :rtype: tuple
2699
+ """
2700
+
2701
+ # pre-check: if re-lifting the block with full optimization (cross-instruction-optimization enabled) gives us
2702
+ # a constant next expression, we don't need to resolve it
2703
+ try:
2704
+ relifted = self.project.factory.block(block.addr, size=block.size, opt_level=1, cross_insn_opt=True).vex
2705
+ except SimError:
2706
+ return False, []
2707
+ if not relifted.jumpkind.startswith("Ijk_Sys") and isinstance(relifted.next, pyvex.IRExpr.Const):
2708
+ # yes!
2709
+ return True, [relifted.next.con.value]
2710
+
2711
+ if block.statements is None:
2712
+ # make sure there are statements
2713
+ block = self.project.factory.block(block.addr, size=block.size).vex
2714
+
2715
+ for res in self.timeless_indirect_jump_resolvers:
2716
+ if res.filter(self, addr, func_addr, block, jumpkind):
2717
+ r, resolved_targets = res.resolve(self, addr, func_addr, block, jumpkind)
2718
+ if r:
2719
+ return True, resolved_targets
2720
+ return False, []
2721
+
2722
+ def _indirect_jump_resolved(self, jump, jump_addr, resolved_by, targets):
2723
+ """
2724
+ Called when an indirect jump is successfully resolved.
2725
+
2726
+ :param IndirectJump jump: The resolved indirect jump, or None if an IndirectJump instance is
2727
+ not available.
2728
+ :param int jump_addr: Address of the resolved indirect jump.
2729
+ :param IndirectJumpResolver resolved_by: The resolver used to resolve this indirect jump.
2730
+ :param list targets: List of indirect jump targets.
2731
+ :param CFGJob job: The job at the start of the block containing the indirect jump.
2732
+
2733
+ :return: None
2734
+ """
2735
+
2736
+ addr = jump.addr if jump is not None else jump_addr
2737
+ l.debug(
2738
+ "The indirect jump at %#x is successfully resolved by %s. It has %d targets.",
2739
+ addr,
2740
+ resolved_by,
2741
+ len(targets),
2742
+ )
2743
+ self.kb.indirect_jumps.update_resolved_addrs(addr, targets)
2744
+
2745
+ def _indirect_jump_unresolved(self, jump):
2746
+ """
2747
+ Called when we cannot resolve an indirect jump.
2748
+
2749
+ :param IndirectJump jump: The unresolved indirect jump.
2750
+
2751
+ :return: None
2752
+ """
2753
+
2754
+ l.debug("Failed to resolve the indirect jump at %#x.", jump.addr)
2755
+ # tell KnowledgeBase that it's not resolved
2756
+ # TODO: self.kb._unresolved_indirect_jumps is not processed during normalization. Fix it.
2757
+ self.kb.unresolved_indirect_jumps.add(jump.addr)
2758
+
2759
+ def _indirect_jump_encountered(
2760
+ self,
2761
+ addr: int,
2762
+ cfg_node: CFGNode,
2763
+ irsb: pyvex.IRSB,
2764
+ func_addr: int,
2765
+ stmt_idx: int = DEFAULT_STATEMENT,
2766
+ ) -> tuple[bool, set[int], IndirectJump | None]:
2767
+ """
2768
+ Called when we encounter an indirect jump. We will try to resolve this indirect jump using timeless (fast)
2769
+ indirect jump resolvers. If it cannot be resolved, we will see if this indirect jump has been resolved before.
2770
+
2771
+ :param addr: Address of the block containing the indirect jump.
2772
+ :param cfg_node: The CFGNode instance of the block that contains the indirect jump.
2773
+ :param irsb: The IRSB instance of the block that contains the indirect jump. It must be lifted with
2774
+ cross-instruction optimization disabled (cross_insn_opt=True when opt_level=1, or
2775
+ opt_level=0).
2776
+ :param func_addr: Address of the current function.
2777
+ :param stmt_idx: ID of the source statement.
2778
+
2779
+ :return: A 3-tuple of (whether it is resolved or not, all resolved targets, an IndirectJump object
2780
+ if there is one or None otherwise)
2781
+ """
2782
+
2783
+ jumpkind = irsb.jumpkind
2784
+ l.debug("IRSB %#x has an indirect jump (%s) as its default exit.", addr, jumpkind)
2785
+
2786
+ # try resolving it fast
2787
+ resolved, resolved_targets = self._resolve_indirect_jump_timelessly(addr, irsb, func_addr, jumpkind)
2788
+ if resolved:
2789
+ l.debug(
2790
+ "Indirect jump at block %#x is resolved by a timeless indirect jump resolver. %d targets found.",
2791
+ addr,
2792
+ len(resolved_targets),
2793
+ )
2794
+ return True, set(resolved_targets), None
2795
+
2796
+ l.debug("Indirect jump at block %#x cannot be resolved by a timeless indirect jump resolver.", addr)
2797
+
2798
+ # Add it to our set. Will process it later if user allows.
2799
+ # Create an IndirectJump instance
2800
+ if addr not in self.indirect_jumps:
2801
+ if self.project.arch.branch_delay_slot:
2802
+ if len(cfg_node.instruction_addrs) < 2:
2803
+ # sanity check
2804
+ # decoding failed when decoding the second instruction (or even the first instruction)
2805
+ return False, set(), None
2806
+ ins_addr = cfg_node.instruction_addrs[-2]
2807
+ elif cfg_node.instruction_addrs:
2808
+ ins_addr = cfg_node.instruction_addrs[-1]
2809
+ else:
2810
+ # fallback
2811
+ ins_addr = addr
2812
+ assert jumpkind is not None
2813
+ ij = IndirectJump(addr, ins_addr, func_addr, jumpkind, stmt_idx, resolved_targets=[])
2814
+ self.indirect_jumps[addr] = ij
2815
+ resolved = False
2816
+ else:
2817
+ ij: IndirectJump = self.indirect_jumps[addr]
2818
+ resolved = len(ij.resolved_targets) > 0
2819
+
2820
+ return resolved, ij.resolved_targets, ij
2821
+
2822
+ def _process_unresolved_indirect_jumps(self):
2823
+ """
2824
+ Resolve all unresolved indirect jumps found in previous scanning.
2825
+
2826
+ Currently we support resolving the following types of indirect jumps:
2827
+ - Ijk_Call: indirect calls where the function address is passed in from a proceeding basic block
2828
+ - Ijk_Boring: jump tables
2829
+ - For an up-to-date list, see analyses/cfg/indirect_jump_resolvers
2830
+
2831
+ :return: A set of concrete indirect jump targets (ints).
2832
+ :rtype: set
2833
+ """
2834
+
2835
+ l.info("%d indirect jumps to resolve.", len(self._indirect_jumps_to_resolve))
2836
+
2837
+ all_targets = set()
2838
+ idx: int
2839
+ jump: IndirectJump
2840
+ for idx, jump in enumerate(self._indirect_jumps_to_resolve):
2841
+ if self._low_priority:
2842
+ self._release_gil(idx, 50, 0.000001)
2843
+ all_targets |= self._process_one_indirect_jump(jump)
2844
+
2845
+ self._indirect_jumps_to_resolve.clear()
2846
+
2847
+ return all_targets
2848
+
2849
+ def _process_one_indirect_jump(self, jump: IndirectJump, func_graph_complete: bool = True) -> set:
2850
+ """
2851
+ Resolve a given indirect jump.
2852
+
2853
+ :param jump: The IndirectJump instance.
2854
+ :param func_graph_complete: True if the function graph is complete at this point (except for this indirect jump
2855
+ and all nodes that it dominates). Indirect jump resolvers may use the current
2856
+ function graph to perform sanity checks. CFGEmulated sets func_graph_complete to
2857
+ False while CFGFast sets it to True (because in CFGFast, indirect jumps are always
2858
+ resolved after direct jump jobs are processed).
2859
+ :return: A set of resolved indirect jump targets (ints).
2860
+ """
2861
+
2862
+ resolved = False
2863
+ resolved_by = None
2864
+ targets = None
2865
+
2866
+ block = self._lift(jump.addr)
2867
+
2868
+ for resolver in self.indirect_jump_resolvers:
2869
+ resolver.base_state = self._base_state
2870
+
2871
+ if not resolver.filter(self, jump.addr, jump.func_addr, block, jump.jumpkind):
2872
+ continue
2873
+
2874
+ resolved, targets = resolver.resolve(
2875
+ self, jump.addr, jump.func_addr, block, jump.jumpkind, func_graph_complete=func_graph_complete
2876
+ )
2877
+ if resolved:
2878
+ resolved_by = resolver
2879
+ break
2880
+
2881
+ if resolved:
2882
+ self._indirect_jump_resolved(jump, jump.addr, resolved_by, targets)
2883
+ else:
2884
+ self._indirect_jump_unresolved(jump)
2885
+
2886
+ return set() if targets is None else set(targets)