angr 9.2.192__cp311-cp311-macosx_10_12_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- angr/__init__.py +366 -0
- angr/__main__.py +182 -0
- angr/ail_callable.py +79 -0
- angr/ailment/__init__.py +83 -0
- angr/ailment/block.py +88 -0
- angr/ailment/block_walker.py +856 -0
- angr/ailment/constant.py +3 -0
- angr/ailment/converter_common.py +11 -0
- angr/ailment/converter_pcode.py +648 -0
- angr/ailment/converter_vex.py +829 -0
- angr/ailment/expression.py +1655 -0
- angr/ailment/manager.py +34 -0
- angr/ailment/statement.py +973 -0
- angr/ailment/tagged_object.py +58 -0
- angr/ailment/utils.py +114 -0
- angr/analyses/__init__.py +117 -0
- angr/analyses/analysis.py +429 -0
- angr/analyses/backward_slice.py +686 -0
- angr/analyses/binary_optimizer.py +670 -0
- angr/analyses/bindiff.py +1512 -0
- angr/analyses/boyscout.py +76 -0
- angr/analyses/callee_cleanup_finder.py +74 -0
- angr/analyses/calling_convention/__init__.py +6 -0
- angr/analyses/calling_convention/calling_convention.py +1113 -0
- angr/analyses/calling_convention/fact_collector.py +647 -0
- angr/analyses/calling_convention/utils.py +60 -0
- angr/analyses/cdg.py +189 -0
- angr/analyses/cfg/__init__.py +23 -0
- angr/analyses/cfg/cfb.py +451 -0
- angr/analyses/cfg/cfg.py +74 -0
- angr/analyses/cfg/cfg_arch_options.py +95 -0
- angr/analyses/cfg/cfg_base.py +2954 -0
- angr/analyses/cfg/cfg_emulated.py +3451 -0
- angr/analyses/cfg/cfg_fast.py +5431 -0
- angr/analyses/cfg/cfg_fast_soot.py +662 -0
- angr/analyses/cfg/cfg_job_base.py +203 -0
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +30 -0
- angr/analyses/cfg/indirect_jump_resolvers/aarch64_macho_got.py +77 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
- angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +159 -0
- angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +339 -0
- angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +82 -0
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2490 -0
- angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
- angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
- angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
- angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
- angr/analyses/cfg_slice_to_sink/graph.py +87 -0
- angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
- angr/analyses/class_identifier.py +63 -0
- angr/analyses/code_tagging.py +123 -0
- angr/analyses/codecave.py +77 -0
- angr/analyses/complete_calling_conventions.py +475 -0
- angr/analyses/congruency_check.py +377 -0
- angr/analyses/data_dep/__init__.py +16 -0
- angr/analyses/data_dep/data_dependency_analysis.py +595 -0
- angr/analyses/data_dep/dep_nodes.py +171 -0
- angr/analyses/data_dep/sim_act_location.py +49 -0
- angr/analyses/datagraph_meta.py +105 -0
- angr/analyses/ddg.py +1670 -0
- angr/analyses/decompiler/__init__.py +41 -0
- angr/analyses/decompiler/ail_simplifier.py +2246 -0
- angr/analyses/decompiler/ailgraph_walker.py +49 -0
- angr/analyses/decompiler/block_io_finder.py +302 -0
- angr/analyses/decompiler/block_similarity.py +199 -0
- angr/analyses/decompiler/block_simplifier.py +397 -0
- angr/analyses/decompiler/callsite_maker.py +579 -0
- angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +618 -0
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +24 -0
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +354 -0
- angr/analyses/decompiler/clinic.py +3662 -0
- angr/analyses/decompiler/condition_processor.py +1323 -0
- angr/analyses/decompiler/counters/__init__.py +16 -0
- angr/analyses/decompiler/counters/boolean_counter.py +27 -0
- angr/analyses/decompiler/counters/call_counter.py +77 -0
- angr/analyses/decompiler/counters/expression_counters.py +77 -0
- angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
- angr/analyses/decompiler/decompilation_cache.py +54 -0
- angr/analyses/decompiler/decompilation_options.py +317 -0
- angr/analyses/decompiler/decompiler.py +796 -0
- angr/analyses/decompiler/dephication/__init__.py +6 -0
- angr/analyses/decompiler/dephication/dephication_base.py +100 -0
- angr/analyses/decompiler/dephication/graph_dephication.py +70 -0
- angr/analyses/decompiler/dephication/graph_rewriting.py +112 -0
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +357 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +528 -0
- angr/analyses/decompiler/dephication/seqnode_dephication.py +156 -0
- angr/analyses/decompiler/dirty_rewriters/__init__.py +7 -0
- angr/analyses/decompiler/dirty_rewriters/amd64_dirty.py +74 -0
- angr/analyses/decompiler/dirty_rewriters/rewriter_base.py +27 -0
- angr/analyses/decompiler/empty_node_remover.py +212 -0
- angr/analyses/decompiler/expression_narrower.py +290 -0
- angr/analyses/decompiler/goto_manager.py +112 -0
- angr/analyses/decompiler/graph_region.py +441 -0
- angr/analyses/decompiler/jump_target_collector.py +37 -0
- angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
- angr/analyses/decompiler/label_collector.py +32 -0
- angr/analyses/decompiler/node_replacer.py +42 -0
- angr/analyses/decompiler/notes/__init__.py +9 -0
- angr/analyses/decompiler/notes/decompilation_note.py +48 -0
- angr/analyses/decompiler/notes/deobfuscated_strings.py +56 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +164 -0
- angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
- angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
- angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +211 -0
- angr/analyses/decompiler/optimization_passes/const_derefs.py +127 -0
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
- angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1221 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +236 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_eval.py +186 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +502 -0
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +138 -0
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +618 -0
- angr/analyses/decompiler/optimization_passes/inlined_strlen_simplifier.py +274 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +337 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +939 -0
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +710 -0
- angr/analyses/decompiler/optimization_passes/peephole_simplifier.py +75 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +263 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier_adv.py +198 -0
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +632 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +166 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
- angr/analyses/decompiler/optimization_passes/static_vvar_rewriter.py +336 -0
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +166 -0
- angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
- angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +477 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
- angr/analyses/decompiler/peephole_optimizations/__init__.py +136 -0
- angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
- angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
- angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
- angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
- angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +182 -0
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
- angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +436 -0
- angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memcpy.py +78 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memset.py +262 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +217 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +106 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy.py +256 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy_consolidation.py +296 -0
- angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
- angr/analyses/decompiler/peephole_optimizations/modulo_simplifier.py +89 -0
- angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
- angr/analyses/decompiler/peephole_optimizations/optimized_div_simplifier.py +356 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
- angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +125 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +273 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_derefs.py +21 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +115 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
- angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +143 -0
- angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
- angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
- angr/analyses/decompiler/presets/__init__.py +22 -0
- angr/analyses/decompiler/presets/basic.py +36 -0
- angr/analyses/decompiler/presets/fast.py +66 -0
- angr/analyses/decompiler/presets/full.py +76 -0
- angr/analyses/decompiler/presets/malware.py +70 -0
- angr/analyses/decompiler/presets/preset.py +37 -0
- angr/analyses/decompiler/redundant_label_remover.py +141 -0
- angr/analyses/decompiler/region_identifier.py +1319 -0
- angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
- angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +838 -0
- angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
- angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
- angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
- angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +270 -0
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
- angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
- angr/analyses/decompiler/region_walker.py +24 -0
- angr/analyses/decompiler/return_maker.py +72 -0
- angr/analyses/decompiler/semantic_naming/__init__.py +37 -0
- angr/analyses/decompiler/semantic_naming/array_index_naming.py +196 -0
- angr/analyses/decompiler/semantic_naming/boolean_naming.py +264 -0
- angr/analyses/decompiler/semantic_naming/call_result_naming.py +220 -0
- angr/analyses/decompiler/semantic_naming/naming_base.py +166 -0
- angr/analyses/decompiler/semantic_naming/orchestrator.py +107 -0
- angr/analyses/decompiler/semantic_naming/pointer_naming.py +334 -0
- angr/analyses/decompiler/semantic_naming/region_loop_counter_naming.py +246 -0
- angr/analyses/decompiler/semantic_naming/size_naming.py +137 -0
- angr/analyses/decompiler/seq_to_blocks.py +20 -0
- angr/analyses/decompiler/sequence_walker.py +261 -0
- angr/analyses/decompiler/ssailification/__init__.py +4 -0
- angr/analyses/decompiler/ssailification/rewriting.py +451 -0
- angr/analyses/decompiler/ssailification/rewriting_engine.py +1091 -0
- angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
- angr/analyses/decompiler/ssailification/ssailification.py +283 -0
- angr/analyses/decompiler/ssailification/traversal.py +127 -0
- angr/analyses/decompiler/ssailification/traversal_engine.py +323 -0
- angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
- angr/analyses/decompiler/stack_item.py +36 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
- angr/analyses/decompiler/structured_codegen/base.py +193 -0
- angr/analyses/decompiler/structured_codegen/c.py +4257 -0
- angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
- angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
- angr/analyses/decompiler/structuring/__init__.py +30 -0
- angr/analyses/decompiler/structuring/dream.py +1217 -0
- angr/analyses/decompiler/structuring/phoenix.py +3636 -0
- angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
- angr/analyses/decompiler/structuring/sailr.py +120 -0
- angr/analyses/decompiler/structuring/structurer_base.py +1140 -0
- angr/analyses/decompiler/structuring/structurer_nodes.py +442 -0
- angr/analyses/decompiler/utils.py +1224 -0
- angr/analyses/deobfuscator/__init__.py +23 -0
- angr/analyses/deobfuscator/api_obf_finder.py +333 -0
- angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +80 -0
- angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
- angr/analyses/deobfuscator/data_transformation_embedder.py +633 -0
- angr/analyses/deobfuscator/hash_lookup_api_deobfuscator.py +156 -0
- angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
- angr/analyses/deobfuscator/scope_ops_analyzer.py +68 -0
- angr/analyses/deobfuscator/string_obf_finder.py +983 -0
- angr/analyses/deobfuscator/string_obf_opt_passes.py +136 -0
- angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
- angr/analyses/disassembly.py +1351 -0
- angr/analyses/disassembly_utils.py +101 -0
- angr/analyses/dominance_frontier.py +57 -0
- angr/analyses/fcp/__init__.py +4 -0
- angr/analyses/fcp/fcp.py +427 -0
- angr/analyses/find_objects_static.py +205 -0
- angr/analyses/flirt/__init__.py +47 -0
- angr/analyses/flirt/consts.py +160 -0
- angr/analyses/flirt/flirt.py +249 -0
- angr/analyses/flirt/flirt_function.py +20 -0
- angr/analyses/flirt/flirt_matcher.py +352 -0
- angr/analyses/flirt/flirt_module.py +32 -0
- angr/analyses/flirt/flirt_node.py +23 -0
- angr/analyses/flirt/flirt_sig.py +359 -0
- angr/analyses/flirt/flirt_utils.py +31 -0
- angr/analyses/forward_analysis/__init__.py +12 -0
- angr/analyses/forward_analysis/forward_analysis.py +619 -0
- angr/analyses/forward_analysis/job_info.py +64 -0
- angr/analyses/forward_analysis/visitors/__init__.py +14 -0
- angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
- angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
- angr/analyses/forward_analysis/visitors/graph.py +242 -0
- angr/analyses/forward_analysis/visitors/loop.py +29 -0
- angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
- angr/analyses/identifier/__init__.py +5 -0
- angr/analyses/identifier/custom_callable.py +137 -0
- angr/analyses/identifier/errors.py +10 -0
- angr/analyses/identifier/func.py +60 -0
- angr/analyses/identifier/functions/__init__.py +37 -0
- angr/analyses/identifier/functions/atoi.py +73 -0
- angr/analyses/identifier/functions/based_atoi.py +125 -0
- angr/analyses/identifier/functions/fdprintf.py +123 -0
- angr/analyses/identifier/functions/free.py +64 -0
- angr/analyses/identifier/functions/int2str.py +287 -0
- angr/analyses/identifier/functions/malloc.py +111 -0
- angr/analyses/identifier/functions/memcmp.py +67 -0
- angr/analyses/identifier/functions/memcpy.py +89 -0
- angr/analyses/identifier/functions/memset.py +43 -0
- angr/analyses/identifier/functions/printf.py +123 -0
- angr/analyses/identifier/functions/recv_until.py +312 -0
- angr/analyses/identifier/functions/skip_calloc.py +73 -0
- angr/analyses/identifier/functions/skip_realloc.py +97 -0
- angr/analyses/identifier/functions/skip_recv_n.py +105 -0
- angr/analyses/identifier/functions/snprintf.py +112 -0
- angr/analyses/identifier/functions/sprintf.py +116 -0
- angr/analyses/identifier/functions/strcasecmp.py +33 -0
- angr/analyses/identifier/functions/strcmp.py +113 -0
- angr/analyses/identifier/functions/strcpy.py +43 -0
- angr/analyses/identifier/functions/strlen.py +27 -0
- angr/analyses/identifier/functions/strncmp.py +104 -0
- angr/analyses/identifier/functions/strncpy.py +65 -0
- angr/analyses/identifier/functions/strtol.py +89 -0
- angr/analyses/identifier/identify.py +825 -0
- angr/analyses/identifier/runner.py +360 -0
- angr/analyses/init_finder.py +289 -0
- angr/analyses/loop_analysis/__init__.py +4 -0
- angr/analyses/loop_analysis/loop_analysis.py +464 -0
- angr/analyses/loop_analysis.py +349 -0
- angr/analyses/loop_unroller/__init__.py +4 -0
- angr/analyses/loop_unroller/loop_unroller.py +222 -0
- angr/analyses/loopfinder.py +171 -0
- angr/analyses/outliner/__init__.py +7 -0
- angr/analyses/outliner/outliner.py +402 -0
- angr/analyses/patchfinder.py +137 -0
- angr/analyses/pathfinder.py +282 -0
- angr/analyses/propagator/__init__.py +5 -0
- angr/analyses/propagator/engine_base.py +62 -0
- angr/analyses/propagator/engine_vex.py +297 -0
- angr/analyses/propagator/propagator.py +361 -0
- angr/analyses/propagator/top_checker_mixin.py +218 -0
- angr/analyses/propagator/values.py +117 -0
- angr/analyses/propagator/vex_vars.py +68 -0
- angr/analyses/proximity_graph.py +444 -0
- angr/analyses/purity/__init__.py +15 -0
- angr/analyses/purity/analysis.py +78 -0
- angr/analyses/purity/engine.py +593 -0
- angr/analyses/reaching_definitions/__init__.py +67 -0
- angr/analyses/reaching_definitions/call_trace.py +73 -0
- angr/analyses/reaching_definitions/dep_graph.py +433 -0
- angr/analyses/reaching_definitions/engine_ail.py +1128 -0
- angr/analyses/reaching_definitions/engine_vex.py +1128 -0
- angr/analyses/reaching_definitions/external_codeloc.py +0 -0
- angr/analyses/reaching_definitions/function_handler.py +639 -0
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
- angr/analyses/reaching_definitions/function_handler_library/stdio.py +269 -0
- angr/analyses/reaching_definitions/function_handler_library/stdlib.py +195 -0
- angr/analyses/reaching_definitions/function_handler_library/string.py +158 -0
- angr/analyses/reaching_definitions/function_handler_library/unistd.py +51 -0
- angr/analyses/reaching_definitions/heap_allocator.py +70 -0
- angr/analyses/reaching_definitions/rd_initializer.py +237 -0
- angr/analyses/reaching_definitions/rd_state.py +579 -0
- angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
- angr/analyses/reaching_definitions/subject.py +65 -0
- angr/analyses/reassembler.py +2900 -0
- angr/analyses/s_liveness.py +254 -0
- angr/analyses/s_propagator.py +575 -0
- angr/analyses/s_reaching_definitions/__init__.py +12 -0
- angr/analyses/s_reaching_definitions/s_rda_model.py +145 -0
- angr/analyses/s_reaching_definitions/s_rda_view.py +344 -0
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +230 -0
- angr/analyses/smc.py +160 -0
- angr/analyses/soot_class_hierarchy.py +273 -0
- angr/analyses/stack_pointer_tracker.py +954 -0
- angr/analyses/static_hooker.py +53 -0
- angr/analyses/typehoon/__init__.py +5 -0
- angr/analyses/typehoon/dfa.py +118 -0
- angr/analyses/typehoon/lifter.py +133 -0
- angr/analyses/typehoon/simple_solver.py +2009 -0
- angr/analyses/typehoon/translator.py +283 -0
- angr/analyses/typehoon/typeconsts.py +439 -0
- angr/analyses/typehoon/typehoon.py +338 -0
- angr/analyses/typehoon/typevars.py +633 -0
- angr/analyses/typehoon/variance.py +11 -0
- angr/analyses/unpacker/__init__.py +6 -0
- angr/analyses/unpacker/obfuscation_detector.py +103 -0
- angr/analyses/unpacker/packing_detector.py +138 -0
- angr/analyses/variable_recovery/__init__.py +9 -0
- angr/analyses/variable_recovery/annotations.py +58 -0
- angr/analyses/variable_recovery/engine_ail.py +978 -0
- angr/analyses/variable_recovery/engine_base.py +1256 -0
- angr/analyses/variable_recovery/engine_vex.py +594 -0
- angr/analyses/variable_recovery/irsb_scanner.py +143 -0
- angr/analyses/variable_recovery/variable_recovery.py +574 -0
- angr/analyses/variable_recovery/variable_recovery_base.py +489 -0
- angr/analyses/variable_recovery/variable_recovery_fast.py +669 -0
- angr/analyses/veritesting.py +626 -0
- angr/analyses/vfg.py +1898 -0
- angr/analyses/vsa_ddg.py +420 -0
- angr/analyses/vtable.py +92 -0
- angr/analyses/xrefs.py +286 -0
- angr/angrdb/__init__.py +14 -0
- angr/angrdb/db.py +215 -0
- angr/angrdb/models.py +184 -0
- angr/angrdb/serializers/__init__.py +10 -0
- angr/angrdb/serializers/cfg_model.py +41 -0
- angr/angrdb/serializers/comments.py +60 -0
- angr/angrdb/serializers/funcs.py +61 -0
- angr/angrdb/serializers/kb.py +111 -0
- angr/angrdb/serializers/labels.py +59 -0
- angr/angrdb/serializers/loader.py +165 -0
- angr/angrdb/serializers/structured_code.py +167 -0
- angr/angrdb/serializers/variables.py +58 -0
- angr/angrdb/serializers/xrefs.py +48 -0
- angr/annocfg.py +317 -0
- angr/blade.py +431 -0
- angr/block.py +509 -0
- angr/callable.py +176 -0
- angr/calling_conventions.py +2613 -0
- angr/code_location.py +249 -0
- angr/codenode.py +145 -0
- angr/concretization_strategies/__init__.py +32 -0
- angr/concretization_strategies/any.py +17 -0
- angr/concretization_strategies/any_named.py +35 -0
- angr/concretization_strategies/base.py +81 -0
- angr/concretization_strategies/controlled_data.py +58 -0
- angr/concretization_strategies/eval.py +19 -0
- angr/concretization_strategies/logging.py +35 -0
- angr/concretization_strategies/max.py +25 -0
- angr/concretization_strategies/nonzero.py +16 -0
- angr/concretization_strategies/nonzero_range.py +22 -0
- angr/concretization_strategies/norepeats.py +37 -0
- angr/concretization_strategies/norepeats_range.py +37 -0
- angr/concretization_strategies/range.py +19 -0
- angr/concretization_strategies/signed_add.py +31 -0
- angr/concretization_strategies/single.py +15 -0
- angr/concretization_strategies/solutions.py +20 -0
- angr/concretization_strategies/unlimited_range.py +17 -0
- angr/distributed/__init__.py +9 -0
- angr/distributed/server.py +197 -0
- angr/distributed/worker.py +185 -0
- angr/emulator.py +144 -0
- angr/engines/__init__.py +69 -0
- angr/engines/ail/__init__.py +16 -0
- angr/engines/ail/callstack.py +58 -0
- angr/engines/ail/engine_light.py +903 -0
- angr/engines/ail/engine_successors.py +24 -0
- angr/engines/ail/setup.py +57 -0
- angr/engines/concrete.py +66 -0
- angr/engines/engine.py +29 -0
- angr/engines/failure.py +27 -0
- angr/engines/hook.py +93 -0
- angr/engines/icicle.py +294 -0
- angr/engines/light/__init__.py +23 -0
- angr/engines/light/data.py +681 -0
- angr/engines/light/engine.py +1297 -0
- angr/engines/pcode/__init__.py +9 -0
- angr/engines/pcode/behavior.py +998 -0
- angr/engines/pcode/cc.py +148 -0
- angr/engines/pcode/emulate.py +440 -0
- angr/engines/pcode/engine.py +242 -0
- angr/engines/pcode/lifter.py +1428 -0
- angr/engines/procedure.py +70 -0
- angr/engines/soot/__init__.py +5 -0
- angr/engines/soot/engine.py +410 -0
- angr/engines/soot/exceptions.py +17 -0
- angr/engines/soot/expressions/__init__.py +87 -0
- angr/engines/soot/expressions/arrayref.py +22 -0
- angr/engines/soot/expressions/base.py +21 -0
- angr/engines/soot/expressions/binop.py +28 -0
- angr/engines/soot/expressions/cast.py +22 -0
- angr/engines/soot/expressions/condition.py +35 -0
- angr/engines/soot/expressions/constants.py +47 -0
- angr/engines/soot/expressions/instanceOf.py +15 -0
- angr/engines/soot/expressions/instancefieldref.py +8 -0
- angr/engines/soot/expressions/invoke.py +114 -0
- angr/engines/soot/expressions/length.py +8 -0
- angr/engines/soot/expressions/local.py +8 -0
- angr/engines/soot/expressions/new.py +16 -0
- angr/engines/soot/expressions/newArray.py +54 -0
- angr/engines/soot/expressions/newMultiArray.py +86 -0
- angr/engines/soot/expressions/paramref.py +8 -0
- angr/engines/soot/expressions/phi.py +30 -0
- angr/engines/soot/expressions/staticfieldref.py +8 -0
- angr/engines/soot/expressions/thisref.py +7 -0
- angr/engines/soot/expressions/unsupported.py +7 -0
- angr/engines/soot/field_dispatcher.py +46 -0
- angr/engines/soot/method_dispatcher.py +46 -0
- angr/engines/soot/statements/__init__.py +44 -0
- angr/engines/soot/statements/assign.py +30 -0
- angr/engines/soot/statements/base.py +79 -0
- angr/engines/soot/statements/goto.py +14 -0
- angr/engines/soot/statements/identity.py +15 -0
- angr/engines/soot/statements/if_.py +19 -0
- angr/engines/soot/statements/invoke.py +12 -0
- angr/engines/soot/statements/return_.py +20 -0
- angr/engines/soot/statements/switch.py +41 -0
- angr/engines/soot/statements/throw.py +15 -0
- angr/engines/soot/values/__init__.py +38 -0
- angr/engines/soot/values/arrayref.py +122 -0
- angr/engines/soot/values/base.py +7 -0
- angr/engines/soot/values/constants.py +18 -0
- angr/engines/soot/values/instancefieldref.py +44 -0
- angr/engines/soot/values/local.py +18 -0
- angr/engines/soot/values/paramref.py +18 -0
- angr/engines/soot/values/staticfieldref.py +38 -0
- angr/engines/soot/values/strref.py +38 -0
- angr/engines/soot/values/thisref.py +149 -0
- angr/engines/successors.py +608 -0
- angr/engines/syscall.py +51 -0
- angr/engines/unicorn.py +490 -0
- angr/engines/vex/__init__.py +20 -0
- angr/engines/vex/claripy/__init__.py +5 -0
- angr/engines/vex/claripy/ccall.py +2097 -0
- angr/engines/vex/claripy/datalayer.py +141 -0
- angr/engines/vex/claripy/irop.py +1276 -0
- angr/engines/vex/heavy/__init__.py +16 -0
- angr/engines/vex/heavy/actions.py +231 -0
- angr/engines/vex/heavy/concretizers.py +403 -0
- angr/engines/vex/heavy/dirty.py +466 -0
- angr/engines/vex/heavy/heavy.py +370 -0
- angr/engines/vex/heavy/inspect.py +52 -0
- angr/engines/vex/heavy/resilience.py +85 -0
- angr/engines/vex/heavy/super_fastpath.py +34 -0
- angr/engines/vex/lifter.py +420 -0
- angr/engines/vex/light/__init__.py +11 -0
- angr/engines/vex/light/light.py +551 -0
- angr/engines/vex/light/resilience.py +74 -0
- angr/engines/vex/light/slicing.py +52 -0
- angr/errors.py +611 -0
- angr/exploration_techniques/__init__.py +53 -0
- angr/exploration_techniques/base.py +126 -0
- angr/exploration_techniques/bucketizer.py +94 -0
- angr/exploration_techniques/common.py +56 -0
- angr/exploration_techniques/dfs.py +37 -0
- angr/exploration_techniques/director.py +520 -0
- angr/exploration_techniques/driller_core.py +100 -0
- angr/exploration_techniques/explorer.py +152 -0
- angr/exploration_techniques/lengthlimiter.py +22 -0
- angr/exploration_techniques/local_loop_seer.py +65 -0
- angr/exploration_techniques/loop_seer.py +236 -0
- angr/exploration_techniques/manual_mergepoint.py +82 -0
- angr/exploration_techniques/memory_watcher.py +43 -0
- angr/exploration_techniques/oppologist.py +92 -0
- angr/exploration_techniques/slicecutor.py +118 -0
- angr/exploration_techniques/spiller.py +280 -0
- angr/exploration_techniques/spiller_db.py +27 -0
- angr/exploration_techniques/stochastic.py +56 -0
- angr/exploration_techniques/stub_stasher.py +19 -0
- angr/exploration_techniques/suggestions.py +159 -0
- angr/exploration_techniques/tech_builder.py +49 -0
- angr/exploration_techniques/threading.py +69 -0
- angr/exploration_techniques/timeout.py +34 -0
- angr/exploration_techniques/tracer.py +1098 -0
- angr/exploration_techniques/unique.py +106 -0
- angr/exploration_techniques/veritesting.py +37 -0
- angr/factory.py +413 -0
- angr/flirt/__init__.py +124 -0
- angr/flirt/build_sig.py +305 -0
- angr/graph_utils.py +0 -0
- angr/keyed_region.py +525 -0
- angr/knowledge_base.py +146 -0
- angr/knowledge_plugins/__init__.py +43 -0
- angr/knowledge_plugins/callsite_prototypes.py +95 -0
- angr/knowledge_plugins/cfg/__init__.py +18 -0
- angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
- angr/knowledge_plugins/cfg/cfg_model.py +1043 -0
- angr/knowledge_plugins/cfg/cfg_node.py +536 -0
- angr/knowledge_plugins/cfg/indirect_jump.py +131 -0
- angr/knowledge_plugins/cfg/memory_data.py +156 -0
- angr/knowledge_plugins/comments.py +16 -0
- angr/knowledge_plugins/custom_strings.py +38 -0
- angr/knowledge_plugins/data.py +22 -0
- angr/knowledge_plugins/debug_variables.py +216 -0
- angr/knowledge_plugins/functions/__init__.py +9 -0
- angr/knowledge_plugins/functions/function.py +1830 -0
- angr/knowledge_plugins/functions/function_manager.py +621 -0
- angr/knowledge_plugins/functions/function_parser.py +360 -0
- angr/knowledge_plugins/functions/soot_function.py +128 -0
- angr/knowledge_plugins/indirect_jumps.py +35 -0
- angr/knowledge_plugins/key_definitions/__init__.py +17 -0
- angr/knowledge_plugins/key_definitions/atoms.py +374 -0
- angr/knowledge_plugins/key_definitions/constants.py +29 -0
- angr/knowledge_plugins/key_definitions/definition.py +216 -0
- angr/knowledge_plugins/key_definitions/environment.py +96 -0
- angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +1020 -0
- angr/knowledge_plugins/key_definitions/liveness.py +165 -0
- angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
- angr/knowledge_plugins/key_definitions/tag.py +78 -0
- angr/knowledge_plugins/key_definitions/undefined.py +70 -0
- angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
- angr/knowledge_plugins/key_definitions/uses.py +178 -0
- angr/knowledge_plugins/labels.py +110 -0
- angr/knowledge_plugins/obfuscations.py +40 -0
- angr/knowledge_plugins/patches.py +126 -0
- angr/knowledge_plugins/plugin.py +24 -0
- angr/knowledge_plugins/propagations/__init__.py +10 -0
- angr/knowledge_plugins/propagations/prop_value.py +191 -0
- angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
- angr/knowledge_plugins/propagations/propagation_model.py +80 -0
- angr/knowledge_plugins/propagations/states.py +552 -0
- angr/knowledge_plugins/structured_code.py +63 -0
- angr/knowledge_plugins/types.py +95 -0
- angr/knowledge_plugins/variables/__init__.py +8 -0
- angr/knowledge_plugins/variables/variable_access.py +113 -0
- angr/knowledge_plugins/variables/variable_manager.py +1375 -0
- angr/knowledge_plugins/xrefs/__init__.py +12 -0
- angr/knowledge_plugins/xrefs/xref.py +150 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
- angr/knowledge_plugins/xrefs/xref_types.py +16 -0
- angr/misc/__init__.py +19 -0
- angr/misc/ansi.py +47 -0
- angr/misc/autoimport.py +90 -0
- angr/misc/bug_report.py +126 -0
- angr/misc/hookset.py +106 -0
- angr/misc/loggers.py +130 -0
- angr/misc/picklable_lock.py +46 -0
- angr/misc/plugins.py +289 -0
- angr/misc/telemetry.py +54 -0
- angr/misc/testing.py +24 -0
- angr/misc/ux.py +31 -0
- angr/procedures/__init__.py +12 -0
- angr/procedures/advapi32/__init__.py +0 -0
- angr/procedures/cgc/__init__.py +3 -0
- angr/procedures/cgc/_terminate.py +11 -0
- angr/procedures/cgc/allocate.py +75 -0
- angr/procedures/cgc/deallocate.py +67 -0
- angr/procedures/cgc/fdwait.py +65 -0
- angr/procedures/cgc/random.py +67 -0
- angr/procedures/cgc/receive.py +93 -0
- angr/procedures/cgc/transmit.py +65 -0
- angr/procedures/definitions/__init__.py +1043 -0
- angr/procedures/definitions/cgc.py +23 -0
- angr/procedures/definitions/common/glibc.json +3516 -0
- angr/procedures/definitions/gnulib.py +41 -0
- angr/procedures/definitions/libstdcpp.py +25 -0
- angr/procedures/definitions/linux_kernel.py +8382 -0
- angr/procedures/definitions/linux_loader.py +7 -0
- angr/procedures/definitions/macho_libsystem.py +18 -0
- angr/procedures/definitions/msvcr.py +25 -0
- angr/procedures/definitions/parse_glibc.py +77 -0
- angr/procedures/definitions/parse_syscalls_from_local_system.py +54 -0
- angr/procedures/definitions/parse_win32json.py +2540 -0
- angr/procedures/definitions/types_stl.py +22 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-4.json +24 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-6.json +18 -0
- angr/procedures/definitions/wdk/clfs.json +189 -0
- angr/procedures/definitions/wdk/fltmgr.json +813 -0
- angr/procedures/definitions/wdk/fwpkclnt.json +24 -0
- angr/procedures/definitions/wdk/fwpuclnt.json +453 -0
- angr/procedures/definitions/wdk/gdi32.json +528 -0
- angr/procedures/definitions/wdk/hal.json +96 -0
- angr/procedures/definitions/wdk/ksecdd.json +72 -0
- angr/procedures/definitions/wdk/ndis.json +336 -0
- angr/procedures/definitions/wdk/ntoskrnl.json +5158 -0
- angr/procedures/definitions/wdk/offreg.json +87 -0
- angr/procedures/definitions/wdk/pshed.json +33 -0
- angr/procedures/definitions/wdk/secur32.json +39 -0
- angr/procedures/definitions/wdk/vhfum.json +30 -0
- angr/procedures/definitions/win32/_types_win32.json +34480 -0
- angr/procedures/definitions/win32/aclui.json +24 -0
- angr/procedures/definitions/win32/activeds.json +81 -0
- angr/procedures/definitions/win32/advapi32.json +2505 -0
- angr/procedures/definitions/win32/advpack.json +165 -0
- angr/procedures/definitions/win32/amsi.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-1.json +45 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-3.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-apiquery-l2-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-backgroundtask-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-enclave-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-errorhandling-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-0.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-file-fromapp-l1-1-0.json +48 -0
- angr/procedures/definitions/win32/api-ms-win-core-handle-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-ioring-l1-1-0.json +51 -0
- angr/procedures/definitions/win32/api-ms-win-core-marshal-l1-1-0.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-3.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-5.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-6.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-7.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-8.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-path-l1-1-0.json +81 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-0.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-2.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-slapi-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-state-helpers-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-synch-l1-2-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-4.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-util-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-wow64-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-0.json +42 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-1.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-dx-d3dkmt-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-deviceinformation-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-expandedresources-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-2.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-4.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-mm-misc-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-net-isolation-l1-1-0.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-security-base-l1-2-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-5.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-1.json +33 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-wsl-api-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/apphelp.json +18 -0
- angr/procedures/definitions/win32/authz.json +114 -0
- angr/procedures/definitions/win32/avicap32.json +27 -0
- angr/procedures/definitions/win32/avifil32.json +195 -0
- angr/procedures/definitions/win32/avrt.json +57 -0
- angr/procedures/definitions/win32/bcp47mrm.json +21 -0
- angr/procedures/definitions/win32/bcrypt.json +174 -0
- angr/procedures/definitions/win32/bcryptprimitives.json +21 -0
- angr/procedures/definitions/win32/bluetoothapis.json +138 -0
- angr/procedures/definitions/win32/bthprops_cpl.json +33 -0
- angr/procedures/definitions/win32/cabinet.json +81 -0
- angr/procedures/definitions/win32/certadm.json +69 -0
- angr/procedures/definitions/win32/certpoleng.json +39 -0
- angr/procedures/definitions/win32/cfgmgr32.json +732 -0
- angr/procedures/definitions/win32/chakra.json +270 -0
- angr/procedures/definitions/win32/cldapi.json +123 -0
- angr/procedures/definitions/win32/clfsw32.json +192 -0
- angr/procedures/definitions/win32/clusapi.json +855 -0
- angr/procedures/definitions/win32/comctl32.json +360 -0
- angr/procedures/definitions/win32/comdlg32.json +78 -0
- angr/procedures/definitions/win32/compstui.json +27 -0
- angr/procedures/definitions/win32/computecore.json +177 -0
- angr/procedures/definitions/win32/computenetwork.json +144 -0
- angr/procedures/definitions/win32/computestorage.json +51 -0
- angr/procedures/definitions/win32/comsvcs.json +36 -0
- angr/procedures/definitions/win32/credui.json +72 -0
- angr/procedures/definitions/win32/crypt32.json +702 -0
- angr/procedures/definitions/win32/cryptnet.json +30 -0
- angr/procedures/definitions/win32/cryptui.json +45 -0
- angr/procedures/definitions/win32/cryptxml.json +72 -0
- angr/procedures/definitions/win32/cscapi.json +27 -0
- angr/procedures/definitions/win32/d2d1.json +54 -0
- angr/procedures/definitions/win32/d3d10.json +96 -0
- angr/procedures/definitions/win32/d3d10_1.json +21 -0
- angr/procedures/definitions/win32/d3d11.json +24 -0
- angr/procedures/definitions/win32/d3d12.json +39 -0
- angr/procedures/definitions/win32/d3d9.json +48 -0
- angr/procedures/definitions/win32/d3dcompiler_47.json +93 -0
- angr/procedures/definitions/win32/d3dcsx.json +42 -0
- angr/procedures/definitions/win32/davclnt.json +69 -0
- angr/procedures/definitions/win32/dbgeng.json +27 -0
- angr/procedures/definitions/win32/dbghelp.json +663 -0
- angr/procedures/definitions/win32/dbgmodel.json +18 -0
- angr/procedures/definitions/win32/dciman32.json +75 -0
- angr/procedures/definitions/win32/dcomp.json +51 -0
- angr/procedures/definitions/win32/ddraw.json +36 -0
- angr/procedures/definitions/win32/deviceaccess.json +18 -0
- angr/procedures/definitions/win32/dflayout.json +18 -0
- angr/procedures/definitions/win32/dhcpcsvc.json +60 -0
- angr/procedures/definitions/win32/dhcpcsvc6.json +33 -0
- angr/procedures/definitions/win32/dhcpsapi.json +603 -0
- angr/procedures/definitions/win32/diagnosticdataquery.json +120 -0
- angr/procedures/definitions/win32/dinput8.json +18 -0
- angr/procedures/definitions/win32/directml.json +21 -0
- angr/procedures/definitions/win32/dmprocessxmlfiltered.json +18 -0
- angr/procedures/definitions/win32/dnsapi.json +207 -0
- angr/procedures/definitions/win32/drt.json +63 -0
- angr/procedures/definitions/win32/drtprov.json +42 -0
- angr/procedures/definitions/win32/drttransport.json +21 -0
- angr/procedures/definitions/win32/dsound.json +45 -0
- angr/procedures/definitions/win32/dsparse.json +72 -0
- angr/procedures/definitions/win32/dsprop.json +36 -0
- angr/procedures/definitions/win32/dssec.json +27 -0
- angr/procedures/definitions/win32/dsuiext.json +27 -0
- angr/procedures/definitions/win32/dwmapi.json +108 -0
- angr/procedures/definitions/win32/dwrite.json +18 -0
- angr/procedures/definitions/win32/dxcompiler.json +21 -0
- angr/procedures/definitions/win32/dxcore.json +18 -0
- angr/procedures/definitions/win32/dxgi.json +33 -0
- angr/procedures/definitions/win32/dxva2.json +129 -0
- angr/procedures/definitions/win32/eappcfg.json +57 -0
- angr/procedures/definitions/win32/eappprxy.json +69 -0
- angr/procedures/definitions/win32/efswrt.json +21 -0
- angr/procedures/definitions/win32/elscore.json +30 -0
- angr/procedures/definitions/win32/esent.json +702 -0
- angr/procedures/definitions/win32/evr.json +36 -0
- angr/procedures/definitions/win32/faultrep.json +27 -0
- angr/procedures/definitions/win32/fhsvcctl.json +36 -0
- angr/procedures/definitions/win32/firewallapi.json +24 -0
- angr/procedures/definitions/win32/fltlib.json +99 -0
- angr/procedures/definitions/win32/fontsub.json +21 -0
- angr/procedures/definitions/win32/forceinline.json +24 -0
- angr/procedures/definitions/win32/fwpuclnt.json +591 -0
- angr/procedures/definitions/win32/fxsutility.json +21 -0
- angr/procedures/definitions/win32/gdi32.json +1308 -0
- angr/procedures/definitions/win32/gdiplus.json +1902 -0
- angr/procedures/definitions/win32/glu32.json +171 -0
- angr/procedures/definitions/win32/gpedit.json +33 -0
- angr/procedures/definitions/win32/hhctrl_ocx.json +21 -0
- angr/procedures/definitions/win32/hid.json +150 -0
- angr/procedures/definitions/win32/hlink.json +99 -0
- angr/procedures/definitions/win32/hrtfapo.json +18 -0
- angr/procedures/definitions/win32/httpapi.json +144 -0
- angr/procedures/definitions/win32/icm32.json +78 -0
- angr/procedures/definitions/win32/icmui.json +21 -0
- angr/procedures/definitions/win32/icu.json +3090 -0
- angr/procedures/definitions/win32/ieframe.json +102 -0
- angr/procedures/definitions/win32/imagehlp.json +84 -0
- angr/procedures/definitions/win32/imgutil.json +42 -0
- angr/procedures/definitions/win32/imm32.json +261 -0
- angr/procedures/definitions/win32/infocardapi.json +66 -0
- angr/procedures/definitions/win32/inkobjcore.json +96 -0
- angr/procedures/definitions/win32/iphlpapi.json +618 -0
- angr/procedures/definitions/win32/iscsidsc.json +252 -0
- angr/procedures/definitions/win32/isolatedwindowsenvironmentutils.json +21 -0
- angr/procedures/definitions/win32/kernel32.json +4566 -0
- angr/procedures/definitions/win32/kernelbase.json +33 -0
- angr/procedures/definitions/win32/keycredmgr.json +27 -0
- angr/procedures/definitions/win32/ksproxy_ax.json +33 -0
- angr/procedures/definitions/win32/ksuser.json +39 -0
- angr/procedures/definitions/win32/ktmw32.json +132 -0
- angr/procedures/definitions/win32/licenseprotection.json +21 -0
- angr/procedures/definitions/win32/loadperf.json +51 -0
- angr/procedures/definitions/win32/magnification.json +72 -0
- angr/procedures/definitions/win32/mapi32.json +213 -0
- angr/procedures/definitions/win32/mdmlocalmanagement.json +24 -0
- angr/procedures/definitions/win32/mdmregistration.json +60 -0
- angr/procedures/definitions/win32/mf.json +201 -0
- angr/procedures/definitions/win32/mfcore.json +21 -0
- angr/procedures/definitions/win32/mfplat.json +450 -0
- angr/procedures/definitions/win32/mfplay.json +18 -0
- angr/procedures/definitions/win32/mfreadwrite.json +30 -0
- angr/procedures/definitions/win32/mfsensorgroup.json +45 -0
- angr/procedures/definitions/win32/mfsrcsnk.json +21 -0
- angr/procedures/definitions/win32/mgmtapi.json +42 -0
- angr/procedures/definitions/win32/mi.json +18 -0
- angr/procedures/definitions/win32/mmdevapi.json +18 -0
- angr/procedures/definitions/win32/mpr.json +156 -0
- angr/procedures/definitions/win32/mprapi.json +351 -0
- angr/procedures/definitions/win32/mqrt.json +117 -0
- angr/procedures/definitions/win32/mrmsupport.json +96 -0
- angr/procedures/definitions/win32/msacm32.json +141 -0
- angr/procedures/definitions/win32/msajapi.json +1656 -0
- angr/procedures/definitions/win32/mscms.json +252 -0
- angr/procedures/definitions/win32/mscoree.json +96 -0
- angr/procedures/definitions/win32/msctfmonitor.json +24 -0
- angr/procedures/definitions/win32/msdelta.json +63 -0
- angr/procedures/definitions/win32/msdmo.json +48 -0
- angr/procedures/definitions/win32/msdrm.json +267 -0
- angr/procedures/definitions/win32/msi.json +807 -0
- angr/procedures/definitions/win32/msimg32.json +24 -0
- angr/procedures/definitions/win32/mspatcha.json +63 -0
- angr/procedures/definitions/win32/mspatchc.json +42 -0
- angr/procedures/definitions/win32/msports.json +36 -0
- angr/procedures/definitions/win32/msrating.json +72 -0
- angr/procedures/definitions/win32/mssign32.json +45 -0
- angr/procedures/definitions/win32/mstask.json +21 -0
- angr/procedures/definitions/win32/msvfw32.json +144 -0
- angr/procedures/definitions/win32/mswsock.json +63 -0
- angr/procedures/definitions/win32/mtxdm.json +18 -0
- angr/procedures/definitions/win32/ncrypt.json +132 -0
- angr/procedures/definitions/win32/ndfapi.json +63 -0
- angr/procedures/definitions/win32/netapi32.json +633 -0
- angr/procedures/definitions/win32/netsh.json +39 -0
- angr/procedures/definitions/win32/netshell.json +21 -0
- angr/procedures/definitions/win32/newdev.json +48 -0
- angr/procedures/definitions/win32/ninput.json +105 -0
- angr/procedures/definitions/win32/normaliz.json +21 -0
- angr/procedures/definitions/win32/ntdll.json +234 -0
- angr/procedures/definitions/win32/ntdllk.json +18 -0
- angr/procedures/definitions/win32/ntdsapi.json +258 -0
- angr/procedures/definitions/win32/ntlanman.json +45 -0
- angr/procedures/definitions/win32/odbc32.json +477 -0
- angr/procedures/definitions/win32/odbcbcp.json +96 -0
- angr/procedures/definitions/win32/ole32.json +966 -0
- angr/procedures/definitions/win32/oleacc.json +66 -0
- angr/procedures/definitions/win32/oleaut32.json +1230 -0
- angr/procedures/definitions/win32/oledlg.json +84 -0
- angr/procedures/definitions/win32/ondemandconnroutehelper.json +30 -0
- angr/procedures/definitions/win32/opengl32.json +1080 -0
- angr/procedures/definitions/win32/opmxbox.json +24 -0
- angr/procedures/definitions/win32/p2p.json +339 -0
- angr/procedures/definitions/win32/p2pgraph.json +126 -0
- angr/procedures/definitions/win32/pdh.json +309 -0
- angr/procedures/definitions/win32/peerdist.json +99 -0
- angr/procedures/definitions/win32/powrprof.json +267 -0
- angr/procedures/definitions/win32/prntvpt.json +48 -0
- angr/procedures/definitions/win32/projectedfslib.json +72 -0
- angr/procedures/definitions/win32/propsys.json +669 -0
- angr/procedures/definitions/win32/psapi.json +96 -0
- angr/procedures/definitions/win32/quartz.json +21 -0
- angr/procedures/definitions/win32/query.json +27 -0
- angr/procedures/definitions/win32/qwave.json +48 -0
- angr/procedures/definitions/win32/rasapi32.json +267 -0
- angr/procedures/definitions/win32/rasdlg.json +33 -0
- angr/procedures/definitions/win32/resutils.json +375 -0
- angr/procedures/definitions/win32/rpcns4.json +198 -0
- angr/procedures/definitions/win32/rpcproxy.json +27 -0
- angr/procedures/definitions/win32/rpcrt4.json +1356 -0
- angr/procedures/definitions/win32/rstrtmgr.json +48 -0
- angr/procedures/definitions/win32/rtm.json +243 -0
- angr/procedures/definitions/win32/rtutils.json +138 -0
- angr/procedures/definitions/win32/rtworkq.json +114 -0
- angr/procedures/definitions/win32/sas.json +18 -0
- angr/procedures/definitions/win32/scarddlg.json +30 -0
- angr/procedures/definitions/win32/schannel.json +42 -0
- angr/procedures/definitions/win32/sechost.json +21 -0
- angr/procedures/definitions/win32/secur32.json +282 -0
- angr/procedures/definitions/win32/sensapi.json +24 -0
- angr/procedures/definitions/win32/sensorsutilsv2.json +135 -0
- angr/procedures/definitions/win32/setupapi.json +1017 -0
- angr/procedures/definitions/win32/sfc.json +33 -0
- angr/procedures/definitions/win32/shdocvw.json +24 -0
- angr/procedures/definitions/win32/shell32.json +747 -0
- angr/procedures/definitions/win32/shlwapi.json +1095 -0
- angr/procedures/definitions/win32/slc.json +111 -0
- angr/procedures/definitions/win32/slcext.json +27 -0
- angr/procedures/definitions/win32/slwga.json +18 -0
- angr/procedures/definitions/win32/snmpapi.json +93 -0
- angr/procedures/definitions/win32/spoolss.json +93 -0
- angr/procedures/definitions/win32/srclient.json +18 -0
- angr/procedures/definitions/win32/srpapi.json +48 -0
- angr/procedures/definitions/win32/sspicli.json +36 -0
- angr/procedures/definitions/win32/sti.json +18 -0
- angr/procedures/definitions/win32/t2embed.json +57 -0
- angr/procedures/definitions/win32/tapi32.json +762 -0
- angr/procedures/definitions/win32/tbs.json +57 -0
- angr/procedures/definitions/win32/tdh.json +96 -0
- angr/procedures/definitions/win32/tokenbinding.json +45 -0
- angr/procedures/definitions/win32/traffic.json +75 -0
- angr/procedures/definitions/win32/txfw32.json +42 -0
- angr/procedures/definitions/win32/ualapi.json +27 -0
- angr/procedures/definitions/win32/uiautomationcore.json +309 -0
- angr/procedures/definitions/win32/urlmon.json +246 -0
- angr/procedures/definitions/win32/user32.json +2298 -0
- angr/procedures/definitions/win32/userenv.json +147 -0
- angr/procedures/definitions/win32/usp10.json +135 -0
- angr/procedures/definitions/win32/uxtheme.json +246 -0
- angr/procedures/definitions/win32/verifier.json +18 -0
- angr/procedures/definitions/win32/version.json +57 -0
- angr/procedures/definitions/win32/vertdll.json +36 -0
- angr/procedures/definitions/win32/virtdisk.json +102 -0
- angr/procedures/definitions/win32/vmdevicehost.json +54 -0
- angr/procedures/definitions/win32/vmsavedstatedumpprovider.json +144 -0
- angr/procedures/definitions/win32/vssapi.json +18 -0
- angr/procedures/definitions/win32/wcmapi.json +30 -0
- angr/procedures/definitions/win32/wdsbp.json +36 -0
- angr/procedures/definitions/win32/wdsclientapi.json +126 -0
- angr/procedures/definitions/win32/wdsmc.json +33 -0
- angr/procedures/definitions/win32/wdspxe.json +108 -0
- angr/procedures/definitions/win32/wdstptc.json +54 -0
- angr/procedures/definitions/win32/webauthn.json +54 -0
- angr/procedures/definitions/win32/webservices.json +594 -0
- angr/procedures/definitions/win32/websocket.json +54 -0
- angr/procedures/definitions/win32/wecapi.json +60 -0
- angr/procedures/definitions/win32/wer.json +78 -0
- angr/procedures/definitions/win32/wevtapi.json +120 -0
- angr/procedures/definitions/win32/winbio.json +177 -0
- angr/procedures/definitions/win32/windows_ai_machinelearning.json +18 -0
- angr/procedures/definitions/win32/windows_media_mediacontrol.json +39 -0
- angr/procedures/definitions/win32/windows_networking.json +18 -0
- angr/procedures/definitions/win32/windows_ui_xaml.json +21 -0
- angr/procedures/definitions/win32/windowscodecs.json +42 -0
- angr/procedures/definitions/win32/winfax.json +183 -0
- angr/procedures/definitions/win32/winhttp.json +183 -0
- angr/procedures/definitions/win32/winhvemulation.json +27 -0
- angr/procedures/definitions/win32/winhvplatform.json +213 -0
- angr/procedures/definitions/win32/wininet.json +903 -0
- angr/procedures/definitions/win32/winml.json +18 -0
- angr/procedures/definitions/win32/winmm.json +543 -0
- angr/procedures/definitions/win32/winscard.json +225 -0
- angr/procedures/definitions/win32/winspool_drv.json +531 -0
- angr/procedures/definitions/win32/wintrust.json +195 -0
- angr/procedures/definitions/win32/winusb.json +117 -0
- angr/procedures/definitions/win32/wlanapi.json +195 -0
- angr/procedures/definitions/win32/wlanui.json +18 -0
- angr/procedures/definitions/win32/wldap32.json +744 -0
- angr/procedures/definitions/win32/wldp.json +42 -0
- angr/procedures/definitions/win32/wmvcore.json +48 -0
- angr/procedures/definitions/win32/wnvapi.json +21 -0
- angr/procedures/definitions/win32/wofutil.json +48 -0
- angr/procedures/definitions/win32/ws2_32.json +495 -0
- angr/procedures/definitions/win32/wscapi.json +33 -0
- angr/procedures/definitions/win32/wsclient.json +24 -0
- angr/procedures/definitions/win32/wsdapi.json +111 -0
- angr/procedures/definitions/win32/wsmsvc.json +114 -0
- angr/procedures/definitions/win32/wsnmp32.json +162 -0
- angr/procedures/definitions/win32/wtsapi32.json +204 -0
- angr/procedures/definitions/win32/xaudio2_8.json +27 -0
- angr/procedures/definitions/win32/xinput1_4.json +36 -0
- angr/procedures/definitions/win32/xmllite.json +33 -0
- angr/procedures/definitions/win32/xolehlp.json +27 -0
- angr/procedures/definitions/win32/xpsprint.json +21 -0
- angr/procedures/glibc/__ctype_b_loc.py +21 -0
- angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
- angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
- angr/procedures/glibc/__errno_location.py +7 -0
- angr/procedures/glibc/__init__.py +3 -0
- angr/procedures/glibc/__libc_init.py +37 -0
- angr/procedures/glibc/__libc_start_main.py +301 -0
- angr/procedures/glibc/dynamic_loading.py +20 -0
- angr/procedures/glibc/scanf.py +19 -0
- angr/procedures/glibc/sscanf.py +10 -0
- angr/procedures/gnulib/__init__.py +3 -0
- angr/procedures/gnulib/xalloc_die.py +14 -0
- angr/procedures/gnulib/xstrtol_fatal.py +14 -0
- angr/procedures/java/__init__.py +42 -0
- angr/procedures/java/unconstrained.py +65 -0
- angr/procedures/java_io/__init__.py +0 -0
- angr/procedures/java_io/read.py +12 -0
- angr/procedures/java_io/write.py +17 -0
- angr/procedures/java_jni/__init__.py +482 -0
- angr/procedures/java_jni/array_operations.py +312 -0
- angr/procedures/java_jni/class_and_interface_operations.py +31 -0
- angr/procedures/java_jni/field_access.py +173 -0
- angr/procedures/java_jni/global_and_local_refs.py +57 -0
- angr/procedures/java_jni/method_calls.py +365 -0
- angr/procedures/java_jni/not_implemented.py +26 -0
- angr/procedures/java_jni/object_operations.py +94 -0
- angr/procedures/java_jni/string_operations.py +87 -0
- angr/procedures/java_jni/version_information.py +12 -0
- angr/procedures/java_lang/__init__.py +0 -0
- angr/procedures/java_lang/character.py +30 -0
- angr/procedures/java_lang/double.py +24 -0
- angr/procedures/java_lang/exit.py +13 -0
- angr/procedures/java_lang/getsimplename.py +18 -0
- angr/procedures/java_lang/integer.py +43 -0
- angr/procedures/java_lang/load_library.py +9 -0
- angr/procedures/java_lang/math.py +15 -0
- angr/procedures/java_lang/string.py +78 -0
- angr/procedures/java_lang/stringbuilder.py +44 -0
- angr/procedures/java_lang/system.py +18 -0
- angr/procedures/java_util/__init__.py +0 -0
- angr/procedures/java_util/collection.py +35 -0
- angr/procedures/java_util/iterator.py +46 -0
- angr/procedures/java_util/list.py +99 -0
- angr/procedures/java_util/map.py +131 -0
- angr/procedures/java_util/random.py +14 -0
- angr/procedures/java_util/scanner_nextline.py +23 -0
- angr/procedures/libc/__init__.py +3 -0
- angr/procedures/libc/abort.py +9 -0
- angr/procedures/libc/access.py +13 -0
- angr/procedures/libc/atoi.py +14 -0
- angr/procedures/libc/atol.py +13 -0
- angr/procedures/libc/calloc.py +8 -0
- angr/procedures/libc/closelog.py +10 -0
- angr/procedures/libc/err.py +14 -0
- angr/procedures/libc/error.py +54 -0
- angr/procedures/libc/exit.py +11 -0
- angr/procedures/libc/fclose.py +19 -0
- angr/procedures/libc/feof.py +21 -0
- angr/procedures/libc/fflush.py +16 -0
- angr/procedures/libc/fgetc.py +27 -0
- angr/procedures/libc/fgets.py +69 -0
- angr/procedures/libc/fopen.py +63 -0
- angr/procedures/libc/fprintf.py +25 -0
- angr/procedures/libc/fputc.py +23 -0
- angr/procedures/libc/fputs.py +24 -0
- angr/procedures/libc/fread.py +24 -0
- angr/procedures/libc/free.py +9 -0
- angr/procedures/libc/fscanf.py +20 -0
- angr/procedures/libc/fseek.py +34 -0
- angr/procedures/libc/ftell.py +22 -0
- angr/procedures/libc/fwrite.py +19 -0
- angr/procedures/libc/getchar.py +13 -0
- angr/procedures/libc/getdelim.py +99 -0
- angr/procedures/libc/getegid.py +8 -0
- angr/procedures/libc/geteuid.py +8 -0
- angr/procedures/libc/getgid.py +8 -0
- angr/procedures/libc/gets.py +68 -0
- angr/procedures/libc/getuid.py +8 -0
- angr/procedures/libc/malloc.py +12 -0
- angr/procedures/libc/memcmp.py +69 -0
- angr/procedures/libc/memcpy.py +45 -0
- angr/procedures/libc/memset.py +72 -0
- angr/procedures/libc/openlog.py +10 -0
- angr/procedures/libc/perror.py +13 -0
- angr/procedures/libc/printf.py +34 -0
- angr/procedures/libc/putchar.py +13 -0
- angr/procedures/libc/puts.py +19 -0
- angr/procedures/libc/rand.py +8 -0
- angr/procedures/libc/realloc.py +8 -0
- angr/procedures/libc/rewind.py +12 -0
- angr/procedures/libc/scanf.py +20 -0
- angr/procedures/libc/setbuf.py +9 -0
- angr/procedures/libc/setvbuf.py +7 -0
- angr/procedures/libc/snprintf.py +36 -0
- angr/procedures/libc/sprintf.py +25 -0
- angr/procedures/libc/srand.py +7 -0
- angr/procedures/libc/sscanf.py +13 -0
- angr/procedures/libc/stpcpy.py +18 -0
- angr/procedures/libc/strcat.py +14 -0
- angr/procedures/libc/strchr.py +48 -0
- angr/procedures/libc/strcmp.py +31 -0
- angr/procedures/libc/strcpy.py +13 -0
- angr/procedures/libc/strlen.py +114 -0
- angr/procedures/libc/strncat.py +19 -0
- angr/procedures/libc/strncmp.py +183 -0
- angr/procedures/libc/strncpy.py +22 -0
- angr/procedures/libc/strnlen.py +13 -0
- angr/procedures/libc/strstr.py +101 -0
- angr/procedures/libc/strtol.py +261 -0
- angr/procedures/libc/strtoul.py +9 -0
- angr/procedures/libc/system.py +13 -0
- angr/procedures/libc/time.py +9 -0
- angr/procedures/libc/tmpnam.py +20 -0
- angr/procedures/libc/tolower.py +10 -0
- angr/procedures/libc/toupper.py +10 -0
- angr/procedures/libc/ungetc.py +20 -0
- angr/procedures/libc/vsnprintf.py +17 -0
- angr/procedures/libc/wchar.py +16 -0
- angr/procedures/libstdcpp/__init__.py +0 -0
- angr/procedures/libstdcpp/_unwind_resume.py +11 -0
- angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
- angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
- angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
- angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
- angr/procedures/libstdcpp/std__terminate.py +13 -0
- angr/procedures/linux_kernel/__init__.py +3 -0
- angr/procedures/linux_kernel/access.py +18 -0
- angr/procedures/linux_kernel/arch_prctl.py +34 -0
- angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
- angr/procedures/linux_kernel/brk.py +18 -0
- angr/procedures/linux_kernel/cwd.py +28 -0
- angr/procedures/linux_kernel/fstat.py +138 -0
- angr/procedures/linux_kernel/fstat64.py +170 -0
- angr/procedures/linux_kernel/futex.py +17 -0
- angr/procedures/linux_kernel/getegid.py +17 -0
- angr/procedures/linux_kernel/geteuid.py +17 -0
- angr/procedures/linux_kernel/getgid.py +17 -0
- angr/procedures/linux_kernel/getpid.py +14 -0
- angr/procedures/linux_kernel/getrlimit.py +24 -0
- angr/procedures/linux_kernel/gettid.py +9 -0
- angr/procedures/linux_kernel/getuid.py +17 -0
- angr/procedures/linux_kernel/iovec.py +47 -0
- angr/procedures/linux_kernel/lseek.py +42 -0
- angr/procedures/linux_kernel/mmap.py +16 -0
- angr/procedures/linux_kernel/mprotect.py +42 -0
- angr/procedures/linux_kernel/munmap.py +8 -0
- angr/procedures/linux_kernel/openat.py +26 -0
- angr/procedures/linux_kernel/set_tid_address.py +8 -0
- angr/procedures/linux_kernel/sigaction.py +19 -0
- angr/procedures/linux_kernel/sigprocmask.py +23 -0
- angr/procedures/linux_kernel/stat.py +23 -0
- angr/procedures/linux_kernel/sysinfo.py +59 -0
- angr/procedures/linux_kernel/tgkill.py +10 -0
- angr/procedures/linux_kernel/time.py +34 -0
- angr/procedures/linux_kernel/uid.py +30 -0
- angr/procedures/linux_kernel/uname.py +29 -0
- angr/procedures/linux_kernel/unlink.py +22 -0
- angr/procedures/linux_kernel/vsyscall.py +16 -0
- angr/procedures/linux_loader/__init__.py +3 -0
- angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
- angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
- angr/procedures/linux_loader/sim_loader.py +54 -0
- angr/procedures/linux_loader/tls.py +40 -0
- angr/procedures/msvcr/__getmainargs.py +16 -0
- angr/procedures/msvcr/__init__.py +4 -0
- angr/procedures/msvcr/_initterm.py +38 -0
- angr/procedures/msvcr/fmode.py +31 -0
- angr/procedures/ntdll/__init__.py +0 -0
- angr/procedures/ntdll/exceptions.py +60 -0
- angr/procedures/posix/__init__.py +3 -0
- angr/procedures/posix/accept.py +29 -0
- angr/procedures/posix/bind.py +13 -0
- angr/procedures/posix/bzero.py +9 -0
- angr/procedures/posix/chroot.py +27 -0
- angr/procedures/posix/close.py +9 -0
- angr/procedures/posix/closedir.py +7 -0
- angr/procedures/posix/dup.py +56 -0
- angr/procedures/posix/fcntl.py +10 -0
- angr/procedures/posix/fdopen.py +76 -0
- angr/procedures/posix/fileno.py +18 -0
- angr/procedures/posix/fork.py +13 -0
- angr/procedures/posix/getenv.py +35 -0
- angr/procedures/posix/gethostbyname.py +43 -0
- angr/procedures/posix/getpass.py +19 -0
- angr/procedures/posix/getsockopt.py +11 -0
- angr/procedures/posix/htonl.py +11 -0
- angr/procedures/posix/htons.py +11 -0
- angr/procedures/posix/inet_ntoa.py +59 -0
- angr/procedures/posix/listen.py +13 -0
- angr/procedures/posix/mmap.py +144 -0
- angr/procedures/posix/open.py +18 -0
- angr/procedures/posix/opendir.py +10 -0
- angr/procedures/posix/poll.py +55 -0
- angr/procedures/posix/pread64.py +46 -0
- angr/procedures/posix/pthread.py +87 -0
- angr/procedures/posix/pwrite64.py +46 -0
- angr/procedures/posix/read.py +13 -0
- angr/procedures/posix/readdir.py +62 -0
- angr/procedures/posix/recv.py +13 -0
- angr/procedures/posix/recvfrom.py +13 -0
- angr/procedures/posix/select.py +48 -0
- angr/procedures/posix/send.py +23 -0
- angr/procedures/posix/setsockopt.py +9 -0
- angr/procedures/posix/sigaction.py +23 -0
- angr/procedures/posix/sim_time.py +48 -0
- angr/procedures/posix/sleep.py +8 -0
- angr/procedures/posix/socket.py +18 -0
- angr/procedures/posix/strcasecmp.py +26 -0
- angr/procedures/posix/strdup.py +18 -0
- angr/procedures/posix/strtok_r.py +64 -0
- angr/procedures/posix/syslog.py +15 -0
- angr/procedures/posix/tz.py +9 -0
- angr/procedures/posix/unlink.py +11 -0
- angr/procedures/posix/usleep.py +8 -0
- angr/procedures/posix/write.py +13 -0
- angr/procedures/procedure_dict.py +50 -0
- angr/procedures/stubs/CallReturn.py +13 -0
- angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
- angr/procedures/stubs/Nop.py +7 -0
- angr/procedures/stubs/PathTerminator.py +9 -0
- angr/procedures/stubs/Redirect.py +18 -0
- angr/procedures/stubs/ReturnChar.py +11 -0
- angr/procedures/stubs/ReturnUnconstrained.py +24 -0
- angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
- angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
- angr/procedures/stubs/UserHook.py +18 -0
- angr/procedures/stubs/__init__.py +3 -0
- angr/procedures/stubs/b64_decode.py +15 -0
- angr/procedures/stubs/caller.py +14 -0
- angr/procedures/stubs/crazy_scanf.py +20 -0
- angr/procedures/stubs/format_parser.py +669 -0
- angr/procedures/stubs/syscall_stub.py +24 -0
- angr/procedures/testing/__init__.py +3 -0
- angr/procedures/testing/manyargs.py +9 -0
- angr/procedures/testing/retreg.py +8 -0
- angr/procedures/tracer/__init__.py +4 -0
- angr/procedures/tracer/random.py +9 -0
- angr/procedures/tracer/receive.py +23 -0
- angr/procedures/tracer/transmit.py +26 -0
- angr/procedures/uclibc/__init__.py +3 -0
- angr/procedures/uclibc/__uClibc_main.py +10 -0
- angr/procedures/win32/EncodePointer.py +7 -0
- angr/procedures/win32/ExitProcess.py +9 -0
- angr/procedures/win32/GetCommandLine.py +12 -0
- angr/procedures/win32/GetCurrentProcessId.py +7 -0
- angr/procedures/win32/GetCurrentThreadId.py +7 -0
- angr/procedures/win32/GetLastInputInfo.py +40 -0
- angr/procedures/win32/GetModuleHandle.py +29 -0
- angr/procedures/win32/GetProcessAffinityMask.py +37 -0
- angr/procedures/win32/InterlockedExchange.py +15 -0
- angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
- angr/procedures/win32/VirtualAlloc.py +114 -0
- angr/procedures/win32/VirtualProtect.py +60 -0
- angr/procedures/win32/__init__.py +3 -0
- angr/procedures/win32/critical_section.py +12 -0
- angr/procedures/win32/dynamic_loading.py +104 -0
- angr/procedures/win32/file_handles.py +47 -0
- angr/procedures/win32/gethostbyname.py +12 -0
- angr/procedures/win32/heap.py +45 -0
- angr/procedures/win32/is_bad_ptr.py +26 -0
- angr/procedures/win32/local_storage.py +88 -0
- angr/procedures/win32/mutex.py +11 -0
- angr/procedures/win32/sim_time.py +135 -0
- angr/procedures/win32/system_paths.py +35 -0
- angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
- angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
- angr/procedures/win32_kernel/__fastfail.py +15 -0
- angr/procedures/win32_kernel/__init__.py +3 -0
- angr/procedures/win_user32/__init__.py +0 -0
- angr/procedures/win_user32/chars.py +15 -0
- angr/procedures/win_user32/keyboard.py +14 -0
- angr/procedures/win_user32/messagebox.py +49 -0
- angr/project.py +860 -0
- angr/protos/__init__.py +19 -0
- angr/protos/cfg_pb2.py +42 -0
- angr/protos/function_pb2.py +38 -0
- angr/protos/primitives_pb2.py +59 -0
- angr/protos/variables_pb2.py +55 -0
- angr/protos/xrefs_pb2.py +36 -0
- angr/py.typed +1 -0
- angr/rustylib.cpython-311-darwin.so +0 -0
- angr/serializable.py +66 -0
- angr/sim_manager.py +971 -0
- angr/sim_options.py +436 -0
- angr/sim_procedure.py +626 -0
- angr/sim_state.py +926 -0
- angr/sim_state_options.py +403 -0
- angr/sim_type.py +4026 -0
- angr/sim_variable.py +470 -0
- angr/simos/__init__.py +47 -0
- angr/simos/cgc.py +153 -0
- angr/simos/javavm.py +458 -0
- angr/simos/linux.py +509 -0
- angr/simos/simos.py +444 -0
- angr/simos/snimmuc_nxp.py +149 -0
- angr/simos/userland.py +163 -0
- angr/simos/windows.py +615 -0
- angr/simos/xbox.py +32 -0
- angr/slicer.py +352 -0
- angr/state_hierarchy.py +262 -0
- angr/state_plugins/__init__.py +84 -0
- angr/state_plugins/callstack.py +478 -0
- angr/state_plugins/cgc.py +155 -0
- angr/state_plugins/debug_variables.py +192 -0
- angr/state_plugins/filesystem.py +463 -0
- angr/state_plugins/gdb.py +148 -0
- angr/state_plugins/globals.py +65 -0
- angr/state_plugins/heap/__init__.py +15 -0
- angr/state_plugins/heap/heap_base.py +128 -0
- angr/state_plugins/heap/heap_brk.py +136 -0
- angr/state_plugins/heap/heap_freelist.py +213 -0
- angr/state_plugins/heap/heap_libc.py +46 -0
- angr/state_plugins/heap/heap_ptmalloc.py +620 -0
- angr/state_plugins/heap/utils.py +22 -0
- angr/state_plugins/history.py +564 -0
- angr/state_plugins/inspect.py +375 -0
- angr/state_plugins/javavm_classloader.py +134 -0
- angr/state_plugins/jni_references.py +95 -0
- angr/state_plugins/libc.py +1263 -0
- angr/state_plugins/light_registers.py +168 -0
- angr/state_plugins/log.py +84 -0
- angr/state_plugins/loop_data.py +92 -0
- angr/state_plugins/plugin.py +176 -0
- angr/state_plugins/posix.py +703 -0
- angr/state_plugins/preconstrainer.py +196 -0
- angr/state_plugins/scratch.py +173 -0
- angr/state_plugins/sim_action.py +326 -0
- angr/state_plugins/sim_action_object.py +271 -0
- angr/state_plugins/sim_event.py +59 -0
- angr/state_plugins/solver.py +1128 -0
- angr/state_plugins/symbolizer.py +291 -0
- angr/state_plugins/trace_additions.py +738 -0
- angr/state_plugins/uc_manager.py +94 -0
- angr/state_plugins/unicorn_engine.py +1920 -0
- angr/state_plugins/view.py +340 -0
- angr/storage/__init__.py +15 -0
- angr/storage/file.py +1210 -0
- angr/storage/memory_mixins/__init__.py +317 -0
- angr/storage/memory_mixins/actions_mixin.py +72 -0
- angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
- angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
- angr/storage/memory_mixins/clouseau_mixin.py +137 -0
- angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
- angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
- angr/storage/memory_mixins/default_filler_mixin.py +144 -0
- angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
- angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
- angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
- angr/storage/memory_mixins/keyvalue_memory_mixin.py +43 -0
- angr/storage/memory_mixins/label_merger_mixin.py +31 -0
- angr/storage/memory_mixins/memory_mixin.py +175 -0
- angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
- angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
- angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
- angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
- angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
- angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +529 -0
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
- angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
- angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
- angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +442 -0
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
- angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
- angr/storage/memory_mixins/simplification_mixin.py +15 -0
- angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
- angr/storage/memory_mixins/slotted_memory.py +140 -0
- angr/storage/memory_mixins/smart_find_mixin.py +161 -0
- angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
- angr/storage/memory_mixins/top_merger_mixin.py +25 -0
- angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
- angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
- angr/storage/memory_object.py +195 -0
- angr/tablespecs.py +91 -0
- angr/unicornlib.dylib +0 -0
- angr/utils/__init__.py +46 -0
- angr/utils/ail.py +176 -0
- angr/utils/algo.py +34 -0
- angr/utils/balancer.py +776 -0
- angr/utils/bits.py +46 -0
- angr/utils/constants.py +9 -0
- angr/utils/cowdict.py +63 -0
- angr/utils/cpp.py +17 -0
- angr/utils/doms.py +150 -0
- angr/utils/dynamic_dictlist.py +89 -0
- angr/utils/endness.py +18 -0
- angr/utils/enums_conv.py +97 -0
- angr/utils/env.py +12 -0
- angr/utils/formatting.py +128 -0
- angr/utils/funcid.py +244 -0
- angr/utils/graph.py +981 -0
- angr/utils/lazy_import.py +13 -0
- angr/utils/library.py +236 -0
- angr/utils/loader.py +55 -0
- angr/utils/mp.py +66 -0
- angr/utils/orderedset.py +74 -0
- angr/utils/ssa/__init__.py +455 -0
- angr/utils/ssa/tmp_uses_collector.py +23 -0
- angr/utils/ssa/vvar_uses_collector.py +36 -0
- angr/utils/strings.py +20 -0
- angr/utils/tagged_interval_map.py +112 -0
- angr/utils/timing.py +74 -0
- angr/utils/types.py +193 -0
- angr/utils/vex.py +11 -0
- angr/vaults.py +367 -0
- angr-9.2.192.dist-info/METADATA +112 -0
- angr-9.2.192.dist-info/RECORD +1442 -0
- angr-9.2.192.dist-info/WHEEL +6 -0
- angr-9.2.192.dist-info/entry_points.txt +2 -0
- angr-9.2.192.dist-info/licenses/LICENSE +27 -0
- angr-9.2.192.dist-info/top_level.txt +1 -0
angr/analyses/vfg.py
ADDED
|
@@ -0,0 +1,1898 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING, Any
|
|
3
|
+
from collections.abc import Callable, Generator
|
|
4
|
+
import logging
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
|
|
7
|
+
import archinfo
|
|
8
|
+
from archinfo.arch_arm import is_arm_arch
|
|
9
|
+
import claripy
|
|
10
|
+
import networkx
|
|
11
|
+
|
|
12
|
+
from angr.utils.graph import GraphUtils
|
|
13
|
+
from angr.analyses import ForwardAnalysis
|
|
14
|
+
from .cfg.cfg_job_base import BlockID, FunctionKey, CFGJobBase
|
|
15
|
+
from angr import sim_options
|
|
16
|
+
from angr.engines.procedure import ProcedureEngine
|
|
17
|
+
from angr.engines import SimSuccessors
|
|
18
|
+
from angr.errors import (
|
|
19
|
+
AngrDelayJobNotice,
|
|
20
|
+
AngrSkipJobNotice,
|
|
21
|
+
AngrVFGError,
|
|
22
|
+
AngrError,
|
|
23
|
+
AngrVFGRestartAnalysisNotice,
|
|
24
|
+
AngrJobMergingFailureNotice,
|
|
25
|
+
SimValueError,
|
|
26
|
+
SimIRSBError,
|
|
27
|
+
SimError,
|
|
28
|
+
)
|
|
29
|
+
from angr.procedures import SIM_PROCEDURES
|
|
30
|
+
from angr.state_plugins.callstack import CallStack
|
|
31
|
+
from angr.analyses import AnalysesHub
|
|
32
|
+
from angr.sim_state import SimState
|
|
33
|
+
from . import Analysis, CFGEmulated
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from angr.knowledge_base import KnowledgeBase
|
|
37
|
+
|
|
38
|
+
l = logging.getLogger(name=__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class VFGJob(CFGJobBase):
|
|
42
|
+
"""
|
|
43
|
+
A job descriptor that contains local variables used during VFG analysis.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, *args, **kwargs) -> None:
|
|
47
|
+
super().__init__(*args, **kwargs)
|
|
48
|
+
|
|
49
|
+
self.call_stack_suffix: list = []
|
|
50
|
+
self.vfg_node: VFGNode | None = None
|
|
51
|
+
self.is_call_jump = None
|
|
52
|
+
self.call_target = None
|
|
53
|
+
self.dbg_exit_status = {}
|
|
54
|
+
self.is_return_jump = None
|
|
55
|
+
|
|
56
|
+
self.sim_successors: SimSuccessors | None = None
|
|
57
|
+
|
|
58
|
+
# if this job has a call successor, do we plan to skip the call successor or not
|
|
59
|
+
self.call_skipped = False
|
|
60
|
+
# if the call is skipped, calling stack of the skipped function is saved in `call_context_key`
|
|
61
|
+
self.call_function_key: FunctionKey | None = None
|
|
62
|
+
|
|
63
|
+
self.call_task: CallAnalysis | None = None
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def block_id(self) -> BlockID | None:
|
|
67
|
+
return self._block_id
|
|
68
|
+
|
|
69
|
+
def callstack_repr(self, kb: KnowledgeBase):
|
|
70
|
+
s = []
|
|
71
|
+
for i in range(0, len(self.call_stack_suffix), 2):
|
|
72
|
+
call_site, func_addr = (
|
|
73
|
+
self.call_stack_suffix[i],
|
|
74
|
+
self.call_stack_suffix[i + 1],
|
|
75
|
+
) # pylint:disable=unsubscriptable-object
|
|
76
|
+
if func_addr is None:
|
|
77
|
+
continue
|
|
78
|
+
|
|
79
|
+
call_site_str = f"{call_site:#x}" if call_site is not None else "None"
|
|
80
|
+
|
|
81
|
+
if func_addr in kb.functions:
|
|
82
|
+
s.append(f"{kb.functions[func_addr].name}[{call_site_str}]")
|
|
83
|
+
else:
|
|
84
|
+
s.append(f"{func_addr:#x}[{call_site_str}]")
|
|
85
|
+
|
|
86
|
+
return "//".join(s)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class PendingJob:
|
|
90
|
+
"""
|
|
91
|
+
Describes a pending job during VFG analysis.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
__slots__ = (
|
|
95
|
+
"block_id",
|
|
96
|
+
"call_stack",
|
|
97
|
+
"src_block_id",
|
|
98
|
+
"src_ins_addr",
|
|
99
|
+
"src_stmt_idx",
|
|
100
|
+
"state",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
def __init__(
|
|
104
|
+
self,
|
|
105
|
+
block_id: BlockID,
|
|
106
|
+
state: SimState,
|
|
107
|
+
call_stack: CallStack,
|
|
108
|
+
src_block_id: BlockID,
|
|
109
|
+
src_stmt_idx: int,
|
|
110
|
+
src_ins_addr: int,
|
|
111
|
+
) -> None:
|
|
112
|
+
self.block_id = block_id
|
|
113
|
+
self.state = state
|
|
114
|
+
self.call_stack = call_stack
|
|
115
|
+
self.src_block_id = src_block_id
|
|
116
|
+
self.src_stmt_idx = src_stmt_idx
|
|
117
|
+
self.src_ins_addr = src_ins_addr
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class AnalysisTask:
|
|
121
|
+
"""
|
|
122
|
+
An analysis task describes a task that should be done before popping this task out of the task stack and discard it.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
def __init__(self) -> None:
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def done(self):
|
|
130
|
+
raise NotImplementedError
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class FunctionAnalysis(AnalysisTask):
|
|
134
|
+
"""
|
|
135
|
+
Analyze a function, generate fix-point states from all endpoints of that function, and then merge them to one state.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
def __init__(self, function_address: int, return_address: int | None) -> None:
|
|
139
|
+
super().__init__()
|
|
140
|
+
|
|
141
|
+
self.function_address = function_address
|
|
142
|
+
self.return_address = return_address
|
|
143
|
+
|
|
144
|
+
self.call_analysis: AnalysisTask | None = None
|
|
145
|
+
|
|
146
|
+
# tracks all jobs that are live currently
|
|
147
|
+
self.jobs = []
|
|
148
|
+
|
|
149
|
+
def __repr__(self):
|
|
150
|
+
return f"<Function @ {self.function_address:#08x} with {len(self.jobs)} jobs>"
|
|
151
|
+
|
|
152
|
+
#
|
|
153
|
+
# Properties
|
|
154
|
+
#
|
|
155
|
+
|
|
156
|
+
@property
|
|
157
|
+
def done(self) -> bool:
|
|
158
|
+
return not self.jobs
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class CallAnalysis(AnalysisTask):
|
|
162
|
+
"""
|
|
163
|
+
Analyze a call by analyze all functions this call might be calling, collect all final states generated by analyzing
|
|
164
|
+
those functions, and merge them into one state.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def __init__(
|
|
168
|
+
self,
|
|
169
|
+
address: int,
|
|
170
|
+
return_address: None,
|
|
171
|
+
function_analysis_tasks: list[Any] | None = None,
|
|
172
|
+
mergeable_plugins: tuple[str, str] | None = None,
|
|
173
|
+
) -> None:
|
|
174
|
+
super().__init__()
|
|
175
|
+
|
|
176
|
+
self.address = address
|
|
177
|
+
self.return_address = return_address
|
|
178
|
+
self.function_analysis_tasks = function_analysis_tasks if function_analysis_tasks is not None else []
|
|
179
|
+
self._mergeable_plugins = mergeable_plugins
|
|
180
|
+
|
|
181
|
+
self.skipped = False
|
|
182
|
+
self._final_jobs = []
|
|
183
|
+
|
|
184
|
+
def __repr__(self):
|
|
185
|
+
return f"<Call @ {self.address:#08x} with {len(self.function_analysis_tasks)} function tasks>"
|
|
186
|
+
|
|
187
|
+
#
|
|
188
|
+
# Properties
|
|
189
|
+
#
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def done(self) -> bool:
|
|
193
|
+
return all(task.done for task in self.function_analysis_tasks)
|
|
194
|
+
|
|
195
|
+
#
|
|
196
|
+
# Public methods
|
|
197
|
+
#
|
|
198
|
+
|
|
199
|
+
def register_function_analysis(self, task: FunctionAnalysis) -> None:
|
|
200
|
+
assert isinstance(task, FunctionAnalysis)
|
|
201
|
+
|
|
202
|
+
self.function_analysis_tasks.append(task)
|
|
203
|
+
task.call_analysis = self
|
|
204
|
+
|
|
205
|
+
def add_final_job(self, job: VFGJob) -> None:
|
|
206
|
+
self._final_jobs.append(job)
|
|
207
|
+
|
|
208
|
+
def merge_jobs(self) -> VFGJob:
|
|
209
|
+
assert self._final_jobs
|
|
210
|
+
|
|
211
|
+
job = self._final_jobs[0]
|
|
212
|
+
|
|
213
|
+
for other in self._final_jobs[1:]:
|
|
214
|
+
job.state = job.state.merge(other.state, plugin_whitelist=self._mergeable_plugins)[0]
|
|
215
|
+
|
|
216
|
+
return job
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class VFGNode:
|
|
220
|
+
"""
|
|
221
|
+
A descriptor of nodes in a Value-Flow Graph
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
def __init__(self, addr: int, key: BlockID, state: SimState | None = None) -> None:
|
|
225
|
+
"""
|
|
226
|
+
Constructor.
|
|
227
|
+
|
|
228
|
+
:param int addr:
|
|
229
|
+
:param BlockID key:
|
|
230
|
+
:param SimState state:
|
|
231
|
+
"""
|
|
232
|
+
self.key = key
|
|
233
|
+
self.addr = addr
|
|
234
|
+
self.state: SimState | None = None
|
|
235
|
+
self.widened_state: SimState | None = None
|
|
236
|
+
self.narrowing_times: int = 0
|
|
237
|
+
self.all_states: list[SimState] = []
|
|
238
|
+
self.events: list = []
|
|
239
|
+
self.input_variables: list = []
|
|
240
|
+
self.actions: list = []
|
|
241
|
+
self.final_states: list[SimState] = []
|
|
242
|
+
|
|
243
|
+
if state:
|
|
244
|
+
self.all_states.append(state)
|
|
245
|
+
self.state = state
|
|
246
|
+
|
|
247
|
+
def __hash__(self) -> int:
|
|
248
|
+
return hash(self.key)
|
|
249
|
+
|
|
250
|
+
def __eq__(self, o):
|
|
251
|
+
return (
|
|
252
|
+
type(self) is type(o)
|
|
253
|
+
and self.key == o.key
|
|
254
|
+
and self.addr == o.addr
|
|
255
|
+
and self.state == o.state
|
|
256
|
+
and self.actions == o.actions
|
|
257
|
+
and self.events == o.events
|
|
258
|
+
and self.narrowing_times == o.narrowing_times
|
|
259
|
+
and self.all_states == o.all_states
|
|
260
|
+
and self.widened_state == o.widened_state
|
|
261
|
+
and self.input_variables == o.input_variables
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
def __repr__(self):
|
|
265
|
+
return f"VFGNode[{self.addr:#x}] <{self.key!r}>"
|
|
266
|
+
|
|
267
|
+
def append_state(self, s, is_widened_state=False):
|
|
268
|
+
"""
|
|
269
|
+
Appended a new state to this VFGNode.
|
|
270
|
+
:param s: The new state to append
|
|
271
|
+
:param is_widened_state: Whether it is a widened state or not.
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
if not is_widened_state:
|
|
275
|
+
self.all_states.append(s)
|
|
276
|
+
self.state = s
|
|
277
|
+
|
|
278
|
+
else:
|
|
279
|
+
self.widened_state = s
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
class VFG(ForwardAnalysis[SimState, VFGNode, VFGJob, BlockID, SimState], Analysis): # pylint:disable=abstract-method
|
|
283
|
+
"""
|
|
284
|
+
This class represents a control-flow graph with static analysis result.
|
|
285
|
+
|
|
286
|
+
Perform abstract interpretation analysis starting from the given function address. The output is an invariant at
|
|
287
|
+
the beginning (or the end) of each basic block.
|
|
288
|
+
|
|
289
|
+
Steps:
|
|
290
|
+
|
|
291
|
+
- Generate a CFG first if CFG is not provided.
|
|
292
|
+
- Identify all merge points (denote the set of merge points as Pw) in the CFG.
|
|
293
|
+
- Cut those loop back edges (can be derived from Pw) so that we gain an acyclic CFG.
|
|
294
|
+
- Identify all variables that are 1) from memory loading 2) from initial values, or 3) phi functions. Denote
|
|
295
|
+
the set of those variables as S_{var}.
|
|
296
|
+
- Start real AI analysis and try to compute a fix point of each merge point. Perform widening/narrowing only on
|
|
297
|
+
variables \\in S_{var}.
|
|
298
|
+
"""
|
|
299
|
+
|
|
300
|
+
# TODO: right now the graph traversal method is not optimal. A new solution is needed to minimize the iteration we
|
|
301
|
+
# TODO: access each node in the graph
|
|
302
|
+
|
|
303
|
+
def __init__(
|
|
304
|
+
self,
|
|
305
|
+
cfg: CFGEmulated | None = None,
|
|
306
|
+
context_sensitivity_level: int = 2,
|
|
307
|
+
start: int | None = None,
|
|
308
|
+
function_start: int | None = None,
|
|
309
|
+
interfunction_level: int = 0,
|
|
310
|
+
initial_state: SimState | None = None,
|
|
311
|
+
avoid_runs: list[int] | None = None,
|
|
312
|
+
remove_options: set[str] | None = None,
|
|
313
|
+
timeout: int | None = None,
|
|
314
|
+
max_iterations_before_widening: int = 8,
|
|
315
|
+
max_iterations: int = 40,
|
|
316
|
+
widening_interval: int = 3,
|
|
317
|
+
final_state_callback: Callable[[SimState, CallStack], Any] | None = None,
|
|
318
|
+
status_callback: Callable[[VFG], Any] | None = None,
|
|
319
|
+
record_function_final_states: bool = False,
|
|
320
|
+
) -> None:
|
|
321
|
+
"""
|
|
322
|
+
:param cfg: The control-flow graph to base this analysis on. If none is provided, we will
|
|
323
|
+
construct a CFGEmulated.
|
|
324
|
+
:param context_sensitivity_level: The level of context-sensitivity of this VFG.
|
|
325
|
+
It ranges from 0 to infinity. Default 2.
|
|
326
|
+
:param function_start: The address of the function to analyze.
|
|
327
|
+
:param interfunction_level: The level of interfunction-ness to be
|
|
328
|
+
:param initial_state: A state to use as the initial one
|
|
329
|
+
:param avoid_runs: A list of runs to avoid
|
|
330
|
+
:param remove_options: State options to remove from the initial state. It only works when `initial_state` is
|
|
331
|
+
None
|
|
332
|
+
:param int timeout:
|
|
333
|
+
:param final_state_callback: callback function when countering final state
|
|
334
|
+
:param status_callback: callback function used in _analysis_core_baremetal
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
ForwardAnalysis.__init__(
|
|
338
|
+
self, order_jobs=True, allow_merging=True, allow_widening=True, status_callback=status_callback
|
|
339
|
+
) # type:ignore
|
|
340
|
+
|
|
341
|
+
# Related CFG.
|
|
342
|
+
# We can still perform analysis if you don't specify a CFG. But providing a CFG may give you better result.
|
|
343
|
+
self._cfg = cfg
|
|
344
|
+
|
|
345
|
+
# Where to start the analysis
|
|
346
|
+
self._start: int = start if start is not None else self.project.entry
|
|
347
|
+
self._function_start: int = function_start if function_start is not None else self._start
|
|
348
|
+
|
|
349
|
+
# Other parameters
|
|
350
|
+
self._avoid_runs: list[int] = [] if avoid_runs is None else avoid_runs
|
|
351
|
+
self._context_sensitivity_level = context_sensitivity_level
|
|
352
|
+
self._interfunction_level = interfunction_level
|
|
353
|
+
self._state_options_to_remove = set() if remove_options is None else remove_options
|
|
354
|
+
self._timeout = timeout
|
|
355
|
+
self._start_at_function = self._start == self._function_start
|
|
356
|
+
|
|
357
|
+
self._initial_state = initial_state
|
|
358
|
+
|
|
359
|
+
self._max_iterations_before_widening = max_iterations_before_widening
|
|
360
|
+
self._max_iterations = max_iterations
|
|
361
|
+
self._widening_interval = widening_interval
|
|
362
|
+
|
|
363
|
+
self._final_state_callback = final_state_callback
|
|
364
|
+
|
|
365
|
+
self._record_function_final_states = record_function_final_states
|
|
366
|
+
|
|
367
|
+
self._nodes: dict[BlockID, VFGNode] = {} # all the vfg nodes, keyed on block IDs
|
|
368
|
+
self._normal_states: dict[BlockID, SimState] = (
|
|
369
|
+
{}
|
|
370
|
+
) # Last available state for each program point without widening
|
|
371
|
+
self._widened_states: dict[BlockID, SimState] = {} # States on which widening has occurred
|
|
372
|
+
|
|
373
|
+
# Initial states of each function, which is context sensitive
|
|
374
|
+
# It maps function key to its states
|
|
375
|
+
self._function_initial_states: defaultdict[int, dict[int, SimState]] = defaultdict(dict)
|
|
376
|
+
# Final states of each function, right after `ret` is called. Also context sensitive.
|
|
377
|
+
# even if a function may have multiple return sites, as long as they all return to the same place, there is
|
|
378
|
+
# only one final state of that function.
|
|
379
|
+
self._function_final_states: defaultdict[int, dict[int, SimState]] = defaultdict(dict)
|
|
380
|
+
|
|
381
|
+
# All final states are put in this list
|
|
382
|
+
self.final_states: list[SimState] = []
|
|
383
|
+
|
|
384
|
+
self._state_initialization_map: defaultdict[int, list[tuple[int, int]]] = defaultdict(list)
|
|
385
|
+
|
|
386
|
+
self._exit_targets: defaultdict[tuple[int | None, ...], list[tuple[BlockID, str]]] = defaultdict(
|
|
387
|
+
list
|
|
388
|
+
) # A dict to log edges and the jumpkind between each basic block
|
|
389
|
+
# A dict to record all blocks that returns to a specific address
|
|
390
|
+
self._return_target_sources: defaultdict[int, list[int]] = defaultdict(list)
|
|
391
|
+
|
|
392
|
+
self._pending_returns: dict[BlockID, PendingJob] = {}
|
|
393
|
+
|
|
394
|
+
self._thumb_addrs: set[int] = set() # set of all addresses that are code in thumb mode
|
|
395
|
+
|
|
396
|
+
self._final_address: int | None = (
|
|
397
|
+
None # Address of the very last instruction. The analysis is terminated there.
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
self._function_merge_points: dict[int, list[int]] = {}
|
|
401
|
+
self._function_widening_points: dict[int, list[int]] = {}
|
|
402
|
+
self._function_node_addrs: dict[int, list[int]] = {} # sorted in reverse post-order
|
|
403
|
+
|
|
404
|
+
self._mergeable_plugins = ("memory", "registers")
|
|
405
|
+
|
|
406
|
+
self._task_stack: list[FunctionAnalysis] = []
|
|
407
|
+
|
|
408
|
+
self._tracing_times: defaultdict[BlockID, int] = defaultdict(int)
|
|
409
|
+
|
|
410
|
+
# counters for debugging
|
|
411
|
+
self._execution_counter: defaultdict[BlockID, int] = defaultdict(int)
|
|
412
|
+
|
|
413
|
+
# Start analysis
|
|
414
|
+
self._analyze()
|
|
415
|
+
|
|
416
|
+
#
|
|
417
|
+
# Internal properties
|
|
418
|
+
#
|
|
419
|
+
|
|
420
|
+
@property
|
|
421
|
+
def _current_function_address(self):
|
|
422
|
+
return self._task_stack[-1].function_address
|
|
423
|
+
|
|
424
|
+
@property
|
|
425
|
+
def _top_task(self) -> FunctionAnalysis | None:
|
|
426
|
+
"""
|
|
427
|
+
Get the first task in the stack.
|
|
428
|
+
|
|
429
|
+
:return: The top task in the stack, or None if the stack is empty.
|
|
430
|
+
:rtype: FunctionAnalysis
|
|
431
|
+
"""
|
|
432
|
+
return self._task_stack[-1] if len(self._task_stack) != 0 else None
|
|
433
|
+
|
|
434
|
+
@property
|
|
435
|
+
def _top_function_analysis_task(self):
|
|
436
|
+
"""
|
|
437
|
+
Get the first FunctionAnalysis task in the stack.
|
|
438
|
+
|
|
439
|
+
:return: The top function analysis task in the stack, or None if there isn't any.
|
|
440
|
+
:rtype: FunctionAnalysis
|
|
441
|
+
"""
|
|
442
|
+
|
|
443
|
+
for r in reversed(self._task_stack):
|
|
444
|
+
if isinstance(r, FunctionAnalysis):
|
|
445
|
+
return r
|
|
446
|
+
return None
|
|
447
|
+
|
|
448
|
+
@property
|
|
449
|
+
def function_initial_states(self):
|
|
450
|
+
return self._function_initial_states
|
|
451
|
+
|
|
452
|
+
@property
|
|
453
|
+
def function_final_states(self):
|
|
454
|
+
return self._function_final_states
|
|
455
|
+
|
|
456
|
+
#
|
|
457
|
+
# Public methods
|
|
458
|
+
#
|
|
459
|
+
|
|
460
|
+
def get_any_node(self, addr: int) -> VFGNode | None:
|
|
461
|
+
"""
|
|
462
|
+
Get any VFG node corresponding to the basic block at @addr.
|
|
463
|
+
Note that depending on the context sensitivity level, there might be
|
|
464
|
+
multiple nodes corresponding to different contexts. This function will
|
|
465
|
+
return the first one it encounters, which might not be what you want.
|
|
466
|
+
"""
|
|
467
|
+
for n in self.graph.nodes():
|
|
468
|
+
if n.addr == addr:
|
|
469
|
+
return n
|
|
470
|
+
return None
|
|
471
|
+
|
|
472
|
+
def get_all_nodes(self, addr) -> Generator[VFGNode]:
|
|
473
|
+
for n in self.graph.nodes():
|
|
474
|
+
if n.addr == addr:
|
|
475
|
+
yield n
|
|
476
|
+
|
|
477
|
+
def irsb_from_node(self, node):
|
|
478
|
+
return self.project.factory.successors(node.state, addr=node.addr)
|
|
479
|
+
|
|
480
|
+
#
|
|
481
|
+
# Operations
|
|
482
|
+
#
|
|
483
|
+
|
|
484
|
+
def copy(self):
|
|
485
|
+
new_vfg = VFG(self.project) # type:ignore
|
|
486
|
+
new_vfg._cfg = self._cfg
|
|
487
|
+
new_vfg._graph = networkx.DiGraph(self.graph)
|
|
488
|
+
new_vfg._nodes = self._nodes.copy()
|
|
489
|
+
new_vfg._exit_targets = defaultdict(list, self._exit_targets)
|
|
490
|
+
return new_vfg
|
|
491
|
+
|
|
492
|
+
# Pickling helpers
|
|
493
|
+
def __setstate__(self, s):
|
|
494
|
+
self.__dict__.update(s)
|
|
495
|
+
|
|
496
|
+
def __getstate__(self):
|
|
497
|
+
return dict(self.__dict__)
|
|
498
|
+
|
|
499
|
+
#
|
|
500
|
+
# Main analysis routines, mostly overriding methods of ForwardAnalysis
|
|
501
|
+
#
|
|
502
|
+
|
|
503
|
+
def _pre_analysis(self) -> None:
|
|
504
|
+
"""
|
|
505
|
+
Executed before analysis starts. Necessary initializations are performed here.
|
|
506
|
+
|
|
507
|
+
:return: None
|
|
508
|
+
"""
|
|
509
|
+
|
|
510
|
+
l.debug("Starting from %#x", self._start)
|
|
511
|
+
|
|
512
|
+
# initialize the task stack
|
|
513
|
+
self._task_stack = []
|
|
514
|
+
|
|
515
|
+
# initialize the execution counter dict
|
|
516
|
+
self._execution_counter = defaultdict(int)
|
|
517
|
+
|
|
518
|
+
# Generate a CFG if no CFG is provided
|
|
519
|
+
if not self._cfg:
|
|
520
|
+
l.debug("Generating a CFG, since none was given...")
|
|
521
|
+
# TODO: can we use a fast CFG instead? note that fast CFG does not care of context sensitivity at all, but
|
|
522
|
+
# TODO: for state merging, we also don't really care about context sensitivity.
|
|
523
|
+
self._cfg: CFGEmulated = self.project.analyses[CFGEmulated].prep()(
|
|
524
|
+
context_sensitivity_level=self._context_sensitivity_level, starts=(self._start,)
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
if not self._cfg.normalized:
|
|
528
|
+
l.warning(
|
|
529
|
+
"The given CFG is not normalized, which might impact the performance/accuracy of the VFG analysis."
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
# Prepare the state
|
|
533
|
+
initial_state = self._prepare_initial_state(self._start, self._initial_state)
|
|
534
|
+
initial_state.ip = self._start
|
|
535
|
+
|
|
536
|
+
if self.project.arch.name.startswith("MIPS"):
|
|
537
|
+
initial_state.regs.t9 = self._start
|
|
538
|
+
|
|
539
|
+
# clear function merge points cache
|
|
540
|
+
self._function_merge_points = {}
|
|
541
|
+
|
|
542
|
+
# Create the initial state
|
|
543
|
+
state = initial_state.copy()
|
|
544
|
+
|
|
545
|
+
if self._start_at_function:
|
|
546
|
+
# set the return address to an address so we can catch it and terminate the VSA analysis
|
|
547
|
+
# TODO: Properly pick an address that will not conflict with any existing code and data in the program
|
|
548
|
+
self._final_address = 0x4FFF0000
|
|
549
|
+
self._set_return_address(state, self._final_address)
|
|
550
|
+
|
|
551
|
+
call_stack = None
|
|
552
|
+
if not self._start_at_function:
|
|
553
|
+
# we should build a custom call stack
|
|
554
|
+
call_stack = CallStack()
|
|
555
|
+
call_stack = call_stack.call(None, self._function_start, retn_target=self._final_address)
|
|
556
|
+
|
|
557
|
+
job = VFGJob(
|
|
558
|
+
state.addr,
|
|
559
|
+
state,
|
|
560
|
+
self._context_sensitivity_level,
|
|
561
|
+
jumpkind="Ijk_Boring",
|
|
562
|
+
final_return_address=self._final_address,
|
|
563
|
+
call_stack=call_stack,
|
|
564
|
+
)
|
|
565
|
+
block_id = BlockID.new(state.addr, job.get_call_stack_suffix(), job.jumpkind)
|
|
566
|
+
job._block_id = block_id
|
|
567
|
+
|
|
568
|
+
self._insert_job(job)
|
|
569
|
+
|
|
570
|
+
# create the task
|
|
571
|
+
function_analysis_task = FunctionAnalysis(self._function_start, self._final_address)
|
|
572
|
+
function_analysis_task.jobs.append(job)
|
|
573
|
+
self._task_stack.append(function_analysis_task)
|
|
574
|
+
|
|
575
|
+
def _job_sorting_key(self, job):
|
|
576
|
+
"""
|
|
577
|
+
Get the sorting key of a VFGJob instance.
|
|
578
|
+
|
|
579
|
+
:param VFGJob job: the VFGJob object.
|
|
580
|
+
:return: An integer that determines the order of this job in the queue.
|
|
581
|
+
:rtype: int
|
|
582
|
+
"""
|
|
583
|
+
|
|
584
|
+
MAX_BLOCKS_PER_FUNCTION = 1000000
|
|
585
|
+
|
|
586
|
+
task_functions = list(
|
|
587
|
+
reversed([task.function_address for task in self._task_stack if isinstance(task, FunctionAnalysis)])
|
|
588
|
+
)
|
|
589
|
+
try:
|
|
590
|
+
function_pos = task_functions.index(job.func_addr)
|
|
591
|
+
except ValueError:
|
|
592
|
+
# not in the list
|
|
593
|
+
# it might be because we followed the wrong path, or there is a bug in the traversal algorithm
|
|
594
|
+
# anyways, do it first
|
|
595
|
+
l.warning("Function address %#x is not found in task stack.", job.func_addr)
|
|
596
|
+
return 0
|
|
597
|
+
|
|
598
|
+
try:
|
|
599
|
+
block_in_function_pos = self._ordered_node_addrs(job.func_addr).index(job.addr)
|
|
600
|
+
except ValueError:
|
|
601
|
+
# block not found. what?
|
|
602
|
+
block_in_function_pos = min(job.addr - job.func_addr, MAX_BLOCKS_PER_FUNCTION - 1)
|
|
603
|
+
|
|
604
|
+
return block_in_function_pos + MAX_BLOCKS_PER_FUNCTION * function_pos
|
|
605
|
+
|
|
606
|
+
# return self._cfg.get_topological_order(self._cfg.get_node(job.block_id))
|
|
607
|
+
|
|
608
|
+
def _job_key(self, job: VFGJob) -> BlockID | None:
|
|
609
|
+
"""
|
|
610
|
+
Return the block ID of the job. Two or more jobs owning the same block ID will be merged together.
|
|
611
|
+
|
|
612
|
+
:param VFGJob job: The VFGJob instance.
|
|
613
|
+
:return: The block ID of the job
|
|
614
|
+
:rtype: BlockID
|
|
615
|
+
"""
|
|
616
|
+
|
|
617
|
+
return job.block_id
|
|
618
|
+
|
|
619
|
+
def _pre_job_handling(self, job: VFGJob) -> None:
|
|
620
|
+
"""
|
|
621
|
+
Some code executed before actually processing the job.
|
|
622
|
+
|
|
623
|
+
:param VFGJob job: the VFGJob object.
|
|
624
|
+
:return: None
|
|
625
|
+
"""
|
|
626
|
+
|
|
627
|
+
# did we reach the final address?
|
|
628
|
+
if self._final_address is not None and job.addr == self._final_address:
|
|
629
|
+
# our analysis should be terminated here
|
|
630
|
+
l.debug("%s is viewed as a final state. Skip.", job)
|
|
631
|
+
raise AngrSkipJobNotice
|
|
632
|
+
|
|
633
|
+
l.debug("Handling VFGJob %s", job)
|
|
634
|
+
|
|
635
|
+
if not self._top_task:
|
|
636
|
+
l.debug("No more tasks available. Skip the job.")
|
|
637
|
+
raise AngrSkipJobNotice
|
|
638
|
+
|
|
639
|
+
assert isinstance(self._top_task, FunctionAnalysis)
|
|
640
|
+
|
|
641
|
+
if job not in self._top_task.jobs:
|
|
642
|
+
# it seems that all jobs of the top task has been done. unwind the task stack
|
|
643
|
+
# make sure this job is at least recorded somewhere
|
|
644
|
+
unwind_count = None
|
|
645
|
+
for i, task in enumerate(reversed(self._task_stack)):
|
|
646
|
+
if isinstance(task, FunctionAnalysis) and job in task.jobs:
|
|
647
|
+
# nice
|
|
648
|
+
unwind_count = i
|
|
649
|
+
|
|
650
|
+
if unwind_count is None:
|
|
651
|
+
l.debug("%s is not recorded. Skip the job.", job)
|
|
652
|
+
raise AngrSkipJobNotice
|
|
653
|
+
# unwind the stack till the target, unless we see any pending jobs for each new top task
|
|
654
|
+
for _ in range(unwind_count):
|
|
655
|
+
if isinstance(self._top_task, FunctionAnalysis):
|
|
656
|
+
# are there any pending job belonging to the current function that we should handle first?
|
|
657
|
+
pending_job_key = self._get_pending_job(self._top_task.function_address)
|
|
658
|
+
if pending_job_key is not None:
|
|
659
|
+
# ah there is
|
|
660
|
+
# analyze it first
|
|
661
|
+
self._trace_pending_job(pending_job_key)
|
|
662
|
+
l.debug(
|
|
663
|
+
"A pending job is found for function %#x. Delay %s.",
|
|
664
|
+
self._top_task.function_address,
|
|
665
|
+
job,
|
|
666
|
+
)
|
|
667
|
+
raise AngrDelayJobNotice
|
|
668
|
+
|
|
669
|
+
task = self._task_stack.pop()
|
|
670
|
+
|
|
671
|
+
if not task.done:
|
|
672
|
+
l.warning("Removing an unfinished task %s. Might be a bug.", task)
|
|
673
|
+
|
|
674
|
+
assert job in self._top_task.jobs
|
|
675
|
+
|
|
676
|
+
# check if this is considered to be a final state
|
|
677
|
+
if self._final_state_callback is not None and self._final_state_callback(job.state, job.call_stack):
|
|
678
|
+
l.debug("%s.state is considered as a final state. Skip the job.", job)
|
|
679
|
+
self.final_states.append(job.state)
|
|
680
|
+
raise AngrSkipJobNotice
|
|
681
|
+
|
|
682
|
+
# increment the execution counter
|
|
683
|
+
self._execution_counter[job.addr] += 1
|
|
684
|
+
|
|
685
|
+
self._top_task.jobs.remove(job)
|
|
686
|
+
|
|
687
|
+
# set up some essential variables and parameters
|
|
688
|
+
job.call_stack_suffix = job.get_call_stack_suffix() # type:ignore
|
|
689
|
+
job.jumpkind = "Ijk_Boring" if job.state.history.jumpkind is None else job.state.history.jumpkind
|
|
690
|
+
|
|
691
|
+
src_block_id = job.src_block_id
|
|
692
|
+
src_exit_stmt_idx = job.src_exit_stmt_idx
|
|
693
|
+
|
|
694
|
+
addr = job.state.solver.eval(job.state.regs.ip)
|
|
695
|
+
input_state = job.state
|
|
696
|
+
block_id = BlockID.new(addr, job.call_stack_suffix, job.jumpkind)
|
|
697
|
+
|
|
698
|
+
if self._tracing_times[block_id] > self._max_iterations:
|
|
699
|
+
l.debug("%s has been traced too many times. Skip", job)
|
|
700
|
+
raise AngrSkipJobNotice
|
|
701
|
+
|
|
702
|
+
self._tracing_times[block_id] += 1
|
|
703
|
+
|
|
704
|
+
if block_id not in self._nodes:
|
|
705
|
+
vfg_node = VFGNode(addr, block_id, state=input_state)
|
|
706
|
+
self._nodes[block_id] = vfg_node
|
|
707
|
+
|
|
708
|
+
else:
|
|
709
|
+
vfg_node = self._nodes[block_id]
|
|
710
|
+
|
|
711
|
+
job.vfg_node = vfg_node
|
|
712
|
+
# log the current state
|
|
713
|
+
vfg_node.state = input_state
|
|
714
|
+
|
|
715
|
+
# Execute this basic block with input state, and get a new SimSuccessors instance
|
|
716
|
+
# unused result var is `error_occurred`
|
|
717
|
+
job.sim_successors, _, restart_analysis = self._get_simsuccessors(input_state, addr)
|
|
718
|
+
|
|
719
|
+
if restart_analysis:
|
|
720
|
+
# We should restart the analysis because of something must be changed in the very initial state
|
|
721
|
+
raise AngrVFGRestartAnalysisNotice
|
|
722
|
+
|
|
723
|
+
if job.sim_successors is None:
|
|
724
|
+
# Ouch, we cannot get the SimSuccessors for some reason
|
|
725
|
+
# Skip this guy
|
|
726
|
+
l.debug("Cannot create SimSuccessors for %s. Skip.", job)
|
|
727
|
+
raise AngrSkipJobNotice
|
|
728
|
+
|
|
729
|
+
self._graph_add_edge(src_block_id, block_id, jumpkind=job.jumpkind, src_exit_stmt_idx=src_exit_stmt_idx)
|
|
730
|
+
|
|
731
|
+
def _get_successors(self, job: VFGJob) -> list[SimState]:
|
|
732
|
+
# Extract initial values
|
|
733
|
+
state = job.state
|
|
734
|
+
addr = job.addr
|
|
735
|
+
|
|
736
|
+
# Obtain successors
|
|
737
|
+
if addr not in self._avoid_runs:
|
|
738
|
+
assert job.sim_successors is not None
|
|
739
|
+
all_successors: list[SimState] = (
|
|
740
|
+
job.sim_successors.flat_successors + job.sim_successors.unconstrained_successors
|
|
741
|
+
)
|
|
742
|
+
else:
|
|
743
|
+
all_successors = []
|
|
744
|
+
|
|
745
|
+
assert job.vfg_node is not None
|
|
746
|
+
# save those states
|
|
747
|
+
if job.vfg_node.final_states is None:
|
|
748
|
+
job.vfg_node.final_states = []
|
|
749
|
+
job.vfg_node.final_states.extend(all_successors)
|
|
750
|
+
|
|
751
|
+
# Update thumb_addrs
|
|
752
|
+
assert job.sim_successors
|
|
753
|
+
if job.sim_successors.sort == "IRSB" and state.thumb:
|
|
754
|
+
self._thumb_addrs.update(job.sim_successors.artifacts["insn_addrs"])
|
|
755
|
+
|
|
756
|
+
if not all_successors:
|
|
757
|
+
if job.sim_successors.sort == "SimProcedure" and isinstance(
|
|
758
|
+
job.sim_successors.artifacts["procedure"], SIM_PROCEDURES["stubs"]["PathTerminator"]
|
|
759
|
+
):
|
|
760
|
+
# If there is no valid exit in this branch and it's not
|
|
761
|
+
# intentional (e.g. caused by a SimProcedure that does not
|
|
762
|
+
# do_return) , we should make it return to its callsite.
|
|
763
|
+
# However, we don't want to use its state as it might be
|
|
764
|
+
# corrupted. Just create a link in the exit_targets map.
|
|
765
|
+
retn_target = job.call_stack.current_return_target
|
|
766
|
+
if retn_target is not None:
|
|
767
|
+
new_call_stack = job.call_stack_copy()
|
|
768
|
+
exit_target_tpl = (*new_call_stack.stack_suffix(self._context_sensitivity_level), retn_target)
|
|
769
|
+
self._exit_targets[(*job.call_stack_suffix, addr)].append((exit_target_tpl, "Ijk_Ret"))
|
|
770
|
+
else:
|
|
771
|
+
# This is intentional. We shall remove all the pending returns generated before along this path.
|
|
772
|
+
self._remove_pending_return(job, self._pending_returns)
|
|
773
|
+
|
|
774
|
+
# If this is a call exit, we shouldn't put the default exit (which
|
|
775
|
+
# is artificial) into the CFG. The exits will be Ijk_Call and
|
|
776
|
+
# Ijk_FakeRet, and Ijk_Call always goes first
|
|
777
|
+
job.is_call_jump = any(self._is_call_jumpkind(i.history.jumpkind) for i in all_successors)
|
|
778
|
+
call_targets = []
|
|
779
|
+
for succ in all_successors:
|
|
780
|
+
if self._is_call_jumpkind(succ.history.jumpkind):
|
|
781
|
+
try:
|
|
782
|
+
call_targets.append(succ.solver.eval_one(succ._ip))
|
|
783
|
+
# finding one is enough!
|
|
784
|
+
break
|
|
785
|
+
except SimValueError:
|
|
786
|
+
# this call has multiple possible targets. ignore it
|
|
787
|
+
pass
|
|
788
|
+
|
|
789
|
+
job.call_target = None if not call_targets else call_targets[0]
|
|
790
|
+
|
|
791
|
+
job.is_return_jump = len(all_successors) and all_successors[0].history.jumpkind == "Ijk_Ret"
|
|
792
|
+
|
|
793
|
+
if job.is_call_jump:
|
|
794
|
+
# create the call task
|
|
795
|
+
|
|
796
|
+
# TODO: correctly fill the return address
|
|
797
|
+
call_task = CallAnalysis(job.addr, None, [], mergeable_plugins=self._mergeable_plugins)
|
|
798
|
+
self._task_stack.append(call_task)
|
|
799
|
+
|
|
800
|
+
job.call_task = call_task
|
|
801
|
+
|
|
802
|
+
return all_successors
|
|
803
|
+
|
|
804
|
+
def _handle_successor(
|
|
805
|
+
self, job: VFGJob, successor: SimState, all_successors: list[SimState]
|
|
806
|
+
) -> list[VFGJob | Any]: # pylint:disable=arguments-renamed
|
|
807
|
+
"""
|
|
808
|
+
Process each successor generated by the job, and return a new list of succeeding jobs.
|
|
809
|
+
|
|
810
|
+
:param VFGJob job: The VFGJob instance.
|
|
811
|
+
:param SimState successor: The succeeding state.
|
|
812
|
+
:param list all_successors: A list of all successors.
|
|
813
|
+
:return: A list of newly created jobs from the successor.
|
|
814
|
+
:rtype: list
|
|
815
|
+
"""
|
|
816
|
+
|
|
817
|
+
# Initialize parameters
|
|
818
|
+
addr = job.addr
|
|
819
|
+
jumpkind = successor.history.jumpkind
|
|
820
|
+
|
|
821
|
+
#
|
|
822
|
+
# Get instruction pointer
|
|
823
|
+
#
|
|
824
|
+
|
|
825
|
+
if job.is_return_jump:
|
|
826
|
+
ret_target = job.call_stack.current_return_target
|
|
827
|
+
if ret_target is None:
|
|
828
|
+
# We have no where to go according to our call stack. However, the callstack might be corrupted
|
|
829
|
+
l.debug("According to the call stack, we have nowhere to return to.")
|
|
830
|
+
return []
|
|
831
|
+
|
|
832
|
+
successor.ip = ret_target
|
|
833
|
+
|
|
834
|
+
# this try-except block is to handle cases where the instruction pointer is symbolic
|
|
835
|
+
try:
|
|
836
|
+
successor_addrs = successor.solver.eval_upto(successor.ip, 2)
|
|
837
|
+
except SimValueError:
|
|
838
|
+
# TODO: Should fall back to reading targets from CFG
|
|
839
|
+
# It cannot be concretized currently. Maybe we could handle
|
|
840
|
+
# it later, maybe it just cannot be concretized
|
|
841
|
+
return []
|
|
842
|
+
|
|
843
|
+
if len(successor_addrs) > 1:
|
|
844
|
+
# multiple concrete targets
|
|
845
|
+
if job.is_return_jump:
|
|
846
|
+
# It might be caused by state merging
|
|
847
|
+
# We may retrieve the correct ip from call stack
|
|
848
|
+
successor.ip = job.call_stack.current_return_target
|
|
849
|
+
|
|
850
|
+
else:
|
|
851
|
+
return self._handle_successor_multitargets(job, successor, all_successors)
|
|
852
|
+
|
|
853
|
+
# Now there should be one single target for the successor
|
|
854
|
+
successor_addr = successor.solver.eval_one(successor.ip)
|
|
855
|
+
|
|
856
|
+
# Get the fake ret successor
|
|
857
|
+
fakeret_successor = None
|
|
858
|
+
if self._is_call_jumpkind(jumpkind):
|
|
859
|
+
fakeret_successor = all_successors[-1]
|
|
860
|
+
|
|
861
|
+
# If the function we're calling into doesn't return, we should discard it
|
|
862
|
+
if self._cfg is not None:
|
|
863
|
+
func = self.kb.functions.function(addr=job.call_target)
|
|
864
|
+
if func is not None and func.returning is False and len(all_successors) == 2:
|
|
865
|
+
del all_successors[-1]
|
|
866
|
+
fakeret_successor = None
|
|
867
|
+
|
|
868
|
+
if self._is_call_jumpkind(jumpkind):
|
|
869
|
+
# Create a new call stack for the successor
|
|
870
|
+
new_call_stack = self._create_callstack(job, successor_addr, jumpkind, fakeret_successor)
|
|
871
|
+
if new_call_stack is None:
|
|
872
|
+
l.debug("Cannot create a new callstack for address %#x", successor_addr)
|
|
873
|
+
job.dbg_exit_status[successor] = ""
|
|
874
|
+
return []
|
|
875
|
+
new_call_stack_suffix = new_call_stack.stack_suffix(self._context_sensitivity_level)
|
|
876
|
+
|
|
877
|
+
new_function_key = FunctionKey.new(successor_addr, new_call_stack_suffix)
|
|
878
|
+
# Save the initial state for the function
|
|
879
|
+
self._save_function_initial_state(new_function_key, successor_addr, successor.copy())
|
|
880
|
+
|
|
881
|
+
# bail out if we hit the interfunction_level cap
|
|
882
|
+
if len(job.call_stack) >= self._interfunction_level:
|
|
883
|
+
l.debug(
|
|
884
|
+
"We are not tracing into a new function %#08x as we hit interfunction_level limit", successor_addr
|
|
885
|
+
)
|
|
886
|
+
|
|
887
|
+
# mark it as skipped
|
|
888
|
+
job.dbg_exit_status[successor] = "Skipped"
|
|
889
|
+
|
|
890
|
+
job.call_skipped = True
|
|
891
|
+
job.call_function_key = new_function_key
|
|
892
|
+
|
|
893
|
+
job.call_task.skipped = True
|
|
894
|
+
|
|
895
|
+
return []
|
|
896
|
+
|
|
897
|
+
elif jumpkind == "Ijk_Ret":
|
|
898
|
+
# Pop the current function out from the call stack
|
|
899
|
+
new_call_stack = self._create_callstack(job, successor_addr, jumpkind, fakeret_successor)
|
|
900
|
+
if new_call_stack is None:
|
|
901
|
+
l.debug("Cannot create a new callstack for address %#x", successor_addr)
|
|
902
|
+
job.dbg_exit_status[successor] = ""
|
|
903
|
+
return []
|
|
904
|
+
new_call_stack_suffix = new_call_stack.stack_suffix(self._context_sensitivity_level)
|
|
905
|
+
|
|
906
|
+
else:
|
|
907
|
+
new_call_stack = job.call_stack
|
|
908
|
+
new_call_stack_suffix = job.call_stack_suffix
|
|
909
|
+
|
|
910
|
+
# Generate the new block ID
|
|
911
|
+
new_block_id = BlockID.new(successor_addr, new_call_stack_suffix, jumpkind)
|
|
912
|
+
|
|
913
|
+
#
|
|
914
|
+
# Generate new VFG jobs
|
|
915
|
+
#
|
|
916
|
+
|
|
917
|
+
if jumpkind == "Ijk_Ret":
|
|
918
|
+
assert not job.is_call_jump
|
|
919
|
+
|
|
920
|
+
# Record this return
|
|
921
|
+
self._return_target_sources[successor_addr].append((*job.call_stack_suffix, addr))
|
|
922
|
+
|
|
923
|
+
# Check if this return is inside our pending returns list
|
|
924
|
+
if new_block_id in self._pending_returns:
|
|
925
|
+
del self._pending_returns[new_block_id]
|
|
926
|
+
|
|
927
|
+
# Check if we have reached a fix-point
|
|
928
|
+
if jumpkind != "Ijk_FakeRet" and new_block_id in self._nodes:
|
|
929
|
+
last_state = self._nodes[new_block_id].state
|
|
930
|
+
|
|
931
|
+
_, _, merged = last_state.merge(successor, plugin_whitelist=self._mergeable_plugins)
|
|
932
|
+
|
|
933
|
+
if merged:
|
|
934
|
+
l.debug("%s didn't reach a fix-point", new_block_id)
|
|
935
|
+
else:
|
|
936
|
+
l.debug("%s reaches a fix-point.", new_block_id)
|
|
937
|
+
job.dbg_exit_status[successor] = "Merged due to reaching a fix-point"
|
|
938
|
+
return []
|
|
939
|
+
|
|
940
|
+
return self._create_new_jobs(job, successor, new_block_id, new_call_stack)
|
|
941
|
+
|
|
942
|
+
def _handle_successor_multitargets(self, job, successor, all_successors):
|
|
943
|
+
"""
|
|
944
|
+
Generate new jobs for all possible successor targets when there are more than one possible concrete value for
|
|
945
|
+
successor.ip
|
|
946
|
+
|
|
947
|
+
:param VFGJob job: The VFGJob instance.
|
|
948
|
+
:param SimState successor: The succeeding state.
|
|
949
|
+
:param list all_successors: All succeeding states from the same VFGJob.
|
|
950
|
+
:return: A list of new succeeding jobs
|
|
951
|
+
:rtype: list
|
|
952
|
+
"""
|
|
953
|
+
|
|
954
|
+
new_jobs = []
|
|
955
|
+
|
|
956
|
+
# Currently we assume a legit jumping target cannot have more than 256 concrete values
|
|
957
|
+
# TODO: make it a setting on VFG
|
|
958
|
+
MAX_NUMBER_OF_CONCRETE_VALUES = 256
|
|
959
|
+
|
|
960
|
+
all_possible_ips = successor.solver.eval_upto(successor.ip, MAX_NUMBER_OF_CONCRETE_VALUES + 1)
|
|
961
|
+
|
|
962
|
+
if len(all_possible_ips) > MAX_NUMBER_OF_CONCRETE_VALUES:
|
|
963
|
+
l.warning(
|
|
964
|
+
"IP can be concretized to more than %d values, which means it might be corrupted.",
|
|
965
|
+
MAX_NUMBER_OF_CONCRETE_VALUES,
|
|
966
|
+
)
|
|
967
|
+
return []
|
|
968
|
+
|
|
969
|
+
# Call this function to generate a successor for each possible IP
|
|
970
|
+
for ip in all_possible_ips:
|
|
971
|
+
concrete_successor = successor.copy()
|
|
972
|
+
concrete_successor.ip = ip
|
|
973
|
+
|
|
974
|
+
concrete_jobs = self._handle_successor(job, concrete_successor, all_successors)
|
|
975
|
+
|
|
976
|
+
if job.is_call_jump: # TODO: take care of syscalls
|
|
977
|
+
for new_job in concrete_jobs:
|
|
978
|
+
# TODO: correctly fill the return address. The return address can be found from the
|
|
979
|
+
# TODO: fakeret successor in the `successors` list
|
|
980
|
+
function_analysis_task = FunctionAnalysis(new_job.addr, None)
|
|
981
|
+
# log the new job
|
|
982
|
+
function_analysis_task.jobs.append(new_job)
|
|
983
|
+
# put it onto the stack
|
|
984
|
+
self._task_stack.append(function_analysis_task)
|
|
985
|
+
# log it in the call_task
|
|
986
|
+
job.call_task.register_function_analysis(function_analysis_task)
|
|
987
|
+
|
|
988
|
+
new_jobs.extend(concrete_jobs)
|
|
989
|
+
|
|
990
|
+
return new_jobs
|
|
991
|
+
|
|
992
|
+
def _post_job_handling(
|
|
993
|
+
self, job: VFGJob, new_jobs: list[VFGJob | Any], successors: list[SimState]
|
|
994
|
+
) -> None: # pylint:disable=unused-argument
|
|
995
|
+
# Debugging output
|
|
996
|
+
if l.level == logging.DEBUG:
|
|
997
|
+
self._post_job_handling_debug(job, successors)
|
|
998
|
+
|
|
999
|
+
# pop all finished tasks from the task stack
|
|
1000
|
+
|
|
1001
|
+
pending_task_func_addrs = {k.func_addr for k in self._pending_returns}
|
|
1002
|
+
while True:
|
|
1003
|
+
task = self._top_task
|
|
1004
|
+
|
|
1005
|
+
if task is None:
|
|
1006
|
+
# the task stack is empty
|
|
1007
|
+
break
|
|
1008
|
+
|
|
1009
|
+
if isinstance(task, CallAnalysis):
|
|
1010
|
+
# the call never returns
|
|
1011
|
+
if task.skipped:
|
|
1012
|
+
l.debug("Calls from %s are skipped.", task)
|
|
1013
|
+
else:
|
|
1014
|
+
l.debug("%s never returns.", task)
|
|
1015
|
+
self._task_stack.pop()
|
|
1016
|
+
|
|
1017
|
+
else:
|
|
1018
|
+
if not task.done or task.function_address in pending_task_func_addrs:
|
|
1019
|
+
break
|
|
1020
|
+
|
|
1021
|
+
l.debug("%s is finished.", task)
|
|
1022
|
+
self._task_stack.pop()
|
|
1023
|
+
|
|
1024
|
+
# the next guy *might be* a call analysis task
|
|
1025
|
+
task = self._top_task
|
|
1026
|
+
if isinstance(task, CallAnalysis) and task.done:
|
|
1027
|
+
# awesome!
|
|
1028
|
+
# pop it from the task stack
|
|
1029
|
+
self._task_stack.pop()
|
|
1030
|
+
|
|
1031
|
+
if task._final_jobs:
|
|
1032
|
+
# merge all jobs, and create a new job
|
|
1033
|
+
new_job = task.merge_jobs()
|
|
1034
|
+
|
|
1035
|
+
# register the job to the top task
|
|
1036
|
+
self._top_task.jobs.append(new_job)
|
|
1037
|
+
|
|
1038
|
+
# insert the job
|
|
1039
|
+
self._insert_job(new_job)
|
|
1040
|
+
|
|
1041
|
+
# if not new_jobs:
|
|
1042
|
+
# # task stack is empty
|
|
1043
|
+
# self.final_states.append(job.state)
|
|
1044
|
+
|
|
1045
|
+
def _intra_analysis(self) -> None:
|
|
1046
|
+
pass
|
|
1047
|
+
|
|
1048
|
+
def _merge_jobs(self, *jobs: VFGJob):
|
|
1049
|
+
l.debug("Merging jobs %s", jobs)
|
|
1050
|
+
|
|
1051
|
+
# there should not be more than two jobs being merged at the same time
|
|
1052
|
+
assert len(jobs) == 2
|
|
1053
|
+
|
|
1054
|
+
addr = jobs[0].addr
|
|
1055
|
+
|
|
1056
|
+
if self.project.is_hooked(addr) and self.project.hooked_by(addr).is_continuation:
|
|
1057
|
+
raise AngrJobMergingFailureNotice
|
|
1058
|
+
|
|
1059
|
+
# update jobs
|
|
1060
|
+
for job in jobs:
|
|
1061
|
+
if job in self._top_function_analysis_task.jobs:
|
|
1062
|
+
self._top_function_analysis_task.jobs.remove(job)
|
|
1063
|
+
|
|
1064
|
+
state_0 = jobs[0].state
|
|
1065
|
+
state_1 = jobs[1].state
|
|
1066
|
+
|
|
1067
|
+
merged_state, _ = self._merge_states(state_0, state_1)
|
|
1068
|
+
|
|
1069
|
+
new_job = VFGJob(
|
|
1070
|
+
jobs[0].addr,
|
|
1071
|
+
merged_state,
|
|
1072
|
+
self._context_sensitivity_level,
|
|
1073
|
+
jumpkind=jobs[0].jumpkind,
|
|
1074
|
+
block_id=jobs[0].block_id,
|
|
1075
|
+
call_stack=jobs[0].call_stack,
|
|
1076
|
+
src_block_id=jobs[0].src_block_id,
|
|
1077
|
+
src_exit_stmt_idx=jobs[0].src_exit_stmt_idx,
|
|
1078
|
+
src_ins_addr=jobs[0].src_ins_addr,
|
|
1079
|
+
)
|
|
1080
|
+
|
|
1081
|
+
self._top_function_analysis_task.jobs.append(new_job)
|
|
1082
|
+
|
|
1083
|
+
return new_job
|
|
1084
|
+
|
|
1085
|
+
def _should_widen_jobs(self, *jobs):
|
|
1086
|
+
"""
|
|
1087
|
+
|
|
1088
|
+
:param iterable jobs:
|
|
1089
|
+
:return: True if should widen, False otherwise
|
|
1090
|
+
:rtype: bool
|
|
1091
|
+
"""
|
|
1092
|
+
|
|
1093
|
+
job_0: VFGJob
|
|
1094
|
+
_: VFGJob
|
|
1095
|
+
job_0, _ = jobs[-2:] # pylint:disable=unbalanced-tuple-unpacking
|
|
1096
|
+
|
|
1097
|
+
addr = job_0.addr
|
|
1098
|
+
|
|
1099
|
+
if addr not in self._widening_points(job_0.func_addr):
|
|
1100
|
+
return False
|
|
1101
|
+
|
|
1102
|
+
tracing_times = self._tracing_times[job_0.block_id]
|
|
1103
|
+
return bool(
|
|
1104
|
+
tracing_times > self._max_iterations_before_widening and tracing_times % self._widening_interval == 0
|
|
1105
|
+
)
|
|
1106
|
+
|
|
1107
|
+
def _widen_jobs(self, *jobs: VFGJob):
|
|
1108
|
+
"""
|
|
1109
|
+
|
|
1110
|
+
:param iterable jobs:
|
|
1111
|
+
:return:
|
|
1112
|
+
"""
|
|
1113
|
+
|
|
1114
|
+
job_0: VFGJob
|
|
1115
|
+
job_1: VFGJob
|
|
1116
|
+
job_0, job_1 = jobs[-2:] # pylint:disable=unbalanced-tuple-unpacking
|
|
1117
|
+
|
|
1118
|
+
assert self._top_function_analysis_task is not None
|
|
1119
|
+
|
|
1120
|
+
# update jobs
|
|
1121
|
+
for job in jobs:
|
|
1122
|
+
if job in self._top_function_analysis_task.jobs:
|
|
1123
|
+
self._top_function_analysis_task.jobs.remove(job)
|
|
1124
|
+
|
|
1125
|
+
l.debug("Widening %s", job_1)
|
|
1126
|
+
|
|
1127
|
+
new_state, _ = self._widen_states(job_0.state, job_1.state)
|
|
1128
|
+
|
|
1129
|
+
new_job = VFGJob(
|
|
1130
|
+
jobs[0].addr,
|
|
1131
|
+
new_state,
|
|
1132
|
+
self._context_sensitivity_level,
|
|
1133
|
+
jumpkind=jobs[0].jumpkind,
|
|
1134
|
+
block_id=jobs[0].block_id,
|
|
1135
|
+
call_stack=jobs[0].call_stack,
|
|
1136
|
+
src_block_id=jobs[0].src_block_id,
|
|
1137
|
+
src_exit_stmt_idx=jobs[0].src_exit_stmt_idx,
|
|
1138
|
+
src_ins_addr=jobs[0].src_ins_addr,
|
|
1139
|
+
)
|
|
1140
|
+
self._top_function_analysis_task.jobs.append(new_job)
|
|
1141
|
+
|
|
1142
|
+
return new_job
|
|
1143
|
+
|
|
1144
|
+
def _job_queue_empty(self) -> None:
|
|
1145
|
+
if self._pending_returns:
|
|
1146
|
+
# We don't have any paths remaining. Let's pop a previously-missing return to
|
|
1147
|
+
# process
|
|
1148
|
+
|
|
1149
|
+
top_task: FunctionAnalysis = self._top_task
|
|
1150
|
+
func_addr = top_task.function_address
|
|
1151
|
+
|
|
1152
|
+
pending_ret_key = self._get_pending_job(func_addr)
|
|
1153
|
+
|
|
1154
|
+
if pending_ret_key is None:
|
|
1155
|
+
# analysis of the current function is somehow terminated
|
|
1156
|
+
# we have to rewind the stack, and try the function that calls the current function
|
|
1157
|
+
l.debug("No pending return for the current function %#x. Unwind the stack.", func_addr)
|
|
1158
|
+
if not self._top_function_analysis_task.done:
|
|
1159
|
+
l.warning(
|
|
1160
|
+
"The top function analysis task is not done yet. This might be a bug. Please report to Fish."
|
|
1161
|
+
)
|
|
1162
|
+
# stack unwinding
|
|
1163
|
+
while True:
|
|
1164
|
+
s = self._task_stack.pop()
|
|
1165
|
+
if isinstance(s, CallAnalysis):
|
|
1166
|
+
break
|
|
1167
|
+
|
|
1168
|
+
return self._job_queue_empty()
|
|
1169
|
+
|
|
1170
|
+
self._trace_pending_job(pending_ret_key)
|
|
1171
|
+
|
|
1172
|
+
l.debug("Tracing a missing return %s", repr(pending_ret_key))
|
|
1173
|
+
return None
|
|
1174
|
+
|
|
1175
|
+
def _post_analysis(self) -> None:
|
|
1176
|
+
pass
|
|
1177
|
+
|
|
1178
|
+
#
|
|
1179
|
+
# State widening, merging, and narrowing
|
|
1180
|
+
#
|
|
1181
|
+
|
|
1182
|
+
def _merge_states(self, *states: SimState):
|
|
1183
|
+
"""
|
|
1184
|
+
Merge two given states, and return a new one.
|
|
1185
|
+
|
|
1186
|
+
:param states: All states to merge.
|
|
1187
|
+
:returns: The merged state, and whether a merging has occurred
|
|
1188
|
+
"""
|
|
1189
|
+
|
|
1190
|
+
# print old_state.dbg_print_stack()
|
|
1191
|
+
# print new_state.dbg_print_stack()
|
|
1192
|
+
|
|
1193
|
+
merged = states[0]
|
|
1194
|
+
merging_occurred = False
|
|
1195
|
+
for state in states[1:]:
|
|
1196
|
+
merged, _, merging_occurred_ = merged.merge(state, plugin_whitelist=self._mergeable_plugins)
|
|
1197
|
+
merging_occurred |= merging_occurred_
|
|
1198
|
+
|
|
1199
|
+
# print "Merged: "
|
|
1200
|
+
# print merged_state.dbg_print_stack()
|
|
1201
|
+
|
|
1202
|
+
return merged, merging_occurred
|
|
1203
|
+
|
|
1204
|
+
@staticmethod
|
|
1205
|
+
def _widen_states(old_state, new_state):
|
|
1206
|
+
"""
|
|
1207
|
+
Perform widen operation on the given states, and return a new one.
|
|
1208
|
+
|
|
1209
|
+
:param old_state:
|
|
1210
|
+
:param new_state:
|
|
1211
|
+
:returns: The widened state, and whether widening has occurred
|
|
1212
|
+
"""
|
|
1213
|
+
|
|
1214
|
+
# print old_state.dbg_print_stack()
|
|
1215
|
+
# print new_state.dbg_print_stack()
|
|
1216
|
+
|
|
1217
|
+
l.debug("Widening state at IP %s", old_state.ip)
|
|
1218
|
+
|
|
1219
|
+
widened_state, widening_occurred = old_state.widen(new_state)
|
|
1220
|
+
|
|
1221
|
+
# print "Widened: "
|
|
1222
|
+
# print widened_state.dbg_print_stack()
|
|
1223
|
+
|
|
1224
|
+
return widened_state, widening_occurred
|
|
1225
|
+
|
|
1226
|
+
@staticmethod
|
|
1227
|
+
def _narrow_states(
|
|
1228
|
+
node, old_state, new_state, previously_widened_state
|
|
1229
|
+
): # pylint:disable=unused-argument,no-self-use
|
|
1230
|
+
"""
|
|
1231
|
+
Try to narrow the state!
|
|
1232
|
+
|
|
1233
|
+
:param old_state:
|
|
1234
|
+
:param new_state:
|
|
1235
|
+
:param previously_widened_state:
|
|
1236
|
+
:returns: The narrowed state, and whether a narrowing has occurred
|
|
1237
|
+
"""
|
|
1238
|
+
|
|
1239
|
+
l.debug("Narrowing state at IP %s", previously_widened_state.ip)
|
|
1240
|
+
|
|
1241
|
+
s = previously_widened_state.copy()
|
|
1242
|
+
|
|
1243
|
+
narrowing_occurred = False
|
|
1244
|
+
|
|
1245
|
+
# TODO: Finish the narrowing logic
|
|
1246
|
+
|
|
1247
|
+
return s, narrowing_occurred
|
|
1248
|
+
|
|
1249
|
+
#
|
|
1250
|
+
# Helper methods
|
|
1251
|
+
#
|
|
1252
|
+
|
|
1253
|
+
def _prepare_initial_state(self, function_start: int, state: SimState | None) -> SimState:
|
|
1254
|
+
"""
|
|
1255
|
+
Get the state to start the analysis for function.
|
|
1256
|
+
|
|
1257
|
+
:param int function_start: Address of the function
|
|
1258
|
+
:param SimState state: The program state to base on.
|
|
1259
|
+
"""
|
|
1260
|
+
|
|
1261
|
+
if state is None:
|
|
1262
|
+
state = self.project.factory.blank_state(mode="static", remove_options=self._state_options_to_remove)
|
|
1263
|
+
|
|
1264
|
+
assert state is not None
|
|
1265
|
+
# make room for arguments passed to the function
|
|
1266
|
+
sp = state.regs.sp
|
|
1267
|
+
sp_val = state.solver.eval_one(sp)
|
|
1268
|
+
state.memory.set_stack_address_mapping(sp_val, state.memory.stack_id(function_start) + "_pre", 0)
|
|
1269
|
+
state.registers.store("sp", sp - 0x100)
|
|
1270
|
+
|
|
1271
|
+
# Set the stack address mapping for the initial stack
|
|
1272
|
+
state.memory.set_stack_size(state.arch.stack_size)
|
|
1273
|
+
initial_sp = state.solver.eval(
|
|
1274
|
+
state.regs.sp
|
|
1275
|
+
) # FIXME: This is bad, as it may lose tracking of multiple sp values
|
|
1276
|
+
initial_sp -= state.arch.bytes
|
|
1277
|
+
state.memory.set_stack_address_mapping(initial_sp, state.memory.stack_id(function_start), function_start)
|
|
1278
|
+
|
|
1279
|
+
return state
|
|
1280
|
+
|
|
1281
|
+
def _set_return_address(self, state: SimState, ret_addr: int) -> None:
|
|
1282
|
+
"""
|
|
1283
|
+
Set the return address of the current state to a specific address. We assume we are at the beginning of a
|
|
1284
|
+
function, or in other words, we are about to execute the very first instruction of the function.
|
|
1285
|
+
|
|
1286
|
+
:param SimState state: The program state
|
|
1287
|
+
:param int ret_addr: The return address
|
|
1288
|
+
:return: None
|
|
1289
|
+
"""
|
|
1290
|
+
|
|
1291
|
+
# TODO: the following code is totally untested other than X86 and AMD64. Don't freak out if you find bugs :)
|
|
1292
|
+
# TODO: Test it
|
|
1293
|
+
|
|
1294
|
+
ret_bvv = claripy.BVV(ret_addr, self.project.arch.bits)
|
|
1295
|
+
|
|
1296
|
+
if self.project.arch.name in ("X86", "AMD64"):
|
|
1297
|
+
state.stack_push(ret_bvv)
|
|
1298
|
+
elif is_arm_arch(self.project.arch):
|
|
1299
|
+
state.regs.lr = ret_bvv
|
|
1300
|
+
elif self.project.arch.name in ("MIPS32", "MIPS64"):
|
|
1301
|
+
state.regs.ra = ret_bvv
|
|
1302
|
+
elif self.project.arch.name in ("PPC32", "PPC64"):
|
|
1303
|
+
state.regs.lr = ret_bvv
|
|
1304
|
+
else:
|
|
1305
|
+
l.warning(
|
|
1306
|
+
"Return address cannot be set for architecture %s. Please add corresponding logic to "
|
|
1307
|
+
"VFG._set_return_address().",
|
|
1308
|
+
self.project.arch.name,
|
|
1309
|
+
)
|
|
1310
|
+
|
|
1311
|
+
def _create_graph(self, return_target_sources=None):
|
|
1312
|
+
"""
|
|
1313
|
+
Create a DiGraph out of the existing edge map.
|
|
1314
|
+
:param return_target_sources: Used for making up those missing returns
|
|
1315
|
+
:returns: A networkx.DiGraph() object
|
|
1316
|
+
"""
|
|
1317
|
+
if return_target_sources is None:
|
|
1318
|
+
# We set it to a defaultdict in order to be consistent with the
|
|
1319
|
+
# actual parameter.
|
|
1320
|
+
return_target_sources = defaultdict(list)
|
|
1321
|
+
|
|
1322
|
+
cfg = networkx.DiGraph()
|
|
1323
|
+
# The corner case: add a node to the graph if there is only one block
|
|
1324
|
+
if len(self._nodes) == 1:
|
|
1325
|
+
cfg.add_node(self._nodes[next(iter(self._nodes.keys()))])
|
|
1326
|
+
|
|
1327
|
+
# Adding edges
|
|
1328
|
+
for tpl, targets in self._exit_targets.items():
|
|
1329
|
+
basic_block = self._nodes[tpl] # Cannot fail :)
|
|
1330
|
+
for ex, jumpkind in targets:
|
|
1331
|
+
if ex in self._nodes:
|
|
1332
|
+
target_bbl = self._nodes[ex]
|
|
1333
|
+
cfg.add_edge(basic_block, target_bbl, jumpkind=jumpkind)
|
|
1334
|
+
|
|
1335
|
+
# Add edges for possibly missing returns
|
|
1336
|
+
if basic_block.addr in return_target_sources:
|
|
1337
|
+
for src_irsb_key in return_target_sources[basic_block.addr]:
|
|
1338
|
+
cfg.add_edge(self._nodes[src_irsb_key], basic_block, jumpkind="Ijk_Ret")
|
|
1339
|
+
else:
|
|
1340
|
+
# Debugging output
|
|
1341
|
+
def addr_formalize(addr):
|
|
1342
|
+
if addr is None:
|
|
1343
|
+
return "None"
|
|
1344
|
+
return f"{addr:#08x}"
|
|
1345
|
+
|
|
1346
|
+
s = "(["
|
|
1347
|
+
for addr in ex[:-1]:
|
|
1348
|
+
s += addr_formalize(addr) + ", "
|
|
1349
|
+
s += f"] {addr_formalize(ex[-1])})"
|
|
1350
|
+
l.warning("Key %s does not exist.", s)
|
|
1351
|
+
|
|
1352
|
+
return cfg
|
|
1353
|
+
|
|
1354
|
+
#
|
|
1355
|
+
# DiGraph manipulation
|
|
1356
|
+
#
|
|
1357
|
+
|
|
1358
|
+
def _graph_get_node(self, block_id: BlockID, terminator_for_nonexistent_node: bool = False) -> VFGNode:
|
|
1359
|
+
"""
|
|
1360
|
+
Get an existing VFGNode instance from the graph.
|
|
1361
|
+
|
|
1362
|
+
:param BlockID block_id: The block ID for the node to get.
|
|
1363
|
+
:param bool terminator_for_nonexistent_node: True if a Terminator (which is a SimProcedure stub) should be
|
|
1364
|
+
created when there is no existing node available for the given
|
|
1365
|
+
block ID.
|
|
1366
|
+
:return: A node in the graph, or None.
|
|
1367
|
+
:rtype: VFGNode
|
|
1368
|
+
"""
|
|
1369
|
+
|
|
1370
|
+
if block_id not in self._nodes:
|
|
1371
|
+
l.error("Trying to look up a node that we don't have yet. Is this okay????")
|
|
1372
|
+
if not terminator_for_nonexistent_node:
|
|
1373
|
+
return None
|
|
1374
|
+
# Generate a PathTerminator node
|
|
1375
|
+
addr = block_id.addr
|
|
1376
|
+
func_addr = block_id.func_addr
|
|
1377
|
+
if func_addr is None:
|
|
1378
|
+
# We'll have to use the current block address instead
|
|
1379
|
+
# TODO: Is it really OK?
|
|
1380
|
+
func_addr = addr
|
|
1381
|
+
|
|
1382
|
+
input_state = self.project.factory.entry_state()
|
|
1383
|
+
input_state.ip = addr
|
|
1384
|
+
pt = VFGNode(addr, block_id, input_state)
|
|
1385
|
+
self._nodes[block_id] = pt
|
|
1386
|
+
|
|
1387
|
+
if isinstance(self.project.arch, archinfo.ArchARM) and addr % 2 == 1:
|
|
1388
|
+
self._thumb_addrs.add(addr)
|
|
1389
|
+
self._thumb_addrs.add(addr - 1)
|
|
1390
|
+
|
|
1391
|
+
l.debug("Block ID %s does not exist. Create a PathTerminator instead.", repr(block_id))
|
|
1392
|
+
|
|
1393
|
+
return self._nodes[block_id]
|
|
1394
|
+
|
|
1395
|
+
def _graph_add_edge(self, src_block_id: BlockID | None, dst_block_id: BlockID, **kwargs) -> None:
|
|
1396
|
+
"""
|
|
1397
|
+
Add an edge onto the graph.
|
|
1398
|
+
|
|
1399
|
+
:param BlockID src_block_id: The block ID for source node.
|
|
1400
|
+
:param BlockID dst_block_id: The block Id for destination node.
|
|
1401
|
+
:param str jumpkind: The jumpkind of the edge.
|
|
1402
|
+
:param exit_stmt_idx: ID of the statement in the source IRSB where this edge is created from. 'default'
|
|
1403
|
+
refers to the default exit.
|
|
1404
|
+
:return: None
|
|
1405
|
+
"""
|
|
1406
|
+
|
|
1407
|
+
dst_node = self._graph_get_node(dst_block_id, terminator_for_nonexistent_node=True)
|
|
1408
|
+
|
|
1409
|
+
if src_block_id is None:
|
|
1410
|
+
self.graph.add_node(dst_node)
|
|
1411
|
+
|
|
1412
|
+
else:
|
|
1413
|
+
src_node = self._graph_get_node(src_block_id, terminator_for_nonexistent_node=True)
|
|
1414
|
+
self.graph.add_edge(src_node, dst_node, **kwargs)
|
|
1415
|
+
|
|
1416
|
+
#
|
|
1417
|
+
# Other methods
|
|
1418
|
+
#
|
|
1419
|
+
|
|
1420
|
+
def _get_simsuccessors(self, state: SimState, addr: int) -> tuple[SimSuccessors, bool, bool]:
|
|
1421
|
+
error_occurred = False
|
|
1422
|
+
restart_analysis = False
|
|
1423
|
+
|
|
1424
|
+
jumpkind = "Ijk_Boring"
|
|
1425
|
+
if state.history.jumpkind:
|
|
1426
|
+
jumpkind = state.history.jumpkind
|
|
1427
|
+
|
|
1428
|
+
try:
|
|
1429
|
+
node = self._cfg.model.get_any_node(addr)
|
|
1430
|
+
num_inst = None if node is None else len(node.instruction_addrs)
|
|
1431
|
+
sim_successors = self.project.factory.successors(state, jumpkind=jumpkind, num_inst=num_inst)
|
|
1432
|
+
except SimIRSBError as ex:
|
|
1433
|
+
# It's a tragedy that we came across some instructions that VEX
|
|
1434
|
+
# does not support. I'll create a terminating stub there
|
|
1435
|
+
l.error("SimIRSBError occurred(%s). Creating a PathTerminator.", ex)
|
|
1436
|
+
error_occurred = True
|
|
1437
|
+
inst = SIM_PROCEDURES["stubs"]["PathTerminator"](state)
|
|
1438
|
+
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
1439
|
+
except claripy.ClaripyError:
|
|
1440
|
+
l.error("ClaripyError: ", exc_info=True)
|
|
1441
|
+
error_occurred = True
|
|
1442
|
+
# Generate a PathTerminator to terminate the current path
|
|
1443
|
+
inst = SIM_PROCEDURES["stubs"]["PathTerminator"](state)
|
|
1444
|
+
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
1445
|
+
except SimError:
|
|
1446
|
+
l.error("SimError: ", exc_info=True)
|
|
1447
|
+
|
|
1448
|
+
error_occurred = True
|
|
1449
|
+
# Generate a PathTerminator to terminate the current path
|
|
1450
|
+
inst = SIM_PROCEDURES["stubs"]["PathTerminator"](state)
|
|
1451
|
+
sim_successors = ProcedureEngine().process(state, procedure=inst)
|
|
1452
|
+
except AngrError as ex:
|
|
1453
|
+
# segment = self.project.loader.main_object.in_which_segment(addr)
|
|
1454
|
+
l.error("AngrError %s when generating SimSuccessors at %#x", ex, addr, exc_info=True)
|
|
1455
|
+
# We might be on a wrong branch, and is likely to encounter the
|
|
1456
|
+
# "No bytes in memory xxx" exception
|
|
1457
|
+
# Just ignore it
|
|
1458
|
+
error_occurred = True
|
|
1459
|
+
sim_successors = None
|
|
1460
|
+
|
|
1461
|
+
return sim_successors, error_occurred, restart_analysis
|
|
1462
|
+
|
|
1463
|
+
def _create_new_jobs(
|
|
1464
|
+
self, job: VFGJob, successor: SimState, new_block_id: BlockID, new_call_stack: CallStack
|
|
1465
|
+
) -> list[VFGJob | Any]:
|
|
1466
|
+
"""
|
|
1467
|
+
Create a list of new VFG jobs for the successor state.
|
|
1468
|
+
|
|
1469
|
+
:param VFGJob job: The VFGJob instance.
|
|
1470
|
+
:param SimState successor: The succeeding state.
|
|
1471
|
+
:param BlockID new_block_id: Block ID for the new VFGJob
|
|
1472
|
+
:param new_call_stack: The new callstack.
|
|
1473
|
+
:return: A list of newly created VFG jobs.
|
|
1474
|
+
:rtype: list
|
|
1475
|
+
"""
|
|
1476
|
+
|
|
1477
|
+
# TODO: basic block stack is probably useless
|
|
1478
|
+
|
|
1479
|
+
jumpkind = successor.history.jumpkind
|
|
1480
|
+
stmt_idx = successor.scratch.stmt_idx
|
|
1481
|
+
ins_addr = successor.scratch.ins_addr
|
|
1482
|
+
# Make a copy of the state in case we use it later
|
|
1483
|
+
successor_state = successor.copy()
|
|
1484
|
+
successor_addr = successor_state.solver.eval(successor_state.ip)
|
|
1485
|
+
|
|
1486
|
+
new_jobs = []
|
|
1487
|
+
|
|
1488
|
+
if jumpkind == "Ijk_FakeRet":
|
|
1489
|
+
assert job.is_call_jump
|
|
1490
|
+
|
|
1491
|
+
# This is the default "fake" return successor generated at each call, if and only if the target function
|
|
1492
|
+
# returns.
|
|
1493
|
+
|
|
1494
|
+
# if the call is skipped (for whatever reason, like we reached the interfunction tracing limit), we use
|
|
1495
|
+
# this FakeRet successor as the final state of the function. Otherwise we save the FakeRet state in case the
|
|
1496
|
+
# callee does not return normally, but don't process them right away.
|
|
1497
|
+
|
|
1498
|
+
# Clear the useless values (like return addresses, parameters) on stack if needed
|
|
1499
|
+
if self._cfg is not None:
|
|
1500
|
+
current_function = self.kb.functions.function(job.call_target)
|
|
1501
|
+
sp_difference = current_function.sp_delta if current_function is not None else 0
|
|
1502
|
+
arch = successor_state.arch
|
|
1503
|
+
reg_sp_offset = arch.sp_offset
|
|
1504
|
+
reg_sp_expr = (
|
|
1505
|
+
successor_state.registers.load(reg_sp_offset, size=arch.bytes, endness=arch.register_endness)
|
|
1506
|
+
+ sp_difference
|
|
1507
|
+
) # type: ignore
|
|
1508
|
+
successor_state.registers.store(arch.sp_offset, reg_sp_expr)
|
|
1509
|
+
|
|
1510
|
+
# Clear the return value with a TOP
|
|
1511
|
+
top_si = claripy.BVS("unnamed", arch.bits)
|
|
1512
|
+
successor_state.registers.store(arch.ret_offset, top_si)
|
|
1513
|
+
|
|
1514
|
+
if job.call_skipped:
|
|
1515
|
+
# TODO: Make sure the return values make sense
|
|
1516
|
+
# if self.project.arch.name == "X86":
|
|
1517
|
+
# successor_state.regs.eax = claripy.BVS(
|
|
1518
|
+
# "ret_val", 32, min=0, max=0xFFFFFFFF, stride=1
|
|
1519
|
+
# )
|
|
1520
|
+
|
|
1521
|
+
new_job = VFGJob(
|
|
1522
|
+
successor_addr,
|
|
1523
|
+
successor_state,
|
|
1524
|
+
self._context_sensitivity_level,
|
|
1525
|
+
block_id=new_block_id,
|
|
1526
|
+
jumpkind="Ijk_Ret",
|
|
1527
|
+
call_stack=new_call_stack,
|
|
1528
|
+
src_block_id=job.block_id,
|
|
1529
|
+
src_exit_stmt_idx=stmt_idx,
|
|
1530
|
+
src_ins_addr=ins_addr,
|
|
1531
|
+
)
|
|
1532
|
+
|
|
1533
|
+
new_jobs.append(new_job)
|
|
1534
|
+
assert isinstance(self._task_stack[-2], FunctionAnalysis)
|
|
1535
|
+
self._task_stack[-2].jobs.append(new_job)
|
|
1536
|
+
job.dbg_exit_status[successor] = "Pending"
|
|
1537
|
+
|
|
1538
|
+
else:
|
|
1539
|
+
self._pending_returns[new_block_id] = PendingJob(
|
|
1540
|
+
new_block_id, successor_state, new_call_stack, job.block_id, stmt_idx, ins_addr
|
|
1541
|
+
) # type: ignore
|
|
1542
|
+
job.dbg_exit_status[successor] = "Pending"
|
|
1543
|
+
|
|
1544
|
+
else:
|
|
1545
|
+
if sim_options.ABSTRACT_MEMORY in successor.options and self._is_call_jumpkind(successor.history.jumpkind):
|
|
1546
|
+
# If this is a call, we create a new stack address mapping
|
|
1547
|
+
reg_sp_si = self._create_stack_region(successor_state, successor_addr)
|
|
1548
|
+
|
|
1549
|
+
# Save the new sp register
|
|
1550
|
+
new_reg_sp_expr = reg_sp_si.annotate(claripy.annotation.RegionAnnotation("global", 0))
|
|
1551
|
+
successor_state.regs.sp = new_reg_sp_expr
|
|
1552
|
+
|
|
1553
|
+
new_job = VFGJob(
|
|
1554
|
+
successor_addr,
|
|
1555
|
+
successor_state,
|
|
1556
|
+
self._context_sensitivity_level,
|
|
1557
|
+
block_id=new_block_id,
|
|
1558
|
+
jumpkind=successor_state.history.jumpkind,
|
|
1559
|
+
call_stack=new_call_stack,
|
|
1560
|
+
src_block_id=job.block_id,
|
|
1561
|
+
src_exit_stmt_idx=stmt_idx,
|
|
1562
|
+
src_ins_addr=ins_addr,
|
|
1563
|
+
)
|
|
1564
|
+
|
|
1565
|
+
if successor.history.jumpkind == "Ijk_Ret":
|
|
1566
|
+
# it's returning to the return site
|
|
1567
|
+
|
|
1568
|
+
# save the state as a final state of the function that we are returning from
|
|
1569
|
+
if self._record_function_final_states:
|
|
1570
|
+
# key of the function that we are returning from
|
|
1571
|
+
source_function_key = FunctionKey.new(job.func_addr, job.call_stack_suffix)
|
|
1572
|
+
self._save_function_final_state(source_function_key, job.func_addr, successor_state)
|
|
1573
|
+
|
|
1574
|
+
# TODO: add an assertion that requires the returning target being the same as the return address we
|
|
1575
|
+
# TODO: stored before
|
|
1576
|
+
|
|
1577
|
+
current_task = self._top_task
|
|
1578
|
+
if current_task.call_analysis is not None:
|
|
1579
|
+
current_task.call_analysis.add_final_job(new_job)
|
|
1580
|
+
|
|
1581
|
+
job.dbg_exit_status[successor] = "Appended to the call analysis task"
|
|
1582
|
+
else:
|
|
1583
|
+
job.dbg_exit_status[successor] = "Discarded (no call analysis task)"
|
|
1584
|
+
|
|
1585
|
+
else:
|
|
1586
|
+
if self._is_call_jumpkind(successor.history.jumpkind):
|
|
1587
|
+
# create a function analysis task
|
|
1588
|
+
# TODO: the return address
|
|
1589
|
+
task = FunctionAnalysis(new_job.addr, None)
|
|
1590
|
+
self._task_stack.append(task)
|
|
1591
|
+
# link it to the call analysis
|
|
1592
|
+
job.call_task.register_function_analysis(task)
|
|
1593
|
+
|
|
1594
|
+
else:
|
|
1595
|
+
task = self._top_task
|
|
1596
|
+
|
|
1597
|
+
# register the job to the function task
|
|
1598
|
+
task.jobs.append(new_job)
|
|
1599
|
+
# insert the new job into the new job array
|
|
1600
|
+
new_jobs.append(new_job)
|
|
1601
|
+
|
|
1602
|
+
job.dbg_exit_status[successor] = "Appended"
|
|
1603
|
+
|
|
1604
|
+
if not job.is_call_jump or jumpkind != "Ijk_FakeRet":
|
|
1605
|
+
new_target = (new_block_id, jumpkind)
|
|
1606
|
+
else:
|
|
1607
|
+
new_target = (new_block_id, "Ijk_FakeRet") # This is the fake return!
|
|
1608
|
+
self._exit_targets[(*job.call_stack_suffix, job.addr)].append(new_target)
|
|
1609
|
+
|
|
1610
|
+
return new_jobs
|
|
1611
|
+
|
|
1612
|
+
def _remove_pending_return(self, job, pending_returns):
|
|
1613
|
+
"""
|
|
1614
|
+
Remove all pending returns that are related to the current job.
|
|
1615
|
+
"""
|
|
1616
|
+
|
|
1617
|
+
# Build the tuples that we want to remove from the dict fake_func_retn_exits
|
|
1618
|
+
tpls_to_remove = []
|
|
1619
|
+
call_stack_copy = job.call_stack_copy()
|
|
1620
|
+
while call_stack_copy.current_return_target is not None:
|
|
1621
|
+
ret_target = call_stack_copy.current_return_target
|
|
1622
|
+
# Remove the current call stack frame
|
|
1623
|
+
call_stack_copy = call_stack_copy.ret(ret_target)
|
|
1624
|
+
call_stack_suffix = call_stack_copy.stack_suffix(self._context_sensitivity_level)
|
|
1625
|
+
tpl = (*call_stack_suffix, ret_target)
|
|
1626
|
+
tpls_to_remove.append(tpl)
|
|
1627
|
+
|
|
1628
|
+
# Remove those tuples from the dict
|
|
1629
|
+
for tpl in tpls_to_remove:
|
|
1630
|
+
if tpl in pending_returns:
|
|
1631
|
+
del pending_returns[tpl]
|
|
1632
|
+
l.debug(
|
|
1633
|
+
"Removed (%s) from FakeExits dict.", ",".join([hex(i) if i is not None else "None" for i in tpl])
|
|
1634
|
+
)
|
|
1635
|
+
|
|
1636
|
+
def _post_job_handling_debug(self, job: VFGJob, successors):
|
|
1637
|
+
"""
|
|
1638
|
+
Print out debugging information after handling a VFGJob and generating the succeeding jobs.
|
|
1639
|
+
|
|
1640
|
+
:param VFGJob job: The VFGJob instance.
|
|
1641
|
+
:param list successors: A list of succeeding states.
|
|
1642
|
+
:return: None
|
|
1643
|
+
"""
|
|
1644
|
+
|
|
1645
|
+
func = self.project.loader.find_symbol(job.addr)
|
|
1646
|
+
function_name = func.name if func is not None else None
|
|
1647
|
+
module_name = self.project.loader.find_object_containing(job.addr).provides
|
|
1648
|
+
|
|
1649
|
+
l.debug(
|
|
1650
|
+
"VFGJob @ %#08x with callstack [ %s ]",
|
|
1651
|
+
job.addr,
|
|
1652
|
+
job.callstack_repr(self.kb),
|
|
1653
|
+
)
|
|
1654
|
+
l.debug("(Function %s of %s)", function_name, module_name)
|
|
1655
|
+
l.debug("- is call jump: %s", job.is_call_jump)
|
|
1656
|
+
for suc in successors:
|
|
1657
|
+
if suc not in job.dbg_exit_status:
|
|
1658
|
+
l.warning("- %s is not found. FIND OUT WHY.", suc)
|
|
1659
|
+
continue
|
|
1660
|
+
|
|
1661
|
+
try:
|
|
1662
|
+
l.debug(
|
|
1663
|
+
"- successor: %#08x of %s [%s]",
|
|
1664
|
+
suc.solver.eval_one(suc.ip),
|
|
1665
|
+
suc.history.jumpkind,
|
|
1666
|
+
job.dbg_exit_status[suc],
|
|
1667
|
+
)
|
|
1668
|
+
except SimValueError:
|
|
1669
|
+
l.debug("- target cannot be concretized. %s [%s]", job.dbg_exit_status[suc], suc.history.jumpkind)
|
|
1670
|
+
l.debug("Remaining/pending jobs: %d/%d", len(self._job_info_queue), len(self._pending_returns))
|
|
1671
|
+
l.debug("Remaining jobs: %s", [f"{ent.job} {id(ent.job)}" for ent in self._job_info_queue])
|
|
1672
|
+
l.debug("Task stack: %s", self._task_stack)
|
|
1673
|
+
|
|
1674
|
+
@staticmethod
|
|
1675
|
+
def _is_call_jumpkind(jumpkind: str) -> bool:
|
|
1676
|
+
return bool(jumpkind == "Ijk_Call" or jumpkind.startswith("Ijk_Sys_"))
|
|
1677
|
+
|
|
1678
|
+
@staticmethod
|
|
1679
|
+
def _is_return_jumpkind(jumpkind):
|
|
1680
|
+
return jumpkind in ("Ijk_Ret", "Ijk_FakeRet")
|
|
1681
|
+
|
|
1682
|
+
@staticmethod
|
|
1683
|
+
def _create_stack_region(successor_state: SimState, successor_ip: int) -> claripy.ast.BV:
|
|
1684
|
+
arch = successor_state.arch
|
|
1685
|
+
reg_sp_offset = arch.sp_offset
|
|
1686
|
+
reg_sp_expr = successor_state.registers.load(reg_sp_offset, size=arch.bytes, endness=arch.register_endness)
|
|
1687
|
+
|
|
1688
|
+
reg_sp_val = successor_state.solver.min(reg_sp_expr)
|
|
1689
|
+
reg_sp_si = claripy.BVV(reg_sp_val, successor_state.arch.bits)
|
|
1690
|
+
|
|
1691
|
+
reg_sp_val = reg_sp_val - arch.bytes # TODO: Is it OK?
|
|
1692
|
+
new_stack_region_id = successor_state.memory.stack_id(successor_ip)
|
|
1693
|
+
successor_state.memory.set_stack_address_mapping(reg_sp_val, new_stack_region_id, successor_ip)
|
|
1694
|
+
|
|
1695
|
+
return reg_sp_si
|
|
1696
|
+
|
|
1697
|
+
def _create_callstack(
|
|
1698
|
+
self, job: VFGJob, successor_ip: int, jumpkind: str, fakeret_successor: SimState | None
|
|
1699
|
+
) -> CallStack:
|
|
1700
|
+
addr = job.addr
|
|
1701
|
+
|
|
1702
|
+
if self._is_call_jumpkind(jumpkind):
|
|
1703
|
+
new_call_stack = job.call_stack_copy()
|
|
1704
|
+
# Notice that in ARM, there are some freaking instructions
|
|
1705
|
+
# like
|
|
1706
|
+
# BLEQ <address>
|
|
1707
|
+
# It should give us three exits: Ijk_Call, Ijk_Boring, and
|
|
1708
|
+
# Ijk_Ret. The last exit is simulated.
|
|
1709
|
+
# Notice: We assume the last exit is the simulated one
|
|
1710
|
+
if fakeret_successor is None:
|
|
1711
|
+
retn_target_addr = None
|
|
1712
|
+
else:
|
|
1713
|
+
retn_target_addr = fakeret_successor.solver.eval_one(fakeret_successor.ip)
|
|
1714
|
+
|
|
1715
|
+
# Create call stack
|
|
1716
|
+
new_call_stack = new_call_stack.call(addr, successor_ip, retn_target=retn_target_addr)
|
|
1717
|
+
|
|
1718
|
+
elif jumpkind == "Ijk_Ret":
|
|
1719
|
+
new_call_stack = job.call_stack_copy()
|
|
1720
|
+
new_call_stack = new_call_stack.ret(successor_ip)
|
|
1721
|
+
|
|
1722
|
+
else:
|
|
1723
|
+
# Normal control flow transition
|
|
1724
|
+
new_call_stack = job.call_stack
|
|
1725
|
+
|
|
1726
|
+
return new_call_stack
|
|
1727
|
+
|
|
1728
|
+
def _save_function_initial_state(self, function_key: FunctionKey, function_address: int, state: SimState) -> None:
|
|
1729
|
+
"""
|
|
1730
|
+
Save the initial state of a function, and merge it with existing ones if there are any.
|
|
1731
|
+
|
|
1732
|
+
:param FunctionKey function_key: The key to this function.
|
|
1733
|
+
:param int function_address: Address of the function.
|
|
1734
|
+
:param SimState state: Initial state of the function.
|
|
1735
|
+
:return: None
|
|
1736
|
+
"""
|
|
1737
|
+
|
|
1738
|
+
l.debug("Saving the initial state for function %#08x with function key %s", function_address, function_key)
|
|
1739
|
+
if function_key in self._function_initial_states[function_address]:
|
|
1740
|
+
existing_state = self._function_initial_states[function_address][function_key]
|
|
1741
|
+
merged_state, _, _ = existing_state.merge(state)
|
|
1742
|
+
self._function_initial_states[function_address][function_key] = merged_state
|
|
1743
|
+
|
|
1744
|
+
else:
|
|
1745
|
+
self._function_initial_states[function_address][function_key] = state
|
|
1746
|
+
|
|
1747
|
+
def _save_function_final_state(self, function_key, function_address, state):
|
|
1748
|
+
"""
|
|
1749
|
+
Save the final state of a function, and merge it with existing ones if there are any.
|
|
1750
|
+
|
|
1751
|
+
:param FunctionKey function_key: The key to this function.
|
|
1752
|
+
:param int function_address: Address of the function.
|
|
1753
|
+
:param SimState state: Initial state of the function.
|
|
1754
|
+
:return: None
|
|
1755
|
+
"""
|
|
1756
|
+
|
|
1757
|
+
l.debug("Saving the final state for function %#08x with function key %s", function_address, function_key)
|
|
1758
|
+
|
|
1759
|
+
if function_key in self._function_final_states[function_address]:
|
|
1760
|
+
existing_state = self._function_final_states[function_address][function_key]
|
|
1761
|
+
merged_state = existing_state.merge(state, plugin_whitelist=self._mergeable_plugins)[0]
|
|
1762
|
+
self._function_final_states[function_address][function_key] = merged_state
|
|
1763
|
+
|
|
1764
|
+
else:
|
|
1765
|
+
self._function_final_states[function_address][function_key] = state
|
|
1766
|
+
|
|
1767
|
+
def _trace_pending_job(self, job_key):
|
|
1768
|
+
pending_job: PendingJob = self._pending_returns.pop(job_key)
|
|
1769
|
+
addr = job_key.addr
|
|
1770
|
+
|
|
1771
|
+
# Unlike CFG, we will still trace those blocks that have been traced before. In other words, we don't
|
|
1772
|
+
# remove fake returns even if they have been traced - otherwise we cannot come to a fix-point.
|
|
1773
|
+
|
|
1774
|
+
block_id = BlockID.new(addr, pending_job.call_stack.stack_suffix(self._context_sensitivity_level), "Ijk_Ret")
|
|
1775
|
+
job = VFGJob(
|
|
1776
|
+
addr,
|
|
1777
|
+
pending_job.state,
|
|
1778
|
+
self._context_sensitivity_level,
|
|
1779
|
+
block_id=block_id,
|
|
1780
|
+
jumpkind=pending_job.state.history.jumpkind,
|
|
1781
|
+
call_stack=pending_job.call_stack,
|
|
1782
|
+
src_block_id=pending_job.src_block_id,
|
|
1783
|
+
src_exit_stmt_idx=pending_job.src_stmt_idx,
|
|
1784
|
+
src_ins_addr=pending_job.src_ins_addr,
|
|
1785
|
+
)
|
|
1786
|
+
self._insert_job(job)
|
|
1787
|
+
self._top_task.jobs.append(job)
|
|
1788
|
+
|
|
1789
|
+
def _get_pending_job(self, func_addr):
|
|
1790
|
+
pending_ret_key = None
|
|
1791
|
+
k: BlockID
|
|
1792
|
+
for k in self._pending_returns:
|
|
1793
|
+
if k.func_addr == func_addr:
|
|
1794
|
+
pending_ret_key = k
|
|
1795
|
+
break
|
|
1796
|
+
|
|
1797
|
+
return pending_ret_key
|
|
1798
|
+
|
|
1799
|
+
def _get_block_addr(self, b): # pylint:disable=R0201
|
|
1800
|
+
if isinstance(b, SimSuccessors):
|
|
1801
|
+
return b.addr
|
|
1802
|
+
raise TypeError(f"Unsupported block type {type(b)}")
|
|
1803
|
+
|
|
1804
|
+
def _get_nx_paths(self, begin, end):
|
|
1805
|
+
"""
|
|
1806
|
+
Get the possible (networkx) simple paths between two nodes or addresses
|
|
1807
|
+
corresponding to nodes.
|
|
1808
|
+
Input: addresses or node instances
|
|
1809
|
+
Return: a list of lists of nodes representing paths.
|
|
1810
|
+
"""
|
|
1811
|
+
if type(begin) is int and type(end) is int: # pylint:disable=unidiomatic-typecheck
|
|
1812
|
+
n_begin = self.get_any_node(begin)
|
|
1813
|
+
n_end = self.get_any_node(end)
|
|
1814
|
+
|
|
1815
|
+
elif isinstance(begin, VFGNode) and isinstance(end, VFGNode): # pylint:disable=unidiomatic-typecheck
|
|
1816
|
+
n_begin = begin
|
|
1817
|
+
n_end = end
|
|
1818
|
+
else:
|
|
1819
|
+
raise AngrVFGError("from and to should be of the same type")
|
|
1820
|
+
|
|
1821
|
+
return networkx.all_simple_paths(self.graph, n_begin, n_end) # type: ignore
|
|
1822
|
+
|
|
1823
|
+
def _merge_points(self, function_address):
|
|
1824
|
+
"""
|
|
1825
|
+
Return the ordered merge points for a specific function.
|
|
1826
|
+
|
|
1827
|
+
:param int function_address: Address of the querying function.
|
|
1828
|
+
:return: A list of sorted merge points (addresses).
|
|
1829
|
+
:rtype: list
|
|
1830
|
+
"""
|
|
1831
|
+
|
|
1832
|
+
# we are entering a new function. now it's time to figure out how to optimally traverse the control flow
|
|
1833
|
+
# graph by generating the sorted merge points
|
|
1834
|
+
try:
|
|
1835
|
+
new_function = self.kb.functions[function_address]
|
|
1836
|
+
except KeyError:
|
|
1837
|
+
# the function does not exist
|
|
1838
|
+
return []
|
|
1839
|
+
|
|
1840
|
+
if function_address not in self._function_merge_points:
|
|
1841
|
+
ordered_merge_points = GraphUtils.find_merge_points(
|
|
1842
|
+
function_address, new_function.endpoints, new_function.graph
|
|
1843
|
+
)
|
|
1844
|
+
self._function_merge_points[function_address] = ordered_merge_points
|
|
1845
|
+
|
|
1846
|
+
return self._function_merge_points[function_address]
|
|
1847
|
+
|
|
1848
|
+
def _widening_points(self, function_address):
|
|
1849
|
+
"""
|
|
1850
|
+
Return the ordered widening points for a specific function.
|
|
1851
|
+
|
|
1852
|
+
:param int function_address: Address of the querying function.
|
|
1853
|
+
:return: A list of sorted merge points (addresses).
|
|
1854
|
+
:rtype: list
|
|
1855
|
+
"""
|
|
1856
|
+
|
|
1857
|
+
# we are entering a new function. now it's time to figure out how to optimally traverse the control flow
|
|
1858
|
+
# graph by generating the sorted merge points
|
|
1859
|
+
try:
|
|
1860
|
+
new_function = self.kb.functions[function_address]
|
|
1861
|
+
except KeyError:
|
|
1862
|
+
# the function does not exist
|
|
1863
|
+
return []
|
|
1864
|
+
|
|
1865
|
+
if function_address not in self._function_widening_points:
|
|
1866
|
+
if not new_function.normalized:
|
|
1867
|
+
new_function.normalize()
|
|
1868
|
+
widening_points = GraphUtils.find_widening_points(
|
|
1869
|
+
function_address, new_function.endpoints, new_function.graph
|
|
1870
|
+
)
|
|
1871
|
+
self._function_widening_points[function_address] = widening_points
|
|
1872
|
+
|
|
1873
|
+
return self._function_widening_points[function_address]
|
|
1874
|
+
|
|
1875
|
+
def _ordered_node_addrs(self, function_address):
|
|
1876
|
+
"""
|
|
1877
|
+
For a given function, return all nodes in an optimal traversal order. If the function does not exist, return an
|
|
1878
|
+
empty list.
|
|
1879
|
+
|
|
1880
|
+
:param int function_address: Address of the function.
|
|
1881
|
+
:return: A ordered list of the nodes.
|
|
1882
|
+
:rtype: list
|
|
1883
|
+
"""
|
|
1884
|
+
|
|
1885
|
+
try:
|
|
1886
|
+
function = self.kb.functions[function_address]
|
|
1887
|
+
except KeyError:
|
|
1888
|
+
# the function does not exist
|
|
1889
|
+
return []
|
|
1890
|
+
|
|
1891
|
+
if function_address not in self._function_node_addrs:
|
|
1892
|
+
sorted_nodes = GraphUtils.quasi_topological_sort_nodes(function.graph)
|
|
1893
|
+
self._function_node_addrs[function_address] = [n.addr for n in sorted_nodes]
|
|
1894
|
+
|
|
1895
|
+
return self._function_node_addrs[function_address]
|
|
1896
|
+
|
|
1897
|
+
|
|
1898
|
+
AnalysesHub.register_default("VFG", VFG)
|