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
|
@@ -0,0 +1,1830 @@
|
|
|
1
|
+
# pylint:disable=too-many-boolean-expressions
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import os
|
|
4
|
+
import logging
|
|
5
|
+
import itertools
|
|
6
|
+
from collections import defaultdict
|
|
7
|
+
from collections.abc import Iterable
|
|
8
|
+
import contextlib
|
|
9
|
+
from typing import overload, TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
import networkx
|
|
12
|
+
import pydemumble
|
|
13
|
+
|
|
14
|
+
from cle.backends.symbol import Symbol
|
|
15
|
+
from archinfo.arch_arm import get_real_address_if_arm
|
|
16
|
+
import claripy
|
|
17
|
+
|
|
18
|
+
from angr.knowledge_plugins.cfg.memory_data import MemoryDataSort
|
|
19
|
+
from angr.codenode import CodeNode, BlockNode, HookNode, SyscallNode
|
|
20
|
+
from angr.serializable import Serializable
|
|
21
|
+
from angr.errors import AngrValueError, SimEngineError, SimMemoryError
|
|
22
|
+
from angr.procedures import SIM_LIBRARIES
|
|
23
|
+
from angr.procedures.definitions import SimSyscallLibrary
|
|
24
|
+
from angr.protos import function_pb2
|
|
25
|
+
from angr.calling_conventions import DEFAULT_CC, default_cc
|
|
26
|
+
from angr.sim_type import SimTypeFunction, parse_defns
|
|
27
|
+
from angr.calling_conventions import SimCC
|
|
28
|
+
from angr.project import Project
|
|
29
|
+
from angr.utils.library import get_cpp_function_name_and_metadata
|
|
30
|
+
from .function_parser import FunctionParser
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from angr.knowledge_plugins.functions.function_manager import FunctionManager
|
|
34
|
+
|
|
35
|
+
l = logging.getLogger(name=__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Function(Serializable):
|
|
39
|
+
"""
|
|
40
|
+
A representation of a function and various information about it.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
__slots__ = (
|
|
44
|
+
"_addr_to_block_node",
|
|
45
|
+
"_argument_registers",
|
|
46
|
+
"_argument_stack_variables",
|
|
47
|
+
"_block_sizes",
|
|
48
|
+
"_call_sites",
|
|
49
|
+
"_callout_sites",
|
|
50
|
+
"_cyclomatic_complexity",
|
|
51
|
+
"_endpoints",
|
|
52
|
+
"_function_manager",
|
|
53
|
+
"_jumpout_sites",
|
|
54
|
+
"_local_block_addrs",
|
|
55
|
+
"_local_blocks",
|
|
56
|
+
"_local_transition_graph",
|
|
57
|
+
"_name",
|
|
58
|
+
"_project",
|
|
59
|
+
"_ret_sites",
|
|
60
|
+
"_retout_sites",
|
|
61
|
+
"_returning",
|
|
62
|
+
"addr",
|
|
63
|
+
"addr",
|
|
64
|
+
"binary_name",
|
|
65
|
+
"bp_on_stack",
|
|
66
|
+
"calling_convention",
|
|
67
|
+
"from_signature",
|
|
68
|
+
"info",
|
|
69
|
+
"is_alignment",
|
|
70
|
+
"is_default_name",
|
|
71
|
+
"is_plt",
|
|
72
|
+
"is_prototype_guessed",
|
|
73
|
+
"is_simprocedure",
|
|
74
|
+
"is_syscall",
|
|
75
|
+
"normalized",
|
|
76
|
+
"previous_names",
|
|
77
|
+
"prototype",
|
|
78
|
+
"prototype_libname",
|
|
79
|
+
"ran_cca",
|
|
80
|
+
"retaddr_on_stack",
|
|
81
|
+
"sp_delta",
|
|
82
|
+
"startpoint",
|
|
83
|
+
"tags",
|
|
84
|
+
"transition_graph",
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
function_manager: FunctionManager | None,
|
|
90
|
+
addr: int,
|
|
91
|
+
name=None,
|
|
92
|
+
syscall=None,
|
|
93
|
+
is_simprocedure: bool | None = None,
|
|
94
|
+
binary_name=None,
|
|
95
|
+
is_plt: bool | None = None,
|
|
96
|
+
returning=None,
|
|
97
|
+
alignment=False,
|
|
98
|
+
calling_convention: SimCC | None = None,
|
|
99
|
+
prototype: SimTypeFunction | None = None,
|
|
100
|
+
prototype_libname: str | None = None,
|
|
101
|
+
is_prototype_guessed: bool = True,
|
|
102
|
+
):
|
|
103
|
+
"""
|
|
104
|
+
Function constructor. If the optional parameters are not provided, they will be automatically determined upon
|
|
105
|
+
the creation of a Function object.
|
|
106
|
+
|
|
107
|
+
:param addr: The address of the function.
|
|
108
|
+
|
|
109
|
+
The following parameters are optional.
|
|
110
|
+
|
|
111
|
+
:param str name: The name of the function.
|
|
112
|
+
:param bool syscall: Whether this function is a syscall or not.
|
|
113
|
+
:param bool is_simprocedure: Whether this function is a SimProcedure or not.
|
|
114
|
+
:param str binary_name: Name of the binary where this function is.
|
|
115
|
+
:param bool is_plt: If this function is a PLT entry.
|
|
116
|
+
:param bool returning: If this function returns.
|
|
117
|
+
:param bool alignment: If this function acts as an alignment filler. Such functions usually only contain nops.
|
|
118
|
+
"""
|
|
119
|
+
self.transition_graph = networkx.classes.digraph.DiGraph()
|
|
120
|
+
self._local_transition_graph = None
|
|
121
|
+
self.normalized = False
|
|
122
|
+
|
|
123
|
+
# block nodes at whose ends the function returns
|
|
124
|
+
self._ret_sites: set[CodeNode] = set()
|
|
125
|
+
# block nodes at whose ends the function jumps out to another function (jumps outside)
|
|
126
|
+
self._jumpout_sites: set[CodeNode] = set()
|
|
127
|
+
# block nodes at whose ends the function calls out to another non-returning function
|
|
128
|
+
self._callout_sites: set[CodeNode] = set()
|
|
129
|
+
# block nodes that ends the function by returning out to another function (returns outside). This is rare.
|
|
130
|
+
self._retout_sites: set[CodeNode] = set()
|
|
131
|
+
# block nodes (basic block nodes) at whose ends the function terminates
|
|
132
|
+
# in theory, if everything works fine, endpoints == ret_sites | jumpout_sites | callout_sites
|
|
133
|
+
self._endpoints: defaultdict[str, set[CodeNode]] = defaultdict(set)
|
|
134
|
+
|
|
135
|
+
self._call_sites = {}
|
|
136
|
+
self.addr = addr
|
|
137
|
+
# startpoint can be None if the corresponding CFGNode is a syscall node
|
|
138
|
+
self.startpoint = None
|
|
139
|
+
self._function_manager = function_manager
|
|
140
|
+
self.is_syscall = None
|
|
141
|
+
self.is_simprocedure = False
|
|
142
|
+
self.is_alignment = alignment
|
|
143
|
+
|
|
144
|
+
# These properties are set by VariableManager
|
|
145
|
+
self.bp_on_stack = False
|
|
146
|
+
self.retaddr_on_stack = False
|
|
147
|
+
self.sp_delta = 0
|
|
148
|
+
# Calling convention
|
|
149
|
+
self.calling_convention = calling_convention
|
|
150
|
+
# Function prototype
|
|
151
|
+
self.prototype = prototype
|
|
152
|
+
self.prototype_libname = prototype_libname
|
|
153
|
+
self.is_prototype_guessed = is_prototype_guessed
|
|
154
|
+
# Whether this function returns or not. `None` means it's not determined yet
|
|
155
|
+
self._returning = None
|
|
156
|
+
|
|
157
|
+
self._addr_to_block_node = {} # map addresses to nodes. it's a cache of blocks. if a block is removed from the
|
|
158
|
+
# function, it may not be removed from _addr_to_block_node. if you want to list
|
|
159
|
+
# all blocks of a function, access .blocks.
|
|
160
|
+
self._block_sizes = {} # map addresses to block sizes
|
|
161
|
+
self._local_blocks = {} # a dict of all blocks inside the function
|
|
162
|
+
self._local_block_addrs = set() # a set of addresses of all blocks inside the function
|
|
163
|
+
|
|
164
|
+
self.info = {} # storing special information, like $gp values for MIPS32
|
|
165
|
+
self.tags = () # store function tags. can be set manually by performing CodeTagging analysis.
|
|
166
|
+
|
|
167
|
+
# Initialize _cyclomatic_complexity to None
|
|
168
|
+
self._cyclomatic_complexity = None
|
|
169
|
+
|
|
170
|
+
# TODO: Can we remove the following two members?
|
|
171
|
+
# Register offsets of those arguments passed in registers
|
|
172
|
+
self._argument_registers = []
|
|
173
|
+
# Stack offsets of those arguments passed in stack variables
|
|
174
|
+
self._argument_stack_variables = []
|
|
175
|
+
|
|
176
|
+
self._project: Project | None = None # will be initialized upon the first access to self.project
|
|
177
|
+
|
|
178
|
+
self.ran_cca = False # this is set by CompleteCallingConventions to avoid reprocessing failed functions
|
|
179
|
+
|
|
180
|
+
#
|
|
181
|
+
# Initialize unspecified properties
|
|
182
|
+
#
|
|
183
|
+
|
|
184
|
+
if syscall is not None:
|
|
185
|
+
self.is_syscall = syscall
|
|
186
|
+
else:
|
|
187
|
+
if self.project is None:
|
|
188
|
+
raise ValueError(
|
|
189
|
+
"'syscall' must be specified if you do not specify a function manager for this new function."
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# Determine whether this function is a syscall or not
|
|
193
|
+
self.is_syscall = self.project.simos.is_syscall_addr(addr)
|
|
194
|
+
|
|
195
|
+
# Determine whether this function is a SimProcedure
|
|
196
|
+
if is_simprocedure is not None:
|
|
197
|
+
self.is_simprocedure = is_simprocedure
|
|
198
|
+
else:
|
|
199
|
+
if self.project is None:
|
|
200
|
+
raise ValueError(
|
|
201
|
+
"'is_simprocedure' must be specified if you do not specify a function manager for this new "
|
|
202
|
+
"function."
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if self.is_syscall or self.project.is_hooked(addr):
|
|
206
|
+
self.is_simprocedure = True
|
|
207
|
+
|
|
208
|
+
# Determine if this function is a PLT entry
|
|
209
|
+
if is_plt is not None:
|
|
210
|
+
self.is_plt = is_plt
|
|
211
|
+
else:
|
|
212
|
+
if self._function_manager is not None:
|
|
213
|
+
# use the faster cached version
|
|
214
|
+
self.is_plt = self._function_manager.is_plt_cached(addr)
|
|
215
|
+
else:
|
|
216
|
+
# Whether this function is a PLT entry or not is primarily relying on the PLT detection in CLE; it may
|
|
217
|
+
# also be updated (to True) during CFG recovery.
|
|
218
|
+
if self.project is None:
|
|
219
|
+
raise ValueError(
|
|
220
|
+
"'is_plt' must be specified if you do not specify a function manager for this new function."
|
|
221
|
+
)
|
|
222
|
+
self.is_plt = self.project.loader.find_plt_stub_name(addr) is not None
|
|
223
|
+
|
|
224
|
+
# Determine the name of this function
|
|
225
|
+
if name is None:
|
|
226
|
+
self._name = self._get_initial_name()
|
|
227
|
+
else:
|
|
228
|
+
self.is_default_name = False
|
|
229
|
+
self._name = name
|
|
230
|
+
self.previous_names = []
|
|
231
|
+
self.from_signature: str | None = None
|
|
232
|
+
|
|
233
|
+
# Determine the name the binary where this function is.
|
|
234
|
+
if binary_name is not None:
|
|
235
|
+
self.binary_name = binary_name
|
|
236
|
+
else:
|
|
237
|
+
self.binary_name = self._get_initial_binary_name()
|
|
238
|
+
|
|
239
|
+
# Determine returning status for SimProcedures and Syscalls
|
|
240
|
+
if returning is not None:
|
|
241
|
+
self._returning = returning
|
|
242
|
+
else:
|
|
243
|
+
if self.project is None:
|
|
244
|
+
raise ValueError(
|
|
245
|
+
"'returning' must be specified if you do not specify a function manager for this new function."
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
self._returning = self._get_initial_returning()
|
|
249
|
+
|
|
250
|
+
self._init_prototype_and_calling_convention()
|
|
251
|
+
|
|
252
|
+
@property
|
|
253
|
+
def name(self):
|
|
254
|
+
return self._name
|
|
255
|
+
|
|
256
|
+
@name.setter
|
|
257
|
+
def name(self, v):
|
|
258
|
+
self.previous_names.append(self._name)
|
|
259
|
+
self._name = v
|
|
260
|
+
self._function_manager._kb.labels[self.addr] = v
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def project(self):
|
|
264
|
+
if self._project is None and self._function_manager is not None:
|
|
265
|
+
# try to set it from function manager
|
|
266
|
+
self._project = self._function_manager._kb._project
|
|
267
|
+
return self._project
|
|
268
|
+
|
|
269
|
+
@property
|
|
270
|
+
def returning(self):
|
|
271
|
+
return self._returning
|
|
272
|
+
|
|
273
|
+
@returning.setter
|
|
274
|
+
def returning(self, v):
|
|
275
|
+
self._returning = v
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def blocks(self):
|
|
279
|
+
"""
|
|
280
|
+
An iterator of all local blocks in the current function.
|
|
281
|
+
|
|
282
|
+
:return: angr.lifter.Block instances.
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
for block_addr, block in self._local_blocks.items():
|
|
286
|
+
with contextlib.suppress(SimEngineError, SimMemoryError):
|
|
287
|
+
yield self.get_block(
|
|
288
|
+
block_addr, size=block.size, byte_string=block.bytestr if isinstance(block, BlockNode) else None
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def cyclomatic_complexity(self):
|
|
293
|
+
"""
|
|
294
|
+
The cyclomatic complexity of the function.
|
|
295
|
+
|
|
296
|
+
Cyclomatic complexity is a software metric used to indicate the complexity of a program.
|
|
297
|
+
It is a quantitative measure of the number of linearly independent paths through a program's source code.
|
|
298
|
+
It is computed using the formula: M = E - N + 2P, where
|
|
299
|
+
E = the number of edges in the graph,
|
|
300
|
+
N = the number of nodes in the graph,
|
|
301
|
+
P = the number of connected components.
|
|
302
|
+
|
|
303
|
+
The cyclomatic complexity value is lazily computed and cached for future use.
|
|
304
|
+
Initially this value is None until it is computed for the first time
|
|
305
|
+
|
|
306
|
+
:return: The cyclomatic complexity of the function.
|
|
307
|
+
:rtype: int
|
|
308
|
+
"""
|
|
309
|
+
if self._cyclomatic_complexity is None:
|
|
310
|
+
self._cyclomatic_complexity = (
|
|
311
|
+
self.transition_graph.number_of_edges() - self.transition_graph.number_of_nodes() + 2
|
|
312
|
+
)
|
|
313
|
+
return self._cyclomatic_complexity
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def xrefs(self):
|
|
317
|
+
"""
|
|
318
|
+
An iterator of all xrefs of the current function.
|
|
319
|
+
|
|
320
|
+
:return: angr.knowledge_plugins.xrefs.xref.XRef instances.
|
|
321
|
+
"""
|
|
322
|
+
for block in self.blocks:
|
|
323
|
+
yield from self._function_manager._kb.xrefs.get_xrefs_by_ins_addr_region(
|
|
324
|
+
block.addr, block.addr + block.size
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
@property
|
|
328
|
+
def block_addrs(self):
|
|
329
|
+
"""
|
|
330
|
+
An iterator of all local block addresses in the current function.
|
|
331
|
+
|
|
332
|
+
:return: block addresses.
|
|
333
|
+
"""
|
|
334
|
+
|
|
335
|
+
return self._local_blocks.keys()
|
|
336
|
+
|
|
337
|
+
@property
|
|
338
|
+
def block_addrs_set(self):
|
|
339
|
+
"""
|
|
340
|
+
Return a set of block addresses for a better performance of inclusion tests.
|
|
341
|
+
|
|
342
|
+
:return: A set of block addresses.
|
|
343
|
+
:rtype: set
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
return self._local_block_addrs
|
|
347
|
+
|
|
348
|
+
def get_block(self, addr: int, size: int | None = None, byte_string: bytes | None = None):
|
|
349
|
+
"""
|
|
350
|
+
Getting a block out of the current function.
|
|
351
|
+
|
|
352
|
+
:param int addr: The address of the block.
|
|
353
|
+
:param int size: The size of the block. This is optional. If not provided, angr will load
|
|
354
|
+
:param byte_string:
|
|
355
|
+
:return:
|
|
356
|
+
"""
|
|
357
|
+
if size is None and addr in self.block_addrs:
|
|
358
|
+
# we know the size
|
|
359
|
+
size = self._block_sizes[addr]
|
|
360
|
+
|
|
361
|
+
assert self.project is not None
|
|
362
|
+
block = self.project.factory.block(addr, size=size, byte_string=byte_string)
|
|
363
|
+
if size is None:
|
|
364
|
+
# update block_size dict
|
|
365
|
+
self._block_sizes[addr] = block.size
|
|
366
|
+
return block
|
|
367
|
+
|
|
368
|
+
# compatibility
|
|
369
|
+
_get_block = get_block
|
|
370
|
+
|
|
371
|
+
def get_block_size(self, addr: int) -> int | None:
|
|
372
|
+
return self._block_sizes.get(addr, None)
|
|
373
|
+
|
|
374
|
+
@property
|
|
375
|
+
def nodes(self) -> Iterable[CodeNode]:
|
|
376
|
+
return self.transition_graph.nodes()
|
|
377
|
+
|
|
378
|
+
def get_node(self, addr) -> BlockNode | None:
|
|
379
|
+
return self._addr_to_block_node.get(addr, None)
|
|
380
|
+
|
|
381
|
+
@property
|
|
382
|
+
def has_unresolved_jumps(self):
|
|
383
|
+
for addr in self.block_addrs:
|
|
384
|
+
if addr in self._function_manager._kb.unresolved_indirect_jumps:
|
|
385
|
+
b = self._function_manager._kb._project.factory.block(addr)
|
|
386
|
+
if b.vex.jumpkind == "Ijk_Boring":
|
|
387
|
+
return True
|
|
388
|
+
return False
|
|
389
|
+
|
|
390
|
+
@property
|
|
391
|
+
def has_unresolved_calls(self):
|
|
392
|
+
for addr in self.block_addrs:
|
|
393
|
+
if addr in self._function_manager._kb.unresolved_indirect_jumps:
|
|
394
|
+
b = self._function_manager._kb._project.factory.block(addr)
|
|
395
|
+
if b.vex.jumpkind == "Ijk_Call":
|
|
396
|
+
return True
|
|
397
|
+
return False
|
|
398
|
+
|
|
399
|
+
@property
|
|
400
|
+
def operations(self):
|
|
401
|
+
"""
|
|
402
|
+
All of the operations that are done by this functions.
|
|
403
|
+
"""
|
|
404
|
+
return [op for block in self.blocks for op in block.vex.operations]
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def code_constants(self):
|
|
408
|
+
"""
|
|
409
|
+
All of the constants that are used by this functions's code.
|
|
410
|
+
"""
|
|
411
|
+
# TODO: remove link register values
|
|
412
|
+
return [const.value for block in self.blocks for const in block.vex.constants]
|
|
413
|
+
|
|
414
|
+
@classmethod
|
|
415
|
+
def _get_cmsg(cls):
|
|
416
|
+
return function_pb2.Function() # pylint:disable=no-member
|
|
417
|
+
|
|
418
|
+
def serialize_to_cmessage(self):
|
|
419
|
+
return FunctionParser.serialize(self)
|
|
420
|
+
|
|
421
|
+
@classmethod
|
|
422
|
+
def parse_from_cmessage(cls, cmsg, **kwargs):
|
|
423
|
+
"""
|
|
424
|
+
:param cmsg:
|
|
425
|
+
|
|
426
|
+
:return Function: The function instantiated out of the cmsg data.
|
|
427
|
+
"""
|
|
428
|
+
return FunctionParser.parse_from_cmsg(cmsg, **kwargs)
|
|
429
|
+
|
|
430
|
+
def string_references(self, minimum_length=2):
|
|
431
|
+
"""
|
|
432
|
+
All of the constant string references used by this function.
|
|
433
|
+
|
|
434
|
+
:param minimum_length: The minimum length of strings to find (default is 1)
|
|
435
|
+
:return: A generator yielding tuples of (address, string) where is address
|
|
436
|
+
is the location of the string in memory.
|
|
437
|
+
"""
|
|
438
|
+
|
|
439
|
+
cfg = self._function_manager._kb.cfgs.get_most_accurate()
|
|
440
|
+
|
|
441
|
+
for x in self.xrefs:
|
|
442
|
+
try:
|
|
443
|
+
md = cfg.memory_data[x.dst]
|
|
444
|
+
except KeyError:
|
|
445
|
+
continue
|
|
446
|
+
if md.sort not in {MemoryDataSort.String, MemoryDataSort.UnicodeString}:
|
|
447
|
+
continue
|
|
448
|
+
if len(md.content) < minimum_length:
|
|
449
|
+
continue
|
|
450
|
+
|
|
451
|
+
yield (md.addr, md.content)
|
|
452
|
+
|
|
453
|
+
@property
|
|
454
|
+
def local_runtime_values(self):
|
|
455
|
+
"""
|
|
456
|
+
Tries to find all runtime values of this function which do not come from inputs.
|
|
457
|
+
These values are generated by starting from a blank state and reanalyzing the basic blocks once each.
|
|
458
|
+
Function calls are skipped, and back edges are never taken so these values are often unreliable,
|
|
459
|
+
This function is good at finding simple constant addresses which the function will use or calculate.
|
|
460
|
+
|
|
461
|
+
:return: a set of constants
|
|
462
|
+
"""
|
|
463
|
+
constants = set()
|
|
464
|
+
|
|
465
|
+
assert self.project is not None
|
|
466
|
+
if not self.project.loader.main_object.contains_addr(self.addr):
|
|
467
|
+
return constants
|
|
468
|
+
|
|
469
|
+
# FIXME the old way was better for architectures like mips, but we need the initial irsb
|
|
470
|
+
# reanalyze function with a new initial state (use persistent registers)
|
|
471
|
+
# initial_state = self._function_manager._cfg.get_any_irsb(self.addr).initial_state
|
|
472
|
+
# fresh_state = self.project.factory.blank_state(mode="fastpath")
|
|
473
|
+
# for reg in initial_state.arch.persistent_regs + ['ip']:
|
|
474
|
+
# fresh_state.registers.store(reg, initial_state.registers.load(reg))
|
|
475
|
+
|
|
476
|
+
# reanalyze function with a new initial state
|
|
477
|
+
fresh_state = self.project.factory.blank_state(mode="fastpath")
|
|
478
|
+
fresh_state.regs.ip = self.addr
|
|
479
|
+
|
|
480
|
+
graph_addrs = {x.addr for x in self.graph.nodes() if isinstance(x, BlockNode)}
|
|
481
|
+
|
|
482
|
+
# process the nodes in a breadth-first order keeping track of which nodes have already been analyzed
|
|
483
|
+
analyzed = set()
|
|
484
|
+
q = [fresh_state]
|
|
485
|
+
analyzed.add(fresh_state.solver.eval(fresh_state.ip))
|
|
486
|
+
while len(q) > 0:
|
|
487
|
+
state = q.pop()
|
|
488
|
+
# make sure its in this function
|
|
489
|
+
if state.solver.eval(state.ip) not in graph_addrs:
|
|
490
|
+
continue
|
|
491
|
+
# don't trace into simprocedures
|
|
492
|
+
if self.project.is_hooked(state.solver.eval(state.ip)):
|
|
493
|
+
continue
|
|
494
|
+
# don't trace outside of the binary
|
|
495
|
+
if not self.project.loader.main_object.contains_addr(state.solver.eval(state.ip)):
|
|
496
|
+
continue
|
|
497
|
+
# don't trace unreachable blocks
|
|
498
|
+
if state.history.jumpkind in {
|
|
499
|
+
"Ijk_EmWarn",
|
|
500
|
+
"Ijk_NoDecode",
|
|
501
|
+
"Ijk_MapFail",
|
|
502
|
+
"Ijk_NoRedir",
|
|
503
|
+
"Ijk_SigTRAP",
|
|
504
|
+
"Ijk_SigSEGV",
|
|
505
|
+
"Ijk_ClientReq",
|
|
506
|
+
}:
|
|
507
|
+
continue
|
|
508
|
+
|
|
509
|
+
curr_ip = state.solver.eval(state.ip)
|
|
510
|
+
|
|
511
|
+
# get runtime values from logs of successors
|
|
512
|
+
successors = self.project.factory.successors(state)
|
|
513
|
+
for succ in successors.flat_successors + successors.unsat_successors:
|
|
514
|
+
for a in succ.history.recent_actions:
|
|
515
|
+
for ao in a.all_objects:
|
|
516
|
+
if not isinstance(ao.ast, claripy.ast.Base):
|
|
517
|
+
constants.add(ao.ast)
|
|
518
|
+
elif not ao.ast.symbolic:
|
|
519
|
+
constants.add(succ.solver.eval(ao.ast))
|
|
520
|
+
|
|
521
|
+
# add successors to the queue to analyze
|
|
522
|
+
if not succ.solver.symbolic(succ.ip):
|
|
523
|
+
succ_ip = succ.solver.eval(succ.ip)
|
|
524
|
+
if succ_ip in self and succ_ip not in analyzed:
|
|
525
|
+
analyzed.add(succ_ip)
|
|
526
|
+
q.insert(0, succ)
|
|
527
|
+
|
|
528
|
+
# force jumps to missing successors
|
|
529
|
+
# (this is a slightly hacky way to force it to explore all the nodes in the function)
|
|
530
|
+
node = self.get_node(curr_ip)
|
|
531
|
+
if node is None:
|
|
532
|
+
# the node does not exist. maybe it's not a block node.
|
|
533
|
+
continue
|
|
534
|
+
missing = {x.addr for x in list(self.graph.successors(node))} - analyzed
|
|
535
|
+
for succ_addr in missing:
|
|
536
|
+
l.info("Forcing jump to missing successor: %#x", succ_addr)
|
|
537
|
+
if succ_addr not in analyzed:
|
|
538
|
+
all_successors = (
|
|
539
|
+
successors.unconstrained_successors + successors.flat_successors + successors.unsat_successors
|
|
540
|
+
)
|
|
541
|
+
if len(all_successors) > 0:
|
|
542
|
+
# set the ip of a copied successor to the successor address
|
|
543
|
+
succ = all_successors[0].copy()
|
|
544
|
+
succ.ip = succ_addr
|
|
545
|
+
analyzed.add(succ_addr)
|
|
546
|
+
q.insert(0, succ)
|
|
547
|
+
else:
|
|
548
|
+
l.warning("Could not reach successor: %#x", succ_addr)
|
|
549
|
+
|
|
550
|
+
return constants
|
|
551
|
+
|
|
552
|
+
@property
|
|
553
|
+
def num_arguments(self):
|
|
554
|
+
return len(self._argument_registers) + len(self._argument_stack_variables)
|
|
555
|
+
|
|
556
|
+
def __contains__(self, val):
|
|
557
|
+
if isinstance(val, int):
|
|
558
|
+
return val in self._block_sizes
|
|
559
|
+
return False
|
|
560
|
+
|
|
561
|
+
def __str__(self):
|
|
562
|
+
return (
|
|
563
|
+
f"Function {self.name} [{self.addr:#x}]\n"
|
|
564
|
+
f" Syscall: {self.is_syscall}\n"
|
|
565
|
+
f" SP difference: {self.sp_delta}\n"
|
|
566
|
+
f" Has return: {self.has_return}\n"
|
|
567
|
+
f" Returning: {'Unknown' if self.returning is None else self.returning}\n"
|
|
568
|
+
f" Alignment: {self.is_alignment}\n"
|
|
569
|
+
f" Arguments: reg: {self._argument_registers}, stack: {self._argument_stack_variables}\n"
|
|
570
|
+
f" Blocks: [{', '.join(f'{i:#x}' for i in self.block_addrs)}]\n"
|
|
571
|
+
f" Cyclomatic Complexity: {self.cyclomatic_complexity}\n"
|
|
572
|
+
f" Calling convention: {self.calling_convention}"
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
def __repr__(self):
|
|
576
|
+
if self.is_syscall:
|
|
577
|
+
return f"<Syscall function {self.name} ({hex(self.addr) if isinstance(self.addr, int) else self.addr})>"
|
|
578
|
+
return f"<Function {self.name} ({hex(self.addr) if isinstance(self.addr, int) else self.addr})>"
|
|
579
|
+
|
|
580
|
+
def __setstate__(self, state):
|
|
581
|
+
for k, v in state.items():
|
|
582
|
+
setattr(self, k, v)
|
|
583
|
+
|
|
584
|
+
def __getstate__(self):
|
|
585
|
+
# self._local_transition_graph is a cache. don't pickle it
|
|
586
|
+
d = {k: getattr(self, k) for k in self.__slots__}
|
|
587
|
+
d["_local_transition_graph"] = None
|
|
588
|
+
d["_project"] = None
|
|
589
|
+
d["_function_manager"] = None
|
|
590
|
+
return d
|
|
591
|
+
|
|
592
|
+
@property
|
|
593
|
+
def endpoints(self):
|
|
594
|
+
return list(itertools.chain(*self._endpoints.values()))
|
|
595
|
+
|
|
596
|
+
@property
|
|
597
|
+
def endpoints_with_type(self):
|
|
598
|
+
return self._endpoints
|
|
599
|
+
|
|
600
|
+
@property
|
|
601
|
+
def ret_sites(self):
|
|
602
|
+
return list(self._ret_sites)
|
|
603
|
+
|
|
604
|
+
@property
|
|
605
|
+
def jumpout_sites(self):
|
|
606
|
+
return list(self._jumpout_sites)
|
|
607
|
+
|
|
608
|
+
@property
|
|
609
|
+
def retout_sites(self):
|
|
610
|
+
return list(self._retout_sites)
|
|
611
|
+
|
|
612
|
+
@property
|
|
613
|
+
def callout_sites(self):
|
|
614
|
+
return list(self._callout_sites)
|
|
615
|
+
|
|
616
|
+
@property
|
|
617
|
+
def size(self):
|
|
618
|
+
return sum(self._block_sizes[addr] for addr in self._local_blocks)
|
|
619
|
+
|
|
620
|
+
@property
|
|
621
|
+
def binary(self):
|
|
622
|
+
"""
|
|
623
|
+
Get the object this function belongs to.
|
|
624
|
+
:return: The object this function belongs to.
|
|
625
|
+
"""
|
|
626
|
+
assert self.project is not None
|
|
627
|
+
return self.project.loader.find_object_containing(self.addr, membership_check=False)
|
|
628
|
+
|
|
629
|
+
@property
|
|
630
|
+
def offset(self) -> int:
|
|
631
|
+
"""
|
|
632
|
+
:return: the function's binary offset (i.e., non-rebased address)
|
|
633
|
+
"""
|
|
634
|
+
return self.addr - self.binary.mapped_base
|
|
635
|
+
|
|
636
|
+
@property
|
|
637
|
+
def symbol(self) -> None | Symbol:
|
|
638
|
+
"""
|
|
639
|
+
:return: the function's Symbol, if any
|
|
640
|
+
"""
|
|
641
|
+
return self.binary.loader.find_symbol(self.addr)
|
|
642
|
+
|
|
643
|
+
@property
|
|
644
|
+
def pseudocode(self) -> str | None:
|
|
645
|
+
"""
|
|
646
|
+
:return: the function's pseudocode
|
|
647
|
+
"""
|
|
648
|
+
if self.project is None:
|
|
649
|
+
l.error("Cannot generate pseudocode because the function is not associated with any angr project.")
|
|
650
|
+
return None
|
|
651
|
+
dec = self.project.analyses.Decompiler(self, cfg=self._function_manager._kb.cfgs.get_most_accurate())
|
|
652
|
+
return dec.codegen.text if dec.codegen else None
|
|
653
|
+
|
|
654
|
+
def add_jumpout_site(self, node: CodeNode):
|
|
655
|
+
"""
|
|
656
|
+
Add a custom jumpout site.
|
|
657
|
+
|
|
658
|
+
:param node: The address of the basic block that control flow leaves during this transition.
|
|
659
|
+
:return: None
|
|
660
|
+
"""
|
|
661
|
+
|
|
662
|
+
node = self._register_node(True, node)
|
|
663
|
+
self._jumpout_sites.add(node)
|
|
664
|
+
self._add_endpoint(node, "transition")
|
|
665
|
+
|
|
666
|
+
def add_retout_site(self, node: CodeNode):
|
|
667
|
+
"""
|
|
668
|
+
Add a custom retout site.
|
|
669
|
+
|
|
670
|
+
Retout (returning to outside of the function) sites are very rare. It mostly occurs during CFG recovery when we
|
|
671
|
+
incorrectly identify the beginning of a function in the first iteration, and then correctly identify that
|
|
672
|
+
function later in the same iteration (function alignments can lead to this bizarre case). We will mark all edges
|
|
673
|
+
going out of the header of that function as a outside edge, because all successors now belong to the
|
|
674
|
+
incorrectly-identified function. This identification error will be fixed in the second iteration of CFG
|
|
675
|
+
recovery. However, we still want to keep track of jumpouts/retouts during the first iteration so other logic in
|
|
676
|
+
CFG recovery still work.
|
|
677
|
+
|
|
678
|
+
:param node: The address of the basic block that control flow leaves the current function after a call.
|
|
679
|
+
:return: None
|
|
680
|
+
"""
|
|
681
|
+
|
|
682
|
+
node = self._register_node(True, node)
|
|
683
|
+
self._retout_sites.add(node)
|
|
684
|
+
self._add_endpoint(node, "return")
|
|
685
|
+
|
|
686
|
+
def _get_initial_name(self):
|
|
687
|
+
"""
|
|
688
|
+
Determine the most suitable name of the function.
|
|
689
|
+
|
|
690
|
+
:return: The initial function name.
|
|
691
|
+
:rtype: string
|
|
692
|
+
"""
|
|
693
|
+
|
|
694
|
+
name = None
|
|
695
|
+
addr = self.addr
|
|
696
|
+
|
|
697
|
+
self.is_default_name = False
|
|
698
|
+
# Try to get a name from existing labels
|
|
699
|
+
if self._function_manager is not None and addr in self._function_manager._kb.labels:
|
|
700
|
+
name = self._function_manager._kb.labels[addr]
|
|
701
|
+
|
|
702
|
+
# try to get the name from a hook
|
|
703
|
+
if name is None and self.project is not None:
|
|
704
|
+
project = self.project
|
|
705
|
+
if project.is_hooked(addr):
|
|
706
|
+
hooker = project.hooked_by(addr)
|
|
707
|
+
if hooker is not None:
|
|
708
|
+
name = hooker.display_name
|
|
709
|
+
elif project.simos.is_syscall_addr(addr):
|
|
710
|
+
syscall_inst = project.simos.syscall_from_addr(addr)
|
|
711
|
+
if syscall_inst is not None:
|
|
712
|
+
name = syscall_inst.display_name
|
|
713
|
+
|
|
714
|
+
# generate an IDA-style sub_X name
|
|
715
|
+
if name is None:
|
|
716
|
+
self.is_default_name = True
|
|
717
|
+
name = f"sub_{addr:x}"
|
|
718
|
+
|
|
719
|
+
return name
|
|
720
|
+
|
|
721
|
+
def _get_initial_binary_name(self) -> str | None:
|
|
722
|
+
"""
|
|
723
|
+
Determine the name of the binary where this function is.
|
|
724
|
+
|
|
725
|
+
:return: None
|
|
726
|
+
"""
|
|
727
|
+
|
|
728
|
+
binary_name = None
|
|
729
|
+
|
|
730
|
+
# if this function is a simprocedure but not a syscall, use its library name as
|
|
731
|
+
# its binary name
|
|
732
|
+
# if it is a syscall, fall back to use self.binary.binary which explicitly says cle##kernel
|
|
733
|
+
if self.project and self.is_simprocedure and not self.is_syscall:
|
|
734
|
+
hooker = self.project.hooked_by(self.addr)
|
|
735
|
+
if hooker is not None:
|
|
736
|
+
binary_name = hooker.library_name
|
|
737
|
+
|
|
738
|
+
if binary_name is None:
|
|
739
|
+
if self._function_manager is not None:
|
|
740
|
+
# use the faster cached version
|
|
741
|
+
binary_name = self._function_manager.get_binary_name_cached(self.addr)
|
|
742
|
+
else:
|
|
743
|
+
if self.binary is not None and self.binary.binary:
|
|
744
|
+
binary_name = os.path.basename(self.binary.binary)
|
|
745
|
+
|
|
746
|
+
return binary_name
|
|
747
|
+
|
|
748
|
+
def _get_initial_returning(self):
|
|
749
|
+
"""
|
|
750
|
+
Determine if this function returns or not *if it is hooked by a SimProcedure or a user hook*.
|
|
751
|
+
|
|
752
|
+
:return: True if the hooker returns, False otherwise.
|
|
753
|
+
:rtype: bool
|
|
754
|
+
"""
|
|
755
|
+
|
|
756
|
+
hooker = None
|
|
757
|
+
assert self.project is not None
|
|
758
|
+
if self.is_syscall:
|
|
759
|
+
hooker = self.project.simos.syscall_from_addr(self.addr)
|
|
760
|
+
elif self.is_simprocedure:
|
|
761
|
+
hooker = self.project.hooked_by(self.addr)
|
|
762
|
+
if hooker:
|
|
763
|
+
if hasattr(hooker, "DYNAMIC_RET") and hooker.DYNAMIC_RET:
|
|
764
|
+
return True
|
|
765
|
+
return hooker.returns
|
|
766
|
+
|
|
767
|
+
# Cannot determine
|
|
768
|
+
return None
|
|
769
|
+
|
|
770
|
+
def _init_prototype_and_calling_convention(self) -> None:
|
|
771
|
+
"""
|
|
772
|
+
Initialize prototype and calling convention from a SimProcedure, if available.
|
|
773
|
+
"""
|
|
774
|
+
hooker = None
|
|
775
|
+
if self.is_syscall and self.project is not None and self.project.simos.is_syscall_addr(self.addr):
|
|
776
|
+
hooker = self.project.simos.syscall_from_addr(self.addr)
|
|
777
|
+
elif self.is_simprocedure and self.project is not None:
|
|
778
|
+
hooker = self.project.hooked_by(self.addr)
|
|
779
|
+
if hooker is None or hooker.guessed_prototype:
|
|
780
|
+
return
|
|
781
|
+
|
|
782
|
+
if hooker.prototype:
|
|
783
|
+
self.prototype_libname = hooker.library_name
|
|
784
|
+
self.prototype = hooker.prototype
|
|
785
|
+
self.is_prototype_guessed = False
|
|
786
|
+
|
|
787
|
+
cc = hooker.cc
|
|
788
|
+
if cc is None and self.project is not None:
|
|
789
|
+
arch = self.project.arch
|
|
790
|
+
if arch.name in DEFAULT_CC:
|
|
791
|
+
cc_cls = default_cc(
|
|
792
|
+
arch.name, platform=self.project.simos.name if self.project.simos is not None else None
|
|
793
|
+
)
|
|
794
|
+
if cc_cls is not None:
|
|
795
|
+
cc = cc_cls(arch)
|
|
796
|
+
self.calling_convention = cc
|
|
797
|
+
|
|
798
|
+
def _clear_transition_graph(self):
|
|
799
|
+
self._block_sizes = {}
|
|
800
|
+
self._addr_to_block_node = {}
|
|
801
|
+
self._local_blocks = {}
|
|
802
|
+
self._local_block_addrs = set()
|
|
803
|
+
self.startpoint = None
|
|
804
|
+
self.transition_graph = networkx.classes.digraph.DiGraph()
|
|
805
|
+
self._local_transition_graph = None
|
|
806
|
+
|
|
807
|
+
self._ret_sites = set()
|
|
808
|
+
self._jumpout_sites = set()
|
|
809
|
+
self._callout_sites = set()
|
|
810
|
+
self._retout_sites = set()
|
|
811
|
+
self._endpoints = defaultdict(set)
|
|
812
|
+
self._call_sites = {}
|
|
813
|
+
|
|
814
|
+
def _confirm_fakeret(self, src, dst):
|
|
815
|
+
if src not in self.transition_graph or dst not in self.transition_graph[src]:
|
|
816
|
+
raise AngrValueError(f"FakeRet edge ({src}, {dst}) is not in transition graph.")
|
|
817
|
+
|
|
818
|
+
data = self.transition_graph[src][dst]
|
|
819
|
+
|
|
820
|
+
if "type" not in data or data["type"] != "fake_return":
|
|
821
|
+
raise AngrValueError(f"Edge ({src}, {dst}) is not a FakeRet edge")
|
|
822
|
+
|
|
823
|
+
# it's confirmed. register the node if needed
|
|
824
|
+
if "outside" not in data or data["outside"] is False:
|
|
825
|
+
dst = self._register_node(True, dst)
|
|
826
|
+
|
|
827
|
+
self.transition_graph[src][dst]["confirmed"] = True
|
|
828
|
+
|
|
829
|
+
def _transit_to(
|
|
830
|
+
self, from_node: CodeNode, to_node, outside=False, ins_addr=None, stmt_idx=None, is_exception=False
|
|
831
|
+
):
|
|
832
|
+
"""
|
|
833
|
+
Registers an edge between basic blocks in this function's transition graph.
|
|
834
|
+
Arguments are CodeNode objects.
|
|
835
|
+
|
|
836
|
+
:param from_node The address of the basic block that control
|
|
837
|
+
flow leaves during this transition.
|
|
838
|
+
:param to_node The address of the basic block that control
|
|
839
|
+
flow enters during this transition.
|
|
840
|
+
:param bool outside: If this is a transition to another function, e.g. tail call optimization
|
|
841
|
+
:return: None
|
|
842
|
+
"""
|
|
843
|
+
|
|
844
|
+
if outside:
|
|
845
|
+
from_node = self._register_node(True, from_node)
|
|
846
|
+
if to_node is not None:
|
|
847
|
+
to_node = self._register_node(False, to_node)
|
|
848
|
+
|
|
849
|
+
self._jumpout_sites.add(from_node)
|
|
850
|
+
else:
|
|
851
|
+
from_node = self._register_node(True, from_node)
|
|
852
|
+
if to_node is not None:
|
|
853
|
+
to_node = self._register_node(True, to_node)
|
|
854
|
+
|
|
855
|
+
type_ = "transition" if not is_exception else "exception"
|
|
856
|
+
if to_node is not None:
|
|
857
|
+
self.transition_graph.add_edge(
|
|
858
|
+
from_node, to_node, type=type_, outside=outside, ins_addr=ins_addr, stmt_idx=stmt_idx
|
|
859
|
+
)
|
|
860
|
+
|
|
861
|
+
if outside:
|
|
862
|
+
# this node is an endpoint of the current function
|
|
863
|
+
self._add_endpoint(from_node, type_)
|
|
864
|
+
|
|
865
|
+
# clear the cache
|
|
866
|
+
self._local_transition_graph = None
|
|
867
|
+
|
|
868
|
+
def _call_to(self, from_node, to_func, ret_node, stmt_idx=None, ins_addr=None, return_to_outside=False):
|
|
869
|
+
"""
|
|
870
|
+
Registers an edge between the caller basic block and callee function.
|
|
871
|
+
|
|
872
|
+
:param from_addr: The basic block that control flow leaves during the transition.
|
|
873
|
+
:type from_addr: angr.knowledge.CodeNode
|
|
874
|
+
:param to_func: The function that we are calling
|
|
875
|
+
:type to_func: Function
|
|
876
|
+
:param ret_node The basic block that control flow should return to after the
|
|
877
|
+
function call.
|
|
878
|
+
:type to_func: angr.knowledge.CodeNode or None
|
|
879
|
+
:param stmt_idx: Statement ID of this call.
|
|
880
|
+
:type stmt_idx: int, str or None
|
|
881
|
+
:param ins_addr: Instruction address of this call.
|
|
882
|
+
:type ins_addr: int or None
|
|
883
|
+
"""
|
|
884
|
+
|
|
885
|
+
from_node = self._register_node(True, from_node)
|
|
886
|
+
|
|
887
|
+
if to_func.is_syscall:
|
|
888
|
+
self.transition_graph.add_edge(from_node, to_func, type="syscall", stmt_idx=stmt_idx, ins_addr=ins_addr)
|
|
889
|
+
else:
|
|
890
|
+
self.transition_graph.add_edge(from_node, to_func, type="call", stmt_idx=stmt_idx, ins_addr=ins_addr)
|
|
891
|
+
if ret_node is not None:
|
|
892
|
+
ret_node = self._register_node(return_to_outside is False, ret_node)
|
|
893
|
+
self._fakeret_to(from_node, ret_node, to_outside=return_to_outside)
|
|
894
|
+
|
|
895
|
+
self._local_transition_graph = None
|
|
896
|
+
|
|
897
|
+
def _fakeret_to(self, from_node, to_node, confirmed=None, to_outside=False):
|
|
898
|
+
from_node = self._register_node(True, from_node)
|
|
899
|
+
if confirmed:
|
|
900
|
+
to_node = self._register_node(not to_outside, to_node)
|
|
901
|
+
|
|
902
|
+
if confirmed is None:
|
|
903
|
+
self.transition_graph.add_edge(from_node, to_node, type="fake_return", outside=to_outside)
|
|
904
|
+
else:
|
|
905
|
+
self.transition_graph.add_edge(
|
|
906
|
+
from_node, to_node, type="fake_return", confirmed=confirmed, outside=to_outside
|
|
907
|
+
)
|
|
908
|
+
|
|
909
|
+
self._local_transition_graph = None
|
|
910
|
+
|
|
911
|
+
def _remove_fakeret(self, from_node, to_node):
|
|
912
|
+
self.transition_graph.remove_edge(from_node, to_node)
|
|
913
|
+
|
|
914
|
+
self._local_transition_graph = None
|
|
915
|
+
|
|
916
|
+
def _return_from_call(self, from_func, to_node, to_outside=False):
|
|
917
|
+
self.transition_graph.add_edge(from_func, to_node, type="return", to_outside=to_outside)
|
|
918
|
+
for _, _, data in self.transition_graph.in_edges(to_node, data=True):
|
|
919
|
+
if "type" in data and data["type"] == "fake_return":
|
|
920
|
+
data["confirmed"] = True
|
|
921
|
+
|
|
922
|
+
self._local_transition_graph = None
|
|
923
|
+
|
|
924
|
+
def _update_local_blocks(self, node: CodeNode):
|
|
925
|
+
if node.addr not in self._local_blocks or self._local_blocks[node.addr] != node:
|
|
926
|
+
self._local_blocks[node.addr] = node
|
|
927
|
+
self._local_block_addrs.add(node.addr)
|
|
928
|
+
|
|
929
|
+
def _update_addr_to_block_cache(self, node: BlockNode):
|
|
930
|
+
if node.addr not in self._addr_to_block_node:
|
|
931
|
+
self._addr_to_block_node[node.addr] = node
|
|
932
|
+
|
|
933
|
+
@overload
|
|
934
|
+
def _register_node(self, is_local: bool, node: CodeNode) -> CodeNode: ...
|
|
935
|
+
|
|
936
|
+
@overload
|
|
937
|
+
def _register_node(self, is_local: bool, node: Function) -> Function: ...
|
|
938
|
+
|
|
939
|
+
def _register_node(self, is_local: bool, node: CodeNode | Function) -> CodeNode | Function:
|
|
940
|
+
# if the node already exists and is the same, we reuse the existing node
|
|
941
|
+
if is_local and self._local_blocks.get(node.addr, None) == node:
|
|
942
|
+
return self._local_blocks[node.addr]
|
|
943
|
+
|
|
944
|
+
if node.addr not in self and node not in self.transition_graph:
|
|
945
|
+
# only add each node to the graph once
|
|
946
|
+
self.transition_graph.add_node(node)
|
|
947
|
+
|
|
948
|
+
if not isinstance(node, CodeNode):
|
|
949
|
+
# function and other things bail here
|
|
950
|
+
return node
|
|
951
|
+
|
|
952
|
+
# this is either a new node or a different node at the same address
|
|
953
|
+
node.set_graph(self.transition_graph)
|
|
954
|
+
if self._block_sizes.get(node.addr, 0) == 0:
|
|
955
|
+
self._block_sizes[node.addr] = node.size
|
|
956
|
+
if node.addr == self.addr and (self.startpoint is None or not self.startpoint.is_hook):
|
|
957
|
+
self.startpoint = node
|
|
958
|
+
if is_local and node.addr not in self._local_blocks:
|
|
959
|
+
self._update_local_blocks(node)
|
|
960
|
+
# add BlockNodes to the addr_to_block_node cache if not already there
|
|
961
|
+
if isinstance(node, BlockNode):
|
|
962
|
+
self._update_addr_to_block_cache(node)
|
|
963
|
+
# else:
|
|
964
|
+
# # checks that we don't have multiple block nodes at a single address
|
|
965
|
+
# assert node == self._addr_to_block_node[node.addr]
|
|
966
|
+
return node
|
|
967
|
+
|
|
968
|
+
def _add_return_site(self, return_site: CodeNode):
|
|
969
|
+
"""
|
|
970
|
+
Registers a basic block as a site for control flow to return from this function.
|
|
971
|
+
|
|
972
|
+
:param return_site: The block node that ends with a return.
|
|
973
|
+
"""
|
|
974
|
+
return_site = self._register_node(True, return_site)
|
|
975
|
+
|
|
976
|
+
self._ret_sites.add(return_site)
|
|
977
|
+
# A return site must be an endpoint of the function - you cannot continue execution of the current function
|
|
978
|
+
# after returning
|
|
979
|
+
self._add_endpoint(return_site, "return")
|
|
980
|
+
|
|
981
|
+
def _add_call_site(self, call_site_addr, call_target_addr, retn_addr):
|
|
982
|
+
"""
|
|
983
|
+
Registers a basic block as calling a function and returning somewhere.
|
|
984
|
+
|
|
985
|
+
:param call_site_addr: The address of a basic block that ends in a call.
|
|
986
|
+
:param call_target_addr: The address of the target of said call.
|
|
987
|
+
:param retn_addr: The address that said call will return to.
|
|
988
|
+
"""
|
|
989
|
+
self._call_sites[call_site_addr] = (call_target_addr, retn_addr)
|
|
990
|
+
|
|
991
|
+
def _add_endpoint(self, endpoint_node, sort):
|
|
992
|
+
"""
|
|
993
|
+
Registers an endpoint with a type of `sort`. The type can be one of the following:
|
|
994
|
+
- call: calling a function that does not return
|
|
995
|
+
- return: returning from the current function
|
|
996
|
+
- transition: a jump/branch targeting a different function
|
|
997
|
+
|
|
998
|
+
It is possible for a block to act as two different sorts of endpoints. For example, consider the following
|
|
999
|
+
block:
|
|
1000
|
+
|
|
1001
|
+
.text:0000000000024350 mov eax, 1
|
|
1002
|
+
.text:0000000000024355 lock xadd [rdi+4], eax
|
|
1003
|
+
.text:000000000002435A retn
|
|
1004
|
+
|
|
1005
|
+
VEX code:
|
|
1006
|
+
00 | ------ IMark(0x424350, 5, 0) ------
|
|
1007
|
+
01 | PUT(rax) = 0x0000000000000001
|
|
1008
|
+
02 | PUT(rip) = 0x0000000000424355
|
|
1009
|
+
03 | ------ IMark(0x424355, 5, 0) ------
|
|
1010
|
+
04 | t11 = GET:I64(rdi)
|
|
1011
|
+
05 | t10 = Add64(t11,0x0000000000000004)
|
|
1012
|
+
06 | t0 = LDle:I32(t10)
|
|
1013
|
+
07 | t2 = Add32(t0,0x00000001)
|
|
1014
|
+
08 | t(4,4294967295) = CASle(t10 :: (t0,None)->(t2,None))
|
|
1015
|
+
09 | t14 = CasCmpNE32(t4,t0)
|
|
1016
|
+
10 | if (t14) { PUT(rip) = 0x424355; Ijk_Boring }
|
|
1017
|
+
11 | PUT(cc_op) = 0x0000000000000003
|
|
1018
|
+
12 | t15 = 32Uto64(t0)
|
|
1019
|
+
13 | PUT(cc_dep1) = t15
|
|
1020
|
+
14 | PUT(cc_dep2) = 0x0000000000000001
|
|
1021
|
+
15 | t17 = 32Uto64(t0)
|
|
1022
|
+
16 | PUT(rax) = t17
|
|
1023
|
+
17 | PUT(rip) = 0x000000000042435a
|
|
1024
|
+
18 | ------ IMark(0x42435a, 1, 0) ------
|
|
1025
|
+
19 | t6 = GET:I64(rsp)
|
|
1026
|
+
20 | t7 = LDle:I64(t6)
|
|
1027
|
+
21 | t8 = Add64(t6,0x0000000000000008)
|
|
1028
|
+
22 | PUT(rsp) = t8
|
|
1029
|
+
23 | t18 = Sub64(t8,0x0000000000000080)
|
|
1030
|
+
24 | ====== AbiHint(0xt18, 128, t7) ======
|
|
1031
|
+
NEXT: PUT(rip) = t7; Ijk_Ret
|
|
1032
|
+
|
|
1033
|
+
This block acts as both a return endpoint and a transition endpoint (transitioning to 0x424355).
|
|
1034
|
+
|
|
1035
|
+
:param endpoint_node: The endpoint node.
|
|
1036
|
+
:param sort: Type of the endpoint.
|
|
1037
|
+
:return: None
|
|
1038
|
+
"""
|
|
1039
|
+
|
|
1040
|
+
self._endpoints[sort].add(endpoint_node)
|
|
1041
|
+
|
|
1042
|
+
def mark_nonreturning_calls_endpoints(self):
|
|
1043
|
+
"""
|
|
1044
|
+
Iterate through all call edges in transition graph. For each call a non-returning function, mark the source
|
|
1045
|
+
basic block as an endpoint.
|
|
1046
|
+
|
|
1047
|
+
This method should only be executed once all functions are recovered and analyzed by CFG recovery, so we know
|
|
1048
|
+
whether each function returns or not.
|
|
1049
|
+
|
|
1050
|
+
:return: None
|
|
1051
|
+
"""
|
|
1052
|
+
|
|
1053
|
+
for src, dst, data in self.transition_graph.edges(data=True):
|
|
1054
|
+
if "type" in data and data["type"] == "call":
|
|
1055
|
+
func_addr = dst.addr
|
|
1056
|
+
if func_addr in self._function_manager:
|
|
1057
|
+
function = self._function_manager[func_addr]
|
|
1058
|
+
if function.returning is False:
|
|
1059
|
+
# the target function does not return
|
|
1060
|
+
the_node = self.get_node(src.addr)
|
|
1061
|
+
if the_node is not None:
|
|
1062
|
+
self._callout_sites.add(the_node)
|
|
1063
|
+
self._add_endpoint(the_node, "call")
|
|
1064
|
+
|
|
1065
|
+
def get_call_sites(self) -> Iterable[int]:
|
|
1066
|
+
"""
|
|
1067
|
+
Gets a list of all the basic blocks that end in calls.
|
|
1068
|
+
|
|
1069
|
+
:return: A view of the addresses of the blocks that end in calls.
|
|
1070
|
+
"""
|
|
1071
|
+
return self._call_sites.keys()
|
|
1072
|
+
|
|
1073
|
+
def get_call_target(self, callsite_addr):
|
|
1074
|
+
"""
|
|
1075
|
+
Get the target of a call.
|
|
1076
|
+
|
|
1077
|
+
:param callsite_addr: The address of a basic block that ends in a call.
|
|
1078
|
+
:return: The target of said call, or None if callsite_addr is not a
|
|
1079
|
+
callsite.
|
|
1080
|
+
"""
|
|
1081
|
+
if callsite_addr in self._call_sites:
|
|
1082
|
+
return self._call_sites[callsite_addr][0]
|
|
1083
|
+
return None
|
|
1084
|
+
|
|
1085
|
+
def get_call_return(self, callsite_addr):
|
|
1086
|
+
"""
|
|
1087
|
+
Get the hypothetical return address of a call.
|
|
1088
|
+
|
|
1089
|
+
:param callsite_addr: The address of the basic block that ends in a call.
|
|
1090
|
+
:return: The likely return target of said call, or None if callsite_addr
|
|
1091
|
+
is not a callsite.
|
|
1092
|
+
"""
|
|
1093
|
+
if callsite_addr in self._call_sites:
|
|
1094
|
+
return self._call_sites[callsite_addr][1]
|
|
1095
|
+
return None
|
|
1096
|
+
|
|
1097
|
+
@property
|
|
1098
|
+
def graph(self):
|
|
1099
|
+
"""
|
|
1100
|
+
Get a local transition graph. A local transition graph is a transition graph that only contains nodes that
|
|
1101
|
+
belong to the current function. All edges, except for the edges going out from the current function or coming
|
|
1102
|
+
from outside the current function, are included.
|
|
1103
|
+
|
|
1104
|
+
The generated graph is cached in self._local_transition_graph.
|
|
1105
|
+
|
|
1106
|
+
:return: A local transition graph.
|
|
1107
|
+
:rtype: networkx.DiGraph
|
|
1108
|
+
"""
|
|
1109
|
+
|
|
1110
|
+
if self._local_transition_graph is not None:
|
|
1111
|
+
return self._local_transition_graph
|
|
1112
|
+
|
|
1113
|
+
g = networkx.classes.digraph.DiGraph()
|
|
1114
|
+
if self.startpoint is not None:
|
|
1115
|
+
g.add_node(self.startpoint)
|
|
1116
|
+
for block in self._local_blocks.values():
|
|
1117
|
+
g.add_node(block)
|
|
1118
|
+
for src, dst, data in self.transition_graph.edges(data=True):
|
|
1119
|
+
if "type" in data and (
|
|
1120
|
+
(data["type"] in ("transition", "exception") and ("outside" not in data or data["outside"] is False))
|
|
1121
|
+
or (data["type"] == "fake_return" and ("outside" not in data or data["outside"] is False))
|
|
1122
|
+
):
|
|
1123
|
+
g.add_edge(src, dst, **data)
|
|
1124
|
+
|
|
1125
|
+
self._local_transition_graph = g
|
|
1126
|
+
|
|
1127
|
+
return g
|
|
1128
|
+
|
|
1129
|
+
def graph_ex(self, exception_edges=True):
|
|
1130
|
+
"""
|
|
1131
|
+
Get a local transition graph with a custom configuration. A local transition graph is a transition graph that
|
|
1132
|
+
only contains nodes that belong to the current function. This method allows user to exclude certain types of
|
|
1133
|
+
edges together with the nodes that are only reachable through such edges, such as exception edges.
|
|
1134
|
+
|
|
1135
|
+
The generated graph is not cached.
|
|
1136
|
+
|
|
1137
|
+
:param bool exception_edges: Should exception edges and the nodes that are only reachable through exception
|
|
1138
|
+
edges be kept.
|
|
1139
|
+
:return: A local transition graph with a special configuration.
|
|
1140
|
+
:rtype: networkx.DiGraph
|
|
1141
|
+
"""
|
|
1142
|
+
|
|
1143
|
+
# graph_ex() should not impact any already cached graph
|
|
1144
|
+
old_cached_graph = self._local_transition_graph
|
|
1145
|
+
graph = self.graph
|
|
1146
|
+
self._local_transition_graph = old_cached_graph # restore the cached graph
|
|
1147
|
+
|
|
1148
|
+
# fast path
|
|
1149
|
+
if exception_edges:
|
|
1150
|
+
return graph
|
|
1151
|
+
|
|
1152
|
+
# BFS on local graph but ignoring certain types of graphs
|
|
1153
|
+
g = networkx.classes.digraph.DiGraph()
|
|
1154
|
+
queue = [n for n in graph if n is self.startpoint or graph.in_degree[n] == 0]
|
|
1155
|
+
traversed = set(queue)
|
|
1156
|
+
|
|
1157
|
+
while queue:
|
|
1158
|
+
node = queue.pop(0)
|
|
1159
|
+
|
|
1160
|
+
g.add_node(node)
|
|
1161
|
+
for _, dst, edge_data in graph.out_edges(node, data=True):
|
|
1162
|
+
edge_type = edge_data.get("type", None)
|
|
1163
|
+
if not exception_edges and edge_type == "exception":
|
|
1164
|
+
# ignore this edge
|
|
1165
|
+
continue
|
|
1166
|
+
g.add_edge(node, dst, **edge_data)
|
|
1167
|
+
|
|
1168
|
+
if dst not in traversed:
|
|
1169
|
+
traversed.add(dst)
|
|
1170
|
+
queue.append(dst)
|
|
1171
|
+
|
|
1172
|
+
return g
|
|
1173
|
+
|
|
1174
|
+
def transition_graph_ex(self, exception_edges=True):
|
|
1175
|
+
"""
|
|
1176
|
+
Get a transition graph with a custom configuration. This method allows user to exclude certain types of edges
|
|
1177
|
+
together with the nodes that are only reachable through such edges, such as exception edges.
|
|
1178
|
+
|
|
1179
|
+
The generated graph is not cached.
|
|
1180
|
+
|
|
1181
|
+
:param bool exception_edges: Should exception edges and the nodes that are only reachable through exception
|
|
1182
|
+
edges be kept.
|
|
1183
|
+
:return: A local transition graph with a special configuration.
|
|
1184
|
+
:rtype: networkx.DiGraph
|
|
1185
|
+
"""
|
|
1186
|
+
|
|
1187
|
+
graph = self.transition_graph
|
|
1188
|
+
|
|
1189
|
+
# fast path
|
|
1190
|
+
if exception_edges:
|
|
1191
|
+
return graph
|
|
1192
|
+
|
|
1193
|
+
# BFS on local graph but ignoring certain types of graphs
|
|
1194
|
+
g = networkx.classes.digraph.DiGraph()
|
|
1195
|
+
queue = [n for n in graph if n is self.startpoint or graph.in_degree[n] == 0]
|
|
1196
|
+
traversed = set(queue)
|
|
1197
|
+
|
|
1198
|
+
while queue:
|
|
1199
|
+
node = queue.pop(0)
|
|
1200
|
+
traversed.add(node)
|
|
1201
|
+
|
|
1202
|
+
g.add_node(node)
|
|
1203
|
+
for _, dst, edge_data in graph.out_edges(node, data=True):
|
|
1204
|
+
edge_type = edge_data.get("type", None)
|
|
1205
|
+
if not exception_edges and edge_type == "exception":
|
|
1206
|
+
# ignore this edge
|
|
1207
|
+
continue
|
|
1208
|
+
g.add_edge(node, dst, **edge_data)
|
|
1209
|
+
|
|
1210
|
+
if dst not in traversed:
|
|
1211
|
+
traversed.add(dst)
|
|
1212
|
+
queue.append(dst)
|
|
1213
|
+
|
|
1214
|
+
return g
|
|
1215
|
+
|
|
1216
|
+
def subgraph(self, ins_addrs):
|
|
1217
|
+
"""
|
|
1218
|
+
Generate a sub control flow graph of instruction addresses based on self.graph
|
|
1219
|
+
|
|
1220
|
+
:param iterable ins_addrs: A collection of instruction addresses that should be included in the subgraph.
|
|
1221
|
+
:return networkx.DiGraph: A subgraph.
|
|
1222
|
+
"""
|
|
1223
|
+
|
|
1224
|
+
# find all basic blocks that include those instructions
|
|
1225
|
+
blocks = []
|
|
1226
|
+
block_addr_to_insns = {}
|
|
1227
|
+
|
|
1228
|
+
for b in self._local_blocks.values():
|
|
1229
|
+
# TODO: should I call get_blocks?
|
|
1230
|
+
block = self.get_block(b.addr, size=b.size, byte_string=b.bytestr)
|
|
1231
|
+
common_insns = set(block.instruction_addrs).intersection(ins_addrs)
|
|
1232
|
+
if common_insns:
|
|
1233
|
+
blocks.append(b)
|
|
1234
|
+
block_addr_to_insns[b.addr] = sorted(common_insns)
|
|
1235
|
+
|
|
1236
|
+
# subgraph = networkx.subgraph(self.graph, blocks)
|
|
1237
|
+
subgraph = self.graph.subgraph(blocks).copy()
|
|
1238
|
+
assert isinstance(subgraph, networkx.DiGraph)
|
|
1239
|
+
g = networkx.classes.digraph.DiGraph()
|
|
1240
|
+
|
|
1241
|
+
for n in subgraph.nodes():
|
|
1242
|
+
insns = block_addr_to_insns[n.addr]
|
|
1243
|
+
|
|
1244
|
+
in_edges = subgraph.in_edges(n)
|
|
1245
|
+
# out_edges = subgraph.out_edges(n)
|
|
1246
|
+
# the first instruction address should be included
|
|
1247
|
+
if len(in_edges) > 1 and n.addr not in insns:
|
|
1248
|
+
insns = [n.addr, *insns]
|
|
1249
|
+
|
|
1250
|
+
for src, _ in in_edges:
|
|
1251
|
+
last_instr = block_addr_to_insns[src.addr][-1]
|
|
1252
|
+
g.add_edge(last_instr, insns[0])
|
|
1253
|
+
|
|
1254
|
+
for i in range(len(insns) - 1):
|
|
1255
|
+
g.add_edge(insns[i], insns[i + 1])
|
|
1256
|
+
|
|
1257
|
+
return g
|
|
1258
|
+
|
|
1259
|
+
def instruction_size(self, insn_addr):
|
|
1260
|
+
"""
|
|
1261
|
+
Get the size of the instruction specified by `insn_addr`.
|
|
1262
|
+
|
|
1263
|
+
:param int insn_addr: Address of the instruction
|
|
1264
|
+
:return int: Size of the instruction in bytes, or None if the instruction is not found.
|
|
1265
|
+
"""
|
|
1266
|
+
|
|
1267
|
+
for block in self.blocks:
|
|
1268
|
+
if insn_addr in block.instruction_addrs:
|
|
1269
|
+
index = block.instruction_addrs.index(insn_addr)
|
|
1270
|
+
if index == len(block.instruction_addrs) - 1:
|
|
1271
|
+
# the very last instruction
|
|
1272
|
+
size = block.addr + block.size - insn_addr
|
|
1273
|
+
else:
|
|
1274
|
+
size = block.instruction_addrs[index + 1] - insn_addr
|
|
1275
|
+
return size
|
|
1276
|
+
|
|
1277
|
+
return None
|
|
1278
|
+
|
|
1279
|
+
def addr_to_instruction_addr(self, addr):
|
|
1280
|
+
"""
|
|
1281
|
+
Obtain the address of the instruction that covers @addr.
|
|
1282
|
+
|
|
1283
|
+
:param int addr: An address.
|
|
1284
|
+
:return: Address of the instruction that covers @addr, or None if this addr is not covered by any
|
|
1285
|
+
instruction of this function.
|
|
1286
|
+
:rtype: int or None
|
|
1287
|
+
"""
|
|
1288
|
+
|
|
1289
|
+
# TODO: Replace the linear search with binary search
|
|
1290
|
+
for b in self.blocks:
|
|
1291
|
+
if b.addr <= addr < b.addr + b.size:
|
|
1292
|
+
# found it
|
|
1293
|
+
for i, instr_addr in enumerate(b.instruction_addrs):
|
|
1294
|
+
if (i < len(b.instruction_addrs) - 1 and instr_addr <= addr < b.instruction_addrs[i + 1]) or (
|
|
1295
|
+
i == len(b.instruction_addrs) - 1 and instr_addr <= addr
|
|
1296
|
+
):
|
|
1297
|
+
return instr_addr
|
|
1298
|
+
# Not covered by any instruction... why?
|
|
1299
|
+
return None
|
|
1300
|
+
return None
|
|
1301
|
+
|
|
1302
|
+
def dbg_print(self):
|
|
1303
|
+
"""
|
|
1304
|
+
Returns a representation of the list of basic blocks in this function.
|
|
1305
|
+
"""
|
|
1306
|
+
return "[{}]".format(", ".join((f"{n.addr:#08x}") for n in self.transition_graph.nodes()))
|
|
1307
|
+
|
|
1308
|
+
def dbg_draw(self, filename):
|
|
1309
|
+
"""
|
|
1310
|
+
Draw the graph and save it to a PNG file.
|
|
1311
|
+
"""
|
|
1312
|
+
import matplotlib.pyplot as pyplot # pylint: disable=import-error,import-outside-toplevel
|
|
1313
|
+
from networkx.drawing.nx_agraph import graphviz_layout # pylint: disable=import-error,import-outside-toplevel
|
|
1314
|
+
|
|
1315
|
+
tmp_graph = networkx.classes.digraph.DiGraph()
|
|
1316
|
+
for from_block, to_block in self.transition_graph.edges():
|
|
1317
|
+
node_a = f"{from_block.addr:#08x}"
|
|
1318
|
+
node_b = f"{to_block.addr:#08x}"
|
|
1319
|
+
if node_b in self._ret_sites:
|
|
1320
|
+
node_b += "[Ret]"
|
|
1321
|
+
if node_a in self._call_sites:
|
|
1322
|
+
node_a += "[Call]"
|
|
1323
|
+
tmp_graph.add_edge(node_a, node_b)
|
|
1324
|
+
pos = graphviz_layout(tmp_graph, prog="fdp") # pylint: disable=no-member
|
|
1325
|
+
networkx.draw(tmp_graph, pos, node_size=1200)
|
|
1326
|
+
pyplot.savefig(filename)
|
|
1327
|
+
|
|
1328
|
+
def _add_argument_register(self, reg_offset):
|
|
1329
|
+
"""
|
|
1330
|
+
Registers a register offset as being used as an argument to the function.
|
|
1331
|
+
|
|
1332
|
+
:param reg_offset: The offset of the register to register.
|
|
1333
|
+
"""
|
|
1334
|
+
if reg_offset in self._function_manager._arg_registers and reg_offset not in self._argument_registers:
|
|
1335
|
+
self._argument_registers.append(reg_offset)
|
|
1336
|
+
|
|
1337
|
+
def _add_argument_stack_variable(self, stack_var_offset):
|
|
1338
|
+
if stack_var_offset not in self._argument_stack_variables:
|
|
1339
|
+
self._argument_stack_variables.append(stack_var_offset)
|
|
1340
|
+
|
|
1341
|
+
@property
|
|
1342
|
+
def arguments(self):
|
|
1343
|
+
if self.calling_convention is None:
|
|
1344
|
+
return self._argument_registers + self._argument_stack_variables
|
|
1345
|
+
if self.prototype is None:
|
|
1346
|
+
return []
|
|
1347
|
+
return self.calling_convention.arg_locs(self.prototype)
|
|
1348
|
+
|
|
1349
|
+
@property
|
|
1350
|
+
def has_return(self):
|
|
1351
|
+
return len(self._ret_sites) > 0
|
|
1352
|
+
|
|
1353
|
+
@property
|
|
1354
|
+
def callable(self):
|
|
1355
|
+
assert self.project is not None
|
|
1356
|
+
return self.project.factory.callable(self.addr)
|
|
1357
|
+
|
|
1358
|
+
def normalize(self):
|
|
1359
|
+
"""
|
|
1360
|
+
Make sure all basic blocks in the transition graph of this function do not overlap. You will end up with a CFG
|
|
1361
|
+
that IDA Pro generates.
|
|
1362
|
+
|
|
1363
|
+
This method does not touch the CFG result. You may call CFG{Emulated, Fast}.normalize() for that matter.
|
|
1364
|
+
|
|
1365
|
+
:return: None
|
|
1366
|
+
"""
|
|
1367
|
+
assert self.project is not None
|
|
1368
|
+
|
|
1369
|
+
# let's put a check here
|
|
1370
|
+
if self.startpoint is None:
|
|
1371
|
+
# this function is empty
|
|
1372
|
+
l.debug("Unexpected error: %s does not have any blocks. normalize() fails.", repr(self))
|
|
1373
|
+
return
|
|
1374
|
+
|
|
1375
|
+
graph = self.transition_graph
|
|
1376
|
+
end_addresses: defaultdict[int, list[BlockNode]] = defaultdict(list)
|
|
1377
|
+
|
|
1378
|
+
for block in self.nodes:
|
|
1379
|
+
if isinstance(block, BlockNode):
|
|
1380
|
+
end_addr = block.addr + block.size
|
|
1381
|
+
end_addresses[end_addr].append(block)
|
|
1382
|
+
|
|
1383
|
+
while any(len(x) > 1 for x in end_addresses.values()):
|
|
1384
|
+
end_addr, all_nodes = next((end_addr, x) for (end_addr, x) in end_addresses.items() if len(x) > 1)
|
|
1385
|
+
|
|
1386
|
+
all_nodes = sorted(all_nodes, key=lambda node: node.size)
|
|
1387
|
+
smallest_node = all_nodes[0]
|
|
1388
|
+
other_nodes = all_nodes[1:]
|
|
1389
|
+
|
|
1390
|
+
is_outside_node = False
|
|
1391
|
+
if smallest_node not in graph:
|
|
1392
|
+
is_outside_node = True
|
|
1393
|
+
|
|
1394
|
+
# Break other nodes
|
|
1395
|
+
for n in other_nodes:
|
|
1396
|
+
new_size = get_real_address_if_arm(self.project.arch, smallest_node.addr) - get_real_address_if_arm(
|
|
1397
|
+
self.project.arch, n.addr
|
|
1398
|
+
)
|
|
1399
|
+
if new_size == 0:
|
|
1400
|
+
# This is the node that has the same size as the smallest one
|
|
1401
|
+
continue
|
|
1402
|
+
|
|
1403
|
+
new_end_addr = n.addr + new_size
|
|
1404
|
+
|
|
1405
|
+
# Does it already exist?
|
|
1406
|
+
new_node = None
|
|
1407
|
+
if new_end_addr in end_addresses:
|
|
1408
|
+
nodes = [i for i in end_addresses[new_end_addr] if i.addr == n.addr]
|
|
1409
|
+
if len(nodes) > 0:
|
|
1410
|
+
new_node = nodes[0]
|
|
1411
|
+
|
|
1412
|
+
if new_node is None:
|
|
1413
|
+
# TODO: Do this correctly for hook nodes
|
|
1414
|
+
# Create a new one
|
|
1415
|
+
new_node = BlockNode(n.addr, new_size, graph=graph, thumb=n.thumb)
|
|
1416
|
+
self._block_sizes[n.addr] = new_size
|
|
1417
|
+
self._addr_to_block_node[n.addr] = new_node
|
|
1418
|
+
# Put the newnode into end_addresses
|
|
1419
|
+
end_addresses[new_end_addr].append(new_node)
|
|
1420
|
+
|
|
1421
|
+
# Modify the CFG
|
|
1422
|
+
original_predecessors = list(graph.in_edges([n], data=True))
|
|
1423
|
+
original_successors = list(graph.out_edges([n], data=True))
|
|
1424
|
+
|
|
1425
|
+
for _, d, data in original_successors:
|
|
1426
|
+
ins_addr = data.get("ins_addr", None)
|
|
1427
|
+
if ins_addr is not None and ins_addr < d.addr:
|
|
1428
|
+
continue
|
|
1429
|
+
if d not in graph[smallest_node]:
|
|
1430
|
+
if d is n:
|
|
1431
|
+
graph.add_edge(smallest_node, new_node, **data)
|
|
1432
|
+
else:
|
|
1433
|
+
graph.add_edge(smallest_node, d, **data)
|
|
1434
|
+
|
|
1435
|
+
for p, _, _ in original_predecessors:
|
|
1436
|
+
graph.remove_edge(p, n)
|
|
1437
|
+
graph.remove_node(n)
|
|
1438
|
+
|
|
1439
|
+
# update local_blocks
|
|
1440
|
+
if n.addr in self._local_blocks and self._local_blocks[n.addr].size != new_node.size:
|
|
1441
|
+
del self._local_blocks[n.addr]
|
|
1442
|
+
self._local_blocks[n.addr] = new_node
|
|
1443
|
+
|
|
1444
|
+
# update block_cache and block_sizes
|
|
1445
|
+
if n.addr in self._block_sizes and self._block_sizes[n.addr] != new_node.size:
|
|
1446
|
+
# the cache needs updating
|
|
1447
|
+
self._block_sizes[n.addr] = new_node.size
|
|
1448
|
+
|
|
1449
|
+
for p, _, data in original_predecessors:
|
|
1450
|
+
if p not in other_nodes:
|
|
1451
|
+
graph.add_edge(p, new_node, **data)
|
|
1452
|
+
|
|
1453
|
+
# We should find the correct successor
|
|
1454
|
+
new_successors = [i for i in all_nodes if i.addr == smallest_node.addr]
|
|
1455
|
+
if new_successors:
|
|
1456
|
+
new_successor = new_successors[0]
|
|
1457
|
+
new_ins_addrs = self.project.factory.block(new_node.addr, size=new_node.size).instruction_addrs
|
|
1458
|
+
if self.project.arch.branch_delay_slot and len(new_ins_addrs) >= 2:
|
|
1459
|
+
new_ins_addr = new_ins_addrs[-2]
|
|
1460
|
+
elif len(new_ins_addrs) >= 1:
|
|
1461
|
+
new_ins_addr = new_ins_addrs[-1]
|
|
1462
|
+
else:
|
|
1463
|
+
# the new node is somehow not decode-able
|
|
1464
|
+
new_ins_addr = new_node.addr + new_node.size - 1
|
|
1465
|
+
graph.add_edge(
|
|
1466
|
+
new_node,
|
|
1467
|
+
new_successor,
|
|
1468
|
+
type="transition",
|
|
1469
|
+
outside=is_outside_node,
|
|
1470
|
+
ins_addr=new_ins_addr,
|
|
1471
|
+
)
|
|
1472
|
+
else:
|
|
1473
|
+
# We gotta create a new one
|
|
1474
|
+
l.error("normalize(): Please report it to Fish.")
|
|
1475
|
+
|
|
1476
|
+
# update endpoints
|
|
1477
|
+
for sortset in self._endpoints.values():
|
|
1478
|
+
if n in sortset:
|
|
1479
|
+
sortset.remove(n)
|
|
1480
|
+
sortset.add(smallest_node)
|
|
1481
|
+
|
|
1482
|
+
end_addresses[end_addr] = [smallest_node]
|
|
1483
|
+
|
|
1484
|
+
# Rebuild startpoint
|
|
1485
|
+
if self.startpoint.size != self._block_sizes[self.startpoint.addr]:
|
|
1486
|
+
self.startpoint = self.get_node(self.startpoint.addr)
|
|
1487
|
+
|
|
1488
|
+
# Clear the cache
|
|
1489
|
+
self._local_transition_graph = None
|
|
1490
|
+
|
|
1491
|
+
self.normalized = True
|
|
1492
|
+
|
|
1493
|
+
def find_declaration(self, ignore_binary_name: bool = False, binary_name_hint: str | None = None) -> bool:
|
|
1494
|
+
"""
|
|
1495
|
+
Find the most likely function declaration from the embedded collection of prototypes, set it to self.prototype,
|
|
1496
|
+
and update self.calling_convention with the declaration.
|
|
1497
|
+
|
|
1498
|
+
:param ignore_binary_name: Do not rely on the executable or library where the function belongs to determine
|
|
1499
|
+
its source library. This is useful when working on statically linked binaries
|
|
1500
|
+
(because all functions will belong to the main executable). We will search for all
|
|
1501
|
+
libraries in angr to find the first declaration match.
|
|
1502
|
+
:param binary_name_hint: Substring of the library name where this function might be originally coming from.
|
|
1503
|
+
Useful for FLIRT-identified functions in statically linked binaries.
|
|
1504
|
+
:return: True if a declaration is found and self.prototype and self.calling_convention are
|
|
1505
|
+
updated. False if we fail to find a matching function declaration, in which case
|
|
1506
|
+
self.prototype or self.calling_convention will be kept untouched.
|
|
1507
|
+
"""
|
|
1508
|
+
|
|
1509
|
+
if not ignore_binary_name:
|
|
1510
|
+
# determine the library name
|
|
1511
|
+
if not self.is_plt:
|
|
1512
|
+
binary_name = self.binary_name
|
|
1513
|
+
if binary_name not in SIM_LIBRARIES:
|
|
1514
|
+
return False
|
|
1515
|
+
else:
|
|
1516
|
+
binary_name = None
|
|
1517
|
+
# PLT entries must have the same declaration as their jump targets
|
|
1518
|
+
# Try to determine which library this PLT entry will jump to
|
|
1519
|
+
edges = self.transition_graph.edges()
|
|
1520
|
+
if len(edges) == 0:
|
|
1521
|
+
return False
|
|
1522
|
+
node = next(iter(edges))[1]
|
|
1523
|
+
if len(edges) == 1 and (type(node) is HookNode or type(node) is SyscallNode):
|
|
1524
|
+
target = node.addr
|
|
1525
|
+
if target in self._function_manager:
|
|
1526
|
+
target_func = self._function_manager[target]
|
|
1527
|
+
binary_name = target_func.binary_name
|
|
1528
|
+
|
|
1529
|
+
# cannot determine the binary name. since we are forced to respect binary name, we give up in this case.
|
|
1530
|
+
if binary_name is None:
|
|
1531
|
+
return False
|
|
1532
|
+
|
|
1533
|
+
lib = SIM_LIBRARIES.get(binary_name, None)
|
|
1534
|
+
libraries = set()
|
|
1535
|
+
if lib is not None:
|
|
1536
|
+
libraries.update(lib)
|
|
1537
|
+
|
|
1538
|
+
else:
|
|
1539
|
+
# try all libraries or all libraries that match the given library name hint
|
|
1540
|
+
libraries = set()
|
|
1541
|
+
for lib_name, libs in SIM_LIBRARIES.items():
|
|
1542
|
+
# TODO: Add support for syscall libraries. Note that syscall libraries have different function
|
|
1543
|
+
# prototypes for .has_prototype() and .get_prototype()...
|
|
1544
|
+
for lib in libs:
|
|
1545
|
+
if not isinstance(lib, SimSyscallLibrary):
|
|
1546
|
+
if binary_name_hint:
|
|
1547
|
+
if binary_name_hint.lower() in lib_name.lower():
|
|
1548
|
+
libraries.add(lib)
|
|
1549
|
+
else:
|
|
1550
|
+
libraries.add(lib)
|
|
1551
|
+
|
|
1552
|
+
if not libraries:
|
|
1553
|
+
return False
|
|
1554
|
+
|
|
1555
|
+
name_variants = [self.name]
|
|
1556
|
+
# remove "_" prefixes
|
|
1557
|
+
if self.name.startswith("_"):
|
|
1558
|
+
name_variants.append(self.name[1:])
|
|
1559
|
+
if self.name.startswith("__"):
|
|
1560
|
+
name_variants.append(self.name[2:])
|
|
1561
|
+
# special handling for libc
|
|
1562
|
+
if self.name.startswith("__libc_"):
|
|
1563
|
+
name_variants.append(self.name[7:])
|
|
1564
|
+
|
|
1565
|
+
for library in libraries:
|
|
1566
|
+
for name in name_variants:
|
|
1567
|
+
if isinstance(library, SimSyscallLibrary):
|
|
1568
|
+
# FIXME: we don't support getting declaration from a syscall library yet. we don't have the concept
|
|
1569
|
+
# of abi at this point.
|
|
1570
|
+
continue
|
|
1571
|
+
if not library.has_prototype(name):
|
|
1572
|
+
continue
|
|
1573
|
+
|
|
1574
|
+
proto = library.get_prototype(name)
|
|
1575
|
+
if self.project is None:
|
|
1576
|
+
# we need to get arch from self.project
|
|
1577
|
+
l.warning(
|
|
1578
|
+
"Function %s does not have .project set. A possible prototype is found, but we cannot set it "
|
|
1579
|
+
"without .project.arch."
|
|
1580
|
+
)
|
|
1581
|
+
return False
|
|
1582
|
+
self.prototype = proto.with_arch(self.project.arch)
|
|
1583
|
+
self.prototype_libname = library.name
|
|
1584
|
+
self.returning = library.is_returning(name)
|
|
1585
|
+
|
|
1586
|
+
# update self.calling_convention if necessary
|
|
1587
|
+
if self.calling_convention is None:
|
|
1588
|
+
if self.project.arch.name in library.default_ccs and self.is_syscall is False:
|
|
1589
|
+
self.calling_convention = library.default_ccs[self.project.arch.name](self.project.arch)
|
|
1590
|
+
elif self.project.arch.name in DEFAULT_CC:
|
|
1591
|
+
cc_cls = default_cc(
|
|
1592
|
+
self.project.arch.name,
|
|
1593
|
+
platform=self.project.simos.name if self.project.simos is not None else None,
|
|
1594
|
+
syscall=self.is_syscall is True,
|
|
1595
|
+
)
|
|
1596
|
+
if cc_cls is not None:
|
|
1597
|
+
self.calling_convention = cc_cls(self.project.arch)
|
|
1598
|
+
|
|
1599
|
+
return True
|
|
1600
|
+
|
|
1601
|
+
return False
|
|
1602
|
+
|
|
1603
|
+
@staticmethod
|
|
1604
|
+
def _addr_to_funcloc(addr):
|
|
1605
|
+
# FIXME
|
|
1606
|
+
if isinstance(addr, tuple):
|
|
1607
|
+
return addr[0]
|
|
1608
|
+
# int, long
|
|
1609
|
+
return addr
|
|
1610
|
+
|
|
1611
|
+
def is_rust_function(self):
|
|
1612
|
+
ast = pydemumble.demangle(self.name)
|
|
1613
|
+
if ast:
|
|
1614
|
+
nodes = ast.split("::")
|
|
1615
|
+
if len(nodes) >= 2:
|
|
1616
|
+
last_node = nodes[-1]
|
|
1617
|
+
return (
|
|
1618
|
+
len(last_node) == 17
|
|
1619
|
+
and last_node.startswith("h")
|
|
1620
|
+
and all(c in "0123456789abcdef" for c in last_node[1:])
|
|
1621
|
+
)
|
|
1622
|
+
return False
|
|
1623
|
+
|
|
1624
|
+
@staticmethod
|
|
1625
|
+
def _rust_fmt_node(node):
|
|
1626
|
+
result = []
|
|
1627
|
+
rest = node
|
|
1628
|
+
if rest.startswith("_$"):
|
|
1629
|
+
rest = rest[1:]
|
|
1630
|
+
while True:
|
|
1631
|
+
if rest.startswith("."):
|
|
1632
|
+
if len(rest) > 1 and rest[1] == ".":
|
|
1633
|
+
result.append("::")
|
|
1634
|
+
rest = rest[2:]
|
|
1635
|
+
else:
|
|
1636
|
+
result.append(".")
|
|
1637
|
+
rest = rest[1:]
|
|
1638
|
+
elif rest.startswith("$"):
|
|
1639
|
+
if "$" in rest[1:]:
|
|
1640
|
+
escape, rest = rest[1:].split("$", 1)
|
|
1641
|
+
else:
|
|
1642
|
+
break
|
|
1643
|
+
|
|
1644
|
+
unescaped = {"SP": "@", "BP": "*", "RF": "&", "LT": "<", "GT": ">", "LP": "(", "RP": ")", "C": ","}.get(
|
|
1645
|
+
escape
|
|
1646
|
+
)
|
|
1647
|
+
|
|
1648
|
+
if unescaped is None and escape.startswith("u"):
|
|
1649
|
+
digits = escape[1:]
|
|
1650
|
+
if all(c in "0123456789abcdef" for c in digits):
|
|
1651
|
+
c = chr(int(digits, 16))
|
|
1652
|
+
if ord(c) >= 32 and ord(c) != 127:
|
|
1653
|
+
result.append(c)
|
|
1654
|
+
continue
|
|
1655
|
+
if unescaped:
|
|
1656
|
+
result.append(unescaped)
|
|
1657
|
+
else:
|
|
1658
|
+
break
|
|
1659
|
+
else:
|
|
1660
|
+
idx = min((rest.find(c) for c in "$." if c in rest), default=len(rest))
|
|
1661
|
+
result.append(rest[:idx])
|
|
1662
|
+
rest = rest[idx:]
|
|
1663
|
+
if not rest:
|
|
1664
|
+
break
|
|
1665
|
+
return "".join(result)
|
|
1666
|
+
|
|
1667
|
+
@property
|
|
1668
|
+
def demangled_name(self):
|
|
1669
|
+
ast = pydemumble.demangle(self.name).strip()
|
|
1670
|
+
if self.is_rust_function():
|
|
1671
|
+
nodes = ast.split("::")[:-1]
|
|
1672
|
+
ast = "::".join([Function._rust_fmt_node(node) for node in nodes])
|
|
1673
|
+
return ast if ast else self.name
|
|
1674
|
+
|
|
1675
|
+
@property
|
|
1676
|
+
def short_name(self):
|
|
1677
|
+
if self.is_rust_function():
|
|
1678
|
+
ast = pydemumble.demangle(self.name)
|
|
1679
|
+
return Function._rust_fmt_node(ast.split("::")[-2])
|
|
1680
|
+
func_name, meta = get_cpp_function_name_and_metadata(self.demangled_name)
|
|
1681
|
+
if meta["ctor"]:
|
|
1682
|
+
return "<ctor>"
|
|
1683
|
+
if meta["dtor"]:
|
|
1684
|
+
return "<dtor>"
|
|
1685
|
+
if "<" and ">" in func_name:
|
|
1686
|
+
# remove template arguments
|
|
1687
|
+
depth = 0
|
|
1688
|
+
new_name_chars = []
|
|
1689
|
+
suffix = ""
|
|
1690
|
+
if func_name.endswith(("<<", ">>")):
|
|
1691
|
+
suffix = func_name[-2:]
|
|
1692
|
+
func_name = func_name[:-2]
|
|
1693
|
+
for c in func_name:
|
|
1694
|
+
if c == "<":
|
|
1695
|
+
depth += 1
|
|
1696
|
+
elif c == ">":
|
|
1697
|
+
depth -= 1
|
|
1698
|
+
else:
|
|
1699
|
+
if depth == 0:
|
|
1700
|
+
new_name_chars.append(c)
|
|
1701
|
+
func_name = "".join(new_name_chars) + suffix
|
|
1702
|
+
return func_name.split("::")[-1] if "::" in func_name else func_name
|
|
1703
|
+
|
|
1704
|
+
def get_unambiguous_name(self, display_name: str | None = None) -> str:
|
|
1705
|
+
"""
|
|
1706
|
+
Get a disambiguated function name.
|
|
1707
|
+
|
|
1708
|
+
:param display_name: Name to display, otherwise the function name.
|
|
1709
|
+
:return: The function name in the form:
|
|
1710
|
+
::<name> when the function binary is the main object.
|
|
1711
|
+
::<obj>::<name> when the function binary is not the main object.
|
|
1712
|
+
::<addr>::<name> when the function binary is an unnamed non-main object, or when multiple functions with
|
|
1713
|
+
the same name are defined in the function binary.
|
|
1714
|
+
"""
|
|
1715
|
+
assert self.project is not None
|
|
1716
|
+
must_disambiguate_by_addr = self.binary is not self.project.loader.main_object and self.binary_name is None
|
|
1717
|
+
|
|
1718
|
+
# If there are multiple functions with the same name in the same object, disambiguate by address
|
|
1719
|
+
if not must_disambiguate_by_addr:
|
|
1720
|
+
for func in self._function_manager.get_by_name(self.name):
|
|
1721
|
+
if func is not self and func.binary is self.binary:
|
|
1722
|
+
must_disambiguate_by_addr = True
|
|
1723
|
+
break
|
|
1724
|
+
|
|
1725
|
+
separator = "::"
|
|
1726
|
+
n = separator
|
|
1727
|
+
if must_disambiguate_by_addr:
|
|
1728
|
+
n += hex(self.addr) + separator
|
|
1729
|
+
elif self.binary is not self.project.loader.main_object and self.binary_name is not None:
|
|
1730
|
+
n += self.binary_name + separator
|
|
1731
|
+
return n + (display_name or self.name)
|
|
1732
|
+
|
|
1733
|
+
def apply_definition(self, definition: str, calling_convention: SimCC | type[SimCC] | None = None) -> None:
|
|
1734
|
+
assert self.project is not None
|
|
1735
|
+
if not definition.endswith(";"):
|
|
1736
|
+
definition += ";"
|
|
1737
|
+
func_def = parse_defns(definition, arch=self.project.arch)
|
|
1738
|
+
if len(func_def.keys()) > 1:
|
|
1739
|
+
raise Exception(f"Too many definitions: {list(func_def.keys())} ")
|
|
1740
|
+
|
|
1741
|
+
name: str
|
|
1742
|
+
ty: SimTypeFunction
|
|
1743
|
+
name, ty = func_def.popitem()
|
|
1744
|
+
self.name = name
|
|
1745
|
+
self.prototype = ty.with_arch(self.project.arch)
|
|
1746
|
+
# setup the calling convention
|
|
1747
|
+
# If a SimCC object is passed assume that this is sane and just use it
|
|
1748
|
+
if isinstance(calling_convention, SimCC):
|
|
1749
|
+
self.calling_convention = calling_convention
|
|
1750
|
+
|
|
1751
|
+
# If it is a subclass of SimCC we can instantiate it
|
|
1752
|
+
elif isinstance(calling_convention, type) and issubclass(calling_convention, SimCC):
|
|
1753
|
+
self.calling_convention = calling_convention(self.project.arch)
|
|
1754
|
+
|
|
1755
|
+
# If none is specified default to something
|
|
1756
|
+
elif calling_convention is None:
|
|
1757
|
+
self.calling_convention = self.project.factory.cc()
|
|
1758
|
+
|
|
1759
|
+
else:
|
|
1760
|
+
raise TypeError("calling_convention has to be one of: [SimCC, type(SimCC), None]")
|
|
1761
|
+
|
|
1762
|
+
def functions_reachable(self) -> set[Function]:
|
|
1763
|
+
"""
|
|
1764
|
+
:return: The set of all functions that can be reached from the function represented by self.
|
|
1765
|
+
"""
|
|
1766
|
+
called = set()
|
|
1767
|
+
|
|
1768
|
+
def _find_called(function_address):
|
|
1769
|
+
successors = set(self._function_manager.callgraph.successors(function_address)) - called
|
|
1770
|
+
for s in successors:
|
|
1771
|
+
called.add(s)
|
|
1772
|
+
_find_called(s)
|
|
1773
|
+
|
|
1774
|
+
_find_called(self.addr)
|
|
1775
|
+
return {self._function_manager.function(a) for a in called}
|
|
1776
|
+
|
|
1777
|
+
def holes(self, min_size: int = 8) -> int:
|
|
1778
|
+
"""
|
|
1779
|
+
Find the number of non-consecutive areas in the function that are at least `min_size` bytes large.
|
|
1780
|
+
"""
|
|
1781
|
+
|
|
1782
|
+
block_addrs = sorted(self._local_block_addrs)
|
|
1783
|
+
if not block_addrs:
|
|
1784
|
+
return 0
|
|
1785
|
+
holes = 0
|
|
1786
|
+
for i, addr in enumerate(block_addrs):
|
|
1787
|
+
if i == len(block_addrs) - 1:
|
|
1788
|
+
break
|
|
1789
|
+
next_addr = block_addrs[i + 1]
|
|
1790
|
+
if next_addr > addr + self._block_sizes[addr] and next_addr - (addr + self._block_sizes[addr]) >= min_size:
|
|
1791
|
+
holes += 1
|
|
1792
|
+
return holes
|
|
1793
|
+
|
|
1794
|
+
def copy(self):
|
|
1795
|
+
func = Function(self._function_manager, self.addr, name=self.name, syscall=self.is_syscall)
|
|
1796
|
+
func.transition_graph = networkx.DiGraph(self.transition_graph)
|
|
1797
|
+
func.normalized = self.normalized
|
|
1798
|
+
func._ret_sites = self._ret_sites.copy()
|
|
1799
|
+
func._jumpout_sites = self._jumpout_sites.copy()
|
|
1800
|
+
func._retout_sites = self._retout_sites.copy()
|
|
1801
|
+
func._endpoints = self._endpoints.copy()
|
|
1802
|
+
func._call_sites = self._call_sites.copy()
|
|
1803
|
+
func._project = self._project
|
|
1804
|
+
func.previous_names = list(self.previous_names)
|
|
1805
|
+
func.is_plt = self.is_plt
|
|
1806
|
+
func.is_simprocedure = self.is_simprocedure
|
|
1807
|
+
func.binary_name = self.binary_name
|
|
1808
|
+
func.bp_on_stack = self.bp_on_stack
|
|
1809
|
+
func.retaddr_on_stack = self.retaddr_on_stack
|
|
1810
|
+
func.sp_delta = self.sp_delta
|
|
1811
|
+
func.calling_convention = self.calling_convention
|
|
1812
|
+
func.prototype = self.prototype
|
|
1813
|
+
func._returning = self._returning
|
|
1814
|
+
func.is_alignment = self.is_alignment
|
|
1815
|
+
func.startpoint = self.startpoint
|
|
1816
|
+
func._addr_to_block_node = self._addr_to_block_node.copy()
|
|
1817
|
+
func._block_sizes = self._block_sizes.copy()
|
|
1818
|
+
func._local_blocks = self._local_blocks.copy()
|
|
1819
|
+
func._local_block_addrs = self._local_block_addrs.copy()
|
|
1820
|
+
func.info = self.info.copy()
|
|
1821
|
+
func.tags = self.tags
|
|
1822
|
+
|
|
1823
|
+
return func
|
|
1824
|
+
|
|
1825
|
+
def pp(self, **kwargs):
|
|
1826
|
+
"""
|
|
1827
|
+
Pretty-print the function disassembly.
|
|
1828
|
+
"""
|
|
1829
|
+
assert self.project is not None
|
|
1830
|
+
print(self.project.analyses.Disassembly(self).render(**kwargs))
|