angr 9.2.192__cp311-cp311-macosx_10_12_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- angr/__init__.py +366 -0
- angr/__main__.py +182 -0
- angr/ail_callable.py +79 -0
- angr/ailment/__init__.py +83 -0
- angr/ailment/block.py +88 -0
- angr/ailment/block_walker.py +856 -0
- angr/ailment/constant.py +3 -0
- angr/ailment/converter_common.py +11 -0
- angr/ailment/converter_pcode.py +648 -0
- angr/ailment/converter_vex.py +829 -0
- angr/ailment/expression.py +1655 -0
- angr/ailment/manager.py +34 -0
- angr/ailment/statement.py +973 -0
- angr/ailment/tagged_object.py +58 -0
- angr/ailment/utils.py +114 -0
- angr/analyses/__init__.py +117 -0
- angr/analyses/analysis.py +429 -0
- angr/analyses/backward_slice.py +686 -0
- angr/analyses/binary_optimizer.py +670 -0
- angr/analyses/bindiff.py +1512 -0
- angr/analyses/boyscout.py +76 -0
- angr/analyses/callee_cleanup_finder.py +74 -0
- angr/analyses/calling_convention/__init__.py +6 -0
- angr/analyses/calling_convention/calling_convention.py +1113 -0
- angr/analyses/calling_convention/fact_collector.py +647 -0
- angr/analyses/calling_convention/utils.py +60 -0
- angr/analyses/cdg.py +189 -0
- angr/analyses/cfg/__init__.py +23 -0
- angr/analyses/cfg/cfb.py +451 -0
- angr/analyses/cfg/cfg.py +74 -0
- angr/analyses/cfg/cfg_arch_options.py +95 -0
- angr/analyses/cfg/cfg_base.py +2954 -0
- angr/analyses/cfg/cfg_emulated.py +3451 -0
- angr/analyses/cfg/cfg_fast.py +5431 -0
- angr/analyses/cfg/cfg_fast_soot.py +662 -0
- angr/analyses/cfg/cfg_job_base.py +203 -0
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +30 -0
- angr/analyses/cfg/indirect_jump_resolvers/aarch64_macho_got.py +77 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
- angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +159 -0
- angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +339 -0
- angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +82 -0
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2490 -0
- angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
- angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
- angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
- angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
- angr/analyses/cfg_slice_to_sink/graph.py +87 -0
- angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
- angr/analyses/class_identifier.py +63 -0
- angr/analyses/code_tagging.py +123 -0
- angr/analyses/codecave.py +77 -0
- angr/analyses/complete_calling_conventions.py +475 -0
- angr/analyses/congruency_check.py +377 -0
- angr/analyses/data_dep/__init__.py +16 -0
- angr/analyses/data_dep/data_dependency_analysis.py +595 -0
- angr/analyses/data_dep/dep_nodes.py +171 -0
- angr/analyses/data_dep/sim_act_location.py +49 -0
- angr/analyses/datagraph_meta.py +105 -0
- angr/analyses/ddg.py +1670 -0
- angr/analyses/decompiler/__init__.py +41 -0
- angr/analyses/decompiler/ail_simplifier.py +2246 -0
- angr/analyses/decompiler/ailgraph_walker.py +49 -0
- angr/analyses/decompiler/block_io_finder.py +302 -0
- angr/analyses/decompiler/block_similarity.py +199 -0
- angr/analyses/decompiler/block_simplifier.py +397 -0
- angr/analyses/decompiler/callsite_maker.py +579 -0
- angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +618 -0
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +24 -0
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +354 -0
- angr/analyses/decompiler/clinic.py +3662 -0
- angr/analyses/decompiler/condition_processor.py +1323 -0
- angr/analyses/decompiler/counters/__init__.py +16 -0
- angr/analyses/decompiler/counters/boolean_counter.py +27 -0
- angr/analyses/decompiler/counters/call_counter.py +77 -0
- angr/analyses/decompiler/counters/expression_counters.py +77 -0
- angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
- angr/analyses/decompiler/decompilation_cache.py +54 -0
- angr/analyses/decompiler/decompilation_options.py +317 -0
- angr/analyses/decompiler/decompiler.py +796 -0
- angr/analyses/decompiler/dephication/__init__.py +6 -0
- angr/analyses/decompiler/dephication/dephication_base.py +100 -0
- angr/analyses/decompiler/dephication/graph_dephication.py +70 -0
- angr/analyses/decompiler/dephication/graph_rewriting.py +112 -0
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +357 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +528 -0
- angr/analyses/decompiler/dephication/seqnode_dephication.py +156 -0
- angr/analyses/decompiler/dirty_rewriters/__init__.py +7 -0
- angr/analyses/decompiler/dirty_rewriters/amd64_dirty.py +74 -0
- angr/analyses/decompiler/dirty_rewriters/rewriter_base.py +27 -0
- angr/analyses/decompiler/empty_node_remover.py +212 -0
- angr/analyses/decompiler/expression_narrower.py +290 -0
- angr/analyses/decompiler/goto_manager.py +112 -0
- angr/analyses/decompiler/graph_region.py +441 -0
- angr/analyses/decompiler/jump_target_collector.py +37 -0
- angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
- angr/analyses/decompiler/label_collector.py +32 -0
- angr/analyses/decompiler/node_replacer.py +42 -0
- angr/analyses/decompiler/notes/__init__.py +9 -0
- angr/analyses/decompiler/notes/decompilation_note.py +48 -0
- angr/analyses/decompiler/notes/deobfuscated_strings.py +56 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +164 -0
- angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
- angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
- angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +211 -0
- angr/analyses/decompiler/optimization_passes/const_derefs.py +127 -0
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
- angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1221 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +236 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_eval.py +186 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +502 -0
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +138 -0
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +618 -0
- angr/analyses/decompiler/optimization_passes/inlined_strlen_simplifier.py +274 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +337 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +939 -0
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +710 -0
- angr/analyses/decompiler/optimization_passes/peephole_simplifier.py +75 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +263 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier_adv.py +198 -0
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +632 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +166 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
- angr/analyses/decompiler/optimization_passes/static_vvar_rewriter.py +336 -0
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +166 -0
- angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
- angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +477 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
- angr/analyses/decompiler/peephole_optimizations/__init__.py +136 -0
- angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
- angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
- angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
- angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
- angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +182 -0
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
- angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +436 -0
- angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memcpy.py +78 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memset.py +262 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +217 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +106 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy.py +256 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy_consolidation.py +296 -0
- angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
- angr/analyses/decompiler/peephole_optimizations/modulo_simplifier.py +89 -0
- angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
- angr/analyses/decompiler/peephole_optimizations/optimized_div_simplifier.py +356 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
- angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +125 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +273 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_derefs.py +21 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +115 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
- angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +143 -0
- angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
- angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
- angr/analyses/decompiler/presets/__init__.py +22 -0
- angr/analyses/decompiler/presets/basic.py +36 -0
- angr/analyses/decompiler/presets/fast.py +66 -0
- angr/analyses/decompiler/presets/full.py +76 -0
- angr/analyses/decompiler/presets/malware.py +70 -0
- angr/analyses/decompiler/presets/preset.py +37 -0
- angr/analyses/decompiler/redundant_label_remover.py +141 -0
- angr/analyses/decompiler/region_identifier.py +1319 -0
- angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
- angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +838 -0
- angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
- angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
- angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
- angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +270 -0
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
- angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
- angr/analyses/decompiler/region_walker.py +24 -0
- angr/analyses/decompiler/return_maker.py +72 -0
- angr/analyses/decompiler/semantic_naming/__init__.py +37 -0
- angr/analyses/decompiler/semantic_naming/array_index_naming.py +196 -0
- angr/analyses/decompiler/semantic_naming/boolean_naming.py +264 -0
- angr/analyses/decompiler/semantic_naming/call_result_naming.py +220 -0
- angr/analyses/decompiler/semantic_naming/naming_base.py +166 -0
- angr/analyses/decompiler/semantic_naming/orchestrator.py +107 -0
- angr/analyses/decompiler/semantic_naming/pointer_naming.py +334 -0
- angr/analyses/decompiler/semantic_naming/region_loop_counter_naming.py +246 -0
- angr/analyses/decompiler/semantic_naming/size_naming.py +137 -0
- angr/analyses/decompiler/seq_to_blocks.py +20 -0
- angr/analyses/decompiler/sequence_walker.py +261 -0
- angr/analyses/decompiler/ssailification/__init__.py +4 -0
- angr/analyses/decompiler/ssailification/rewriting.py +451 -0
- angr/analyses/decompiler/ssailification/rewriting_engine.py +1091 -0
- angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
- angr/analyses/decompiler/ssailification/ssailification.py +283 -0
- angr/analyses/decompiler/ssailification/traversal.py +127 -0
- angr/analyses/decompiler/ssailification/traversal_engine.py +323 -0
- angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
- angr/analyses/decompiler/stack_item.py +36 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
- angr/analyses/decompiler/structured_codegen/base.py +193 -0
- angr/analyses/decompiler/structured_codegen/c.py +4257 -0
- angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
- angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
- angr/analyses/decompiler/structuring/__init__.py +30 -0
- angr/analyses/decompiler/structuring/dream.py +1217 -0
- angr/analyses/decompiler/structuring/phoenix.py +3636 -0
- angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
- angr/analyses/decompiler/structuring/sailr.py +120 -0
- angr/analyses/decompiler/structuring/structurer_base.py +1140 -0
- angr/analyses/decompiler/structuring/structurer_nodes.py +442 -0
- angr/analyses/decompiler/utils.py +1224 -0
- angr/analyses/deobfuscator/__init__.py +23 -0
- angr/analyses/deobfuscator/api_obf_finder.py +333 -0
- angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +80 -0
- angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
- angr/analyses/deobfuscator/data_transformation_embedder.py +633 -0
- angr/analyses/deobfuscator/hash_lookup_api_deobfuscator.py +156 -0
- angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
- angr/analyses/deobfuscator/scope_ops_analyzer.py +68 -0
- angr/analyses/deobfuscator/string_obf_finder.py +983 -0
- angr/analyses/deobfuscator/string_obf_opt_passes.py +136 -0
- angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
- angr/analyses/disassembly.py +1351 -0
- angr/analyses/disassembly_utils.py +101 -0
- angr/analyses/dominance_frontier.py +57 -0
- angr/analyses/fcp/__init__.py +4 -0
- angr/analyses/fcp/fcp.py +427 -0
- angr/analyses/find_objects_static.py +205 -0
- angr/analyses/flirt/__init__.py +47 -0
- angr/analyses/flirt/consts.py +160 -0
- angr/analyses/flirt/flirt.py +249 -0
- angr/analyses/flirt/flirt_function.py +20 -0
- angr/analyses/flirt/flirt_matcher.py +352 -0
- angr/analyses/flirt/flirt_module.py +32 -0
- angr/analyses/flirt/flirt_node.py +23 -0
- angr/analyses/flirt/flirt_sig.py +359 -0
- angr/analyses/flirt/flirt_utils.py +31 -0
- angr/analyses/forward_analysis/__init__.py +12 -0
- angr/analyses/forward_analysis/forward_analysis.py +619 -0
- angr/analyses/forward_analysis/job_info.py +64 -0
- angr/analyses/forward_analysis/visitors/__init__.py +14 -0
- angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
- angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
- angr/analyses/forward_analysis/visitors/graph.py +242 -0
- angr/analyses/forward_analysis/visitors/loop.py +29 -0
- angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
- angr/analyses/identifier/__init__.py +5 -0
- angr/analyses/identifier/custom_callable.py +137 -0
- angr/analyses/identifier/errors.py +10 -0
- angr/analyses/identifier/func.py +60 -0
- angr/analyses/identifier/functions/__init__.py +37 -0
- angr/analyses/identifier/functions/atoi.py +73 -0
- angr/analyses/identifier/functions/based_atoi.py +125 -0
- angr/analyses/identifier/functions/fdprintf.py +123 -0
- angr/analyses/identifier/functions/free.py +64 -0
- angr/analyses/identifier/functions/int2str.py +287 -0
- angr/analyses/identifier/functions/malloc.py +111 -0
- angr/analyses/identifier/functions/memcmp.py +67 -0
- angr/analyses/identifier/functions/memcpy.py +89 -0
- angr/analyses/identifier/functions/memset.py +43 -0
- angr/analyses/identifier/functions/printf.py +123 -0
- angr/analyses/identifier/functions/recv_until.py +312 -0
- angr/analyses/identifier/functions/skip_calloc.py +73 -0
- angr/analyses/identifier/functions/skip_realloc.py +97 -0
- angr/analyses/identifier/functions/skip_recv_n.py +105 -0
- angr/analyses/identifier/functions/snprintf.py +112 -0
- angr/analyses/identifier/functions/sprintf.py +116 -0
- angr/analyses/identifier/functions/strcasecmp.py +33 -0
- angr/analyses/identifier/functions/strcmp.py +113 -0
- angr/analyses/identifier/functions/strcpy.py +43 -0
- angr/analyses/identifier/functions/strlen.py +27 -0
- angr/analyses/identifier/functions/strncmp.py +104 -0
- angr/analyses/identifier/functions/strncpy.py +65 -0
- angr/analyses/identifier/functions/strtol.py +89 -0
- angr/analyses/identifier/identify.py +825 -0
- angr/analyses/identifier/runner.py +360 -0
- angr/analyses/init_finder.py +289 -0
- angr/analyses/loop_analysis/__init__.py +4 -0
- angr/analyses/loop_analysis/loop_analysis.py +464 -0
- angr/analyses/loop_analysis.py +349 -0
- angr/analyses/loop_unroller/__init__.py +4 -0
- angr/analyses/loop_unroller/loop_unroller.py +222 -0
- angr/analyses/loopfinder.py +171 -0
- angr/analyses/outliner/__init__.py +7 -0
- angr/analyses/outliner/outliner.py +402 -0
- angr/analyses/patchfinder.py +137 -0
- angr/analyses/pathfinder.py +282 -0
- angr/analyses/propagator/__init__.py +5 -0
- angr/analyses/propagator/engine_base.py +62 -0
- angr/analyses/propagator/engine_vex.py +297 -0
- angr/analyses/propagator/propagator.py +361 -0
- angr/analyses/propagator/top_checker_mixin.py +218 -0
- angr/analyses/propagator/values.py +117 -0
- angr/analyses/propagator/vex_vars.py +68 -0
- angr/analyses/proximity_graph.py +444 -0
- angr/analyses/purity/__init__.py +15 -0
- angr/analyses/purity/analysis.py +78 -0
- angr/analyses/purity/engine.py +593 -0
- angr/analyses/reaching_definitions/__init__.py +67 -0
- angr/analyses/reaching_definitions/call_trace.py +73 -0
- angr/analyses/reaching_definitions/dep_graph.py +433 -0
- angr/analyses/reaching_definitions/engine_ail.py +1128 -0
- angr/analyses/reaching_definitions/engine_vex.py +1128 -0
- angr/analyses/reaching_definitions/external_codeloc.py +0 -0
- angr/analyses/reaching_definitions/function_handler.py +639 -0
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
- angr/analyses/reaching_definitions/function_handler_library/stdio.py +269 -0
- angr/analyses/reaching_definitions/function_handler_library/stdlib.py +195 -0
- angr/analyses/reaching_definitions/function_handler_library/string.py +158 -0
- angr/analyses/reaching_definitions/function_handler_library/unistd.py +51 -0
- angr/analyses/reaching_definitions/heap_allocator.py +70 -0
- angr/analyses/reaching_definitions/rd_initializer.py +237 -0
- angr/analyses/reaching_definitions/rd_state.py +579 -0
- angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
- angr/analyses/reaching_definitions/subject.py +65 -0
- angr/analyses/reassembler.py +2900 -0
- angr/analyses/s_liveness.py +254 -0
- angr/analyses/s_propagator.py +575 -0
- angr/analyses/s_reaching_definitions/__init__.py +12 -0
- angr/analyses/s_reaching_definitions/s_rda_model.py +145 -0
- angr/analyses/s_reaching_definitions/s_rda_view.py +344 -0
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +230 -0
- angr/analyses/smc.py +160 -0
- angr/analyses/soot_class_hierarchy.py +273 -0
- angr/analyses/stack_pointer_tracker.py +954 -0
- angr/analyses/static_hooker.py +53 -0
- angr/analyses/typehoon/__init__.py +5 -0
- angr/analyses/typehoon/dfa.py +118 -0
- angr/analyses/typehoon/lifter.py +133 -0
- angr/analyses/typehoon/simple_solver.py +2009 -0
- angr/analyses/typehoon/translator.py +283 -0
- angr/analyses/typehoon/typeconsts.py +439 -0
- angr/analyses/typehoon/typehoon.py +338 -0
- angr/analyses/typehoon/typevars.py +633 -0
- angr/analyses/typehoon/variance.py +11 -0
- angr/analyses/unpacker/__init__.py +6 -0
- angr/analyses/unpacker/obfuscation_detector.py +103 -0
- angr/analyses/unpacker/packing_detector.py +138 -0
- angr/analyses/variable_recovery/__init__.py +9 -0
- angr/analyses/variable_recovery/annotations.py +58 -0
- angr/analyses/variable_recovery/engine_ail.py +978 -0
- angr/analyses/variable_recovery/engine_base.py +1256 -0
- angr/analyses/variable_recovery/engine_vex.py +594 -0
- angr/analyses/variable_recovery/irsb_scanner.py +143 -0
- angr/analyses/variable_recovery/variable_recovery.py +574 -0
- angr/analyses/variable_recovery/variable_recovery_base.py +489 -0
- angr/analyses/variable_recovery/variable_recovery_fast.py +669 -0
- angr/analyses/veritesting.py +626 -0
- angr/analyses/vfg.py +1898 -0
- angr/analyses/vsa_ddg.py +420 -0
- angr/analyses/vtable.py +92 -0
- angr/analyses/xrefs.py +286 -0
- angr/angrdb/__init__.py +14 -0
- angr/angrdb/db.py +215 -0
- angr/angrdb/models.py +184 -0
- angr/angrdb/serializers/__init__.py +10 -0
- angr/angrdb/serializers/cfg_model.py +41 -0
- angr/angrdb/serializers/comments.py +60 -0
- angr/angrdb/serializers/funcs.py +61 -0
- angr/angrdb/serializers/kb.py +111 -0
- angr/angrdb/serializers/labels.py +59 -0
- angr/angrdb/serializers/loader.py +165 -0
- angr/angrdb/serializers/structured_code.py +167 -0
- angr/angrdb/serializers/variables.py +58 -0
- angr/angrdb/serializers/xrefs.py +48 -0
- angr/annocfg.py +317 -0
- angr/blade.py +431 -0
- angr/block.py +509 -0
- angr/callable.py +176 -0
- angr/calling_conventions.py +2613 -0
- angr/code_location.py +249 -0
- angr/codenode.py +145 -0
- angr/concretization_strategies/__init__.py +32 -0
- angr/concretization_strategies/any.py +17 -0
- angr/concretization_strategies/any_named.py +35 -0
- angr/concretization_strategies/base.py +81 -0
- angr/concretization_strategies/controlled_data.py +58 -0
- angr/concretization_strategies/eval.py +19 -0
- angr/concretization_strategies/logging.py +35 -0
- angr/concretization_strategies/max.py +25 -0
- angr/concretization_strategies/nonzero.py +16 -0
- angr/concretization_strategies/nonzero_range.py +22 -0
- angr/concretization_strategies/norepeats.py +37 -0
- angr/concretization_strategies/norepeats_range.py +37 -0
- angr/concretization_strategies/range.py +19 -0
- angr/concretization_strategies/signed_add.py +31 -0
- angr/concretization_strategies/single.py +15 -0
- angr/concretization_strategies/solutions.py +20 -0
- angr/concretization_strategies/unlimited_range.py +17 -0
- angr/distributed/__init__.py +9 -0
- angr/distributed/server.py +197 -0
- angr/distributed/worker.py +185 -0
- angr/emulator.py +144 -0
- angr/engines/__init__.py +69 -0
- angr/engines/ail/__init__.py +16 -0
- angr/engines/ail/callstack.py +58 -0
- angr/engines/ail/engine_light.py +903 -0
- angr/engines/ail/engine_successors.py +24 -0
- angr/engines/ail/setup.py +57 -0
- angr/engines/concrete.py +66 -0
- angr/engines/engine.py +29 -0
- angr/engines/failure.py +27 -0
- angr/engines/hook.py +93 -0
- angr/engines/icicle.py +294 -0
- angr/engines/light/__init__.py +23 -0
- angr/engines/light/data.py +681 -0
- angr/engines/light/engine.py +1297 -0
- angr/engines/pcode/__init__.py +9 -0
- angr/engines/pcode/behavior.py +998 -0
- angr/engines/pcode/cc.py +148 -0
- angr/engines/pcode/emulate.py +440 -0
- angr/engines/pcode/engine.py +242 -0
- angr/engines/pcode/lifter.py +1428 -0
- angr/engines/procedure.py +70 -0
- angr/engines/soot/__init__.py +5 -0
- angr/engines/soot/engine.py +410 -0
- angr/engines/soot/exceptions.py +17 -0
- angr/engines/soot/expressions/__init__.py +87 -0
- angr/engines/soot/expressions/arrayref.py +22 -0
- angr/engines/soot/expressions/base.py +21 -0
- angr/engines/soot/expressions/binop.py +28 -0
- angr/engines/soot/expressions/cast.py +22 -0
- angr/engines/soot/expressions/condition.py +35 -0
- angr/engines/soot/expressions/constants.py +47 -0
- angr/engines/soot/expressions/instanceOf.py +15 -0
- angr/engines/soot/expressions/instancefieldref.py +8 -0
- angr/engines/soot/expressions/invoke.py +114 -0
- angr/engines/soot/expressions/length.py +8 -0
- angr/engines/soot/expressions/local.py +8 -0
- angr/engines/soot/expressions/new.py +16 -0
- angr/engines/soot/expressions/newArray.py +54 -0
- angr/engines/soot/expressions/newMultiArray.py +86 -0
- angr/engines/soot/expressions/paramref.py +8 -0
- angr/engines/soot/expressions/phi.py +30 -0
- angr/engines/soot/expressions/staticfieldref.py +8 -0
- angr/engines/soot/expressions/thisref.py +7 -0
- angr/engines/soot/expressions/unsupported.py +7 -0
- angr/engines/soot/field_dispatcher.py +46 -0
- angr/engines/soot/method_dispatcher.py +46 -0
- angr/engines/soot/statements/__init__.py +44 -0
- angr/engines/soot/statements/assign.py +30 -0
- angr/engines/soot/statements/base.py +79 -0
- angr/engines/soot/statements/goto.py +14 -0
- angr/engines/soot/statements/identity.py +15 -0
- angr/engines/soot/statements/if_.py +19 -0
- angr/engines/soot/statements/invoke.py +12 -0
- angr/engines/soot/statements/return_.py +20 -0
- angr/engines/soot/statements/switch.py +41 -0
- angr/engines/soot/statements/throw.py +15 -0
- angr/engines/soot/values/__init__.py +38 -0
- angr/engines/soot/values/arrayref.py +122 -0
- angr/engines/soot/values/base.py +7 -0
- angr/engines/soot/values/constants.py +18 -0
- angr/engines/soot/values/instancefieldref.py +44 -0
- angr/engines/soot/values/local.py +18 -0
- angr/engines/soot/values/paramref.py +18 -0
- angr/engines/soot/values/staticfieldref.py +38 -0
- angr/engines/soot/values/strref.py +38 -0
- angr/engines/soot/values/thisref.py +149 -0
- angr/engines/successors.py +608 -0
- angr/engines/syscall.py +51 -0
- angr/engines/unicorn.py +490 -0
- angr/engines/vex/__init__.py +20 -0
- angr/engines/vex/claripy/__init__.py +5 -0
- angr/engines/vex/claripy/ccall.py +2097 -0
- angr/engines/vex/claripy/datalayer.py +141 -0
- angr/engines/vex/claripy/irop.py +1276 -0
- angr/engines/vex/heavy/__init__.py +16 -0
- angr/engines/vex/heavy/actions.py +231 -0
- angr/engines/vex/heavy/concretizers.py +403 -0
- angr/engines/vex/heavy/dirty.py +466 -0
- angr/engines/vex/heavy/heavy.py +370 -0
- angr/engines/vex/heavy/inspect.py +52 -0
- angr/engines/vex/heavy/resilience.py +85 -0
- angr/engines/vex/heavy/super_fastpath.py +34 -0
- angr/engines/vex/lifter.py +420 -0
- angr/engines/vex/light/__init__.py +11 -0
- angr/engines/vex/light/light.py +551 -0
- angr/engines/vex/light/resilience.py +74 -0
- angr/engines/vex/light/slicing.py +52 -0
- angr/errors.py +611 -0
- angr/exploration_techniques/__init__.py +53 -0
- angr/exploration_techniques/base.py +126 -0
- angr/exploration_techniques/bucketizer.py +94 -0
- angr/exploration_techniques/common.py +56 -0
- angr/exploration_techniques/dfs.py +37 -0
- angr/exploration_techniques/director.py +520 -0
- angr/exploration_techniques/driller_core.py +100 -0
- angr/exploration_techniques/explorer.py +152 -0
- angr/exploration_techniques/lengthlimiter.py +22 -0
- angr/exploration_techniques/local_loop_seer.py +65 -0
- angr/exploration_techniques/loop_seer.py +236 -0
- angr/exploration_techniques/manual_mergepoint.py +82 -0
- angr/exploration_techniques/memory_watcher.py +43 -0
- angr/exploration_techniques/oppologist.py +92 -0
- angr/exploration_techniques/slicecutor.py +118 -0
- angr/exploration_techniques/spiller.py +280 -0
- angr/exploration_techniques/spiller_db.py +27 -0
- angr/exploration_techniques/stochastic.py +56 -0
- angr/exploration_techniques/stub_stasher.py +19 -0
- angr/exploration_techniques/suggestions.py +159 -0
- angr/exploration_techniques/tech_builder.py +49 -0
- angr/exploration_techniques/threading.py +69 -0
- angr/exploration_techniques/timeout.py +34 -0
- angr/exploration_techniques/tracer.py +1098 -0
- angr/exploration_techniques/unique.py +106 -0
- angr/exploration_techniques/veritesting.py +37 -0
- angr/factory.py +413 -0
- angr/flirt/__init__.py +124 -0
- angr/flirt/build_sig.py +305 -0
- angr/graph_utils.py +0 -0
- angr/keyed_region.py +525 -0
- angr/knowledge_base.py +146 -0
- angr/knowledge_plugins/__init__.py +43 -0
- angr/knowledge_plugins/callsite_prototypes.py +95 -0
- angr/knowledge_plugins/cfg/__init__.py +18 -0
- angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
- angr/knowledge_plugins/cfg/cfg_model.py +1043 -0
- angr/knowledge_plugins/cfg/cfg_node.py +536 -0
- angr/knowledge_plugins/cfg/indirect_jump.py +131 -0
- angr/knowledge_plugins/cfg/memory_data.py +156 -0
- angr/knowledge_plugins/comments.py +16 -0
- angr/knowledge_plugins/custom_strings.py +38 -0
- angr/knowledge_plugins/data.py +22 -0
- angr/knowledge_plugins/debug_variables.py +216 -0
- angr/knowledge_plugins/functions/__init__.py +9 -0
- angr/knowledge_plugins/functions/function.py +1830 -0
- angr/knowledge_plugins/functions/function_manager.py +621 -0
- angr/knowledge_plugins/functions/function_parser.py +360 -0
- angr/knowledge_plugins/functions/soot_function.py +128 -0
- angr/knowledge_plugins/indirect_jumps.py +35 -0
- angr/knowledge_plugins/key_definitions/__init__.py +17 -0
- angr/knowledge_plugins/key_definitions/atoms.py +374 -0
- angr/knowledge_plugins/key_definitions/constants.py +29 -0
- angr/knowledge_plugins/key_definitions/definition.py +216 -0
- angr/knowledge_plugins/key_definitions/environment.py +96 -0
- angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +1020 -0
- angr/knowledge_plugins/key_definitions/liveness.py +165 -0
- angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
- angr/knowledge_plugins/key_definitions/tag.py +78 -0
- angr/knowledge_plugins/key_definitions/undefined.py +70 -0
- angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
- angr/knowledge_plugins/key_definitions/uses.py +178 -0
- angr/knowledge_plugins/labels.py +110 -0
- angr/knowledge_plugins/obfuscations.py +40 -0
- angr/knowledge_plugins/patches.py +126 -0
- angr/knowledge_plugins/plugin.py +24 -0
- angr/knowledge_plugins/propagations/__init__.py +10 -0
- angr/knowledge_plugins/propagations/prop_value.py +191 -0
- angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
- angr/knowledge_plugins/propagations/propagation_model.py +80 -0
- angr/knowledge_plugins/propagations/states.py +552 -0
- angr/knowledge_plugins/structured_code.py +63 -0
- angr/knowledge_plugins/types.py +95 -0
- angr/knowledge_plugins/variables/__init__.py +8 -0
- angr/knowledge_plugins/variables/variable_access.py +113 -0
- angr/knowledge_plugins/variables/variable_manager.py +1375 -0
- angr/knowledge_plugins/xrefs/__init__.py +12 -0
- angr/knowledge_plugins/xrefs/xref.py +150 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
- angr/knowledge_plugins/xrefs/xref_types.py +16 -0
- angr/misc/__init__.py +19 -0
- angr/misc/ansi.py +47 -0
- angr/misc/autoimport.py +90 -0
- angr/misc/bug_report.py +126 -0
- angr/misc/hookset.py +106 -0
- angr/misc/loggers.py +130 -0
- angr/misc/picklable_lock.py +46 -0
- angr/misc/plugins.py +289 -0
- angr/misc/telemetry.py +54 -0
- angr/misc/testing.py +24 -0
- angr/misc/ux.py +31 -0
- angr/procedures/__init__.py +12 -0
- angr/procedures/advapi32/__init__.py +0 -0
- angr/procedures/cgc/__init__.py +3 -0
- angr/procedures/cgc/_terminate.py +11 -0
- angr/procedures/cgc/allocate.py +75 -0
- angr/procedures/cgc/deallocate.py +67 -0
- angr/procedures/cgc/fdwait.py +65 -0
- angr/procedures/cgc/random.py +67 -0
- angr/procedures/cgc/receive.py +93 -0
- angr/procedures/cgc/transmit.py +65 -0
- angr/procedures/definitions/__init__.py +1043 -0
- angr/procedures/definitions/cgc.py +23 -0
- angr/procedures/definitions/common/glibc.json +3516 -0
- angr/procedures/definitions/gnulib.py +41 -0
- angr/procedures/definitions/libstdcpp.py +25 -0
- angr/procedures/definitions/linux_kernel.py +8382 -0
- angr/procedures/definitions/linux_loader.py +7 -0
- angr/procedures/definitions/macho_libsystem.py +18 -0
- angr/procedures/definitions/msvcr.py +25 -0
- angr/procedures/definitions/parse_glibc.py +77 -0
- angr/procedures/definitions/parse_syscalls_from_local_system.py +54 -0
- angr/procedures/definitions/parse_win32json.py +2540 -0
- angr/procedures/definitions/types_stl.py +22 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-4.json +24 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-6.json +18 -0
- angr/procedures/definitions/wdk/clfs.json +189 -0
- angr/procedures/definitions/wdk/fltmgr.json +813 -0
- angr/procedures/definitions/wdk/fwpkclnt.json +24 -0
- angr/procedures/definitions/wdk/fwpuclnt.json +453 -0
- angr/procedures/definitions/wdk/gdi32.json +528 -0
- angr/procedures/definitions/wdk/hal.json +96 -0
- angr/procedures/definitions/wdk/ksecdd.json +72 -0
- angr/procedures/definitions/wdk/ndis.json +336 -0
- angr/procedures/definitions/wdk/ntoskrnl.json +5158 -0
- angr/procedures/definitions/wdk/offreg.json +87 -0
- angr/procedures/definitions/wdk/pshed.json +33 -0
- angr/procedures/definitions/wdk/secur32.json +39 -0
- angr/procedures/definitions/wdk/vhfum.json +30 -0
- angr/procedures/definitions/win32/_types_win32.json +34480 -0
- angr/procedures/definitions/win32/aclui.json +24 -0
- angr/procedures/definitions/win32/activeds.json +81 -0
- angr/procedures/definitions/win32/advapi32.json +2505 -0
- angr/procedures/definitions/win32/advpack.json +165 -0
- angr/procedures/definitions/win32/amsi.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-1.json +45 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-3.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-apiquery-l2-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-backgroundtask-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-enclave-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-errorhandling-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-0.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-file-fromapp-l1-1-0.json +48 -0
- angr/procedures/definitions/win32/api-ms-win-core-handle-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-ioring-l1-1-0.json +51 -0
- angr/procedures/definitions/win32/api-ms-win-core-marshal-l1-1-0.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-3.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-5.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-6.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-7.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-8.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-path-l1-1-0.json +81 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-0.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-2.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-slapi-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-state-helpers-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-synch-l1-2-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-4.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-util-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-wow64-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-0.json +42 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-1.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-dx-d3dkmt-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-deviceinformation-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-expandedresources-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-2.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-4.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-mm-misc-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-net-isolation-l1-1-0.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-security-base-l1-2-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-5.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-1.json +33 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-wsl-api-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/apphelp.json +18 -0
- angr/procedures/definitions/win32/authz.json +114 -0
- angr/procedures/definitions/win32/avicap32.json +27 -0
- angr/procedures/definitions/win32/avifil32.json +195 -0
- angr/procedures/definitions/win32/avrt.json +57 -0
- angr/procedures/definitions/win32/bcp47mrm.json +21 -0
- angr/procedures/definitions/win32/bcrypt.json +174 -0
- angr/procedures/definitions/win32/bcryptprimitives.json +21 -0
- angr/procedures/definitions/win32/bluetoothapis.json +138 -0
- angr/procedures/definitions/win32/bthprops_cpl.json +33 -0
- angr/procedures/definitions/win32/cabinet.json +81 -0
- angr/procedures/definitions/win32/certadm.json +69 -0
- angr/procedures/definitions/win32/certpoleng.json +39 -0
- angr/procedures/definitions/win32/cfgmgr32.json +732 -0
- angr/procedures/definitions/win32/chakra.json +270 -0
- angr/procedures/definitions/win32/cldapi.json +123 -0
- angr/procedures/definitions/win32/clfsw32.json +192 -0
- angr/procedures/definitions/win32/clusapi.json +855 -0
- angr/procedures/definitions/win32/comctl32.json +360 -0
- angr/procedures/definitions/win32/comdlg32.json +78 -0
- angr/procedures/definitions/win32/compstui.json +27 -0
- angr/procedures/definitions/win32/computecore.json +177 -0
- angr/procedures/definitions/win32/computenetwork.json +144 -0
- angr/procedures/definitions/win32/computestorage.json +51 -0
- angr/procedures/definitions/win32/comsvcs.json +36 -0
- angr/procedures/definitions/win32/credui.json +72 -0
- angr/procedures/definitions/win32/crypt32.json +702 -0
- angr/procedures/definitions/win32/cryptnet.json +30 -0
- angr/procedures/definitions/win32/cryptui.json +45 -0
- angr/procedures/definitions/win32/cryptxml.json +72 -0
- angr/procedures/definitions/win32/cscapi.json +27 -0
- angr/procedures/definitions/win32/d2d1.json +54 -0
- angr/procedures/definitions/win32/d3d10.json +96 -0
- angr/procedures/definitions/win32/d3d10_1.json +21 -0
- angr/procedures/definitions/win32/d3d11.json +24 -0
- angr/procedures/definitions/win32/d3d12.json +39 -0
- angr/procedures/definitions/win32/d3d9.json +48 -0
- angr/procedures/definitions/win32/d3dcompiler_47.json +93 -0
- angr/procedures/definitions/win32/d3dcsx.json +42 -0
- angr/procedures/definitions/win32/davclnt.json +69 -0
- angr/procedures/definitions/win32/dbgeng.json +27 -0
- angr/procedures/definitions/win32/dbghelp.json +663 -0
- angr/procedures/definitions/win32/dbgmodel.json +18 -0
- angr/procedures/definitions/win32/dciman32.json +75 -0
- angr/procedures/definitions/win32/dcomp.json +51 -0
- angr/procedures/definitions/win32/ddraw.json +36 -0
- angr/procedures/definitions/win32/deviceaccess.json +18 -0
- angr/procedures/definitions/win32/dflayout.json +18 -0
- angr/procedures/definitions/win32/dhcpcsvc.json +60 -0
- angr/procedures/definitions/win32/dhcpcsvc6.json +33 -0
- angr/procedures/definitions/win32/dhcpsapi.json +603 -0
- angr/procedures/definitions/win32/diagnosticdataquery.json +120 -0
- angr/procedures/definitions/win32/dinput8.json +18 -0
- angr/procedures/definitions/win32/directml.json +21 -0
- angr/procedures/definitions/win32/dmprocessxmlfiltered.json +18 -0
- angr/procedures/definitions/win32/dnsapi.json +207 -0
- angr/procedures/definitions/win32/drt.json +63 -0
- angr/procedures/definitions/win32/drtprov.json +42 -0
- angr/procedures/definitions/win32/drttransport.json +21 -0
- angr/procedures/definitions/win32/dsound.json +45 -0
- angr/procedures/definitions/win32/dsparse.json +72 -0
- angr/procedures/definitions/win32/dsprop.json +36 -0
- angr/procedures/definitions/win32/dssec.json +27 -0
- angr/procedures/definitions/win32/dsuiext.json +27 -0
- angr/procedures/definitions/win32/dwmapi.json +108 -0
- angr/procedures/definitions/win32/dwrite.json +18 -0
- angr/procedures/definitions/win32/dxcompiler.json +21 -0
- angr/procedures/definitions/win32/dxcore.json +18 -0
- angr/procedures/definitions/win32/dxgi.json +33 -0
- angr/procedures/definitions/win32/dxva2.json +129 -0
- angr/procedures/definitions/win32/eappcfg.json +57 -0
- angr/procedures/definitions/win32/eappprxy.json +69 -0
- angr/procedures/definitions/win32/efswrt.json +21 -0
- angr/procedures/definitions/win32/elscore.json +30 -0
- angr/procedures/definitions/win32/esent.json +702 -0
- angr/procedures/definitions/win32/evr.json +36 -0
- angr/procedures/definitions/win32/faultrep.json +27 -0
- angr/procedures/definitions/win32/fhsvcctl.json +36 -0
- angr/procedures/definitions/win32/firewallapi.json +24 -0
- angr/procedures/definitions/win32/fltlib.json +99 -0
- angr/procedures/definitions/win32/fontsub.json +21 -0
- angr/procedures/definitions/win32/forceinline.json +24 -0
- angr/procedures/definitions/win32/fwpuclnt.json +591 -0
- angr/procedures/definitions/win32/fxsutility.json +21 -0
- angr/procedures/definitions/win32/gdi32.json +1308 -0
- angr/procedures/definitions/win32/gdiplus.json +1902 -0
- angr/procedures/definitions/win32/glu32.json +171 -0
- angr/procedures/definitions/win32/gpedit.json +33 -0
- angr/procedures/definitions/win32/hhctrl_ocx.json +21 -0
- angr/procedures/definitions/win32/hid.json +150 -0
- angr/procedures/definitions/win32/hlink.json +99 -0
- angr/procedures/definitions/win32/hrtfapo.json +18 -0
- angr/procedures/definitions/win32/httpapi.json +144 -0
- angr/procedures/definitions/win32/icm32.json +78 -0
- angr/procedures/definitions/win32/icmui.json +21 -0
- angr/procedures/definitions/win32/icu.json +3090 -0
- angr/procedures/definitions/win32/ieframe.json +102 -0
- angr/procedures/definitions/win32/imagehlp.json +84 -0
- angr/procedures/definitions/win32/imgutil.json +42 -0
- angr/procedures/definitions/win32/imm32.json +261 -0
- angr/procedures/definitions/win32/infocardapi.json +66 -0
- angr/procedures/definitions/win32/inkobjcore.json +96 -0
- angr/procedures/definitions/win32/iphlpapi.json +618 -0
- angr/procedures/definitions/win32/iscsidsc.json +252 -0
- angr/procedures/definitions/win32/isolatedwindowsenvironmentutils.json +21 -0
- angr/procedures/definitions/win32/kernel32.json +4566 -0
- angr/procedures/definitions/win32/kernelbase.json +33 -0
- angr/procedures/definitions/win32/keycredmgr.json +27 -0
- angr/procedures/definitions/win32/ksproxy_ax.json +33 -0
- angr/procedures/definitions/win32/ksuser.json +39 -0
- angr/procedures/definitions/win32/ktmw32.json +132 -0
- angr/procedures/definitions/win32/licenseprotection.json +21 -0
- angr/procedures/definitions/win32/loadperf.json +51 -0
- angr/procedures/definitions/win32/magnification.json +72 -0
- angr/procedures/definitions/win32/mapi32.json +213 -0
- angr/procedures/definitions/win32/mdmlocalmanagement.json +24 -0
- angr/procedures/definitions/win32/mdmregistration.json +60 -0
- angr/procedures/definitions/win32/mf.json +201 -0
- angr/procedures/definitions/win32/mfcore.json +21 -0
- angr/procedures/definitions/win32/mfplat.json +450 -0
- angr/procedures/definitions/win32/mfplay.json +18 -0
- angr/procedures/definitions/win32/mfreadwrite.json +30 -0
- angr/procedures/definitions/win32/mfsensorgroup.json +45 -0
- angr/procedures/definitions/win32/mfsrcsnk.json +21 -0
- angr/procedures/definitions/win32/mgmtapi.json +42 -0
- angr/procedures/definitions/win32/mi.json +18 -0
- angr/procedures/definitions/win32/mmdevapi.json +18 -0
- angr/procedures/definitions/win32/mpr.json +156 -0
- angr/procedures/definitions/win32/mprapi.json +351 -0
- angr/procedures/definitions/win32/mqrt.json +117 -0
- angr/procedures/definitions/win32/mrmsupport.json +96 -0
- angr/procedures/definitions/win32/msacm32.json +141 -0
- angr/procedures/definitions/win32/msajapi.json +1656 -0
- angr/procedures/definitions/win32/mscms.json +252 -0
- angr/procedures/definitions/win32/mscoree.json +96 -0
- angr/procedures/definitions/win32/msctfmonitor.json +24 -0
- angr/procedures/definitions/win32/msdelta.json +63 -0
- angr/procedures/definitions/win32/msdmo.json +48 -0
- angr/procedures/definitions/win32/msdrm.json +267 -0
- angr/procedures/definitions/win32/msi.json +807 -0
- angr/procedures/definitions/win32/msimg32.json +24 -0
- angr/procedures/definitions/win32/mspatcha.json +63 -0
- angr/procedures/definitions/win32/mspatchc.json +42 -0
- angr/procedures/definitions/win32/msports.json +36 -0
- angr/procedures/definitions/win32/msrating.json +72 -0
- angr/procedures/definitions/win32/mssign32.json +45 -0
- angr/procedures/definitions/win32/mstask.json +21 -0
- angr/procedures/definitions/win32/msvfw32.json +144 -0
- angr/procedures/definitions/win32/mswsock.json +63 -0
- angr/procedures/definitions/win32/mtxdm.json +18 -0
- angr/procedures/definitions/win32/ncrypt.json +132 -0
- angr/procedures/definitions/win32/ndfapi.json +63 -0
- angr/procedures/definitions/win32/netapi32.json +633 -0
- angr/procedures/definitions/win32/netsh.json +39 -0
- angr/procedures/definitions/win32/netshell.json +21 -0
- angr/procedures/definitions/win32/newdev.json +48 -0
- angr/procedures/definitions/win32/ninput.json +105 -0
- angr/procedures/definitions/win32/normaliz.json +21 -0
- angr/procedures/definitions/win32/ntdll.json +234 -0
- angr/procedures/definitions/win32/ntdllk.json +18 -0
- angr/procedures/definitions/win32/ntdsapi.json +258 -0
- angr/procedures/definitions/win32/ntlanman.json +45 -0
- angr/procedures/definitions/win32/odbc32.json +477 -0
- angr/procedures/definitions/win32/odbcbcp.json +96 -0
- angr/procedures/definitions/win32/ole32.json +966 -0
- angr/procedures/definitions/win32/oleacc.json +66 -0
- angr/procedures/definitions/win32/oleaut32.json +1230 -0
- angr/procedures/definitions/win32/oledlg.json +84 -0
- angr/procedures/definitions/win32/ondemandconnroutehelper.json +30 -0
- angr/procedures/definitions/win32/opengl32.json +1080 -0
- angr/procedures/definitions/win32/opmxbox.json +24 -0
- angr/procedures/definitions/win32/p2p.json +339 -0
- angr/procedures/definitions/win32/p2pgraph.json +126 -0
- angr/procedures/definitions/win32/pdh.json +309 -0
- angr/procedures/definitions/win32/peerdist.json +99 -0
- angr/procedures/definitions/win32/powrprof.json +267 -0
- angr/procedures/definitions/win32/prntvpt.json +48 -0
- angr/procedures/definitions/win32/projectedfslib.json +72 -0
- angr/procedures/definitions/win32/propsys.json +669 -0
- angr/procedures/definitions/win32/psapi.json +96 -0
- angr/procedures/definitions/win32/quartz.json +21 -0
- angr/procedures/definitions/win32/query.json +27 -0
- angr/procedures/definitions/win32/qwave.json +48 -0
- angr/procedures/definitions/win32/rasapi32.json +267 -0
- angr/procedures/definitions/win32/rasdlg.json +33 -0
- angr/procedures/definitions/win32/resutils.json +375 -0
- angr/procedures/definitions/win32/rpcns4.json +198 -0
- angr/procedures/definitions/win32/rpcproxy.json +27 -0
- angr/procedures/definitions/win32/rpcrt4.json +1356 -0
- angr/procedures/definitions/win32/rstrtmgr.json +48 -0
- angr/procedures/definitions/win32/rtm.json +243 -0
- angr/procedures/definitions/win32/rtutils.json +138 -0
- angr/procedures/definitions/win32/rtworkq.json +114 -0
- angr/procedures/definitions/win32/sas.json +18 -0
- angr/procedures/definitions/win32/scarddlg.json +30 -0
- angr/procedures/definitions/win32/schannel.json +42 -0
- angr/procedures/definitions/win32/sechost.json +21 -0
- angr/procedures/definitions/win32/secur32.json +282 -0
- angr/procedures/definitions/win32/sensapi.json +24 -0
- angr/procedures/definitions/win32/sensorsutilsv2.json +135 -0
- angr/procedures/definitions/win32/setupapi.json +1017 -0
- angr/procedures/definitions/win32/sfc.json +33 -0
- angr/procedures/definitions/win32/shdocvw.json +24 -0
- angr/procedures/definitions/win32/shell32.json +747 -0
- angr/procedures/definitions/win32/shlwapi.json +1095 -0
- angr/procedures/definitions/win32/slc.json +111 -0
- angr/procedures/definitions/win32/slcext.json +27 -0
- angr/procedures/definitions/win32/slwga.json +18 -0
- angr/procedures/definitions/win32/snmpapi.json +93 -0
- angr/procedures/definitions/win32/spoolss.json +93 -0
- angr/procedures/definitions/win32/srclient.json +18 -0
- angr/procedures/definitions/win32/srpapi.json +48 -0
- angr/procedures/definitions/win32/sspicli.json +36 -0
- angr/procedures/definitions/win32/sti.json +18 -0
- angr/procedures/definitions/win32/t2embed.json +57 -0
- angr/procedures/definitions/win32/tapi32.json +762 -0
- angr/procedures/definitions/win32/tbs.json +57 -0
- angr/procedures/definitions/win32/tdh.json +96 -0
- angr/procedures/definitions/win32/tokenbinding.json +45 -0
- angr/procedures/definitions/win32/traffic.json +75 -0
- angr/procedures/definitions/win32/txfw32.json +42 -0
- angr/procedures/definitions/win32/ualapi.json +27 -0
- angr/procedures/definitions/win32/uiautomationcore.json +309 -0
- angr/procedures/definitions/win32/urlmon.json +246 -0
- angr/procedures/definitions/win32/user32.json +2298 -0
- angr/procedures/definitions/win32/userenv.json +147 -0
- angr/procedures/definitions/win32/usp10.json +135 -0
- angr/procedures/definitions/win32/uxtheme.json +246 -0
- angr/procedures/definitions/win32/verifier.json +18 -0
- angr/procedures/definitions/win32/version.json +57 -0
- angr/procedures/definitions/win32/vertdll.json +36 -0
- angr/procedures/definitions/win32/virtdisk.json +102 -0
- angr/procedures/definitions/win32/vmdevicehost.json +54 -0
- angr/procedures/definitions/win32/vmsavedstatedumpprovider.json +144 -0
- angr/procedures/definitions/win32/vssapi.json +18 -0
- angr/procedures/definitions/win32/wcmapi.json +30 -0
- angr/procedures/definitions/win32/wdsbp.json +36 -0
- angr/procedures/definitions/win32/wdsclientapi.json +126 -0
- angr/procedures/definitions/win32/wdsmc.json +33 -0
- angr/procedures/definitions/win32/wdspxe.json +108 -0
- angr/procedures/definitions/win32/wdstptc.json +54 -0
- angr/procedures/definitions/win32/webauthn.json +54 -0
- angr/procedures/definitions/win32/webservices.json +594 -0
- angr/procedures/definitions/win32/websocket.json +54 -0
- angr/procedures/definitions/win32/wecapi.json +60 -0
- angr/procedures/definitions/win32/wer.json +78 -0
- angr/procedures/definitions/win32/wevtapi.json +120 -0
- angr/procedures/definitions/win32/winbio.json +177 -0
- angr/procedures/definitions/win32/windows_ai_machinelearning.json +18 -0
- angr/procedures/definitions/win32/windows_media_mediacontrol.json +39 -0
- angr/procedures/definitions/win32/windows_networking.json +18 -0
- angr/procedures/definitions/win32/windows_ui_xaml.json +21 -0
- angr/procedures/definitions/win32/windowscodecs.json +42 -0
- angr/procedures/definitions/win32/winfax.json +183 -0
- angr/procedures/definitions/win32/winhttp.json +183 -0
- angr/procedures/definitions/win32/winhvemulation.json +27 -0
- angr/procedures/definitions/win32/winhvplatform.json +213 -0
- angr/procedures/definitions/win32/wininet.json +903 -0
- angr/procedures/definitions/win32/winml.json +18 -0
- angr/procedures/definitions/win32/winmm.json +543 -0
- angr/procedures/definitions/win32/winscard.json +225 -0
- angr/procedures/definitions/win32/winspool_drv.json +531 -0
- angr/procedures/definitions/win32/wintrust.json +195 -0
- angr/procedures/definitions/win32/winusb.json +117 -0
- angr/procedures/definitions/win32/wlanapi.json +195 -0
- angr/procedures/definitions/win32/wlanui.json +18 -0
- angr/procedures/definitions/win32/wldap32.json +744 -0
- angr/procedures/definitions/win32/wldp.json +42 -0
- angr/procedures/definitions/win32/wmvcore.json +48 -0
- angr/procedures/definitions/win32/wnvapi.json +21 -0
- angr/procedures/definitions/win32/wofutil.json +48 -0
- angr/procedures/definitions/win32/ws2_32.json +495 -0
- angr/procedures/definitions/win32/wscapi.json +33 -0
- angr/procedures/definitions/win32/wsclient.json +24 -0
- angr/procedures/definitions/win32/wsdapi.json +111 -0
- angr/procedures/definitions/win32/wsmsvc.json +114 -0
- angr/procedures/definitions/win32/wsnmp32.json +162 -0
- angr/procedures/definitions/win32/wtsapi32.json +204 -0
- angr/procedures/definitions/win32/xaudio2_8.json +27 -0
- angr/procedures/definitions/win32/xinput1_4.json +36 -0
- angr/procedures/definitions/win32/xmllite.json +33 -0
- angr/procedures/definitions/win32/xolehlp.json +27 -0
- angr/procedures/definitions/win32/xpsprint.json +21 -0
- angr/procedures/glibc/__ctype_b_loc.py +21 -0
- angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
- angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
- angr/procedures/glibc/__errno_location.py +7 -0
- angr/procedures/glibc/__init__.py +3 -0
- angr/procedures/glibc/__libc_init.py +37 -0
- angr/procedures/glibc/__libc_start_main.py +301 -0
- angr/procedures/glibc/dynamic_loading.py +20 -0
- angr/procedures/glibc/scanf.py +19 -0
- angr/procedures/glibc/sscanf.py +10 -0
- angr/procedures/gnulib/__init__.py +3 -0
- angr/procedures/gnulib/xalloc_die.py +14 -0
- angr/procedures/gnulib/xstrtol_fatal.py +14 -0
- angr/procedures/java/__init__.py +42 -0
- angr/procedures/java/unconstrained.py +65 -0
- angr/procedures/java_io/__init__.py +0 -0
- angr/procedures/java_io/read.py +12 -0
- angr/procedures/java_io/write.py +17 -0
- angr/procedures/java_jni/__init__.py +482 -0
- angr/procedures/java_jni/array_operations.py +312 -0
- angr/procedures/java_jni/class_and_interface_operations.py +31 -0
- angr/procedures/java_jni/field_access.py +173 -0
- angr/procedures/java_jni/global_and_local_refs.py +57 -0
- angr/procedures/java_jni/method_calls.py +365 -0
- angr/procedures/java_jni/not_implemented.py +26 -0
- angr/procedures/java_jni/object_operations.py +94 -0
- angr/procedures/java_jni/string_operations.py +87 -0
- angr/procedures/java_jni/version_information.py +12 -0
- angr/procedures/java_lang/__init__.py +0 -0
- angr/procedures/java_lang/character.py +30 -0
- angr/procedures/java_lang/double.py +24 -0
- angr/procedures/java_lang/exit.py +13 -0
- angr/procedures/java_lang/getsimplename.py +18 -0
- angr/procedures/java_lang/integer.py +43 -0
- angr/procedures/java_lang/load_library.py +9 -0
- angr/procedures/java_lang/math.py +15 -0
- angr/procedures/java_lang/string.py +78 -0
- angr/procedures/java_lang/stringbuilder.py +44 -0
- angr/procedures/java_lang/system.py +18 -0
- angr/procedures/java_util/__init__.py +0 -0
- angr/procedures/java_util/collection.py +35 -0
- angr/procedures/java_util/iterator.py +46 -0
- angr/procedures/java_util/list.py +99 -0
- angr/procedures/java_util/map.py +131 -0
- angr/procedures/java_util/random.py +14 -0
- angr/procedures/java_util/scanner_nextline.py +23 -0
- angr/procedures/libc/__init__.py +3 -0
- angr/procedures/libc/abort.py +9 -0
- angr/procedures/libc/access.py +13 -0
- angr/procedures/libc/atoi.py +14 -0
- angr/procedures/libc/atol.py +13 -0
- angr/procedures/libc/calloc.py +8 -0
- angr/procedures/libc/closelog.py +10 -0
- angr/procedures/libc/err.py +14 -0
- angr/procedures/libc/error.py +54 -0
- angr/procedures/libc/exit.py +11 -0
- angr/procedures/libc/fclose.py +19 -0
- angr/procedures/libc/feof.py +21 -0
- angr/procedures/libc/fflush.py +16 -0
- angr/procedures/libc/fgetc.py +27 -0
- angr/procedures/libc/fgets.py +69 -0
- angr/procedures/libc/fopen.py +63 -0
- angr/procedures/libc/fprintf.py +25 -0
- angr/procedures/libc/fputc.py +23 -0
- angr/procedures/libc/fputs.py +24 -0
- angr/procedures/libc/fread.py +24 -0
- angr/procedures/libc/free.py +9 -0
- angr/procedures/libc/fscanf.py +20 -0
- angr/procedures/libc/fseek.py +34 -0
- angr/procedures/libc/ftell.py +22 -0
- angr/procedures/libc/fwrite.py +19 -0
- angr/procedures/libc/getchar.py +13 -0
- angr/procedures/libc/getdelim.py +99 -0
- angr/procedures/libc/getegid.py +8 -0
- angr/procedures/libc/geteuid.py +8 -0
- angr/procedures/libc/getgid.py +8 -0
- angr/procedures/libc/gets.py +68 -0
- angr/procedures/libc/getuid.py +8 -0
- angr/procedures/libc/malloc.py +12 -0
- angr/procedures/libc/memcmp.py +69 -0
- angr/procedures/libc/memcpy.py +45 -0
- angr/procedures/libc/memset.py +72 -0
- angr/procedures/libc/openlog.py +10 -0
- angr/procedures/libc/perror.py +13 -0
- angr/procedures/libc/printf.py +34 -0
- angr/procedures/libc/putchar.py +13 -0
- angr/procedures/libc/puts.py +19 -0
- angr/procedures/libc/rand.py +8 -0
- angr/procedures/libc/realloc.py +8 -0
- angr/procedures/libc/rewind.py +12 -0
- angr/procedures/libc/scanf.py +20 -0
- angr/procedures/libc/setbuf.py +9 -0
- angr/procedures/libc/setvbuf.py +7 -0
- angr/procedures/libc/snprintf.py +36 -0
- angr/procedures/libc/sprintf.py +25 -0
- angr/procedures/libc/srand.py +7 -0
- angr/procedures/libc/sscanf.py +13 -0
- angr/procedures/libc/stpcpy.py +18 -0
- angr/procedures/libc/strcat.py +14 -0
- angr/procedures/libc/strchr.py +48 -0
- angr/procedures/libc/strcmp.py +31 -0
- angr/procedures/libc/strcpy.py +13 -0
- angr/procedures/libc/strlen.py +114 -0
- angr/procedures/libc/strncat.py +19 -0
- angr/procedures/libc/strncmp.py +183 -0
- angr/procedures/libc/strncpy.py +22 -0
- angr/procedures/libc/strnlen.py +13 -0
- angr/procedures/libc/strstr.py +101 -0
- angr/procedures/libc/strtol.py +261 -0
- angr/procedures/libc/strtoul.py +9 -0
- angr/procedures/libc/system.py +13 -0
- angr/procedures/libc/time.py +9 -0
- angr/procedures/libc/tmpnam.py +20 -0
- angr/procedures/libc/tolower.py +10 -0
- angr/procedures/libc/toupper.py +10 -0
- angr/procedures/libc/ungetc.py +20 -0
- angr/procedures/libc/vsnprintf.py +17 -0
- angr/procedures/libc/wchar.py +16 -0
- angr/procedures/libstdcpp/__init__.py +0 -0
- angr/procedures/libstdcpp/_unwind_resume.py +11 -0
- angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
- angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
- angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
- angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
- angr/procedures/libstdcpp/std__terminate.py +13 -0
- angr/procedures/linux_kernel/__init__.py +3 -0
- angr/procedures/linux_kernel/access.py +18 -0
- angr/procedures/linux_kernel/arch_prctl.py +34 -0
- angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
- angr/procedures/linux_kernel/brk.py +18 -0
- angr/procedures/linux_kernel/cwd.py +28 -0
- angr/procedures/linux_kernel/fstat.py +138 -0
- angr/procedures/linux_kernel/fstat64.py +170 -0
- angr/procedures/linux_kernel/futex.py +17 -0
- angr/procedures/linux_kernel/getegid.py +17 -0
- angr/procedures/linux_kernel/geteuid.py +17 -0
- angr/procedures/linux_kernel/getgid.py +17 -0
- angr/procedures/linux_kernel/getpid.py +14 -0
- angr/procedures/linux_kernel/getrlimit.py +24 -0
- angr/procedures/linux_kernel/gettid.py +9 -0
- angr/procedures/linux_kernel/getuid.py +17 -0
- angr/procedures/linux_kernel/iovec.py +47 -0
- angr/procedures/linux_kernel/lseek.py +42 -0
- angr/procedures/linux_kernel/mmap.py +16 -0
- angr/procedures/linux_kernel/mprotect.py +42 -0
- angr/procedures/linux_kernel/munmap.py +8 -0
- angr/procedures/linux_kernel/openat.py +26 -0
- angr/procedures/linux_kernel/set_tid_address.py +8 -0
- angr/procedures/linux_kernel/sigaction.py +19 -0
- angr/procedures/linux_kernel/sigprocmask.py +23 -0
- angr/procedures/linux_kernel/stat.py +23 -0
- angr/procedures/linux_kernel/sysinfo.py +59 -0
- angr/procedures/linux_kernel/tgkill.py +10 -0
- angr/procedures/linux_kernel/time.py +34 -0
- angr/procedures/linux_kernel/uid.py +30 -0
- angr/procedures/linux_kernel/uname.py +29 -0
- angr/procedures/linux_kernel/unlink.py +22 -0
- angr/procedures/linux_kernel/vsyscall.py +16 -0
- angr/procedures/linux_loader/__init__.py +3 -0
- angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
- angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
- angr/procedures/linux_loader/sim_loader.py +54 -0
- angr/procedures/linux_loader/tls.py +40 -0
- angr/procedures/msvcr/__getmainargs.py +16 -0
- angr/procedures/msvcr/__init__.py +4 -0
- angr/procedures/msvcr/_initterm.py +38 -0
- angr/procedures/msvcr/fmode.py +31 -0
- angr/procedures/ntdll/__init__.py +0 -0
- angr/procedures/ntdll/exceptions.py +60 -0
- angr/procedures/posix/__init__.py +3 -0
- angr/procedures/posix/accept.py +29 -0
- angr/procedures/posix/bind.py +13 -0
- angr/procedures/posix/bzero.py +9 -0
- angr/procedures/posix/chroot.py +27 -0
- angr/procedures/posix/close.py +9 -0
- angr/procedures/posix/closedir.py +7 -0
- angr/procedures/posix/dup.py +56 -0
- angr/procedures/posix/fcntl.py +10 -0
- angr/procedures/posix/fdopen.py +76 -0
- angr/procedures/posix/fileno.py +18 -0
- angr/procedures/posix/fork.py +13 -0
- angr/procedures/posix/getenv.py +35 -0
- angr/procedures/posix/gethostbyname.py +43 -0
- angr/procedures/posix/getpass.py +19 -0
- angr/procedures/posix/getsockopt.py +11 -0
- angr/procedures/posix/htonl.py +11 -0
- angr/procedures/posix/htons.py +11 -0
- angr/procedures/posix/inet_ntoa.py +59 -0
- angr/procedures/posix/listen.py +13 -0
- angr/procedures/posix/mmap.py +144 -0
- angr/procedures/posix/open.py +18 -0
- angr/procedures/posix/opendir.py +10 -0
- angr/procedures/posix/poll.py +55 -0
- angr/procedures/posix/pread64.py +46 -0
- angr/procedures/posix/pthread.py +87 -0
- angr/procedures/posix/pwrite64.py +46 -0
- angr/procedures/posix/read.py +13 -0
- angr/procedures/posix/readdir.py +62 -0
- angr/procedures/posix/recv.py +13 -0
- angr/procedures/posix/recvfrom.py +13 -0
- angr/procedures/posix/select.py +48 -0
- angr/procedures/posix/send.py +23 -0
- angr/procedures/posix/setsockopt.py +9 -0
- angr/procedures/posix/sigaction.py +23 -0
- angr/procedures/posix/sim_time.py +48 -0
- angr/procedures/posix/sleep.py +8 -0
- angr/procedures/posix/socket.py +18 -0
- angr/procedures/posix/strcasecmp.py +26 -0
- angr/procedures/posix/strdup.py +18 -0
- angr/procedures/posix/strtok_r.py +64 -0
- angr/procedures/posix/syslog.py +15 -0
- angr/procedures/posix/tz.py +9 -0
- angr/procedures/posix/unlink.py +11 -0
- angr/procedures/posix/usleep.py +8 -0
- angr/procedures/posix/write.py +13 -0
- angr/procedures/procedure_dict.py +50 -0
- angr/procedures/stubs/CallReturn.py +13 -0
- angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
- angr/procedures/stubs/Nop.py +7 -0
- angr/procedures/stubs/PathTerminator.py +9 -0
- angr/procedures/stubs/Redirect.py +18 -0
- angr/procedures/stubs/ReturnChar.py +11 -0
- angr/procedures/stubs/ReturnUnconstrained.py +24 -0
- angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
- angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
- angr/procedures/stubs/UserHook.py +18 -0
- angr/procedures/stubs/__init__.py +3 -0
- angr/procedures/stubs/b64_decode.py +15 -0
- angr/procedures/stubs/caller.py +14 -0
- angr/procedures/stubs/crazy_scanf.py +20 -0
- angr/procedures/stubs/format_parser.py +669 -0
- angr/procedures/stubs/syscall_stub.py +24 -0
- angr/procedures/testing/__init__.py +3 -0
- angr/procedures/testing/manyargs.py +9 -0
- angr/procedures/testing/retreg.py +8 -0
- angr/procedures/tracer/__init__.py +4 -0
- angr/procedures/tracer/random.py +9 -0
- angr/procedures/tracer/receive.py +23 -0
- angr/procedures/tracer/transmit.py +26 -0
- angr/procedures/uclibc/__init__.py +3 -0
- angr/procedures/uclibc/__uClibc_main.py +10 -0
- angr/procedures/win32/EncodePointer.py +7 -0
- angr/procedures/win32/ExitProcess.py +9 -0
- angr/procedures/win32/GetCommandLine.py +12 -0
- angr/procedures/win32/GetCurrentProcessId.py +7 -0
- angr/procedures/win32/GetCurrentThreadId.py +7 -0
- angr/procedures/win32/GetLastInputInfo.py +40 -0
- angr/procedures/win32/GetModuleHandle.py +29 -0
- angr/procedures/win32/GetProcessAffinityMask.py +37 -0
- angr/procedures/win32/InterlockedExchange.py +15 -0
- angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
- angr/procedures/win32/VirtualAlloc.py +114 -0
- angr/procedures/win32/VirtualProtect.py +60 -0
- angr/procedures/win32/__init__.py +3 -0
- angr/procedures/win32/critical_section.py +12 -0
- angr/procedures/win32/dynamic_loading.py +104 -0
- angr/procedures/win32/file_handles.py +47 -0
- angr/procedures/win32/gethostbyname.py +12 -0
- angr/procedures/win32/heap.py +45 -0
- angr/procedures/win32/is_bad_ptr.py +26 -0
- angr/procedures/win32/local_storage.py +88 -0
- angr/procedures/win32/mutex.py +11 -0
- angr/procedures/win32/sim_time.py +135 -0
- angr/procedures/win32/system_paths.py +35 -0
- angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
- angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
- angr/procedures/win32_kernel/__fastfail.py +15 -0
- angr/procedures/win32_kernel/__init__.py +3 -0
- angr/procedures/win_user32/__init__.py +0 -0
- angr/procedures/win_user32/chars.py +15 -0
- angr/procedures/win_user32/keyboard.py +14 -0
- angr/procedures/win_user32/messagebox.py +49 -0
- angr/project.py +860 -0
- angr/protos/__init__.py +19 -0
- angr/protos/cfg_pb2.py +42 -0
- angr/protos/function_pb2.py +38 -0
- angr/protos/primitives_pb2.py +59 -0
- angr/protos/variables_pb2.py +55 -0
- angr/protos/xrefs_pb2.py +36 -0
- angr/py.typed +1 -0
- angr/rustylib.cpython-311-darwin.so +0 -0
- angr/serializable.py +66 -0
- angr/sim_manager.py +971 -0
- angr/sim_options.py +436 -0
- angr/sim_procedure.py +626 -0
- angr/sim_state.py +926 -0
- angr/sim_state_options.py +403 -0
- angr/sim_type.py +4026 -0
- angr/sim_variable.py +470 -0
- angr/simos/__init__.py +47 -0
- angr/simos/cgc.py +153 -0
- angr/simos/javavm.py +458 -0
- angr/simos/linux.py +509 -0
- angr/simos/simos.py +444 -0
- angr/simos/snimmuc_nxp.py +149 -0
- angr/simos/userland.py +163 -0
- angr/simos/windows.py +615 -0
- angr/simos/xbox.py +32 -0
- angr/slicer.py +352 -0
- angr/state_hierarchy.py +262 -0
- angr/state_plugins/__init__.py +84 -0
- angr/state_plugins/callstack.py +478 -0
- angr/state_plugins/cgc.py +155 -0
- angr/state_plugins/debug_variables.py +192 -0
- angr/state_plugins/filesystem.py +463 -0
- angr/state_plugins/gdb.py +148 -0
- angr/state_plugins/globals.py +65 -0
- angr/state_plugins/heap/__init__.py +15 -0
- angr/state_plugins/heap/heap_base.py +128 -0
- angr/state_plugins/heap/heap_brk.py +136 -0
- angr/state_plugins/heap/heap_freelist.py +213 -0
- angr/state_plugins/heap/heap_libc.py +46 -0
- angr/state_plugins/heap/heap_ptmalloc.py +620 -0
- angr/state_plugins/heap/utils.py +22 -0
- angr/state_plugins/history.py +564 -0
- angr/state_plugins/inspect.py +375 -0
- angr/state_plugins/javavm_classloader.py +134 -0
- angr/state_plugins/jni_references.py +95 -0
- angr/state_plugins/libc.py +1263 -0
- angr/state_plugins/light_registers.py +168 -0
- angr/state_plugins/log.py +84 -0
- angr/state_plugins/loop_data.py +92 -0
- angr/state_plugins/plugin.py +176 -0
- angr/state_plugins/posix.py +703 -0
- angr/state_plugins/preconstrainer.py +196 -0
- angr/state_plugins/scratch.py +173 -0
- angr/state_plugins/sim_action.py +326 -0
- angr/state_plugins/sim_action_object.py +271 -0
- angr/state_plugins/sim_event.py +59 -0
- angr/state_plugins/solver.py +1128 -0
- angr/state_plugins/symbolizer.py +291 -0
- angr/state_plugins/trace_additions.py +738 -0
- angr/state_plugins/uc_manager.py +94 -0
- angr/state_plugins/unicorn_engine.py +1920 -0
- angr/state_plugins/view.py +340 -0
- angr/storage/__init__.py +15 -0
- angr/storage/file.py +1210 -0
- angr/storage/memory_mixins/__init__.py +317 -0
- angr/storage/memory_mixins/actions_mixin.py +72 -0
- angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
- angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
- angr/storage/memory_mixins/clouseau_mixin.py +137 -0
- angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
- angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
- angr/storage/memory_mixins/default_filler_mixin.py +144 -0
- angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
- angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
- angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
- angr/storage/memory_mixins/keyvalue_memory_mixin.py +43 -0
- angr/storage/memory_mixins/label_merger_mixin.py +31 -0
- angr/storage/memory_mixins/memory_mixin.py +175 -0
- angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
- angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
- angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
- angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
- angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
- angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +529 -0
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
- angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
- angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
- angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +442 -0
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
- angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
- angr/storage/memory_mixins/simplification_mixin.py +15 -0
- angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
- angr/storage/memory_mixins/slotted_memory.py +140 -0
- angr/storage/memory_mixins/smart_find_mixin.py +161 -0
- angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
- angr/storage/memory_mixins/top_merger_mixin.py +25 -0
- angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
- angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
- angr/storage/memory_object.py +195 -0
- angr/tablespecs.py +91 -0
- angr/unicornlib.dylib +0 -0
- angr/utils/__init__.py +46 -0
- angr/utils/ail.py +176 -0
- angr/utils/algo.py +34 -0
- angr/utils/balancer.py +776 -0
- angr/utils/bits.py +46 -0
- angr/utils/constants.py +9 -0
- angr/utils/cowdict.py +63 -0
- angr/utils/cpp.py +17 -0
- angr/utils/doms.py +150 -0
- angr/utils/dynamic_dictlist.py +89 -0
- angr/utils/endness.py +18 -0
- angr/utils/enums_conv.py +97 -0
- angr/utils/env.py +12 -0
- angr/utils/formatting.py +128 -0
- angr/utils/funcid.py +244 -0
- angr/utils/graph.py +981 -0
- angr/utils/lazy_import.py +13 -0
- angr/utils/library.py +236 -0
- angr/utils/loader.py +55 -0
- angr/utils/mp.py +66 -0
- angr/utils/orderedset.py +74 -0
- angr/utils/ssa/__init__.py +455 -0
- angr/utils/ssa/tmp_uses_collector.py +23 -0
- angr/utils/ssa/vvar_uses_collector.py +36 -0
- angr/utils/strings.py +20 -0
- angr/utils/tagged_interval_map.py +112 -0
- angr/utils/timing.py +74 -0
- angr/utils/types.py +193 -0
- angr/utils/vex.py +11 -0
- angr/vaults.py +367 -0
- angr-9.2.192.dist-info/METADATA +112 -0
- angr-9.2.192.dist-info/RECORD +1442 -0
- angr-9.2.192.dist-info/WHEEL +6 -0
- angr-9.2.192.dist-info/entry_points.txt +2 -0
- angr-9.2.192.dist-info/licenses/LICENSE +27 -0
- angr-9.2.192.dist-info/top_level.txt +1 -0
angr/analyses/bindiff.py
ADDED
|
@@ -0,0 +1,1512 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import logging
|
|
3
|
+
import math
|
|
4
|
+
import types
|
|
5
|
+
from collections import deque, defaultdict
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
from functools import partial
|
|
8
|
+
|
|
9
|
+
import networkx
|
|
10
|
+
|
|
11
|
+
from angr.analyses import AnalysesHub, Analysis, CFGFast
|
|
12
|
+
from angr.errors import SimEngineError, SimMemoryError
|
|
13
|
+
from angr.knowledge_plugins.cfg.memory_data import MemoryDataSort
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from angr.knowledge_plugins import Function
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# todo include an explanation of the algorithm
|
|
21
|
+
# todo include a method that detects any change other than constants
|
|
22
|
+
# todo use function names / string references where available
|
|
23
|
+
|
|
24
|
+
l = logging.getLogger(name=__name__)
|
|
25
|
+
|
|
26
|
+
# basic block changes
|
|
27
|
+
DIFF_TYPE = "type"
|
|
28
|
+
DIFF_VALUE = "value"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# exception for trying find basic block changes
|
|
32
|
+
class UnmatchedStatementsException(Exception):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# statement difference classes
|
|
37
|
+
class Difference:
|
|
38
|
+
def __init__(self, diff_type, value_a, value_b):
|
|
39
|
+
self.type = diff_type
|
|
40
|
+
self.value_a = value_a
|
|
41
|
+
self.value_b = value_b
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ConstantChange:
|
|
45
|
+
def __init__(self, offset, value_a, value_b):
|
|
46
|
+
self.offset = offset
|
|
47
|
+
self.value_a = value_a
|
|
48
|
+
self.value_b = value_b
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# helper methods
|
|
52
|
+
def _euclidean_dist(vector_a, vector_b):
|
|
53
|
+
"""
|
|
54
|
+
:param vector_a: A list of numbers.
|
|
55
|
+
:param vector_b: A list of numbers.
|
|
56
|
+
:returns: The euclidean distance between the two vectors.
|
|
57
|
+
"""
|
|
58
|
+
dist = 0
|
|
59
|
+
for x, y in zip(vector_a, vector_b):
|
|
60
|
+
dist += (x - y) * (x - y)
|
|
61
|
+
return math.sqrt(dist)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _get_closest_matches(input_attributes, target_attributes):
|
|
65
|
+
"""
|
|
66
|
+
:param input_attributes: First dictionary of objects to attribute tuples.
|
|
67
|
+
:param target_attributes: Second dictionary of blocks to attribute tuples.
|
|
68
|
+
:returns: A dictionary of objects in the input_attributes to the closest objects in the
|
|
69
|
+
target_attributes.
|
|
70
|
+
"""
|
|
71
|
+
closest_matches = {}
|
|
72
|
+
|
|
73
|
+
# for each object in the first set find the objects with the closest target attributes
|
|
74
|
+
for a in input_attributes:
|
|
75
|
+
best_dist = float("inf")
|
|
76
|
+
best_matches = []
|
|
77
|
+
for b in target_attributes:
|
|
78
|
+
dist = _euclidean_dist(input_attributes[a], target_attributes[b])
|
|
79
|
+
if dist < best_dist:
|
|
80
|
+
best_matches = [b]
|
|
81
|
+
best_dist = dist
|
|
82
|
+
elif dist == best_dist:
|
|
83
|
+
best_matches.append(b)
|
|
84
|
+
closest_matches[a] = best_matches
|
|
85
|
+
|
|
86
|
+
return closest_matches
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# from https://rosettacode.org/wiki/Levenshtein_distance
|
|
90
|
+
def _levenshtein_distance(s1, s2):
|
|
91
|
+
"""
|
|
92
|
+
:param s1: A list or string
|
|
93
|
+
:param s2: Another list or string
|
|
94
|
+
:returns: The levenshtein distance between the two
|
|
95
|
+
"""
|
|
96
|
+
if len(s1) > len(s2):
|
|
97
|
+
s1, s2 = s2, s1
|
|
98
|
+
distances = range(len(s1) + 1)
|
|
99
|
+
for index2, num2 in enumerate(s2):
|
|
100
|
+
new_distances = [index2 + 1]
|
|
101
|
+
for index1, num1 in enumerate(s1):
|
|
102
|
+
if num1 == num2:
|
|
103
|
+
new_distances.append(distances[index1])
|
|
104
|
+
else:
|
|
105
|
+
new_distances.append(1 + min((distances[index1], distances[index1 + 1], new_distances[-1])))
|
|
106
|
+
distances = new_distances
|
|
107
|
+
return distances[-1]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _normalized_levenshtein_distance(s1, s2, acceptable_differences):
|
|
111
|
+
"""
|
|
112
|
+
This function calculates the levenshtein distance but allows for elements in the lists to be different by any number
|
|
113
|
+
in the set acceptable_differences.
|
|
114
|
+
|
|
115
|
+
:param s1: A list.
|
|
116
|
+
:param s2: Another list.
|
|
117
|
+
:param acceptable_differences: A set of numbers. If (s2[i]-s1[i]) is in the set then they are considered equal.
|
|
118
|
+
:returns:
|
|
119
|
+
"""
|
|
120
|
+
if len(s1) > len(s2):
|
|
121
|
+
s1, s2 = s2, s1
|
|
122
|
+
acceptable_differences = {-i for i in acceptable_differences}
|
|
123
|
+
distances = range(len(s1) + 1)
|
|
124
|
+
for index2, num2 in enumerate(s2):
|
|
125
|
+
new_distances = [index2 + 1]
|
|
126
|
+
for index1, num1 in enumerate(s1):
|
|
127
|
+
if num2 - num1 in acceptable_differences:
|
|
128
|
+
new_distances.append(distances[index1])
|
|
129
|
+
else:
|
|
130
|
+
new_distances.append(1 + min((distances[index1], distances[index1 + 1], new_distances[-1])))
|
|
131
|
+
distances = new_distances
|
|
132
|
+
return distances[-1]
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _is_better_match(x, y, matched_a, matched_b, attributes_dict_a, attributes_dict_b):
|
|
136
|
+
"""
|
|
137
|
+
:param x: The first element of a possible match.
|
|
138
|
+
:param y: The second element of a possible match.
|
|
139
|
+
:param matched_a: The current matches for the first set.
|
|
140
|
+
:param matched_b: The current matches for the second set.
|
|
141
|
+
:param attributes_dict_a: The attributes for each element in the first set.
|
|
142
|
+
:param attributes_dict_b: The attributes for each element in the second set.
|
|
143
|
+
:returns: True/False
|
|
144
|
+
"""
|
|
145
|
+
if x not in attributes_dict_a or y not in attributes_dict_b:
|
|
146
|
+
return False
|
|
147
|
+
|
|
148
|
+
attributes_x = attributes_dict_a[x]
|
|
149
|
+
attributes_y = attributes_dict_b[y]
|
|
150
|
+
if x in matched_a:
|
|
151
|
+
attributes_match = attributes_dict_b[matched_a[x]]
|
|
152
|
+
if _euclidean_dist(attributes_x, attributes_y) >= _euclidean_dist(attributes_x, attributes_match):
|
|
153
|
+
return False
|
|
154
|
+
if y in matched_b:
|
|
155
|
+
attributes_match = attributes_dict_a[matched_b[y]]
|
|
156
|
+
if _euclidean_dist(attributes_x, attributes_y) >= _euclidean_dist(attributes_y, attributes_match):
|
|
157
|
+
return False
|
|
158
|
+
return True
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def differing_constants(block_a, block_b):
|
|
162
|
+
"""
|
|
163
|
+
Compares two basic blocks and finds all the constants that differ from the first block to the second.
|
|
164
|
+
|
|
165
|
+
:param block_a: The first block to compare.
|
|
166
|
+
:param block_b: The second block to compare.
|
|
167
|
+
:returns: Returns a list of differing constants in the form of ConstantChange, which has the offset in the
|
|
168
|
+
block and the respective constants.
|
|
169
|
+
"""
|
|
170
|
+
if block_a.size == 0 or block_b.size == 0:
|
|
171
|
+
return []
|
|
172
|
+
if not block_a.instruction_addrs or not block_b.instruction_addrs:
|
|
173
|
+
return []
|
|
174
|
+
|
|
175
|
+
statements_a = [s for s in block_a.vex.statements if s.tag != "Ist_IMark"] + [block_a.vex.next]
|
|
176
|
+
statements_b = [s for s in block_b.vex.statements if s.tag != "Ist_IMark"] + [block_b.vex.next]
|
|
177
|
+
if len(statements_a) != len(statements_b):
|
|
178
|
+
raise UnmatchedStatementsException("Blocks have different numbers of statements")
|
|
179
|
+
|
|
180
|
+
start_1 = min(block_a.instruction_addrs)
|
|
181
|
+
start_2 = min(block_b.instruction_addrs)
|
|
182
|
+
|
|
183
|
+
changes = []
|
|
184
|
+
|
|
185
|
+
# check statements
|
|
186
|
+
current_offset = None
|
|
187
|
+
for statement, statement_2 in zip(statements_a, statements_b):
|
|
188
|
+
# sanity check
|
|
189
|
+
if statement.tag != statement_2.tag:
|
|
190
|
+
raise UnmatchedStatementsException("Statement tag has changed")
|
|
191
|
+
|
|
192
|
+
if statement.tag == "Ist_IMark":
|
|
193
|
+
if statement.addr - start_1 != statement_2.addr - start_2:
|
|
194
|
+
raise UnmatchedStatementsException("Instruction length has changed")
|
|
195
|
+
current_offset = statement.addr - start_1
|
|
196
|
+
continue
|
|
197
|
+
|
|
198
|
+
differences = compare_statement_dict(statement, statement_2)
|
|
199
|
+
for d in differences:
|
|
200
|
+
if d.type != DIFF_VALUE:
|
|
201
|
+
raise UnmatchedStatementsException("Instruction has changed")
|
|
202
|
+
changes.append(ConstantChange(current_offset, d.value_a, d.value_b))
|
|
203
|
+
|
|
204
|
+
return changes
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def compare_statement_dict(statement_1, statement_2):
|
|
208
|
+
# should return whether or not the statement's type/effects changed
|
|
209
|
+
# need to return the specific number that changed too
|
|
210
|
+
|
|
211
|
+
if type(statement_1) is not type(statement_2):
|
|
212
|
+
return [Difference(DIFF_TYPE, None, None)]
|
|
213
|
+
|
|
214
|
+
# None
|
|
215
|
+
if statement_1 is None and statement_2 is None:
|
|
216
|
+
return []
|
|
217
|
+
|
|
218
|
+
# constants
|
|
219
|
+
if isinstance(statement_1, (int, float, str, bytes)):
|
|
220
|
+
if (
|
|
221
|
+
isinstance(statement_1, float) and math.isnan(statement_1) and math.isnan(statement_2)
|
|
222
|
+
) or statement_1 == statement_2:
|
|
223
|
+
return []
|
|
224
|
+
return [Difference(None, statement_1, statement_2)]
|
|
225
|
+
|
|
226
|
+
# tuples/lists
|
|
227
|
+
if isinstance(statement_1, (tuple, list)):
|
|
228
|
+
if len(statement_1) != len(statement_2):
|
|
229
|
+
return Difference(DIFF_TYPE, None, None)
|
|
230
|
+
|
|
231
|
+
differences = []
|
|
232
|
+
for s1, s2 in zip(statement_1, statement_2):
|
|
233
|
+
differences += compare_statement_dict(s1, s2)
|
|
234
|
+
return differences
|
|
235
|
+
|
|
236
|
+
# Yan's weird types
|
|
237
|
+
differences = []
|
|
238
|
+
for attr in statement_1.__slots__:
|
|
239
|
+
# don't check arch, property, or methods
|
|
240
|
+
if attr == "arch":
|
|
241
|
+
continue
|
|
242
|
+
if hasattr(statement_1.__class__, attr) and isinstance(getattr(statement_1.__class__, attr), property):
|
|
243
|
+
continue
|
|
244
|
+
if isinstance(getattr(statement_1, attr), types.MethodType):
|
|
245
|
+
continue
|
|
246
|
+
|
|
247
|
+
new_diffs = compare_statement_dict(getattr(statement_1, attr), getattr(statement_2, attr))
|
|
248
|
+
# set the difference types
|
|
249
|
+
for diff in new_diffs:
|
|
250
|
+
if diff.type is None:
|
|
251
|
+
diff.type = attr
|
|
252
|
+
differences += new_diffs
|
|
253
|
+
|
|
254
|
+
return differences
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class NormalizedBlock:
|
|
258
|
+
# block may span multiple calls
|
|
259
|
+
def __init__(self, block, function):
|
|
260
|
+
addresses = [block.addr]
|
|
261
|
+
if block.addr in function.merged_blocks:
|
|
262
|
+
for a in function.merged_blocks[block.addr]:
|
|
263
|
+
addresses.append(a.addr)
|
|
264
|
+
|
|
265
|
+
self.addr = block.addr
|
|
266
|
+
self.addresses = addresses
|
|
267
|
+
self.statements = []
|
|
268
|
+
self.all_constants = []
|
|
269
|
+
self.operations = []
|
|
270
|
+
self.call_targets = []
|
|
271
|
+
self.blocks = []
|
|
272
|
+
self.instruction_addrs = []
|
|
273
|
+
|
|
274
|
+
if block.addr in function.call_sites:
|
|
275
|
+
self.call_targets = function.call_sites[block.addr]
|
|
276
|
+
|
|
277
|
+
self.jumpkind = None
|
|
278
|
+
|
|
279
|
+
for a in addresses:
|
|
280
|
+
block = function.project.factory.block(a)
|
|
281
|
+
self.instruction_addrs += block.instruction_addrs
|
|
282
|
+
irsb = block.vex
|
|
283
|
+
self.blocks.append(block)
|
|
284
|
+
self.statements += irsb.statements
|
|
285
|
+
self.all_constants += irsb.all_constants
|
|
286
|
+
self.operations += irsb.operations
|
|
287
|
+
self.jumpkind = irsb.jumpkind
|
|
288
|
+
|
|
289
|
+
self.size = sum([b.size for b in self.blocks])
|
|
290
|
+
|
|
291
|
+
def __repr__(self):
|
|
292
|
+
size = sum([b.size for b in self.blocks])
|
|
293
|
+
return f"<Normalized Block for {self.addr:#x}, {size} bytes>"
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class NormalizedFunction:
|
|
297
|
+
# a more normalized function
|
|
298
|
+
def __init__(self, function: Function):
|
|
299
|
+
# start by copying the graph
|
|
300
|
+
self.graph: networkx.DiGraph = function.graph.copy()
|
|
301
|
+
self.project = function._function_manager._kb._project
|
|
302
|
+
self.call_sites = {}
|
|
303
|
+
self.startpoint = function.startpoint
|
|
304
|
+
self.merged_blocks = {}
|
|
305
|
+
self.orig_function = function
|
|
306
|
+
|
|
307
|
+
# find nodes which end in call and combine them
|
|
308
|
+
done = False
|
|
309
|
+
while not done:
|
|
310
|
+
done = True
|
|
311
|
+
for node in self.graph.nodes():
|
|
312
|
+
try:
|
|
313
|
+
bl = self.project.factory.block(node.addr)
|
|
314
|
+
except (SimMemoryError, SimEngineError):
|
|
315
|
+
continue
|
|
316
|
+
|
|
317
|
+
# merge if it ends with a single call, and the successor has only one predecessor and succ is after
|
|
318
|
+
successors = list(self.graph.successors(node))
|
|
319
|
+
if (
|
|
320
|
+
bl.vex.jumpkind == "Ijk_Call"
|
|
321
|
+
and len(successors) == 1
|
|
322
|
+
and len(list(self.graph.predecessors(successors[0]))) == 1
|
|
323
|
+
and successors[0].addr > node.addr
|
|
324
|
+
):
|
|
325
|
+
# add edges to the successors of its successor, and delete the original successors
|
|
326
|
+
succ = next(iter(self.graph.successors(node)))
|
|
327
|
+
for s in self.graph.successors(succ):
|
|
328
|
+
self.graph.add_edge(node, s)
|
|
329
|
+
self.graph.remove_node(succ)
|
|
330
|
+
done = False
|
|
331
|
+
|
|
332
|
+
# add to merged blocks
|
|
333
|
+
if node not in self.merged_blocks:
|
|
334
|
+
self.merged_blocks[node] = []
|
|
335
|
+
self.merged_blocks[node].append(succ)
|
|
336
|
+
if succ in self.merged_blocks:
|
|
337
|
+
self.merged_blocks[node] += self.merged_blocks[succ]
|
|
338
|
+
del self.merged_blocks[succ]
|
|
339
|
+
|
|
340
|
+
# stop iterating and start over
|
|
341
|
+
break
|
|
342
|
+
|
|
343
|
+
# set up call sites
|
|
344
|
+
for n in self.graph.nodes():
|
|
345
|
+
call_targets = []
|
|
346
|
+
if n.addr in self.orig_function.get_call_sites():
|
|
347
|
+
call_targets.append(self.orig_function.get_call_target(n.addr))
|
|
348
|
+
if n.addr in self.merged_blocks:
|
|
349
|
+
for block in self.merged_blocks[n]:
|
|
350
|
+
if block.addr in self.orig_function.get_call_sites():
|
|
351
|
+
call_targets.append(self.orig_function.get_call_target(block.addr))
|
|
352
|
+
if len(call_targets) > 0:
|
|
353
|
+
self.call_sites[n] = call_targets
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
class FunctionDiff:
|
|
357
|
+
"""
|
|
358
|
+
This class computes the a diff between two functions.
|
|
359
|
+
"""
|
|
360
|
+
|
|
361
|
+
def __init__(self, function_a: Function, function_b: Function, bindiff=None):
|
|
362
|
+
"""
|
|
363
|
+
:param function_a: The first angr Function object to diff.
|
|
364
|
+
:param function_b: The second angr Function object.
|
|
365
|
+
:param bindiff: An optional Bindiff object. Used for some extra normalization during basic block comparison.
|
|
366
|
+
"""
|
|
367
|
+
self._function_a = NormalizedFunction(function_a)
|
|
368
|
+
self._function_b = NormalizedFunction(function_b)
|
|
369
|
+
self._project_a = self._function_a.project
|
|
370
|
+
self._project_b = self._function_b.project
|
|
371
|
+
self._bindiff = bindiff
|
|
372
|
+
|
|
373
|
+
self._attributes_a = {}
|
|
374
|
+
self._attributes_b = {}
|
|
375
|
+
|
|
376
|
+
self._block_matches = set()
|
|
377
|
+
self._unmatched_blocks_from_a = set()
|
|
378
|
+
self._unmatched_blocks_from_b = set()
|
|
379
|
+
|
|
380
|
+
self._compute_diff()
|
|
381
|
+
|
|
382
|
+
@property
|
|
383
|
+
def probably_identical(self):
|
|
384
|
+
"""
|
|
385
|
+
:returns: Whether or not these two functions are identical.
|
|
386
|
+
"""
|
|
387
|
+
if len(self._unmatched_blocks_from_a | self._unmatched_blocks_from_b) > 0:
|
|
388
|
+
return False
|
|
389
|
+
return all(self.blocks_probably_identical(a, b) for a, b in self._block_matches)
|
|
390
|
+
|
|
391
|
+
@property
|
|
392
|
+
def identical_blocks(self):
|
|
393
|
+
"""
|
|
394
|
+
:returns: A list of block matches which appear to be identical
|
|
395
|
+
"""
|
|
396
|
+
identical_blocks = []
|
|
397
|
+
for block_a, block_b in self._block_matches:
|
|
398
|
+
if self.blocks_probably_identical(block_a, block_b):
|
|
399
|
+
identical_blocks.append((block_a, block_b))
|
|
400
|
+
return identical_blocks
|
|
401
|
+
|
|
402
|
+
@property
|
|
403
|
+
def differing_blocks(self):
|
|
404
|
+
"""
|
|
405
|
+
:returns: A list of block matches which appear to differ
|
|
406
|
+
"""
|
|
407
|
+
differing_blocks = []
|
|
408
|
+
for block_a, block_b in self._block_matches:
|
|
409
|
+
if not self.blocks_probably_identical(block_a, block_b):
|
|
410
|
+
differing_blocks.append((block_a, block_b))
|
|
411
|
+
return differing_blocks
|
|
412
|
+
|
|
413
|
+
@property
|
|
414
|
+
def blocks_with_differing_constants(self):
|
|
415
|
+
"""
|
|
416
|
+
:return: A list of block matches which appear to differ
|
|
417
|
+
"""
|
|
418
|
+
differing_blocks = []
|
|
419
|
+
diffs = {}
|
|
420
|
+
for block_a, block_b in self._block_matches:
|
|
421
|
+
if self.blocks_probably_identical(block_a, block_b) and not self.blocks_probably_identical(
|
|
422
|
+
block_a, block_b, check_constants=True
|
|
423
|
+
):
|
|
424
|
+
differing_blocks.append((block_a, block_b))
|
|
425
|
+
for block_a, block_b in differing_blocks:
|
|
426
|
+
ba = NormalizedBlock(block_a, self._function_a)
|
|
427
|
+
bb = NormalizedBlock(block_b, self._function_b)
|
|
428
|
+
diffs[(block_a, block_b)] = FunctionDiff._block_diff_constants(ba, bb)
|
|
429
|
+
return diffs
|
|
430
|
+
|
|
431
|
+
@property
|
|
432
|
+
def block_matches(self):
|
|
433
|
+
return self._block_matches
|
|
434
|
+
|
|
435
|
+
@property
|
|
436
|
+
def unmatched_blocks(self):
|
|
437
|
+
return self._unmatched_blocks_from_a, self._unmatched_blocks_from_b
|
|
438
|
+
|
|
439
|
+
@staticmethod
|
|
440
|
+
def get_normalized_block(addr, function):
|
|
441
|
+
"""
|
|
442
|
+
:param addr: Where to start the normalized block.
|
|
443
|
+
:param function: A function containing the block address.
|
|
444
|
+
:returns: A normalized basic block.
|
|
445
|
+
"""
|
|
446
|
+
return NormalizedBlock(addr, function)
|
|
447
|
+
|
|
448
|
+
def block_similarity(self, block_a, block_b):
|
|
449
|
+
"""
|
|
450
|
+
:param block_a: The first block address.
|
|
451
|
+
:param block_b: The second block address.
|
|
452
|
+
:returns: The similarity of the basic blocks, normalized for the base address of the block and function
|
|
453
|
+
call addresses.
|
|
454
|
+
"""
|
|
455
|
+
|
|
456
|
+
# handle sim procedure blocks
|
|
457
|
+
if self._project_a.is_hooked(block_a) and self._project_b.is_hooked(block_b):
|
|
458
|
+
if self._project_a._sim_procedures[block_a] == self._project_b._sim_procedures[block_b]:
|
|
459
|
+
return 1.0
|
|
460
|
+
return 0.0
|
|
461
|
+
|
|
462
|
+
try:
|
|
463
|
+
block_a = NormalizedBlock(block_a, self._function_a)
|
|
464
|
+
except (SimMemoryError, SimEngineError):
|
|
465
|
+
block_a = None
|
|
466
|
+
|
|
467
|
+
try:
|
|
468
|
+
block_b = NormalizedBlock(block_b, self._function_b)
|
|
469
|
+
except (SimMemoryError, SimEngineError):
|
|
470
|
+
block_b = None
|
|
471
|
+
|
|
472
|
+
# if both were None then they are assumed to be the same, if only one was the same they are assumed to differ
|
|
473
|
+
if block_a is None and block_b is None:
|
|
474
|
+
return 1.0
|
|
475
|
+
if block_a is None or block_b is None:
|
|
476
|
+
return 0.0
|
|
477
|
+
|
|
478
|
+
# get all elements for computing similarity
|
|
479
|
+
tags_a = [s.tag for s in block_a.statements]
|
|
480
|
+
tags_b = [s.tag for s in block_b.statements]
|
|
481
|
+
consts_a = [c.value for c in block_a.all_constants]
|
|
482
|
+
consts_b = [c.value for c in block_b.all_constants]
|
|
483
|
+
all_registers_a = [s.offset for s in block_a.statements if hasattr(s, "offset")]
|
|
484
|
+
all_registers_b = [s.offset for s in block_b.statements if hasattr(s, "offset")]
|
|
485
|
+
jumpkind_a = block_a.jumpkind
|
|
486
|
+
jumpkind_b = block_b.jumpkind
|
|
487
|
+
|
|
488
|
+
# compute total distance
|
|
489
|
+
total_dist = 0
|
|
490
|
+
total_dist += _levenshtein_distance(tags_a, tags_b)
|
|
491
|
+
total_dist += _levenshtein_distance(block_a.operations, block_b.operations)
|
|
492
|
+
total_dist += _levenshtein_distance(all_registers_a, all_registers_b)
|
|
493
|
+
acceptable_differences = self._get_acceptable_constant_differences(block_a, block_b)
|
|
494
|
+
total_dist += _normalized_levenshtein_distance(consts_a, consts_b, acceptable_differences)
|
|
495
|
+
total_dist += 0 if jumpkind_a == jumpkind_b else 1
|
|
496
|
+
|
|
497
|
+
# compute similarity
|
|
498
|
+
num_values = max(len(tags_a), len(tags_b))
|
|
499
|
+
num_values += max(len(consts_a), len(consts_b))
|
|
500
|
+
num_values += max(len(block_a.operations), len(block_b.operations))
|
|
501
|
+
num_values += 1 # jumpkind
|
|
502
|
+
return 1 - (float(total_dist) / num_values)
|
|
503
|
+
|
|
504
|
+
def blocks_probably_identical(self, block_a, block_b, check_constants=False):
|
|
505
|
+
"""
|
|
506
|
+
:param block_a: The first block address.
|
|
507
|
+
:param block_b: The second block address.
|
|
508
|
+
:param check_constants: Whether or not to require matching constants in blocks.
|
|
509
|
+
:returns: Whether or not the blocks appear to be identical.
|
|
510
|
+
"""
|
|
511
|
+
# handle sim procedure blocks
|
|
512
|
+
if self._project_a.is_hooked(block_a) and self._project_b.is_hooked(block_b):
|
|
513
|
+
return self._project_a._sim_procedures[block_a] == self._project_b._sim_procedures[block_b]
|
|
514
|
+
|
|
515
|
+
try:
|
|
516
|
+
block_a = NormalizedBlock(block_a, self._function_a)
|
|
517
|
+
except (SimMemoryError, SimEngineError):
|
|
518
|
+
block_a = None
|
|
519
|
+
|
|
520
|
+
try:
|
|
521
|
+
block_b = NormalizedBlock(block_b, self._function_b)
|
|
522
|
+
except (SimMemoryError, SimEngineError):
|
|
523
|
+
block_b = None
|
|
524
|
+
|
|
525
|
+
# if both were None then they are assumed to be the same, if only one was None they are assumed to differ
|
|
526
|
+
if block_a is None and block_b is None:
|
|
527
|
+
return True
|
|
528
|
+
if block_a is None or block_b is None:
|
|
529
|
+
return False
|
|
530
|
+
|
|
531
|
+
# if they represent a different number of blocks they are not the same
|
|
532
|
+
if len(block_a.blocks) != len(block_b.blocks):
|
|
533
|
+
return False
|
|
534
|
+
|
|
535
|
+
# check differing constants
|
|
536
|
+
try:
|
|
537
|
+
diff_constants = FunctionDiff._block_diff_constants(block_a, block_b)
|
|
538
|
+
except UnmatchedStatementsException:
|
|
539
|
+
return False
|
|
540
|
+
|
|
541
|
+
if not check_constants:
|
|
542
|
+
return True
|
|
543
|
+
|
|
544
|
+
# get values of differences that probably indicate no change
|
|
545
|
+
acceptable_differences = self._get_acceptable_constant_differences(block_a, block_b)
|
|
546
|
+
|
|
547
|
+
# todo match globals
|
|
548
|
+
for c in diff_constants:
|
|
549
|
+
if (c.value_a, c.value_b) in self._block_matches:
|
|
550
|
+
# constants point to matched basic blocks
|
|
551
|
+
continue
|
|
552
|
+
if self._bindiff is not None and (c.value_a and c.value_b) in self._bindiff.function_matches:
|
|
553
|
+
# constants point to matched functions
|
|
554
|
+
continue
|
|
555
|
+
# if both are in the binary we'll assume it's okay, although we should really match globals
|
|
556
|
+
# TODO use global matches
|
|
557
|
+
if self._project_a.loader.main_object.contains_addr(
|
|
558
|
+
c.value_a
|
|
559
|
+
) and self._project_b.loader.main_object.contains_addr(c.value_b):
|
|
560
|
+
continue
|
|
561
|
+
# if the difference is equal to the difference in block addr's or successor addr's we'll say it's also okay
|
|
562
|
+
if c.value_b - c.value_a in acceptable_differences:
|
|
563
|
+
continue
|
|
564
|
+
# otherwise they probably are different
|
|
565
|
+
return False
|
|
566
|
+
|
|
567
|
+
# the blocks appear to be identical
|
|
568
|
+
return True
|
|
569
|
+
|
|
570
|
+
@staticmethod
|
|
571
|
+
def _block_diff_constants(block_a, block_b):
|
|
572
|
+
diff_constants = []
|
|
573
|
+
for irsb_a, irsb_b in zip(block_a.blocks, block_b.blocks):
|
|
574
|
+
diff_constants += differing_constants(irsb_a, irsb_b)
|
|
575
|
+
return diff_constants
|
|
576
|
+
|
|
577
|
+
@staticmethod
|
|
578
|
+
def _compute_block_attributes(function: NormalizedFunction):
|
|
579
|
+
"""
|
|
580
|
+
:param function: A normalized function object.
|
|
581
|
+
:returns: A dictionary of basic block addresses to tuples of attributes.
|
|
582
|
+
"""
|
|
583
|
+
# The attributes we use are the distance form function start, distance from function exit and whether
|
|
584
|
+
# or not it has a subfunction call
|
|
585
|
+
distances_from_start = FunctionDiff._distances_from_function_start(function)
|
|
586
|
+
distances_from_exit = FunctionDiff._distances_from_function_exit(function)
|
|
587
|
+
call_sites = function.call_sites
|
|
588
|
+
|
|
589
|
+
attributes = {}
|
|
590
|
+
for block in function.graph.nodes():
|
|
591
|
+
number_of_subfunction_calls = len(call_sites[block]) if block in call_sites else 0
|
|
592
|
+
# there really shouldn't be blocks that can't be reached from the start, but there are for now
|
|
593
|
+
dist_start = distances_from_start.get(block, 10000)
|
|
594
|
+
dist_exit = distances_from_exit.get(block, 10000)
|
|
595
|
+
|
|
596
|
+
attributes[block] = (dist_start, dist_exit, number_of_subfunction_calls)
|
|
597
|
+
|
|
598
|
+
return attributes
|
|
599
|
+
|
|
600
|
+
@staticmethod
|
|
601
|
+
def _distances_from_function_start(function: NormalizedFunction):
|
|
602
|
+
"""
|
|
603
|
+
:param function: A normalized Function object.
|
|
604
|
+
:returns: A dictionary of basic block addresses and their distance to the start of the function.
|
|
605
|
+
"""
|
|
606
|
+
return networkx.single_source_shortest_path_length(function.graph, function.startpoint)
|
|
607
|
+
|
|
608
|
+
@staticmethod
|
|
609
|
+
def _distances_from_function_exit(function: NormalizedFunction):
|
|
610
|
+
"""
|
|
611
|
+
:param function: A normalized Function object.
|
|
612
|
+
:returns: A dictionary of basic block addresses and their distance to the exit of the function.
|
|
613
|
+
"""
|
|
614
|
+
reverse_graph: networkx.DiGraph = function.graph.reverse()
|
|
615
|
+
# we aren't guaranteed to have an exit from the function so explicitly add the node
|
|
616
|
+
reverse_graph.add_node("start")
|
|
617
|
+
found_exits = False
|
|
618
|
+
for n in function.graph.nodes():
|
|
619
|
+
if len(list(function.graph.successors(n))) == 0:
|
|
620
|
+
reverse_graph.add_edge("start", n)
|
|
621
|
+
found_exits = True
|
|
622
|
+
|
|
623
|
+
# if there were no exits (a function with a while 1) let's consider the block with the highest address to
|
|
624
|
+
# be the exit. This isn't the most scientific way, but since this case is pretty rare it should be okay
|
|
625
|
+
if not found_exits:
|
|
626
|
+
last = max(function.graph.nodes(), key=lambda x: x.addr)
|
|
627
|
+
reverse_graph.add_edge("start", last)
|
|
628
|
+
|
|
629
|
+
dists = networkx.single_source_shortest_path_length(reverse_graph, "start")
|
|
630
|
+
|
|
631
|
+
# remove temp node
|
|
632
|
+
del dists["start"]
|
|
633
|
+
|
|
634
|
+
# correct for the added node
|
|
635
|
+
for n in dists:
|
|
636
|
+
dists[n] -= 1
|
|
637
|
+
|
|
638
|
+
return dists
|
|
639
|
+
|
|
640
|
+
def _compute_diff(self):
|
|
641
|
+
"""
|
|
642
|
+
Computes the diff of the functions and saves the result.
|
|
643
|
+
"""
|
|
644
|
+
# get the attributes for all blocks
|
|
645
|
+
l.debug(
|
|
646
|
+
"Computing diff of functions: %s, %s",
|
|
647
|
+
(f"{self._function_a.startpoint.addr:#x}") if self._function_a.startpoint is not None else "None",
|
|
648
|
+
(f"{self._function_b.startpoint.addr:#x}") if self._function_b.startpoint is not None else "None",
|
|
649
|
+
)
|
|
650
|
+
self.attributes_a = self._compute_block_attributes(self._function_a)
|
|
651
|
+
self.attributes_b = self._compute_block_attributes(self._function_b)
|
|
652
|
+
|
|
653
|
+
# get the initial matches
|
|
654
|
+
initial_matches = self._get_block_matches(
|
|
655
|
+
self.attributes_a, self.attributes_b, tiebreak_with_block_similarity=False
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
# Use a queue so we process matches in the order that they are found
|
|
659
|
+
to_process = deque(initial_matches)
|
|
660
|
+
|
|
661
|
+
# Keep track of which matches we've already added to the queue
|
|
662
|
+
processed_matches = set(initial_matches)
|
|
663
|
+
|
|
664
|
+
# Keep a dict of current matches, which will be updated if better matches are found
|
|
665
|
+
matched_a = {}
|
|
666
|
+
matched_b = {}
|
|
667
|
+
for x, y in processed_matches:
|
|
668
|
+
matched_a[x] = y
|
|
669
|
+
matched_b[y] = x
|
|
670
|
+
|
|
671
|
+
# while queue is not empty
|
|
672
|
+
while to_process:
|
|
673
|
+
(block_a, block_b) = to_process.pop()
|
|
674
|
+
l.debug("FunctionDiff: Processing (%#x, %#x)", block_a.addr, block_b.addr)
|
|
675
|
+
|
|
676
|
+
# we could find new matches in the successors or predecessors of functions
|
|
677
|
+
block_a_succ = list(self._function_a.graph.successors(block_a))
|
|
678
|
+
block_b_succ = list(self._function_b.graph.successors(block_b))
|
|
679
|
+
block_a_pred = list(self._function_a.graph.predecessors(block_a))
|
|
680
|
+
block_b_pred = list(self._function_b.graph.predecessors(block_b))
|
|
681
|
+
|
|
682
|
+
# propagate the difference in blocks as delta
|
|
683
|
+
delta = tuple((i - j) for i, j in zip(self.attributes_b[block_b], self.attributes_a[block_a]))
|
|
684
|
+
|
|
685
|
+
# get possible new matches
|
|
686
|
+
new_matches = []
|
|
687
|
+
|
|
688
|
+
# if the blocks are identical then the successors should most likely be matched in the same order
|
|
689
|
+
if self.blocks_probably_identical(block_a, block_b) and len(block_a_succ) == len(block_b_succ):
|
|
690
|
+
ordered_succ_a = self._get_ordered_successors(self._project_a, block_a, block_a_succ)
|
|
691
|
+
ordered_succ_b = self._get_ordered_successors(self._project_b, block_b, block_b_succ)
|
|
692
|
+
new_matches.extend(zip(ordered_succ_a, ordered_succ_b))
|
|
693
|
+
|
|
694
|
+
new_matches += self._get_block_matches(
|
|
695
|
+
self.attributes_a,
|
|
696
|
+
self.attributes_b,
|
|
697
|
+
block_a_succ,
|
|
698
|
+
block_b_succ,
|
|
699
|
+
delta,
|
|
700
|
+
tiebreak_with_block_similarity=True,
|
|
701
|
+
)
|
|
702
|
+
new_matches += self._get_block_matches(
|
|
703
|
+
self.attributes_a,
|
|
704
|
+
self.attributes_b,
|
|
705
|
+
block_a_pred,
|
|
706
|
+
block_b_pred,
|
|
707
|
+
delta,
|
|
708
|
+
tiebreak_with_block_similarity=True,
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
# for each of the possible new matches add it if it improves the matching
|
|
712
|
+
for x, y in new_matches:
|
|
713
|
+
if (x, y) not in processed_matches:
|
|
714
|
+
processed_matches.add((x, y))
|
|
715
|
+
l.debug("FunctionDiff: checking if (%#x, %#x) is better", x.addr, y.addr)
|
|
716
|
+
# if it's a better match than what we already have use it
|
|
717
|
+
if _is_better_match(x, y, matched_a, matched_b, self.attributes_a, self.attributes_b):
|
|
718
|
+
l.debug("FunctionDiff: adding possible match (%#x, %#x)", x.addr, y.addr)
|
|
719
|
+
if x in matched_a:
|
|
720
|
+
old_match = matched_a[x]
|
|
721
|
+
del matched_b[old_match]
|
|
722
|
+
if y in matched_b:
|
|
723
|
+
old_match = matched_b[y]
|
|
724
|
+
del matched_a[old_match]
|
|
725
|
+
matched_a[x] = y
|
|
726
|
+
matched_b[y] = x
|
|
727
|
+
to_process.appendleft((x, y))
|
|
728
|
+
|
|
729
|
+
# reformat matches into a set of pairs
|
|
730
|
+
self._block_matches = set(matched_a.items())
|
|
731
|
+
|
|
732
|
+
# get the unmatched blocks
|
|
733
|
+
self._unmatched_blocks_from_a = {x for x in self._function_a.graph.nodes() if x not in matched_a}
|
|
734
|
+
self._unmatched_blocks_from_b = {x for x in self._function_b.graph.nodes() if x not in matched_b}
|
|
735
|
+
|
|
736
|
+
@staticmethod
|
|
737
|
+
def _get_ordered_successors(project, block, succ):
|
|
738
|
+
try:
|
|
739
|
+
# add them in order of the vex
|
|
740
|
+
addr = block.addr
|
|
741
|
+
succ = set(succ)
|
|
742
|
+
ordered_succ = []
|
|
743
|
+
bl = project.factory.block(addr)
|
|
744
|
+
for x in bl.vex.all_constants:
|
|
745
|
+
if x in succ:
|
|
746
|
+
ordered_succ.append(x)
|
|
747
|
+
|
|
748
|
+
# add the rest (sorting might be better than no order)
|
|
749
|
+
for s in sorted(succ - set(ordered_succ), key=lambda x: x.addr):
|
|
750
|
+
ordered_succ.append(s)
|
|
751
|
+
return ordered_succ
|
|
752
|
+
except (SimMemoryError, SimEngineError):
|
|
753
|
+
return sorted(succ, key=lambda x: x.addr)
|
|
754
|
+
|
|
755
|
+
def _get_block_matches(
|
|
756
|
+
self,
|
|
757
|
+
attributes_a,
|
|
758
|
+
attributes_b,
|
|
759
|
+
filter_set_a=None,
|
|
760
|
+
filter_set_b=None,
|
|
761
|
+
delta=(0, 0, 0),
|
|
762
|
+
tiebreak_with_block_similarity=False,
|
|
763
|
+
):
|
|
764
|
+
"""
|
|
765
|
+
:param attributes_a: A dict of blocks to their attributes
|
|
766
|
+
:param attributes_b: A dict of blocks to their attributes
|
|
767
|
+
|
|
768
|
+
The following parameters are optional.
|
|
769
|
+
|
|
770
|
+
:param filter_set_a: A set to limit attributes_a to the blocks in this set.
|
|
771
|
+
:param filter_set_b: A set to limit attributes_b to the blocks in this set.
|
|
772
|
+
:param delta: An offset to add to each vector in attributes_a.
|
|
773
|
+
:returns: A list of tuples of matching objects.
|
|
774
|
+
"""
|
|
775
|
+
# get the attributes that are in the sets
|
|
776
|
+
if filter_set_a is None:
|
|
777
|
+
filtered_attributes_a = dict(attributes_a.items())
|
|
778
|
+
else:
|
|
779
|
+
filtered_attributes_a = {k: v for k, v in attributes_a.items() if k in filter_set_a}
|
|
780
|
+
|
|
781
|
+
if filter_set_b is None:
|
|
782
|
+
filtered_attributes_b = dict(attributes_b.items())
|
|
783
|
+
else:
|
|
784
|
+
filtered_attributes_b = {k: v for k, v in attributes_b.items() if k in filter_set_b}
|
|
785
|
+
|
|
786
|
+
# add delta
|
|
787
|
+
for k in filtered_attributes_a:
|
|
788
|
+
filtered_attributes_a[k] = tuple((i + j) for i, j in zip(filtered_attributes_a[k], delta))
|
|
789
|
+
for k in filtered_attributes_b:
|
|
790
|
+
filtered_attributes_b[k] = tuple((i + j) for i, j in zip(filtered_attributes_b[k], delta))
|
|
791
|
+
|
|
792
|
+
# get closest
|
|
793
|
+
closest_a = _get_closest_matches(filtered_attributes_a, filtered_attributes_b)
|
|
794
|
+
closest_b = _get_closest_matches(filtered_attributes_b, filtered_attributes_a)
|
|
795
|
+
|
|
796
|
+
if tiebreak_with_block_similarity:
|
|
797
|
+
# use block similarity to break ties in the first set
|
|
798
|
+
for a in closest_a:
|
|
799
|
+
if len(closest_a[a]) > 1:
|
|
800
|
+
best_similarity = 0
|
|
801
|
+
best = []
|
|
802
|
+
for x in closest_a[a]:
|
|
803
|
+
similarity = self.block_similarity(a, x)
|
|
804
|
+
if similarity > best_similarity:
|
|
805
|
+
best_similarity = similarity
|
|
806
|
+
best = [x]
|
|
807
|
+
elif similarity == best_similarity:
|
|
808
|
+
best.append(x)
|
|
809
|
+
closest_a[a] = best
|
|
810
|
+
|
|
811
|
+
# use block similarity to break ties in the second set
|
|
812
|
+
for b in closest_b:
|
|
813
|
+
if len(closest_b[b]) > 1:
|
|
814
|
+
best_similarity = 0
|
|
815
|
+
best = []
|
|
816
|
+
for x in closest_b[b]:
|
|
817
|
+
similarity = self.block_similarity(x, b)
|
|
818
|
+
if similarity > best_similarity:
|
|
819
|
+
best_similarity = similarity
|
|
820
|
+
best = [x]
|
|
821
|
+
elif similarity == best_similarity:
|
|
822
|
+
best.append(x)
|
|
823
|
+
closest_b[b] = best
|
|
824
|
+
|
|
825
|
+
# a match (x,y) is good if x is the closest to y and y is the closest to x
|
|
826
|
+
matches = []
|
|
827
|
+
for a in closest_a:
|
|
828
|
+
if len(closest_a[a]) == 1:
|
|
829
|
+
match = closest_a[a][0]
|
|
830
|
+
if len(closest_b[match]) == 1 and closest_b[match][0] == a:
|
|
831
|
+
matches.append((a, match))
|
|
832
|
+
|
|
833
|
+
return matches
|
|
834
|
+
|
|
835
|
+
def _get_acceptable_constant_differences(self, block_a, block_b):
|
|
836
|
+
# keep a set of the acceptable differences in constants between the two blocks
|
|
837
|
+
acceptable_differences = set()
|
|
838
|
+
acceptable_differences.add(0)
|
|
839
|
+
|
|
840
|
+
block_a_base = block_a.instruction_addrs[0]
|
|
841
|
+
block_b_base = block_b.instruction_addrs[0]
|
|
842
|
+
acceptable_differences.add(block_b_base - block_a_base)
|
|
843
|
+
|
|
844
|
+
# get matching successors
|
|
845
|
+
for target_a, target_b in zip(block_a.call_targets, block_b.call_targets):
|
|
846
|
+
# these can be none if we couldn't resolve the call target
|
|
847
|
+
if target_a is None or target_b is None:
|
|
848
|
+
continue
|
|
849
|
+
acceptable_differences.add(target_b - target_a)
|
|
850
|
+
acceptable_differences.add((target_b - block_b_base) - (target_a - block_a_base))
|
|
851
|
+
|
|
852
|
+
# get the difference between the data segments
|
|
853
|
+
# this is hackish
|
|
854
|
+
if (
|
|
855
|
+
".bss" in self._project_a.loader.main_object.sections_map
|
|
856
|
+
and ".bss" in self._project_b.loader.main_object.sections_map
|
|
857
|
+
):
|
|
858
|
+
bss_a = self._project_a.loader.main_object.sections_map[".bss"].min_addr
|
|
859
|
+
bss_b = self._project_b.loader.main_object.sections_map[".bss"].min_addr
|
|
860
|
+
acceptable_differences.add(bss_b - bss_a)
|
|
861
|
+
acceptable_differences.add((bss_b - block_b_base) - (bss_a - block_a_base))
|
|
862
|
+
|
|
863
|
+
return acceptable_differences
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
class BinDiff(Analysis):
|
|
867
|
+
"""
|
|
868
|
+
This class computes the a diff between two binaries represented by angr Projects
|
|
869
|
+
"""
|
|
870
|
+
|
|
871
|
+
def __init__(self, other_project, cfg_a=None, cfg_b=None):
|
|
872
|
+
"""
|
|
873
|
+
:param other_project: The second project to diff
|
|
874
|
+
"""
|
|
875
|
+
if cfg_a is None:
|
|
876
|
+
l.debug("Computing cfg's")
|
|
877
|
+
self.cfg_a = self.project.analyses[CFGFast].prep(fail_fast=self._fail_fast)().model
|
|
878
|
+
self.cfg_b = other_project.analyses[CFGFast].prep(fail_fast=self._fail_fast)().model
|
|
879
|
+
l.debug("Done computing cfg's")
|
|
880
|
+
else:
|
|
881
|
+
self.cfg_a = cfg_a
|
|
882
|
+
self.cfg_b = cfg_b
|
|
883
|
+
self.funcs_a = self.kb.functions
|
|
884
|
+
self.funcs_b = other_project.kb.functions
|
|
885
|
+
|
|
886
|
+
self._p2 = other_project
|
|
887
|
+
self._attributes_a = {}
|
|
888
|
+
self._attributes_b = {}
|
|
889
|
+
|
|
890
|
+
self._function_diffs = {}
|
|
891
|
+
self.function_matches = set()
|
|
892
|
+
self._unmatched_functions_from_a = set()
|
|
893
|
+
self._unmatched_functions_from_b = set()
|
|
894
|
+
|
|
895
|
+
self._compute_diff()
|
|
896
|
+
|
|
897
|
+
def functions_probably_identical(self, func_a_addr, func_b_addr, check_consts=False):
|
|
898
|
+
"""
|
|
899
|
+
Compare two functions and return True if they appear identical.
|
|
900
|
+
|
|
901
|
+
:param func_a_addr: The address of the first function (in the first binary).
|
|
902
|
+
:param func_b_addr: The address of the second function (in the second binary).
|
|
903
|
+
:returns: Whether or not the functions appear to be identical.
|
|
904
|
+
"""
|
|
905
|
+
if self.project.is_hooked(func_a_addr) and self._p2.is_hooked(func_b_addr):
|
|
906
|
+
return self.project._sim_procedures[func_a_addr] == self._p2._sim_procedures[func_b_addr]
|
|
907
|
+
|
|
908
|
+
func_diff = self.get_function_diff(func_a_addr, func_b_addr)
|
|
909
|
+
if check_consts:
|
|
910
|
+
return func_diff.probably_identical_with_consts
|
|
911
|
+
|
|
912
|
+
return func_diff.probably_identical
|
|
913
|
+
|
|
914
|
+
@property
|
|
915
|
+
def identical_functions(self):
|
|
916
|
+
"""
|
|
917
|
+
:returns: A list of function matches that appear to be identical
|
|
918
|
+
"""
|
|
919
|
+
identical_funcs = []
|
|
920
|
+
for func_a, func_b in self.function_matches:
|
|
921
|
+
if self.functions_probably_identical(func_a, func_b):
|
|
922
|
+
identical_funcs.append((func_a, func_b))
|
|
923
|
+
return identical_funcs
|
|
924
|
+
|
|
925
|
+
@property
|
|
926
|
+
def differing_functions(self):
|
|
927
|
+
"""
|
|
928
|
+
:returns: A list of function matches that appear to differ
|
|
929
|
+
"""
|
|
930
|
+
different_funcs = []
|
|
931
|
+
for func_a, func_b in self.function_matches:
|
|
932
|
+
if not self.functions_probably_identical(func_a, func_b):
|
|
933
|
+
different_funcs.append((func_a, func_b))
|
|
934
|
+
return different_funcs
|
|
935
|
+
|
|
936
|
+
def differing_functions_with_consts(self):
|
|
937
|
+
"""
|
|
938
|
+
:return: A list of function matches that appear to differ including just by constants
|
|
939
|
+
"""
|
|
940
|
+
different_funcs = []
|
|
941
|
+
for func_a, func_b in self.function_matches:
|
|
942
|
+
if not self.functions_probably_identical(func_a, func_b, check_consts=True):
|
|
943
|
+
different_funcs.append((func_a, func_b))
|
|
944
|
+
return different_funcs
|
|
945
|
+
|
|
946
|
+
@property
|
|
947
|
+
def differing_blocks(self):
|
|
948
|
+
"""
|
|
949
|
+
:returns: A list of block matches that appear to differ
|
|
950
|
+
"""
|
|
951
|
+
differing_blocks = []
|
|
952
|
+
for func_a, func_b in self.function_matches:
|
|
953
|
+
differing_blocks.extend(self.get_function_diff(func_a, func_b).differing_blocks)
|
|
954
|
+
return differing_blocks
|
|
955
|
+
|
|
956
|
+
@property
|
|
957
|
+
def identical_blocks(self):
|
|
958
|
+
"""
|
|
959
|
+
:return A list of all block matches that appear to be identical
|
|
960
|
+
"""
|
|
961
|
+
identical_blocks = []
|
|
962
|
+
for func_a, func_b in self.function_matches:
|
|
963
|
+
identical_blocks.extend(self.get_function_diff(func_a, func_b).identical_blocks)
|
|
964
|
+
return identical_blocks
|
|
965
|
+
|
|
966
|
+
@property
|
|
967
|
+
def blocks_with_differing_constants(self):
|
|
968
|
+
"""
|
|
969
|
+
:return: A dict of block matches with differing constants to the tuple of constants
|
|
970
|
+
"""
|
|
971
|
+
diffs = {}
|
|
972
|
+
for func_a, func_b in self.function_matches:
|
|
973
|
+
diffs.update(self.get_function_diff(func_a, func_b).blocks_with_differing_constants)
|
|
974
|
+
return diffs
|
|
975
|
+
|
|
976
|
+
@property
|
|
977
|
+
def unmatched_functions(self):
|
|
978
|
+
return self._unmatched_functions_from_a, self._unmatched_functions_from_b
|
|
979
|
+
|
|
980
|
+
# gets the diff of two functions in the binaries
|
|
981
|
+
def get_function_diff(self, function_addr_a, function_addr_b):
|
|
982
|
+
"""
|
|
983
|
+
:param function_addr_a: The address of the first function (in the first binary)
|
|
984
|
+
:param function_addr_b: The address of the second function (in the second binary)
|
|
985
|
+
:returns: the FunctionDiff of the two functions
|
|
986
|
+
"""
|
|
987
|
+
pair = (function_addr_a, function_addr_b)
|
|
988
|
+
if pair not in self._function_diffs:
|
|
989
|
+
function_a = self.funcs_a.function(function_addr_a)
|
|
990
|
+
function_b = self.funcs_b.function(function_addr_b)
|
|
991
|
+
self._function_diffs[pair] = FunctionDiff(function_a, function_b, self)
|
|
992
|
+
return self._function_diffs[pair]
|
|
993
|
+
|
|
994
|
+
@staticmethod
|
|
995
|
+
def _compute_function_attributes(funcs, exclude_func_addrs: set[int] | None = None):
|
|
996
|
+
"""
|
|
997
|
+
:returns: a dictionary of function addresses to tuples of attributes
|
|
998
|
+
"""
|
|
999
|
+
# the attributes we use are the number of basic blocks, number of edges, and number of subfunction calls
|
|
1000
|
+
attributes = {}
|
|
1001
|
+
all_funcs = set(funcs.callgraph)
|
|
1002
|
+
for function_addr in funcs:
|
|
1003
|
+
if not funcs.contains_addr(function_addr):
|
|
1004
|
+
continue
|
|
1005
|
+
if exclude_func_addrs and function_addr in exclude_func_addrs:
|
|
1006
|
+
continue
|
|
1007
|
+
func = funcs.get_by_addr(function_addr)
|
|
1008
|
+
# skip syscalls and functions which are None in the cfg
|
|
1009
|
+
if func.is_syscall or func.is_alignment or func.is_plt:
|
|
1010
|
+
continue
|
|
1011
|
+
normalized_function = NormalizedFunction(func)
|
|
1012
|
+
number_of_basic_blocks = len(normalized_function.graph.nodes())
|
|
1013
|
+
number_of_edges = len(normalized_function.graph.edges())
|
|
1014
|
+
number_of_subfunction_calls = funcs.callgraph.out_degree[function_addr] if function_addr in all_funcs else 0
|
|
1015
|
+
attributes[function_addr] = number_of_basic_blocks, number_of_edges, number_of_subfunction_calls
|
|
1016
|
+
|
|
1017
|
+
return attributes
|
|
1018
|
+
|
|
1019
|
+
def _get_call_site_matches(self, func_a, func_b):
|
|
1020
|
+
possible_matches = set()
|
|
1021
|
+
|
|
1022
|
+
# Make sure those functions are not SimProcedures
|
|
1023
|
+
f_a = self.funcs_a.function(func_a)
|
|
1024
|
+
f_b = self.funcs_b.function(func_b)
|
|
1025
|
+
if f_a.startpoint is None or f_b.startpoint is None:
|
|
1026
|
+
return possible_matches
|
|
1027
|
+
|
|
1028
|
+
fd = self.get_function_diff(func_a, func_b)
|
|
1029
|
+
basic_block_matches = fd.block_matches
|
|
1030
|
+
function_a = fd._function_a
|
|
1031
|
+
function_b = fd._function_b
|
|
1032
|
+
for a, b in basic_block_matches:
|
|
1033
|
+
if a in function_a.call_sites and b in function_b.call_sites:
|
|
1034
|
+
# add them in order
|
|
1035
|
+
for target_a, target_b in zip(function_a.call_sites[a], function_b.call_sites[b]):
|
|
1036
|
+
possible_matches.add((target_a, target_b))
|
|
1037
|
+
# add them in reverse, since if a new call was added the ordering from each side
|
|
1038
|
+
# will remain constant until the change
|
|
1039
|
+
for target_a, target_b in zip(reversed(function_a.call_sites[a]), reversed(function_b.call_sites[b])):
|
|
1040
|
+
possible_matches.add((target_a, target_b))
|
|
1041
|
+
|
|
1042
|
+
return possible_matches
|
|
1043
|
+
|
|
1044
|
+
def _get_plt_matches(self):
|
|
1045
|
+
plt_matches = []
|
|
1046
|
+
if not hasattr(self.project.loader.main_object, "plt") or not hasattr(self._p2.loader.main_object, "plt"):
|
|
1047
|
+
return []
|
|
1048
|
+
for name, addr in self.project.loader.main_object.plt.items():
|
|
1049
|
+
if name in self._p2.loader.main_object.plt:
|
|
1050
|
+
plt_matches.append((addr, self._p2.loader.main_object.plt[name]))
|
|
1051
|
+
|
|
1052
|
+
# in the case of sim procedures the actual sim procedure might be in the interfunction graph, not the plt entry
|
|
1053
|
+
func_to_addr_a = {}
|
|
1054
|
+
func_to_addr_b = {}
|
|
1055
|
+
for k, hook in self.project._sim_procedures.items():
|
|
1056
|
+
if "resolves" in hook.kwargs:
|
|
1057
|
+
func_to_addr_a[hook.kwargs["resolves"]] = k
|
|
1058
|
+
|
|
1059
|
+
for k, hook in self._p2._sim_procedures.items():
|
|
1060
|
+
if "resolves" in hook.kwargs:
|
|
1061
|
+
func_to_addr_b[hook.kwargs["resolves"]] = k
|
|
1062
|
+
|
|
1063
|
+
for name, addr in func_to_addr_a.items():
|
|
1064
|
+
if name in func_to_addr_b:
|
|
1065
|
+
plt_matches.append((addr, func_to_addr_b[name]))
|
|
1066
|
+
|
|
1067
|
+
# remove ones that aren't in the interfunction graph, because these seem to not be consistent
|
|
1068
|
+
all_funcs_a = set(self.funcs_a.callgraph.nodes())
|
|
1069
|
+
all_funcs_b = set(self.funcs_b.callgraph.nodes())
|
|
1070
|
+
return [x for x in plt_matches if x[0] in all_funcs_a and x[1] in all_funcs_b]
|
|
1071
|
+
|
|
1072
|
+
def _get_name_matches(self):
|
|
1073
|
+
names_to_addrs_a = defaultdict(list)
|
|
1074
|
+
for f in self.funcs_a.values():
|
|
1075
|
+
if not f.name.startswith("sub_"):
|
|
1076
|
+
names_to_addrs_a[f.name].append(f.addr)
|
|
1077
|
+
|
|
1078
|
+
names_to_addrs_b = defaultdict(list)
|
|
1079
|
+
for f in self.funcs_b.values():
|
|
1080
|
+
if not f.name.startswith("sub_"):
|
|
1081
|
+
names_to_addrs_b[f.name].append(f.addr)
|
|
1082
|
+
|
|
1083
|
+
name_matches = []
|
|
1084
|
+
for name, addrs in names_to_addrs_a.items():
|
|
1085
|
+
if name in names_to_addrs_b:
|
|
1086
|
+
for addr_a, addr_b in zip(addrs, names_to_addrs_b[name]):
|
|
1087
|
+
# if binary a and binary b have different numbers of functions with the same name, we will see them
|
|
1088
|
+
# in unmatched functions in the end.
|
|
1089
|
+
name_matches.append((addr_a, addr_b))
|
|
1090
|
+
|
|
1091
|
+
return name_matches
|
|
1092
|
+
|
|
1093
|
+
def _get_string_reference_matches(self) -> list[tuple[int, int]]:
|
|
1094
|
+
strs_main: dict[str, int | None] = {}
|
|
1095
|
+
strs_secondary: dict[str, int | None] = {}
|
|
1096
|
+
|
|
1097
|
+
for mem_data in self.cfg_a.memory_data.values():
|
|
1098
|
+
if mem_data.sort == MemoryDataSort.String:
|
|
1099
|
+
if mem_data.content not in strs_main:
|
|
1100
|
+
strs_main[mem_data.content] = mem_data.addr
|
|
1101
|
+
else:
|
|
1102
|
+
# unfortunately there are multiple strings with the same value...
|
|
1103
|
+
strs_main[mem_data.content] = None
|
|
1104
|
+
|
|
1105
|
+
for mem_data in self.cfg_b.memory_data.values():
|
|
1106
|
+
if mem_data.sort == MemoryDataSort.String:
|
|
1107
|
+
if mem_data.content not in strs_secondary:
|
|
1108
|
+
strs_secondary[mem_data.content] = mem_data.addr
|
|
1109
|
+
else:
|
|
1110
|
+
# unfortunately there are multiple strings with the same value...
|
|
1111
|
+
strs_secondary[mem_data.content] = None
|
|
1112
|
+
|
|
1113
|
+
shared_strs = set(strs_main.keys()) & set(strs_secondary.keys())
|
|
1114
|
+
matches = []
|
|
1115
|
+
# check cross-references
|
|
1116
|
+
for s in shared_strs:
|
|
1117
|
+
if strs_main[s] is None or strs_secondary[s] is None:
|
|
1118
|
+
continue
|
|
1119
|
+
addr_main = strs_main[s]
|
|
1120
|
+
addr_secondary = strs_secondary[s]
|
|
1121
|
+
xrefs_main = self.kb.xrefs.get_xrefs_by_dst(addr_main)
|
|
1122
|
+
xrefs_secondary = self._p2.kb.xrefs.get_xrefs_by_dst(addr_secondary)
|
|
1123
|
+
if len(xrefs_main) == len(xrefs_secondary) == 1:
|
|
1124
|
+
xref_main = next(iter(xrefs_main))
|
|
1125
|
+
xref_secondary = next(iter(xrefs_secondary))
|
|
1126
|
+
cfgnode_main = self.cfg_a.get_any_node(xref_main.block_addr)
|
|
1127
|
+
cfgnode_secondary = self.cfg_b.get_any_node(xref_secondary.block_addr)
|
|
1128
|
+
if cfgnode_main is not None and cfgnode_secondary is not None:
|
|
1129
|
+
matches.append((cfgnode_main.function_address, cfgnode_secondary.function_address))
|
|
1130
|
+
|
|
1131
|
+
return sorted(set(matches))
|
|
1132
|
+
|
|
1133
|
+
@staticmethod
|
|
1134
|
+
def _approximate_matcher_func_block_and_edge_count(
|
|
1135
|
+
main_funcs, secondary_funcs, new_matches: list, size_tolerance=0.1
|
|
1136
|
+
) -> None:
|
|
1137
|
+
# functions likely match if they have the same number of blocks and the same number of edges
|
|
1138
|
+
main_funcs = sorted(main_funcs, key=lambda x: x.addr)
|
|
1139
|
+
secondary_funcs = sorted(secondary_funcs, key=lambda x: x.addr)
|
|
1140
|
+
m, s = 0, 0
|
|
1141
|
+
while m < len(main_funcs) and s < len(secondary_funcs):
|
|
1142
|
+
mf = main_funcs[m]
|
|
1143
|
+
sf = secondary_funcs[s]
|
|
1144
|
+
# best case: there is a direct match
|
|
1145
|
+
if len(mf.block_addrs_set) == len(sf.block_addrs_set) and len(mf.graph.edges) == len(sf.graph.edges):
|
|
1146
|
+
# ensure function sizes are roughly the same
|
|
1147
|
+
if abs(mf.size - sf.size) / max(mf.size, sf.size) < size_tolerance:
|
|
1148
|
+
l.info(
|
|
1149
|
+
"Approximate matcher (block&edge count) found %#x (%s) and %#x (%s).",
|
|
1150
|
+
mf.addr,
|
|
1151
|
+
mf.name,
|
|
1152
|
+
sf.addr,
|
|
1153
|
+
sf.name,
|
|
1154
|
+
)
|
|
1155
|
+
new_matches.append((mf.addr, sf.addr))
|
|
1156
|
+
m += 1
|
|
1157
|
+
s += 1
|
|
1158
|
+
else:
|
|
1159
|
+
if len(main_funcs) - m > len(secondary_funcs) - s:
|
|
1160
|
+
# more main funcs than secondary funcs; we increment m in case a function in the main binary
|
|
1161
|
+
# is removed
|
|
1162
|
+
m += 1
|
|
1163
|
+
elif len(main_funcs) - m < len(secondary_funcs) - s:
|
|
1164
|
+
# more secondary funcs than main funcs; we increment s in case a function in the secondary
|
|
1165
|
+
# binary is removed
|
|
1166
|
+
s += 1
|
|
1167
|
+
else:
|
|
1168
|
+
m += 1
|
|
1169
|
+
s += 1
|
|
1170
|
+
|
|
1171
|
+
@staticmethod
|
|
1172
|
+
def _get_function_max_addr(func) -> int | None:
|
|
1173
|
+
if not func.block_addrs_set:
|
|
1174
|
+
return None
|
|
1175
|
+
last_block_addr = max(func.block_addrs_set)
|
|
1176
|
+
block_size = func.get_block_size(last_block_addr)
|
|
1177
|
+
return last_block_addr + block_size
|
|
1178
|
+
|
|
1179
|
+
def _get_function_string_refs(self, proj, cfg, func) -> set[bytes]:
|
|
1180
|
+
strs = set()
|
|
1181
|
+
func_max_addr = self._get_function_max_addr(func)
|
|
1182
|
+
if func_max_addr is None:
|
|
1183
|
+
return strs
|
|
1184
|
+
xrefs = proj.kb.xrefs.get_xrefs_by_ins_addr_region(func.addr, func_max_addr)
|
|
1185
|
+
for xref in xrefs:
|
|
1186
|
+
if xref.dst in cfg.memory_data:
|
|
1187
|
+
md = cfg.memory_data[xref.dst]
|
|
1188
|
+
if md.sort == MemoryDataSort.String:
|
|
1189
|
+
strs.add(md.content)
|
|
1190
|
+
return strs
|
|
1191
|
+
|
|
1192
|
+
def _approximate_matcher_func_string_refs(self, main_funcs, secondary_funcs, new_matches: list) -> None:
|
|
1193
|
+
# functions likely match if they both refer to the same strings
|
|
1194
|
+
strs_to_funcs_main = defaultdict(list)
|
|
1195
|
+
strs_to_funcs_secondary = defaultdict(list)
|
|
1196
|
+
|
|
1197
|
+
for func in main_funcs:
|
|
1198
|
+
strs = self._get_function_string_refs(self.project, self.cfg_a, func)
|
|
1199
|
+
if strs:
|
|
1200
|
+
strs_to_funcs_main[frozenset(strs)].append(func)
|
|
1201
|
+
|
|
1202
|
+
for func in secondary_funcs:
|
|
1203
|
+
strs = self._get_function_string_refs(self._p2, self.cfg_b, func)
|
|
1204
|
+
if strs:
|
|
1205
|
+
strs_to_funcs_secondary[frozenset(strs)].append(func)
|
|
1206
|
+
|
|
1207
|
+
for strs_main, funcs_main in strs_to_funcs_main.items():
|
|
1208
|
+
if strs_main in strs_to_funcs_secondary and len(funcs_main) == 1:
|
|
1209
|
+
funcs_secondary = strs_to_funcs_secondary[strs_main]
|
|
1210
|
+
if len(funcs_secondary) == 1:
|
|
1211
|
+
# found a match!
|
|
1212
|
+
mf = funcs_main[0]
|
|
1213
|
+
sf = funcs_secondary[0]
|
|
1214
|
+
l.info(
|
|
1215
|
+
"Approximate matcher (string refs) found %#x (%s) and %#x (%s).",
|
|
1216
|
+
mf.addr,
|
|
1217
|
+
mf.name,
|
|
1218
|
+
sf.addr,
|
|
1219
|
+
sf.name,
|
|
1220
|
+
)
|
|
1221
|
+
new_matches.append((mf.addr, sf.addr))
|
|
1222
|
+
|
|
1223
|
+
@staticmethod
|
|
1224
|
+
def _get_function_callees(
|
|
1225
|
+
proj, funcs, func, main2secondary: dict[int, int] | None = None, funcs_secondary=None
|
|
1226
|
+
) -> tuple[str, ...]:
|
|
1227
|
+
callees = proj.kb.functions.callgraph.successors(func.addr)
|
|
1228
|
+
# convert callees to meaningful function names
|
|
1229
|
+
callee_names = []
|
|
1230
|
+
for callee in callees:
|
|
1231
|
+
if callee == func.addr:
|
|
1232
|
+
name = "!self"
|
|
1233
|
+
else:
|
|
1234
|
+
if main2secondary is not None and funcs_secondary is not None and callee in main2secondary:
|
|
1235
|
+
callee = main2secondary[callee]
|
|
1236
|
+
func = funcs_secondary.get_by_addr(callee)
|
|
1237
|
+
name = func.name
|
|
1238
|
+
else:
|
|
1239
|
+
func = funcs.get_by_addr(callee)
|
|
1240
|
+
name = None if func.is_default_name else func.name
|
|
1241
|
+
if name is not None:
|
|
1242
|
+
callee_names.append(name)
|
|
1243
|
+
else:
|
|
1244
|
+
# has at least one unknown/unmatched callee
|
|
1245
|
+
return ()
|
|
1246
|
+
return tuple(sorted(callee_names))
|
|
1247
|
+
|
|
1248
|
+
def _approximate_matcher_func_callees(
|
|
1249
|
+
self, main2secondary: dict[int, int], main_funcs, secondary_funcs, new_matches: list
|
|
1250
|
+
) -> None:
|
|
1251
|
+
# functions likely match if they both call the same callees
|
|
1252
|
+
callees_to_funcs_main = defaultdict(list)
|
|
1253
|
+
callees_to_funcs_secondary = defaultdict(list)
|
|
1254
|
+
|
|
1255
|
+
for func in main_funcs:
|
|
1256
|
+
callees = self._get_function_callees(
|
|
1257
|
+
self.project, self.funcs_a, func, main2secondary=main2secondary, funcs_secondary=self.funcs_b
|
|
1258
|
+
)
|
|
1259
|
+
if callees:
|
|
1260
|
+
callees_to_funcs_main[callees].append(func)
|
|
1261
|
+
|
|
1262
|
+
for func in secondary_funcs:
|
|
1263
|
+
callees = self._get_function_callees(self._p2, self.funcs_b, func)
|
|
1264
|
+
if callees:
|
|
1265
|
+
callees_to_funcs_secondary[callees].append(func)
|
|
1266
|
+
|
|
1267
|
+
for callees_main, funcs_main in callees_to_funcs_main.items():
|
|
1268
|
+
if callees_main in callees_to_funcs_secondary and len(funcs_main) == 1:
|
|
1269
|
+
funcs_secondary = callees_to_funcs_secondary[callees_main]
|
|
1270
|
+
if len(funcs_secondary) == 1:
|
|
1271
|
+
# found a match!
|
|
1272
|
+
mf = funcs_main[0]
|
|
1273
|
+
sf = funcs_secondary[0]
|
|
1274
|
+
l.info(
|
|
1275
|
+
"Approximate matcher (callees) found %#x (%s) and %#x (%s).",
|
|
1276
|
+
mf.addr,
|
|
1277
|
+
mf.name,
|
|
1278
|
+
sf.addr,
|
|
1279
|
+
sf.name,
|
|
1280
|
+
)
|
|
1281
|
+
new_matches.append((mf.addr, sf.addr))
|
|
1282
|
+
|
|
1283
|
+
def _get_approximate_matches_between_matched_pairs(self, matches: list[tuple[int, int]], matcher):
|
|
1284
|
+
sorted_matches = sorted(matches, key=lambda x: x[0])
|
|
1285
|
+
new_matches = []
|
|
1286
|
+
|
|
1287
|
+
for idx, (addr1_main, addr1_secondary) in enumerate(sorted_matches):
|
|
1288
|
+
if idx == len(sorted_matches) - 1:
|
|
1289
|
+
break
|
|
1290
|
+
addr2_main, addr2_secondary = sorted_matches[idx + 1]
|
|
1291
|
+
if addr1_secondary >= addr2_secondary:
|
|
1292
|
+
continue
|
|
1293
|
+
|
|
1294
|
+
# either two main functions are named, or two secondary functions are named
|
|
1295
|
+
f1_main = self.funcs_a.get_by_addr(addr1_main)
|
|
1296
|
+
f2_main = self.funcs_a.get_by_addr(addr2_main)
|
|
1297
|
+
f1_secondary = self.funcs_b.get_by_addr(addr1_secondary)
|
|
1298
|
+
f2_secondary = self.funcs_b.get_by_addr(addr2_secondary)
|
|
1299
|
+
if not (
|
|
1300
|
+
(not f1_main.is_default_name and not f2_main.is_default_name)
|
|
1301
|
+
or (not f1_secondary.is_default_name and not f2_secondary.is_default_name)
|
|
1302
|
+
):
|
|
1303
|
+
continue
|
|
1304
|
+
|
|
1305
|
+
# are there any functions in between?
|
|
1306
|
+
main_funcaddrs = list(self.funcs_a._function_map.irange(minimum=addr1_main + 1, maximum=addr2_main - 1))
|
|
1307
|
+
secondary_funcaddrs = list(
|
|
1308
|
+
self.funcs_b._function_map.irange(minimum=addr1_secondary + 1, maximum=addr2_secondary - 1)
|
|
1309
|
+
)
|
|
1310
|
+
# eliminate bad funcs
|
|
1311
|
+
main_funcs = [self.funcs_a.get_by_addr(addr) for addr in main_funcaddrs]
|
|
1312
|
+
main_funcs = [
|
|
1313
|
+
f
|
|
1314
|
+
for f in main_funcs
|
|
1315
|
+
if not f.is_syscall and not f.is_simprocedure and not f.is_alignment and not f.is_plt
|
|
1316
|
+
]
|
|
1317
|
+
secondary_funcs = [self.funcs_b.get_by_addr(addr) for addr in secondary_funcaddrs]
|
|
1318
|
+
secondary_funcs = [
|
|
1319
|
+
f
|
|
1320
|
+
for f in secondary_funcs
|
|
1321
|
+
if not f.is_syscall and not f.is_simprocedure and not f.is_alignment and not f.is_plt
|
|
1322
|
+
]
|
|
1323
|
+
if (
|
|
1324
|
+
main_funcs
|
|
1325
|
+
and secondary_funcs
|
|
1326
|
+
and len(main_funcs) > 0
|
|
1327
|
+
and len(secondary_funcs) > 0
|
|
1328
|
+
and len(main_funcs) < 100
|
|
1329
|
+
and len(secondary_funcs) < 100
|
|
1330
|
+
):
|
|
1331
|
+
# more checks
|
|
1332
|
+
matcher(main_funcs, secondary_funcs, new_matches)
|
|
1333
|
+
|
|
1334
|
+
return new_matches
|
|
1335
|
+
|
|
1336
|
+
def _compute_diff(self):
|
|
1337
|
+
# get the initial matches
|
|
1338
|
+
l.info("Getting PLT-based matches...")
|
|
1339
|
+
initial_matches = self._get_plt_matches()
|
|
1340
|
+
l.info("... initial matches: %d", len(initial_matches))
|
|
1341
|
+
|
|
1342
|
+
l.info("Getting function name-based matches...")
|
|
1343
|
+
initial_matches += self._get_name_matches()
|
|
1344
|
+
l.info("... initial matches: %d", len(initial_matches))
|
|
1345
|
+
|
|
1346
|
+
l.info("Getting string reference-based matches...")
|
|
1347
|
+
initial_matches += self._get_string_reference_matches()
|
|
1348
|
+
l.info("... initial matches: %d", len(initial_matches))
|
|
1349
|
+
|
|
1350
|
+
l.info("Getting adjacent function matches based on function block and edge counts...")
|
|
1351
|
+
initial_matches += self._get_approximate_matches_between_matched_pairs(
|
|
1352
|
+
initial_matches, self._approximate_matcher_func_block_and_edge_count
|
|
1353
|
+
)
|
|
1354
|
+
l.info("... initial matches: %d", len(initial_matches))
|
|
1355
|
+
|
|
1356
|
+
l.info("Getting adjacent function matches based on string references...")
|
|
1357
|
+
initial_matches += self._get_approximate_matches_between_matched_pairs(
|
|
1358
|
+
initial_matches, self._approximate_matcher_func_string_refs
|
|
1359
|
+
)
|
|
1360
|
+
l.info("... initial matches: %d", len(initial_matches))
|
|
1361
|
+
|
|
1362
|
+
l.info("Getting adjacent function matches based on callees...")
|
|
1363
|
+
main2secondary = dict(initial_matches)
|
|
1364
|
+
initial_matches += self._get_approximate_matches_between_matched_pairs(
|
|
1365
|
+
initial_matches, partial(self._approximate_matcher_func_callees, main2secondary)
|
|
1366
|
+
)
|
|
1367
|
+
l.info("... initial matches: %d", len(initial_matches))
|
|
1368
|
+
|
|
1369
|
+
# dedup
|
|
1370
|
+
initial_matches = sorted(set(initial_matches))
|
|
1371
|
+
l.info("We got %d initial matches so far. Time to get busy...", len(initial_matches))
|
|
1372
|
+
|
|
1373
|
+
# get the attributes for all functions
|
|
1374
|
+
l.info("Computing function attributes for main project...")
|
|
1375
|
+
self.attributes_a = self._compute_function_attributes(
|
|
1376
|
+
self.funcs_a, exclude_func_addrs={a for a, _ in initial_matches}
|
|
1377
|
+
)
|
|
1378
|
+
l.info("Computing function attributes for secondary project...")
|
|
1379
|
+
self.attributes_b = self._compute_function_attributes(
|
|
1380
|
+
self.funcs_b, exclude_func_addrs={a for _, a in initial_matches}
|
|
1381
|
+
)
|
|
1382
|
+
|
|
1383
|
+
l.info("Getting function attribute-based matches...")
|
|
1384
|
+
attribute_based_matches = self._get_function_matches(self.attributes_a, self.attributes_b)
|
|
1385
|
+
l.info("Got %d attribute-based matches.", len(attribute_based_matches))
|
|
1386
|
+
|
|
1387
|
+
# Use a queue so we process matches in the order that they are found
|
|
1388
|
+
to_process = deque(attribute_based_matches)
|
|
1389
|
+
|
|
1390
|
+
# Keep track of which matches we've already added to the queue
|
|
1391
|
+
processed_matches = set(initial_matches + attribute_based_matches)
|
|
1392
|
+
|
|
1393
|
+
# Keep a dict of current matches, which will be updated if better matches are found
|
|
1394
|
+
matched_a = {}
|
|
1395
|
+
matched_b = {}
|
|
1396
|
+
for x, y in processed_matches:
|
|
1397
|
+
matched_a[x] = y
|
|
1398
|
+
matched_b[y] = x
|
|
1399
|
+
|
|
1400
|
+
callgraph_a_nodes = set(self.funcs_a.callgraph.nodes())
|
|
1401
|
+
callgraph_b_nodes = set(self.funcs_b.callgraph.nodes())
|
|
1402
|
+
|
|
1403
|
+
# while queue is not empty
|
|
1404
|
+
while to_process:
|
|
1405
|
+
(func_a, func_b) = to_process.pop()
|
|
1406
|
+
l.debug("Processing (%#x, %#x)", func_a, func_b)
|
|
1407
|
+
|
|
1408
|
+
# we could find new matches in the successors or predecessors of functions
|
|
1409
|
+
if not self.project.loader.main_object.contains_addr(func_a):
|
|
1410
|
+
continue
|
|
1411
|
+
if not self._p2.loader.main_object.contains_addr(func_b):
|
|
1412
|
+
continue
|
|
1413
|
+
|
|
1414
|
+
func_a_succ = self.funcs_a.callgraph.successors(func_a) if func_a in callgraph_a_nodes else []
|
|
1415
|
+
func_b_succ = self.funcs_b.callgraph.successors(func_b) if func_b in callgraph_b_nodes else []
|
|
1416
|
+
func_a_pred = self.funcs_a.callgraph.predecessors(func_a) if func_a in callgraph_a_nodes else []
|
|
1417
|
+
func_b_pred = self.funcs_b.callgraph.predecessors(func_b) if func_b in callgraph_b_nodes else []
|
|
1418
|
+
|
|
1419
|
+
# get possible new matches
|
|
1420
|
+
new_matches = set(
|
|
1421
|
+
self._get_function_matches(self.attributes_a, self.attributes_b, func_a_succ, func_b_succ)
|
|
1422
|
+
)
|
|
1423
|
+
new_matches |= set(
|
|
1424
|
+
self._get_function_matches(self.attributes_a, self.attributes_b, func_a_pred, func_b_pred)
|
|
1425
|
+
)
|
|
1426
|
+
|
|
1427
|
+
# could also find matches as function calls of matched basic blocks
|
|
1428
|
+
new_matches.update(self._get_call_site_matches(func_a, func_b))
|
|
1429
|
+
|
|
1430
|
+
# for each of the possible new matches add it if it improves the matching
|
|
1431
|
+
for x, y in new_matches:
|
|
1432
|
+
# skip none functions and syscalls
|
|
1433
|
+
func_a = self.funcs_a.function(x)
|
|
1434
|
+
if func_a is None or func_a.is_simprocedure or func_a.is_syscall:
|
|
1435
|
+
continue
|
|
1436
|
+
func_b = self.funcs_b.function(y)
|
|
1437
|
+
if func_b is None or func_b.is_simprocedure or func_b.is_syscall:
|
|
1438
|
+
continue
|
|
1439
|
+
|
|
1440
|
+
if (x, y) not in processed_matches:
|
|
1441
|
+
processed_matches.add((x, y))
|
|
1442
|
+
# if it's a better match than what we already have use it
|
|
1443
|
+
l.debug("Checking function match %s, %s", hex(x), hex(y))
|
|
1444
|
+
if _is_better_match(x, y, matched_a, matched_b, self.attributes_a, self.attributes_b):
|
|
1445
|
+
l.debug("Adding potential match %s, %s", hex(x), hex(y))
|
|
1446
|
+
if x in matched_a:
|
|
1447
|
+
old_match = matched_a[x]
|
|
1448
|
+
del matched_b[old_match]
|
|
1449
|
+
l.debug("Removing previous match (%#x, %#x)", x, old_match)
|
|
1450
|
+
if y in matched_b:
|
|
1451
|
+
old_match = matched_b[y]
|
|
1452
|
+
del matched_a[old_match]
|
|
1453
|
+
l.debug("Removing previous match (%#x, %#x)", old_match, y)
|
|
1454
|
+
matched_a[x] = y
|
|
1455
|
+
matched_b[y] = x
|
|
1456
|
+
to_process.appendleft((x, y))
|
|
1457
|
+
|
|
1458
|
+
# reformat matches into a set of pairs
|
|
1459
|
+
self.function_matches = set()
|
|
1460
|
+
for x, y in matched_a.items():
|
|
1461
|
+
# only keep if the pair is in the binary ranges
|
|
1462
|
+
if self.project.loader.main_object.contains_addr(x) and self._p2.loader.main_object.contains_addr(y):
|
|
1463
|
+
self.function_matches.add((x, y))
|
|
1464
|
+
|
|
1465
|
+
# get the unmatched functions
|
|
1466
|
+
self._unmatched_functions_from_a = {x for x in self.attributes_a if x not in matched_a}
|
|
1467
|
+
self._unmatched_functions_from_b = {x for x in self.attributes_b if x not in matched_b}
|
|
1468
|
+
|
|
1469
|
+
# remove unneeded function diffs
|
|
1470
|
+
for x, y in dict(self._function_diffs):
|
|
1471
|
+
if (x, y) not in self.function_matches:
|
|
1472
|
+
del self._function_diffs[(x, y)]
|
|
1473
|
+
|
|
1474
|
+
@staticmethod
|
|
1475
|
+
def _get_function_matches(attributes_a, attributes_b, filter_set_a=None, filter_set_b=None):
|
|
1476
|
+
"""
|
|
1477
|
+
:param attributes_a: A dict of functions to their attributes
|
|
1478
|
+
:param attributes_b: A dict of functions to their attributes
|
|
1479
|
+
|
|
1480
|
+
The following parameters are optional.
|
|
1481
|
+
|
|
1482
|
+
:param filter_set_a: A set to limit attributes_a to the functions in this set.
|
|
1483
|
+
:param filter_set_b: A set to limit attributes_b to the functions in this set.
|
|
1484
|
+
:returns: A list of tuples of matching objects.
|
|
1485
|
+
"""
|
|
1486
|
+
# get the attributes that are in the sets
|
|
1487
|
+
if filter_set_a is None:
|
|
1488
|
+
filtered_attributes_a = dict(attributes_a.items())
|
|
1489
|
+
else:
|
|
1490
|
+
filtered_attributes_a = {k: v for k, v in attributes_a.items() if k in filter_set_a}
|
|
1491
|
+
|
|
1492
|
+
if filter_set_b is None:
|
|
1493
|
+
filtered_attributes_b = dict(attributes_b.items())
|
|
1494
|
+
else:
|
|
1495
|
+
filtered_attributes_b = {k: v for k, v in attributes_b.items() if k in filter_set_b}
|
|
1496
|
+
|
|
1497
|
+
# get closest
|
|
1498
|
+
closest_a = _get_closest_matches(filtered_attributes_a, filtered_attributes_b)
|
|
1499
|
+
closest_b = _get_closest_matches(filtered_attributes_b, filtered_attributes_a)
|
|
1500
|
+
|
|
1501
|
+
# a match (x,y) is good if x is the closest to y and y is the closest to x
|
|
1502
|
+
matches = []
|
|
1503
|
+
for a in closest_a:
|
|
1504
|
+
if len(closest_a[a]) == 1:
|
|
1505
|
+
match = closest_a[a][0]
|
|
1506
|
+
if len(closest_b[match]) == 1 and closest_b[match][0] == a:
|
|
1507
|
+
matches.append((a, match))
|
|
1508
|
+
|
|
1509
|
+
return matches
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
AnalysesHub.register_default("BinDiff", BinDiff)
|