angr 9.2.192__cp311-cp311-macosx_10_12_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- angr/__init__.py +366 -0
- angr/__main__.py +182 -0
- angr/ail_callable.py +79 -0
- angr/ailment/__init__.py +83 -0
- angr/ailment/block.py +88 -0
- angr/ailment/block_walker.py +856 -0
- angr/ailment/constant.py +3 -0
- angr/ailment/converter_common.py +11 -0
- angr/ailment/converter_pcode.py +648 -0
- angr/ailment/converter_vex.py +829 -0
- angr/ailment/expression.py +1655 -0
- angr/ailment/manager.py +34 -0
- angr/ailment/statement.py +973 -0
- angr/ailment/tagged_object.py +58 -0
- angr/ailment/utils.py +114 -0
- angr/analyses/__init__.py +117 -0
- angr/analyses/analysis.py +429 -0
- angr/analyses/backward_slice.py +686 -0
- angr/analyses/binary_optimizer.py +670 -0
- angr/analyses/bindiff.py +1512 -0
- angr/analyses/boyscout.py +76 -0
- angr/analyses/callee_cleanup_finder.py +74 -0
- angr/analyses/calling_convention/__init__.py +6 -0
- angr/analyses/calling_convention/calling_convention.py +1113 -0
- angr/analyses/calling_convention/fact_collector.py +647 -0
- angr/analyses/calling_convention/utils.py +60 -0
- angr/analyses/cdg.py +189 -0
- angr/analyses/cfg/__init__.py +23 -0
- angr/analyses/cfg/cfb.py +451 -0
- angr/analyses/cfg/cfg.py +74 -0
- angr/analyses/cfg/cfg_arch_options.py +95 -0
- angr/analyses/cfg/cfg_base.py +2954 -0
- angr/analyses/cfg/cfg_emulated.py +3451 -0
- angr/analyses/cfg/cfg_fast.py +5431 -0
- angr/analyses/cfg/cfg_fast_soot.py +662 -0
- angr/analyses/cfg/cfg_job_base.py +203 -0
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +30 -0
- angr/analyses/cfg/indirect_jump_resolvers/aarch64_macho_got.py +77 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +62 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +51 -0
- angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +159 -0
- angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +339 -0
- angr/analyses/cfg/indirect_jump_resolvers/constant_value_manager.py +107 -0
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +82 -0
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2490 -0
- angr/analyses/cfg/indirect_jump_resolvers/memload_resolver.py +81 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +286 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_got.py +148 -0
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +46 -0
- angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
- angr/analyses/cfg/indirect_jump_resolvers/syscall_resolver.py +92 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +88 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +47 -0
- angr/analyses/cfg_slice_to_sink/__init__.py +11 -0
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
- angr/analyses/cfg_slice_to_sink/graph.py +87 -0
- angr/analyses/cfg_slice_to_sink/transitions.py +27 -0
- angr/analyses/class_identifier.py +63 -0
- angr/analyses/code_tagging.py +123 -0
- angr/analyses/codecave.py +77 -0
- angr/analyses/complete_calling_conventions.py +475 -0
- angr/analyses/congruency_check.py +377 -0
- angr/analyses/data_dep/__init__.py +16 -0
- angr/analyses/data_dep/data_dependency_analysis.py +595 -0
- angr/analyses/data_dep/dep_nodes.py +171 -0
- angr/analyses/data_dep/sim_act_location.py +49 -0
- angr/analyses/datagraph_meta.py +105 -0
- angr/analyses/ddg.py +1670 -0
- angr/analyses/decompiler/__init__.py +41 -0
- angr/analyses/decompiler/ail_simplifier.py +2246 -0
- angr/analyses/decompiler/ailgraph_walker.py +49 -0
- angr/analyses/decompiler/block_io_finder.py +302 -0
- angr/analyses/decompiler/block_similarity.py +199 -0
- angr/analyses/decompiler/block_simplifier.py +397 -0
- angr/analyses/decompiler/callsite_maker.py +579 -0
- angr/analyses/decompiler/ccall_rewriters/__init__.py +9 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +618 -0
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +24 -0
- angr/analyses/decompiler/ccall_rewriters/x86_ccalls.py +354 -0
- angr/analyses/decompiler/clinic.py +3662 -0
- angr/analyses/decompiler/condition_processor.py +1323 -0
- angr/analyses/decompiler/counters/__init__.py +16 -0
- angr/analyses/decompiler/counters/boolean_counter.py +27 -0
- angr/analyses/decompiler/counters/call_counter.py +77 -0
- angr/analyses/decompiler/counters/expression_counters.py +77 -0
- angr/analyses/decompiler/counters/seq_cf_structure_counter.py +63 -0
- angr/analyses/decompiler/decompilation_cache.py +54 -0
- angr/analyses/decompiler/decompilation_options.py +317 -0
- angr/analyses/decompiler/decompiler.py +796 -0
- angr/analyses/decompiler/dephication/__init__.py +6 -0
- angr/analyses/decompiler/dephication/dephication_base.py +100 -0
- angr/analyses/decompiler/dephication/graph_dephication.py +70 -0
- angr/analyses/decompiler/dephication/graph_rewriting.py +112 -0
- angr/analyses/decompiler/dephication/graph_vvar_mapping.py +357 -0
- angr/analyses/decompiler/dephication/rewriting_engine.py +528 -0
- angr/analyses/decompiler/dephication/seqnode_dephication.py +156 -0
- angr/analyses/decompiler/dirty_rewriters/__init__.py +7 -0
- angr/analyses/decompiler/dirty_rewriters/amd64_dirty.py +74 -0
- angr/analyses/decompiler/dirty_rewriters/rewriter_base.py +27 -0
- angr/analyses/decompiler/empty_node_remover.py +212 -0
- angr/analyses/decompiler/expression_narrower.py +290 -0
- angr/analyses/decompiler/goto_manager.py +112 -0
- angr/analyses/decompiler/graph_region.py +441 -0
- angr/analyses/decompiler/jump_target_collector.py +37 -0
- angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +67 -0
- angr/analyses/decompiler/label_collector.py +32 -0
- angr/analyses/decompiler/node_replacer.py +42 -0
- angr/analyses/decompiler/notes/__init__.py +9 -0
- angr/analyses/decompiler/notes/decompilation_note.py +48 -0
- angr/analyses/decompiler/notes/deobfuscated_strings.py +56 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +164 -0
- angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +157 -0
- angr/analyses/decompiler/optimization_passes/call_stmt_rewriter.py +46 -0
- angr/analyses/decompiler/optimization_passes/code_motion.py +362 -0
- angr/analyses/decompiler/optimization_passes/condition_constprop.py +211 -0
- angr/analyses/decompiler/optimization_passes/const_derefs.py +127 -0
- angr/analyses/decompiler/optimization_passes/const_prop_reverter.py +365 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +106 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +82 -0
- angr/analyses/decompiler/optimization_passes/determine_load_sizes.py +64 -0
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +425 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/__init__.py +5 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/ail_merge_graph.py +503 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/duplication_reverter.py +1221 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/errors.py +16 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/similarity.py +126 -0
- angr/analyses/decompiler/optimization_passes/duplication_reverter/utils.py +167 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_concatenation.py +236 -0
- angr/analyses/decompiler/optimization_passes/eager_std_string_eval.py +186 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +502 -0
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +138 -0
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +113 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +618 -0
- angr/analyses/decompiler/optimization_passes/inlined_strlen_simplifier.py +274 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +224 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +337 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +939 -0
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +99 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +710 -0
- angr/analyses/decompiler/optimization_passes/peephole_simplifier.py +75 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +263 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier_adv.py +198 -0
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +171 -0
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +222 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +632 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +61 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +166 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +333 -0
- angr/analyses/decompiler/optimization_passes/static_vvar_rewriter.py +336 -0
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +166 -0
- angr/analyses/decompiler/optimization_passes/switch_reused_entry_rewriter.py +102 -0
- angr/analyses/decompiler/optimization_passes/tag_slicer.py +41 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +477 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +88 -0
- angr/analyses/decompiler/peephole_optimizations/__init__.py +136 -0
- angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +42 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_shr_const_shr_const.py +37 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +23 -0
- angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +236 -0
- angr/analyses/decompiler/peephole_optimizations/base.py +157 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/bitwise_or_to_logical_or.py +34 -0
- angr/analyses/decompiler/peephole_optimizations/bool_expr_xor_1.py +27 -0
- angr/analyses/decompiler/peephole_optimizations/bswap.py +142 -0
- angr/analyses/decompiler/peephole_optimizations/cas_intrinsics.py +182 -0
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +71 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_adjacent_shrs.py +39 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +69 -0
- angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +52 -0
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +436 -0
- angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +56 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memcpy.py +78 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_memset.py +262 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +217 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +106 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy.py +256 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wcscpy_consolidation.py +296 -0
- angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
- angr/analyses/decompiler/peephole_optimizations/modulo_simplifier.py +89 -0
- angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
- angr/analyses/decompiler/peephole_optimizations/optimized_div_simplifier.py +356 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +45 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cxx_destructor_calls.py +32 -0
- angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +46 -0
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +47 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +125 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +273 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_derefs.py +21 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +30 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +36 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +95 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +115 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_conv_mul.py +40 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_cxx_operator_calls.py +90 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +49 -0
- angr/analyses/decompiler/peephole_optimizations/rol_ror.py +130 -0
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +143 -0
- angr/analyses/decompiler/peephole_optimizations/shl_to_mul.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +51 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +28 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +29 -0
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +131 -0
- angr/analyses/decompiler/peephole_optimizations/utils.py +18 -0
- angr/analyses/decompiler/presets/__init__.py +22 -0
- angr/analyses/decompiler/presets/basic.py +36 -0
- angr/analyses/decompiler/presets/fast.py +66 -0
- angr/analyses/decompiler/presets/full.py +76 -0
- angr/analyses/decompiler/presets/malware.py +70 -0
- angr/analyses/decompiler/presets/preset.py +37 -0
- angr/analyses/decompiler/redundant_label_remover.py +141 -0
- angr/analyses/decompiler/region_identifier.py +1319 -0
- angr/analyses/decompiler/region_simplifiers/__init__.py +5 -0
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +95 -0
- angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +82 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +838 -0
- angr/analyses/decompiler/region_simplifiers/goto.py +178 -0
- angr/analyses/decompiler/region_simplifiers/if_.py +135 -0
- angr/analyses/decompiler/region_simplifiers/ifelse.py +91 -0
- angr/analyses/decompiler/region_simplifiers/loop.py +143 -0
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +24 -0
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +270 -0
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +654 -0
- angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +87 -0
- angr/analyses/decompiler/region_walker.py +24 -0
- angr/analyses/decompiler/return_maker.py +72 -0
- angr/analyses/decompiler/semantic_naming/__init__.py +37 -0
- angr/analyses/decompiler/semantic_naming/array_index_naming.py +196 -0
- angr/analyses/decompiler/semantic_naming/boolean_naming.py +264 -0
- angr/analyses/decompiler/semantic_naming/call_result_naming.py +220 -0
- angr/analyses/decompiler/semantic_naming/naming_base.py +166 -0
- angr/analyses/decompiler/semantic_naming/orchestrator.py +107 -0
- angr/analyses/decompiler/semantic_naming/pointer_naming.py +334 -0
- angr/analyses/decompiler/semantic_naming/region_loop_counter_naming.py +246 -0
- angr/analyses/decompiler/semantic_naming/size_naming.py +137 -0
- angr/analyses/decompiler/seq_to_blocks.py +20 -0
- angr/analyses/decompiler/sequence_walker.py +261 -0
- angr/analyses/decompiler/ssailification/__init__.py +4 -0
- angr/analyses/decompiler/ssailification/rewriting.py +451 -0
- angr/analyses/decompiler/ssailification/rewriting_engine.py +1091 -0
- angr/analyses/decompiler/ssailification/rewriting_state.py +61 -0
- angr/analyses/decompiler/ssailification/ssailification.py +283 -0
- angr/analyses/decompiler/ssailification/traversal.py +127 -0
- angr/analyses/decompiler/ssailification/traversal_engine.py +323 -0
- angr/analyses/decompiler/ssailification/traversal_state.py +48 -0
- angr/analyses/decompiler/stack_item.py +36 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +25 -0
- angr/analyses/decompiler/structured_codegen/base.py +193 -0
- angr/analyses/decompiler/structured_codegen/c.py +4257 -0
- angr/analyses/decompiler/structured_codegen/dummy.py +15 -0
- angr/analyses/decompiler/structured_codegen/dwarf_import.py +190 -0
- angr/analyses/decompiler/structuring/__init__.py +30 -0
- angr/analyses/decompiler/structuring/dream.py +1217 -0
- angr/analyses/decompiler/structuring/phoenix.py +3636 -0
- angr/analyses/decompiler/structuring/recursive_structurer.py +187 -0
- angr/analyses/decompiler/structuring/sailr.py +120 -0
- angr/analyses/decompiler/structuring/structurer_base.py +1140 -0
- angr/analyses/decompiler/structuring/structurer_nodes.py +442 -0
- angr/analyses/decompiler/utils.py +1224 -0
- angr/analyses/deobfuscator/__init__.py +23 -0
- angr/analyses/deobfuscator/api_obf_finder.py +333 -0
- angr/analyses/deobfuscator/api_obf_peephole_optimizer.py +80 -0
- angr/analyses/deobfuscator/api_obf_type2_finder.py +166 -0
- angr/analyses/deobfuscator/data_transformation_embedder.py +633 -0
- angr/analyses/deobfuscator/hash_lookup_api_deobfuscator.py +156 -0
- angr/analyses/deobfuscator/irsb_reg_collector.py +54 -0
- angr/analyses/deobfuscator/scope_ops_analyzer.py +68 -0
- angr/analyses/deobfuscator/string_obf_finder.py +983 -0
- angr/analyses/deobfuscator/string_obf_opt_passes.py +136 -0
- angr/analyses/deobfuscator/string_obf_peephole_optimizer.py +47 -0
- angr/analyses/disassembly.py +1351 -0
- angr/analyses/disassembly_utils.py +101 -0
- angr/analyses/dominance_frontier.py +57 -0
- angr/analyses/fcp/__init__.py +4 -0
- angr/analyses/fcp/fcp.py +427 -0
- angr/analyses/find_objects_static.py +205 -0
- angr/analyses/flirt/__init__.py +47 -0
- angr/analyses/flirt/consts.py +160 -0
- angr/analyses/flirt/flirt.py +249 -0
- angr/analyses/flirt/flirt_function.py +20 -0
- angr/analyses/flirt/flirt_matcher.py +352 -0
- angr/analyses/flirt/flirt_module.py +32 -0
- angr/analyses/flirt/flirt_node.py +23 -0
- angr/analyses/flirt/flirt_sig.py +359 -0
- angr/analyses/flirt/flirt_utils.py +31 -0
- angr/analyses/forward_analysis/__init__.py +12 -0
- angr/analyses/forward_analysis/forward_analysis.py +619 -0
- angr/analyses/forward_analysis/job_info.py +64 -0
- angr/analyses/forward_analysis/visitors/__init__.py +14 -0
- angr/analyses/forward_analysis/visitors/call_graph.py +29 -0
- angr/analyses/forward_analysis/visitors/function_graph.py +86 -0
- angr/analyses/forward_analysis/visitors/graph.py +242 -0
- angr/analyses/forward_analysis/visitors/loop.py +29 -0
- angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
- angr/analyses/identifier/__init__.py +5 -0
- angr/analyses/identifier/custom_callable.py +137 -0
- angr/analyses/identifier/errors.py +10 -0
- angr/analyses/identifier/func.py +60 -0
- angr/analyses/identifier/functions/__init__.py +37 -0
- angr/analyses/identifier/functions/atoi.py +73 -0
- angr/analyses/identifier/functions/based_atoi.py +125 -0
- angr/analyses/identifier/functions/fdprintf.py +123 -0
- angr/analyses/identifier/functions/free.py +64 -0
- angr/analyses/identifier/functions/int2str.py +287 -0
- angr/analyses/identifier/functions/malloc.py +111 -0
- angr/analyses/identifier/functions/memcmp.py +67 -0
- angr/analyses/identifier/functions/memcpy.py +89 -0
- angr/analyses/identifier/functions/memset.py +43 -0
- angr/analyses/identifier/functions/printf.py +123 -0
- angr/analyses/identifier/functions/recv_until.py +312 -0
- angr/analyses/identifier/functions/skip_calloc.py +73 -0
- angr/analyses/identifier/functions/skip_realloc.py +97 -0
- angr/analyses/identifier/functions/skip_recv_n.py +105 -0
- angr/analyses/identifier/functions/snprintf.py +112 -0
- angr/analyses/identifier/functions/sprintf.py +116 -0
- angr/analyses/identifier/functions/strcasecmp.py +33 -0
- angr/analyses/identifier/functions/strcmp.py +113 -0
- angr/analyses/identifier/functions/strcpy.py +43 -0
- angr/analyses/identifier/functions/strlen.py +27 -0
- angr/analyses/identifier/functions/strncmp.py +104 -0
- angr/analyses/identifier/functions/strncpy.py +65 -0
- angr/analyses/identifier/functions/strtol.py +89 -0
- angr/analyses/identifier/identify.py +825 -0
- angr/analyses/identifier/runner.py +360 -0
- angr/analyses/init_finder.py +289 -0
- angr/analyses/loop_analysis/__init__.py +4 -0
- angr/analyses/loop_analysis/loop_analysis.py +464 -0
- angr/analyses/loop_analysis.py +349 -0
- angr/analyses/loop_unroller/__init__.py +4 -0
- angr/analyses/loop_unroller/loop_unroller.py +222 -0
- angr/analyses/loopfinder.py +171 -0
- angr/analyses/outliner/__init__.py +7 -0
- angr/analyses/outliner/outliner.py +402 -0
- angr/analyses/patchfinder.py +137 -0
- angr/analyses/pathfinder.py +282 -0
- angr/analyses/propagator/__init__.py +5 -0
- angr/analyses/propagator/engine_base.py +62 -0
- angr/analyses/propagator/engine_vex.py +297 -0
- angr/analyses/propagator/propagator.py +361 -0
- angr/analyses/propagator/top_checker_mixin.py +218 -0
- angr/analyses/propagator/values.py +117 -0
- angr/analyses/propagator/vex_vars.py +68 -0
- angr/analyses/proximity_graph.py +444 -0
- angr/analyses/purity/__init__.py +15 -0
- angr/analyses/purity/analysis.py +78 -0
- angr/analyses/purity/engine.py +593 -0
- angr/analyses/reaching_definitions/__init__.py +67 -0
- angr/analyses/reaching_definitions/call_trace.py +73 -0
- angr/analyses/reaching_definitions/dep_graph.py +433 -0
- angr/analyses/reaching_definitions/engine_ail.py +1128 -0
- angr/analyses/reaching_definitions/engine_vex.py +1128 -0
- angr/analyses/reaching_definitions/external_codeloc.py +0 -0
- angr/analyses/reaching_definitions/function_handler.py +639 -0
- angr/analyses/reaching_definitions/function_handler_library/__init__.py +12 -0
- angr/analyses/reaching_definitions/function_handler_library/stdio.py +269 -0
- angr/analyses/reaching_definitions/function_handler_library/stdlib.py +195 -0
- angr/analyses/reaching_definitions/function_handler_library/string.py +158 -0
- angr/analyses/reaching_definitions/function_handler_library/unistd.py +51 -0
- angr/analyses/reaching_definitions/heap_allocator.py +70 -0
- angr/analyses/reaching_definitions/rd_initializer.py +237 -0
- angr/analyses/reaching_definitions/rd_state.py +579 -0
- angr/analyses/reaching_definitions/reaching_definitions.py +581 -0
- angr/analyses/reaching_definitions/subject.py +65 -0
- angr/analyses/reassembler.py +2900 -0
- angr/analyses/s_liveness.py +254 -0
- angr/analyses/s_propagator.py +575 -0
- angr/analyses/s_reaching_definitions/__init__.py +12 -0
- angr/analyses/s_reaching_definitions/s_rda_model.py +145 -0
- angr/analyses/s_reaching_definitions/s_rda_view.py +344 -0
- angr/analyses/s_reaching_definitions/s_reaching_definitions.py +230 -0
- angr/analyses/smc.py +160 -0
- angr/analyses/soot_class_hierarchy.py +273 -0
- angr/analyses/stack_pointer_tracker.py +954 -0
- angr/analyses/static_hooker.py +53 -0
- angr/analyses/typehoon/__init__.py +5 -0
- angr/analyses/typehoon/dfa.py +118 -0
- angr/analyses/typehoon/lifter.py +133 -0
- angr/analyses/typehoon/simple_solver.py +2009 -0
- angr/analyses/typehoon/translator.py +283 -0
- angr/analyses/typehoon/typeconsts.py +439 -0
- angr/analyses/typehoon/typehoon.py +338 -0
- angr/analyses/typehoon/typevars.py +633 -0
- angr/analyses/typehoon/variance.py +11 -0
- angr/analyses/unpacker/__init__.py +6 -0
- angr/analyses/unpacker/obfuscation_detector.py +103 -0
- angr/analyses/unpacker/packing_detector.py +138 -0
- angr/analyses/variable_recovery/__init__.py +9 -0
- angr/analyses/variable_recovery/annotations.py +58 -0
- angr/analyses/variable_recovery/engine_ail.py +978 -0
- angr/analyses/variable_recovery/engine_base.py +1256 -0
- angr/analyses/variable_recovery/engine_vex.py +594 -0
- angr/analyses/variable_recovery/irsb_scanner.py +143 -0
- angr/analyses/variable_recovery/variable_recovery.py +574 -0
- angr/analyses/variable_recovery/variable_recovery_base.py +489 -0
- angr/analyses/variable_recovery/variable_recovery_fast.py +669 -0
- angr/analyses/veritesting.py +626 -0
- angr/analyses/vfg.py +1898 -0
- angr/analyses/vsa_ddg.py +420 -0
- angr/analyses/vtable.py +92 -0
- angr/analyses/xrefs.py +286 -0
- angr/angrdb/__init__.py +14 -0
- angr/angrdb/db.py +215 -0
- angr/angrdb/models.py +184 -0
- angr/angrdb/serializers/__init__.py +10 -0
- angr/angrdb/serializers/cfg_model.py +41 -0
- angr/angrdb/serializers/comments.py +60 -0
- angr/angrdb/serializers/funcs.py +61 -0
- angr/angrdb/serializers/kb.py +111 -0
- angr/angrdb/serializers/labels.py +59 -0
- angr/angrdb/serializers/loader.py +165 -0
- angr/angrdb/serializers/structured_code.py +167 -0
- angr/angrdb/serializers/variables.py +58 -0
- angr/angrdb/serializers/xrefs.py +48 -0
- angr/annocfg.py +317 -0
- angr/blade.py +431 -0
- angr/block.py +509 -0
- angr/callable.py +176 -0
- angr/calling_conventions.py +2613 -0
- angr/code_location.py +249 -0
- angr/codenode.py +145 -0
- angr/concretization_strategies/__init__.py +32 -0
- angr/concretization_strategies/any.py +17 -0
- angr/concretization_strategies/any_named.py +35 -0
- angr/concretization_strategies/base.py +81 -0
- angr/concretization_strategies/controlled_data.py +58 -0
- angr/concretization_strategies/eval.py +19 -0
- angr/concretization_strategies/logging.py +35 -0
- angr/concretization_strategies/max.py +25 -0
- angr/concretization_strategies/nonzero.py +16 -0
- angr/concretization_strategies/nonzero_range.py +22 -0
- angr/concretization_strategies/norepeats.py +37 -0
- angr/concretization_strategies/norepeats_range.py +37 -0
- angr/concretization_strategies/range.py +19 -0
- angr/concretization_strategies/signed_add.py +31 -0
- angr/concretization_strategies/single.py +15 -0
- angr/concretization_strategies/solutions.py +20 -0
- angr/concretization_strategies/unlimited_range.py +17 -0
- angr/distributed/__init__.py +9 -0
- angr/distributed/server.py +197 -0
- angr/distributed/worker.py +185 -0
- angr/emulator.py +144 -0
- angr/engines/__init__.py +69 -0
- angr/engines/ail/__init__.py +16 -0
- angr/engines/ail/callstack.py +58 -0
- angr/engines/ail/engine_light.py +903 -0
- angr/engines/ail/engine_successors.py +24 -0
- angr/engines/ail/setup.py +57 -0
- angr/engines/concrete.py +66 -0
- angr/engines/engine.py +29 -0
- angr/engines/failure.py +27 -0
- angr/engines/hook.py +93 -0
- angr/engines/icicle.py +294 -0
- angr/engines/light/__init__.py +23 -0
- angr/engines/light/data.py +681 -0
- angr/engines/light/engine.py +1297 -0
- angr/engines/pcode/__init__.py +9 -0
- angr/engines/pcode/behavior.py +998 -0
- angr/engines/pcode/cc.py +148 -0
- angr/engines/pcode/emulate.py +440 -0
- angr/engines/pcode/engine.py +242 -0
- angr/engines/pcode/lifter.py +1428 -0
- angr/engines/procedure.py +70 -0
- angr/engines/soot/__init__.py +5 -0
- angr/engines/soot/engine.py +410 -0
- angr/engines/soot/exceptions.py +17 -0
- angr/engines/soot/expressions/__init__.py +87 -0
- angr/engines/soot/expressions/arrayref.py +22 -0
- angr/engines/soot/expressions/base.py +21 -0
- angr/engines/soot/expressions/binop.py +28 -0
- angr/engines/soot/expressions/cast.py +22 -0
- angr/engines/soot/expressions/condition.py +35 -0
- angr/engines/soot/expressions/constants.py +47 -0
- angr/engines/soot/expressions/instanceOf.py +15 -0
- angr/engines/soot/expressions/instancefieldref.py +8 -0
- angr/engines/soot/expressions/invoke.py +114 -0
- angr/engines/soot/expressions/length.py +8 -0
- angr/engines/soot/expressions/local.py +8 -0
- angr/engines/soot/expressions/new.py +16 -0
- angr/engines/soot/expressions/newArray.py +54 -0
- angr/engines/soot/expressions/newMultiArray.py +86 -0
- angr/engines/soot/expressions/paramref.py +8 -0
- angr/engines/soot/expressions/phi.py +30 -0
- angr/engines/soot/expressions/staticfieldref.py +8 -0
- angr/engines/soot/expressions/thisref.py +7 -0
- angr/engines/soot/expressions/unsupported.py +7 -0
- angr/engines/soot/field_dispatcher.py +46 -0
- angr/engines/soot/method_dispatcher.py +46 -0
- angr/engines/soot/statements/__init__.py +44 -0
- angr/engines/soot/statements/assign.py +30 -0
- angr/engines/soot/statements/base.py +79 -0
- angr/engines/soot/statements/goto.py +14 -0
- angr/engines/soot/statements/identity.py +15 -0
- angr/engines/soot/statements/if_.py +19 -0
- angr/engines/soot/statements/invoke.py +12 -0
- angr/engines/soot/statements/return_.py +20 -0
- angr/engines/soot/statements/switch.py +41 -0
- angr/engines/soot/statements/throw.py +15 -0
- angr/engines/soot/values/__init__.py +38 -0
- angr/engines/soot/values/arrayref.py +122 -0
- angr/engines/soot/values/base.py +7 -0
- angr/engines/soot/values/constants.py +18 -0
- angr/engines/soot/values/instancefieldref.py +44 -0
- angr/engines/soot/values/local.py +18 -0
- angr/engines/soot/values/paramref.py +18 -0
- angr/engines/soot/values/staticfieldref.py +38 -0
- angr/engines/soot/values/strref.py +38 -0
- angr/engines/soot/values/thisref.py +149 -0
- angr/engines/successors.py +608 -0
- angr/engines/syscall.py +51 -0
- angr/engines/unicorn.py +490 -0
- angr/engines/vex/__init__.py +20 -0
- angr/engines/vex/claripy/__init__.py +5 -0
- angr/engines/vex/claripy/ccall.py +2097 -0
- angr/engines/vex/claripy/datalayer.py +141 -0
- angr/engines/vex/claripy/irop.py +1276 -0
- angr/engines/vex/heavy/__init__.py +16 -0
- angr/engines/vex/heavy/actions.py +231 -0
- angr/engines/vex/heavy/concretizers.py +403 -0
- angr/engines/vex/heavy/dirty.py +466 -0
- angr/engines/vex/heavy/heavy.py +370 -0
- angr/engines/vex/heavy/inspect.py +52 -0
- angr/engines/vex/heavy/resilience.py +85 -0
- angr/engines/vex/heavy/super_fastpath.py +34 -0
- angr/engines/vex/lifter.py +420 -0
- angr/engines/vex/light/__init__.py +11 -0
- angr/engines/vex/light/light.py +551 -0
- angr/engines/vex/light/resilience.py +74 -0
- angr/engines/vex/light/slicing.py +52 -0
- angr/errors.py +611 -0
- angr/exploration_techniques/__init__.py +53 -0
- angr/exploration_techniques/base.py +126 -0
- angr/exploration_techniques/bucketizer.py +94 -0
- angr/exploration_techniques/common.py +56 -0
- angr/exploration_techniques/dfs.py +37 -0
- angr/exploration_techniques/director.py +520 -0
- angr/exploration_techniques/driller_core.py +100 -0
- angr/exploration_techniques/explorer.py +152 -0
- angr/exploration_techniques/lengthlimiter.py +22 -0
- angr/exploration_techniques/local_loop_seer.py +65 -0
- angr/exploration_techniques/loop_seer.py +236 -0
- angr/exploration_techniques/manual_mergepoint.py +82 -0
- angr/exploration_techniques/memory_watcher.py +43 -0
- angr/exploration_techniques/oppologist.py +92 -0
- angr/exploration_techniques/slicecutor.py +118 -0
- angr/exploration_techniques/spiller.py +280 -0
- angr/exploration_techniques/spiller_db.py +27 -0
- angr/exploration_techniques/stochastic.py +56 -0
- angr/exploration_techniques/stub_stasher.py +19 -0
- angr/exploration_techniques/suggestions.py +159 -0
- angr/exploration_techniques/tech_builder.py +49 -0
- angr/exploration_techniques/threading.py +69 -0
- angr/exploration_techniques/timeout.py +34 -0
- angr/exploration_techniques/tracer.py +1098 -0
- angr/exploration_techniques/unique.py +106 -0
- angr/exploration_techniques/veritesting.py +37 -0
- angr/factory.py +413 -0
- angr/flirt/__init__.py +124 -0
- angr/flirt/build_sig.py +305 -0
- angr/graph_utils.py +0 -0
- angr/keyed_region.py +525 -0
- angr/knowledge_base.py +146 -0
- angr/knowledge_plugins/__init__.py +43 -0
- angr/knowledge_plugins/callsite_prototypes.py +95 -0
- angr/knowledge_plugins/cfg/__init__.py +18 -0
- angr/knowledge_plugins/cfg/cfg_manager.py +95 -0
- angr/knowledge_plugins/cfg/cfg_model.py +1043 -0
- angr/knowledge_plugins/cfg/cfg_node.py +536 -0
- angr/knowledge_plugins/cfg/indirect_jump.py +131 -0
- angr/knowledge_plugins/cfg/memory_data.py +156 -0
- angr/knowledge_plugins/comments.py +16 -0
- angr/knowledge_plugins/custom_strings.py +38 -0
- angr/knowledge_plugins/data.py +22 -0
- angr/knowledge_plugins/debug_variables.py +216 -0
- angr/knowledge_plugins/functions/__init__.py +9 -0
- angr/knowledge_plugins/functions/function.py +1830 -0
- angr/knowledge_plugins/functions/function_manager.py +621 -0
- angr/knowledge_plugins/functions/function_parser.py +360 -0
- angr/knowledge_plugins/functions/soot_function.py +128 -0
- angr/knowledge_plugins/indirect_jumps.py +35 -0
- angr/knowledge_plugins/key_definitions/__init__.py +17 -0
- angr/knowledge_plugins/key_definitions/atoms.py +374 -0
- angr/knowledge_plugins/key_definitions/constants.py +29 -0
- angr/knowledge_plugins/key_definitions/definition.py +216 -0
- angr/knowledge_plugins/key_definitions/environment.py +96 -0
- angr/knowledge_plugins/key_definitions/heap_address.py +33 -0
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +82 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +1020 -0
- angr/knowledge_plugins/key_definitions/liveness.py +165 -0
- angr/knowledge_plugins/key_definitions/rd_model.py +171 -0
- angr/knowledge_plugins/key_definitions/tag.py +78 -0
- angr/knowledge_plugins/key_definitions/undefined.py +70 -0
- angr/knowledge_plugins/key_definitions/unknown_size.py +86 -0
- angr/knowledge_plugins/key_definitions/uses.py +178 -0
- angr/knowledge_plugins/labels.py +110 -0
- angr/knowledge_plugins/obfuscations.py +40 -0
- angr/knowledge_plugins/patches.py +126 -0
- angr/knowledge_plugins/plugin.py +24 -0
- angr/knowledge_plugins/propagations/__init__.py +10 -0
- angr/knowledge_plugins/propagations/prop_value.py +191 -0
- angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
- angr/knowledge_plugins/propagations/propagation_model.py +80 -0
- angr/knowledge_plugins/propagations/states.py +552 -0
- angr/knowledge_plugins/structured_code.py +63 -0
- angr/knowledge_plugins/types.py +95 -0
- angr/knowledge_plugins/variables/__init__.py +8 -0
- angr/knowledge_plugins/variables/variable_access.py +113 -0
- angr/knowledge_plugins/variables/variable_manager.py +1375 -0
- angr/knowledge_plugins/xrefs/__init__.py +12 -0
- angr/knowledge_plugins/xrefs/xref.py +150 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +127 -0
- angr/knowledge_plugins/xrefs/xref_types.py +16 -0
- angr/misc/__init__.py +19 -0
- angr/misc/ansi.py +47 -0
- angr/misc/autoimport.py +90 -0
- angr/misc/bug_report.py +126 -0
- angr/misc/hookset.py +106 -0
- angr/misc/loggers.py +130 -0
- angr/misc/picklable_lock.py +46 -0
- angr/misc/plugins.py +289 -0
- angr/misc/telemetry.py +54 -0
- angr/misc/testing.py +24 -0
- angr/misc/ux.py +31 -0
- angr/procedures/__init__.py +12 -0
- angr/procedures/advapi32/__init__.py +0 -0
- angr/procedures/cgc/__init__.py +3 -0
- angr/procedures/cgc/_terminate.py +11 -0
- angr/procedures/cgc/allocate.py +75 -0
- angr/procedures/cgc/deallocate.py +67 -0
- angr/procedures/cgc/fdwait.py +65 -0
- angr/procedures/cgc/random.py +67 -0
- angr/procedures/cgc/receive.py +93 -0
- angr/procedures/cgc/transmit.py +65 -0
- angr/procedures/definitions/__init__.py +1043 -0
- angr/procedures/definitions/cgc.py +23 -0
- angr/procedures/definitions/common/glibc.json +3516 -0
- angr/procedures/definitions/gnulib.py +41 -0
- angr/procedures/definitions/libstdcpp.py +25 -0
- angr/procedures/definitions/linux_kernel.py +8382 -0
- angr/procedures/definitions/linux_loader.py +7 -0
- angr/procedures/definitions/macho_libsystem.py +18 -0
- angr/procedures/definitions/msvcr.py +25 -0
- angr/procedures/definitions/parse_glibc.py +77 -0
- angr/procedures/definitions/parse_syscalls_from_local_system.py +54 -0
- angr/procedures/definitions/parse_win32json.py +2540 -0
- angr/procedures/definitions/types_stl.py +22 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-4.json +24 -0
- angr/procedures/definitions/wdk/api-ms-win-dx-d3dkmt-l1-1-6.json +18 -0
- angr/procedures/definitions/wdk/clfs.json +189 -0
- angr/procedures/definitions/wdk/fltmgr.json +813 -0
- angr/procedures/definitions/wdk/fwpkclnt.json +24 -0
- angr/procedures/definitions/wdk/fwpuclnt.json +453 -0
- angr/procedures/definitions/wdk/gdi32.json +528 -0
- angr/procedures/definitions/wdk/hal.json +96 -0
- angr/procedures/definitions/wdk/ksecdd.json +72 -0
- angr/procedures/definitions/wdk/ndis.json +336 -0
- angr/procedures/definitions/wdk/ntoskrnl.json +5158 -0
- angr/procedures/definitions/wdk/offreg.json +87 -0
- angr/procedures/definitions/wdk/pshed.json +33 -0
- angr/procedures/definitions/wdk/secur32.json +39 -0
- angr/procedures/definitions/wdk/vhfum.json +30 -0
- angr/procedures/definitions/win32/_types_win32.json +34480 -0
- angr/procedures/definitions/win32/aclui.json +24 -0
- angr/procedures/definitions/win32/activeds.json +81 -0
- angr/procedures/definitions/win32/advapi32.json +2505 -0
- angr/procedures/definitions/win32/advpack.json +165 -0
- angr/procedures/definitions/win32/amsi.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-1.json +45 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-3.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-appmodel-runtime-l1-1-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-apiquery-l2-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-backgroundtask-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-comm-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-enclave-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-errorhandling-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-0.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-core-featurestaging-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-file-fromapp-l1-1-0.json +48 -0
- angr/procedures/definitions/win32/api-ms-win-core-handle-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-ioring-l1-1-0.json +51 -0
- angr/procedures/definitions/win32/api-ms-win-core-marshal-l1-1-0.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-3.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-5.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-6.json +27 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-7.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-memory-l1-1-8.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-path-l1-1-0.json +81 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-0.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-psm-appnotify-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-realtime-l1-1-2.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-slapi-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-state-helpers-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-synch-l1-2-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-4.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-sysinfo-l1-2-6.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-core-util-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-core-wow64-l1-1-1.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-0.json +42 -0
- angr/procedures/definitions/win32/api-ms-win-devices-query-l1-1-1.json +30 -0
- angr/procedures/definitions/win32/api-ms-win-dx-d3dkmt-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-deviceinformation-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-expandedresources-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-1.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-2.json +36 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-3.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-gaming-tcui-l1-1-4.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-mm-misc-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-net-isolation-l1-1-0.json +39 -0
- angr/procedures/definitions/win32/api-ms-win-security-base-l1-2-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-0.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-security-isolatedcontainer-l1-1-1.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-3.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-4.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-service-core-l1-1-5.json +21 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-0.json +24 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-1.json +33 -0
- angr/procedures/definitions/win32/api-ms-win-shcore-scaling-l1-1-2.json +18 -0
- angr/procedures/definitions/win32/api-ms-win-wsl-api-l1-1-0.json +36 -0
- angr/procedures/definitions/win32/apphelp.json +18 -0
- angr/procedures/definitions/win32/authz.json +114 -0
- angr/procedures/definitions/win32/avicap32.json +27 -0
- angr/procedures/definitions/win32/avifil32.json +195 -0
- angr/procedures/definitions/win32/avrt.json +57 -0
- angr/procedures/definitions/win32/bcp47mrm.json +21 -0
- angr/procedures/definitions/win32/bcrypt.json +174 -0
- angr/procedures/definitions/win32/bcryptprimitives.json +21 -0
- angr/procedures/definitions/win32/bluetoothapis.json +138 -0
- angr/procedures/definitions/win32/bthprops_cpl.json +33 -0
- angr/procedures/definitions/win32/cabinet.json +81 -0
- angr/procedures/definitions/win32/certadm.json +69 -0
- angr/procedures/definitions/win32/certpoleng.json +39 -0
- angr/procedures/definitions/win32/cfgmgr32.json +732 -0
- angr/procedures/definitions/win32/chakra.json +270 -0
- angr/procedures/definitions/win32/cldapi.json +123 -0
- angr/procedures/definitions/win32/clfsw32.json +192 -0
- angr/procedures/definitions/win32/clusapi.json +855 -0
- angr/procedures/definitions/win32/comctl32.json +360 -0
- angr/procedures/definitions/win32/comdlg32.json +78 -0
- angr/procedures/definitions/win32/compstui.json +27 -0
- angr/procedures/definitions/win32/computecore.json +177 -0
- angr/procedures/definitions/win32/computenetwork.json +144 -0
- angr/procedures/definitions/win32/computestorage.json +51 -0
- angr/procedures/definitions/win32/comsvcs.json +36 -0
- angr/procedures/definitions/win32/credui.json +72 -0
- angr/procedures/definitions/win32/crypt32.json +702 -0
- angr/procedures/definitions/win32/cryptnet.json +30 -0
- angr/procedures/definitions/win32/cryptui.json +45 -0
- angr/procedures/definitions/win32/cryptxml.json +72 -0
- angr/procedures/definitions/win32/cscapi.json +27 -0
- angr/procedures/definitions/win32/d2d1.json +54 -0
- angr/procedures/definitions/win32/d3d10.json +96 -0
- angr/procedures/definitions/win32/d3d10_1.json +21 -0
- angr/procedures/definitions/win32/d3d11.json +24 -0
- angr/procedures/definitions/win32/d3d12.json +39 -0
- angr/procedures/definitions/win32/d3d9.json +48 -0
- angr/procedures/definitions/win32/d3dcompiler_47.json +93 -0
- angr/procedures/definitions/win32/d3dcsx.json +42 -0
- angr/procedures/definitions/win32/davclnt.json +69 -0
- angr/procedures/definitions/win32/dbgeng.json +27 -0
- angr/procedures/definitions/win32/dbghelp.json +663 -0
- angr/procedures/definitions/win32/dbgmodel.json +18 -0
- angr/procedures/definitions/win32/dciman32.json +75 -0
- angr/procedures/definitions/win32/dcomp.json +51 -0
- angr/procedures/definitions/win32/ddraw.json +36 -0
- angr/procedures/definitions/win32/deviceaccess.json +18 -0
- angr/procedures/definitions/win32/dflayout.json +18 -0
- angr/procedures/definitions/win32/dhcpcsvc.json +60 -0
- angr/procedures/definitions/win32/dhcpcsvc6.json +33 -0
- angr/procedures/definitions/win32/dhcpsapi.json +603 -0
- angr/procedures/definitions/win32/diagnosticdataquery.json +120 -0
- angr/procedures/definitions/win32/dinput8.json +18 -0
- angr/procedures/definitions/win32/directml.json +21 -0
- angr/procedures/definitions/win32/dmprocessxmlfiltered.json +18 -0
- angr/procedures/definitions/win32/dnsapi.json +207 -0
- angr/procedures/definitions/win32/drt.json +63 -0
- angr/procedures/definitions/win32/drtprov.json +42 -0
- angr/procedures/definitions/win32/drttransport.json +21 -0
- angr/procedures/definitions/win32/dsound.json +45 -0
- angr/procedures/definitions/win32/dsparse.json +72 -0
- angr/procedures/definitions/win32/dsprop.json +36 -0
- angr/procedures/definitions/win32/dssec.json +27 -0
- angr/procedures/definitions/win32/dsuiext.json +27 -0
- angr/procedures/definitions/win32/dwmapi.json +108 -0
- angr/procedures/definitions/win32/dwrite.json +18 -0
- angr/procedures/definitions/win32/dxcompiler.json +21 -0
- angr/procedures/definitions/win32/dxcore.json +18 -0
- angr/procedures/definitions/win32/dxgi.json +33 -0
- angr/procedures/definitions/win32/dxva2.json +129 -0
- angr/procedures/definitions/win32/eappcfg.json +57 -0
- angr/procedures/definitions/win32/eappprxy.json +69 -0
- angr/procedures/definitions/win32/efswrt.json +21 -0
- angr/procedures/definitions/win32/elscore.json +30 -0
- angr/procedures/definitions/win32/esent.json +702 -0
- angr/procedures/definitions/win32/evr.json +36 -0
- angr/procedures/definitions/win32/faultrep.json +27 -0
- angr/procedures/definitions/win32/fhsvcctl.json +36 -0
- angr/procedures/definitions/win32/firewallapi.json +24 -0
- angr/procedures/definitions/win32/fltlib.json +99 -0
- angr/procedures/definitions/win32/fontsub.json +21 -0
- angr/procedures/definitions/win32/forceinline.json +24 -0
- angr/procedures/definitions/win32/fwpuclnt.json +591 -0
- angr/procedures/definitions/win32/fxsutility.json +21 -0
- angr/procedures/definitions/win32/gdi32.json +1308 -0
- angr/procedures/definitions/win32/gdiplus.json +1902 -0
- angr/procedures/definitions/win32/glu32.json +171 -0
- angr/procedures/definitions/win32/gpedit.json +33 -0
- angr/procedures/definitions/win32/hhctrl_ocx.json +21 -0
- angr/procedures/definitions/win32/hid.json +150 -0
- angr/procedures/definitions/win32/hlink.json +99 -0
- angr/procedures/definitions/win32/hrtfapo.json +18 -0
- angr/procedures/definitions/win32/httpapi.json +144 -0
- angr/procedures/definitions/win32/icm32.json +78 -0
- angr/procedures/definitions/win32/icmui.json +21 -0
- angr/procedures/definitions/win32/icu.json +3090 -0
- angr/procedures/definitions/win32/ieframe.json +102 -0
- angr/procedures/definitions/win32/imagehlp.json +84 -0
- angr/procedures/definitions/win32/imgutil.json +42 -0
- angr/procedures/definitions/win32/imm32.json +261 -0
- angr/procedures/definitions/win32/infocardapi.json +66 -0
- angr/procedures/definitions/win32/inkobjcore.json +96 -0
- angr/procedures/definitions/win32/iphlpapi.json +618 -0
- angr/procedures/definitions/win32/iscsidsc.json +252 -0
- angr/procedures/definitions/win32/isolatedwindowsenvironmentutils.json +21 -0
- angr/procedures/definitions/win32/kernel32.json +4566 -0
- angr/procedures/definitions/win32/kernelbase.json +33 -0
- angr/procedures/definitions/win32/keycredmgr.json +27 -0
- angr/procedures/definitions/win32/ksproxy_ax.json +33 -0
- angr/procedures/definitions/win32/ksuser.json +39 -0
- angr/procedures/definitions/win32/ktmw32.json +132 -0
- angr/procedures/definitions/win32/licenseprotection.json +21 -0
- angr/procedures/definitions/win32/loadperf.json +51 -0
- angr/procedures/definitions/win32/magnification.json +72 -0
- angr/procedures/definitions/win32/mapi32.json +213 -0
- angr/procedures/definitions/win32/mdmlocalmanagement.json +24 -0
- angr/procedures/definitions/win32/mdmregistration.json +60 -0
- angr/procedures/definitions/win32/mf.json +201 -0
- angr/procedures/definitions/win32/mfcore.json +21 -0
- angr/procedures/definitions/win32/mfplat.json +450 -0
- angr/procedures/definitions/win32/mfplay.json +18 -0
- angr/procedures/definitions/win32/mfreadwrite.json +30 -0
- angr/procedures/definitions/win32/mfsensorgroup.json +45 -0
- angr/procedures/definitions/win32/mfsrcsnk.json +21 -0
- angr/procedures/definitions/win32/mgmtapi.json +42 -0
- angr/procedures/definitions/win32/mi.json +18 -0
- angr/procedures/definitions/win32/mmdevapi.json +18 -0
- angr/procedures/definitions/win32/mpr.json +156 -0
- angr/procedures/definitions/win32/mprapi.json +351 -0
- angr/procedures/definitions/win32/mqrt.json +117 -0
- angr/procedures/definitions/win32/mrmsupport.json +96 -0
- angr/procedures/definitions/win32/msacm32.json +141 -0
- angr/procedures/definitions/win32/msajapi.json +1656 -0
- angr/procedures/definitions/win32/mscms.json +252 -0
- angr/procedures/definitions/win32/mscoree.json +96 -0
- angr/procedures/definitions/win32/msctfmonitor.json +24 -0
- angr/procedures/definitions/win32/msdelta.json +63 -0
- angr/procedures/definitions/win32/msdmo.json +48 -0
- angr/procedures/definitions/win32/msdrm.json +267 -0
- angr/procedures/definitions/win32/msi.json +807 -0
- angr/procedures/definitions/win32/msimg32.json +24 -0
- angr/procedures/definitions/win32/mspatcha.json +63 -0
- angr/procedures/definitions/win32/mspatchc.json +42 -0
- angr/procedures/definitions/win32/msports.json +36 -0
- angr/procedures/definitions/win32/msrating.json +72 -0
- angr/procedures/definitions/win32/mssign32.json +45 -0
- angr/procedures/definitions/win32/mstask.json +21 -0
- angr/procedures/definitions/win32/msvfw32.json +144 -0
- angr/procedures/definitions/win32/mswsock.json +63 -0
- angr/procedures/definitions/win32/mtxdm.json +18 -0
- angr/procedures/definitions/win32/ncrypt.json +132 -0
- angr/procedures/definitions/win32/ndfapi.json +63 -0
- angr/procedures/definitions/win32/netapi32.json +633 -0
- angr/procedures/definitions/win32/netsh.json +39 -0
- angr/procedures/definitions/win32/netshell.json +21 -0
- angr/procedures/definitions/win32/newdev.json +48 -0
- angr/procedures/definitions/win32/ninput.json +105 -0
- angr/procedures/definitions/win32/normaliz.json +21 -0
- angr/procedures/definitions/win32/ntdll.json +234 -0
- angr/procedures/definitions/win32/ntdllk.json +18 -0
- angr/procedures/definitions/win32/ntdsapi.json +258 -0
- angr/procedures/definitions/win32/ntlanman.json +45 -0
- angr/procedures/definitions/win32/odbc32.json +477 -0
- angr/procedures/definitions/win32/odbcbcp.json +96 -0
- angr/procedures/definitions/win32/ole32.json +966 -0
- angr/procedures/definitions/win32/oleacc.json +66 -0
- angr/procedures/definitions/win32/oleaut32.json +1230 -0
- angr/procedures/definitions/win32/oledlg.json +84 -0
- angr/procedures/definitions/win32/ondemandconnroutehelper.json +30 -0
- angr/procedures/definitions/win32/opengl32.json +1080 -0
- angr/procedures/definitions/win32/opmxbox.json +24 -0
- angr/procedures/definitions/win32/p2p.json +339 -0
- angr/procedures/definitions/win32/p2pgraph.json +126 -0
- angr/procedures/definitions/win32/pdh.json +309 -0
- angr/procedures/definitions/win32/peerdist.json +99 -0
- angr/procedures/definitions/win32/powrprof.json +267 -0
- angr/procedures/definitions/win32/prntvpt.json +48 -0
- angr/procedures/definitions/win32/projectedfslib.json +72 -0
- angr/procedures/definitions/win32/propsys.json +669 -0
- angr/procedures/definitions/win32/psapi.json +96 -0
- angr/procedures/definitions/win32/quartz.json +21 -0
- angr/procedures/definitions/win32/query.json +27 -0
- angr/procedures/definitions/win32/qwave.json +48 -0
- angr/procedures/definitions/win32/rasapi32.json +267 -0
- angr/procedures/definitions/win32/rasdlg.json +33 -0
- angr/procedures/definitions/win32/resutils.json +375 -0
- angr/procedures/definitions/win32/rpcns4.json +198 -0
- angr/procedures/definitions/win32/rpcproxy.json +27 -0
- angr/procedures/definitions/win32/rpcrt4.json +1356 -0
- angr/procedures/definitions/win32/rstrtmgr.json +48 -0
- angr/procedures/definitions/win32/rtm.json +243 -0
- angr/procedures/definitions/win32/rtutils.json +138 -0
- angr/procedures/definitions/win32/rtworkq.json +114 -0
- angr/procedures/definitions/win32/sas.json +18 -0
- angr/procedures/definitions/win32/scarddlg.json +30 -0
- angr/procedures/definitions/win32/schannel.json +42 -0
- angr/procedures/definitions/win32/sechost.json +21 -0
- angr/procedures/definitions/win32/secur32.json +282 -0
- angr/procedures/definitions/win32/sensapi.json +24 -0
- angr/procedures/definitions/win32/sensorsutilsv2.json +135 -0
- angr/procedures/definitions/win32/setupapi.json +1017 -0
- angr/procedures/definitions/win32/sfc.json +33 -0
- angr/procedures/definitions/win32/shdocvw.json +24 -0
- angr/procedures/definitions/win32/shell32.json +747 -0
- angr/procedures/definitions/win32/shlwapi.json +1095 -0
- angr/procedures/definitions/win32/slc.json +111 -0
- angr/procedures/definitions/win32/slcext.json +27 -0
- angr/procedures/definitions/win32/slwga.json +18 -0
- angr/procedures/definitions/win32/snmpapi.json +93 -0
- angr/procedures/definitions/win32/spoolss.json +93 -0
- angr/procedures/definitions/win32/srclient.json +18 -0
- angr/procedures/definitions/win32/srpapi.json +48 -0
- angr/procedures/definitions/win32/sspicli.json +36 -0
- angr/procedures/definitions/win32/sti.json +18 -0
- angr/procedures/definitions/win32/t2embed.json +57 -0
- angr/procedures/definitions/win32/tapi32.json +762 -0
- angr/procedures/definitions/win32/tbs.json +57 -0
- angr/procedures/definitions/win32/tdh.json +96 -0
- angr/procedures/definitions/win32/tokenbinding.json +45 -0
- angr/procedures/definitions/win32/traffic.json +75 -0
- angr/procedures/definitions/win32/txfw32.json +42 -0
- angr/procedures/definitions/win32/ualapi.json +27 -0
- angr/procedures/definitions/win32/uiautomationcore.json +309 -0
- angr/procedures/definitions/win32/urlmon.json +246 -0
- angr/procedures/definitions/win32/user32.json +2298 -0
- angr/procedures/definitions/win32/userenv.json +147 -0
- angr/procedures/definitions/win32/usp10.json +135 -0
- angr/procedures/definitions/win32/uxtheme.json +246 -0
- angr/procedures/definitions/win32/verifier.json +18 -0
- angr/procedures/definitions/win32/version.json +57 -0
- angr/procedures/definitions/win32/vertdll.json +36 -0
- angr/procedures/definitions/win32/virtdisk.json +102 -0
- angr/procedures/definitions/win32/vmdevicehost.json +54 -0
- angr/procedures/definitions/win32/vmsavedstatedumpprovider.json +144 -0
- angr/procedures/definitions/win32/vssapi.json +18 -0
- angr/procedures/definitions/win32/wcmapi.json +30 -0
- angr/procedures/definitions/win32/wdsbp.json +36 -0
- angr/procedures/definitions/win32/wdsclientapi.json +126 -0
- angr/procedures/definitions/win32/wdsmc.json +33 -0
- angr/procedures/definitions/win32/wdspxe.json +108 -0
- angr/procedures/definitions/win32/wdstptc.json +54 -0
- angr/procedures/definitions/win32/webauthn.json +54 -0
- angr/procedures/definitions/win32/webservices.json +594 -0
- angr/procedures/definitions/win32/websocket.json +54 -0
- angr/procedures/definitions/win32/wecapi.json +60 -0
- angr/procedures/definitions/win32/wer.json +78 -0
- angr/procedures/definitions/win32/wevtapi.json +120 -0
- angr/procedures/definitions/win32/winbio.json +177 -0
- angr/procedures/definitions/win32/windows_ai_machinelearning.json +18 -0
- angr/procedures/definitions/win32/windows_media_mediacontrol.json +39 -0
- angr/procedures/definitions/win32/windows_networking.json +18 -0
- angr/procedures/definitions/win32/windows_ui_xaml.json +21 -0
- angr/procedures/definitions/win32/windowscodecs.json +42 -0
- angr/procedures/definitions/win32/winfax.json +183 -0
- angr/procedures/definitions/win32/winhttp.json +183 -0
- angr/procedures/definitions/win32/winhvemulation.json +27 -0
- angr/procedures/definitions/win32/winhvplatform.json +213 -0
- angr/procedures/definitions/win32/wininet.json +903 -0
- angr/procedures/definitions/win32/winml.json +18 -0
- angr/procedures/definitions/win32/winmm.json +543 -0
- angr/procedures/definitions/win32/winscard.json +225 -0
- angr/procedures/definitions/win32/winspool_drv.json +531 -0
- angr/procedures/definitions/win32/wintrust.json +195 -0
- angr/procedures/definitions/win32/winusb.json +117 -0
- angr/procedures/definitions/win32/wlanapi.json +195 -0
- angr/procedures/definitions/win32/wlanui.json +18 -0
- angr/procedures/definitions/win32/wldap32.json +744 -0
- angr/procedures/definitions/win32/wldp.json +42 -0
- angr/procedures/definitions/win32/wmvcore.json +48 -0
- angr/procedures/definitions/win32/wnvapi.json +21 -0
- angr/procedures/definitions/win32/wofutil.json +48 -0
- angr/procedures/definitions/win32/ws2_32.json +495 -0
- angr/procedures/definitions/win32/wscapi.json +33 -0
- angr/procedures/definitions/win32/wsclient.json +24 -0
- angr/procedures/definitions/win32/wsdapi.json +111 -0
- angr/procedures/definitions/win32/wsmsvc.json +114 -0
- angr/procedures/definitions/win32/wsnmp32.json +162 -0
- angr/procedures/definitions/win32/wtsapi32.json +204 -0
- angr/procedures/definitions/win32/xaudio2_8.json +27 -0
- angr/procedures/definitions/win32/xinput1_4.json +36 -0
- angr/procedures/definitions/win32/xmllite.json +33 -0
- angr/procedures/definitions/win32/xolehlp.json +27 -0
- angr/procedures/definitions/win32/xpsprint.json +21 -0
- angr/procedures/glibc/__ctype_b_loc.py +21 -0
- angr/procedures/glibc/__ctype_tolower_loc.py +21 -0
- angr/procedures/glibc/__ctype_toupper_loc.py +21 -0
- angr/procedures/glibc/__errno_location.py +7 -0
- angr/procedures/glibc/__init__.py +3 -0
- angr/procedures/glibc/__libc_init.py +37 -0
- angr/procedures/glibc/__libc_start_main.py +301 -0
- angr/procedures/glibc/dynamic_loading.py +20 -0
- angr/procedures/glibc/scanf.py +19 -0
- angr/procedures/glibc/sscanf.py +10 -0
- angr/procedures/gnulib/__init__.py +3 -0
- angr/procedures/gnulib/xalloc_die.py +14 -0
- angr/procedures/gnulib/xstrtol_fatal.py +14 -0
- angr/procedures/java/__init__.py +42 -0
- angr/procedures/java/unconstrained.py +65 -0
- angr/procedures/java_io/__init__.py +0 -0
- angr/procedures/java_io/read.py +12 -0
- angr/procedures/java_io/write.py +17 -0
- angr/procedures/java_jni/__init__.py +482 -0
- angr/procedures/java_jni/array_operations.py +312 -0
- angr/procedures/java_jni/class_and_interface_operations.py +31 -0
- angr/procedures/java_jni/field_access.py +173 -0
- angr/procedures/java_jni/global_and_local_refs.py +57 -0
- angr/procedures/java_jni/method_calls.py +365 -0
- angr/procedures/java_jni/not_implemented.py +26 -0
- angr/procedures/java_jni/object_operations.py +94 -0
- angr/procedures/java_jni/string_operations.py +87 -0
- angr/procedures/java_jni/version_information.py +12 -0
- angr/procedures/java_lang/__init__.py +0 -0
- angr/procedures/java_lang/character.py +30 -0
- angr/procedures/java_lang/double.py +24 -0
- angr/procedures/java_lang/exit.py +13 -0
- angr/procedures/java_lang/getsimplename.py +18 -0
- angr/procedures/java_lang/integer.py +43 -0
- angr/procedures/java_lang/load_library.py +9 -0
- angr/procedures/java_lang/math.py +15 -0
- angr/procedures/java_lang/string.py +78 -0
- angr/procedures/java_lang/stringbuilder.py +44 -0
- angr/procedures/java_lang/system.py +18 -0
- angr/procedures/java_util/__init__.py +0 -0
- angr/procedures/java_util/collection.py +35 -0
- angr/procedures/java_util/iterator.py +46 -0
- angr/procedures/java_util/list.py +99 -0
- angr/procedures/java_util/map.py +131 -0
- angr/procedures/java_util/random.py +14 -0
- angr/procedures/java_util/scanner_nextline.py +23 -0
- angr/procedures/libc/__init__.py +3 -0
- angr/procedures/libc/abort.py +9 -0
- angr/procedures/libc/access.py +13 -0
- angr/procedures/libc/atoi.py +14 -0
- angr/procedures/libc/atol.py +13 -0
- angr/procedures/libc/calloc.py +8 -0
- angr/procedures/libc/closelog.py +10 -0
- angr/procedures/libc/err.py +14 -0
- angr/procedures/libc/error.py +54 -0
- angr/procedures/libc/exit.py +11 -0
- angr/procedures/libc/fclose.py +19 -0
- angr/procedures/libc/feof.py +21 -0
- angr/procedures/libc/fflush.py +16 -0
- angr/procedures/libc/fgetc.py +27 -0
- angr/procedures/libc/fgets.py +69 -0
- angr/procedures/libc/fopen.py +63 -0
- angr/procedures/libc/fprintf.py +25 -0
- angr/procedures/libc/fputc.py +23 -0
- angr/procedures/libc/fputs.py +24 -0
- angr/procedures/libc/fread.py +24 -0
- angr/procedures/libc/free.py +9 -0
- angr/procedures/libc/fscanf.py +20 -0
- angr/procedures/libc/fseek.py +34 -0
- angr/procedures/libc/ftell.py +22 -0
- angr/procedures/libc/fwrite.py +19 -0
- angr/procedures/libc/getchar.py +13 -0
- angr/procedures/libc/getdelim.py +99 -0
- angr/procedures/libc/getegid.py +8 -0
- angr/procedures/libc/geteuid.py +8 -0
- angr/procedures/libc/getgid.py +8 -0
- angr/procedures/libc/gets.py +68 -0
- angr/procedures/libc/getuid.py +8 -0
- angr/procedures/libc/malloc.py +12 -0
- angr/procedures/libc/memcmp.py +69 -0
- angr/procedures/libc/memcpy.py +45 -0
- angr/procedures/libc/memset.py +72 -0
- angr/procedures/libc/openlog.py +10 -0
- angr/procedures/libc/perror.py +13 -0
- angr/procedures/libc/printf.py +34 -0
- angr/procedures/libc/putchar.py +13 -0
- angr/procedures/libc/puts.py +19 -0
- angr/procedures/libc/rand.py +8 -0
- angr/procedures/libc/realloc.py +8 -0
- angr/procedures/libc/rewind.py +12 -0
- angr/procedures/libc/scanf.py +20 -0
- angr/procedures/libc/setbuf.py +9 -0
- angr/procedures/libc/setvbuf.py +7 -0
- angr/procedures/libc/snprintf.py +36 -0
- angr/procedures/libc/sprintf.py +25 -0
- angr/procedures/libc/srand.py +7 -0
- angr/procedures/libc/sscanf.py +13 -0
- angr/procedures/libc/stpcpy.py +18 -0
- angr/procedures/libc/strcat.py +14 -0
- angr/procedures/libc/strchr.py +48 -0
- angr/procedures/libc/strcmp.py +31 -0
- angr/procedures/libc/strcpy.py +13 -0
- angr/procedures/libc/strlen.py +114 -0
- angr/procedures/libc/strncat.py +19 -0
- angr/procedures/libc/strncmp.py +183 -0
- angr/procedures/libc/strncpy.py +22 -0
- angr/procedures/libc/strnlen.py +13 -0
- angr/procedures/libc/strstr.py +101 -0
- angr/procedures/libc/strtol.py +261 -0
- angr/procedures/libc/strtoul.py +9 -0
- angr/procedures/libc/system.py +13 -0
- angr/procedures/libc/time.py +9 -0
- angr/procedures/libc/tmpnam.py +20 -0
- angr/procedures/libc/tolower.py +10 -0
- angr/procedures/libc/toupper.py +10 -0
- angr/procedures/libc/ungetc.py +20 -0
- angr/procedures/libc/vsnprintf.py +17 -0
- angr/procedures/libc/wchar.py +16 -0
- angr/procedures/libstdcpp/__init__.py +0 -0
- angr/procedures/libstdcpp/_unwind_resume.py +11 -0
- angr/procedures/libstdcpp/std____throw_bad_alloc.py +13 -0
- angr/procedures/libstdcpp/std____throw_bad_cast.py +13 -0
- angr/procedures/libstdcpp/std____throw_length_error.py +13 -0
- angr/procedures/libstdcpp/std____throw_logic_error.py +13 -0
- angr/procedures/libstdcpp/std__terminate.py +13 -0
- angr/procedures/linux_kernel/__init__.py +3 -0
- angr/procedures/linux_kernel/access.py +18 -0
- angr/procedures/linux_kernel/arch_prctl.py +34 -0
- angr/procedures/linux_kernel/arm_user_helpers.py +59 -0
- angr/procedures/linux_kernel/brk.py +18 -0
- angr/procedures/linux_kernel/cwd.py +28 -0
- angr/procedures/linux_kernel/fstat.py +138 -0
- angr/procedures/linux_kernel/fstat64.py +170 -0
- angr/procedures/linux_kernel/futex.py +17 -0
- angr/procedures/linux_kernel/getegid.py +17 -0
- angr/procedures/linux_kernel/geteuid.py +17 -0
- angr/procedures/linux_kernel/getgid.py +17 -0
- angr/procedures/linux_kernel/getpid.py +14 -0
- angr/procedures/linux_kernel/getrlimit.py +24 -0
- angr/procedures/linux_kernel/gettid.py +9 -0
- angr/procedures/linux_kernel/getuid.py +17 -0
- angr/procedures/linux_kernel/iovec.py +47 -0
- angr/procedures/linux_kernel/lseek.py +42 -0
- angr/procedures/linux_kernel/mmap.py +16 -0
- angr/procedures/linux_kernel/mprotect.py +42 -0
- angr/procedures/linux_kernel/munmap.py +8 -0
- angr/procedures/linux_kernel/openat.py +26 -0
- angr/procedures/linux_kernel/set_tid_address.py +8 -0
- angr/procedures/linux_kernel/sigaction.py +19 -0
- angr/procedures/linux_kernel/sigprocmask.py +23 -0
- angr/procedures/linux_kernel/stat.py +23 -0
- angr/procedures/linux_kernel/sysinfo.py +59 -0
- angr/procedures/linux_kernel/tgkill.py +10 -0
- angr/procedures/linux_kernel/time.py +34 -0
- angr/procedures/linux_kernel/uid.py +30 -0
- angr/procedures/linux_kernel/uname.py +29 -0
- angr/procedures/linux_kernel/unlink.py +22 -0
- angr/procedures/linux_kernel/vsyscall.py +16 -0
- angr/procedures/linux_loader/__init__.py +3 -0
- angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +7 -0
- angr/procedures/linux_loader/_dl_rtld_lock.py +15 -0
- angr/procedures/linux_loader/sim_loader.py +54 -0
- angr/procedures/linux_loader/tls.py +40 -0
- angr/procedures/msvcr/__getmainargs.py +16 -0
- angr/procedures/msvcr/__init__.py +4 -0
- angr/procedures/msvcr/_initterm.py +38 -0
- angr/procedures/msvcr/fmode.py +31 -0
- angr/procedures/ntdll/__init__.py +0 -0
- angr/procedures/ntdll/exceptions.py +60 -0
- angr/procedures/posix/__init__.py +3 -0
- angr/procedures/posix/accept.py +29 -0
- angr/procedures/posix/bind.py +13 -0
- angr/procedures/posix/bzero.py +9 -0
- angr/procedures/posix/chroot.py +27 -0
- angr/procedures/posix/close.py +9 -0
- angr/procedures/posix/closedir.py +7 -0
- angr/procedures/posix/dup.py +56 -0
- angr/procedures/posix/fcntl.py +10 -0
- angr/procedures/posix/fdopen.py +76 -0
- angr/procedures/posix/fileno.py +18 -0
- angr/procedures/posix/fork.py +13 -0
- angr/procedures/posix/getenv.py +35 -0
- angr/procedures/posix/gethostbyname.py +43 -0
- angr/procedures/posix/getpass.py +19 -0
- angr/procedures/posix/getsockopt.py +11 -0
- angr/procedures/posix/htonl.py +11 -0
- angr/procedures/posix/htons.py +11 -0
- angr/procedures/posix/inet_ntoa.py +59 -0
- angr/procedures/posix/listen.py +13 -0
- angr/procedures/posix/mmap.py +144 -0
- angr/procedures/posix/open.py +18 -0
- angr/procedures/posix/opendir.py +10 -0
- angr/procedures/posix/poll.py +55 -0
- angr/procedures/posix/pread64.py +46 -0
- angr/procedures/posix/pthread.py +87 -0
- angr/procedures/posix/pwrite64.py +46 -0
- angr/procedures/posix/read.py +13 -0
- angr/procedures/posix/readdir.py +62 -0
- angr/procedures/posix/recv.py +13 -0
- angr/procedures/posix/recvfrom.py +13 -0
- angr/procedures/posix/select.py +48 -0
- angr/procedures/posix/send.py +23 -0
- angr/procedures/posix/setsockopt.py +9 -0
- angr/procedures/posix/sigaction.py +23 -0
- angr/procedures/posix/sim_time.py +48 -0
- angr/procedures/posix/sleep.py +8 -0
- angr/procedures/posix/socket.py +18 -0
- angr/procedures/posix/strcasecmp.py +26 -0
- angr/procedures/posix/strdup.py +18 -0
- angr/procedures/posix/strtok_r.py +64 -0
- angr/procedures/posix/syslog.py +15 -0
- angr/procedures/posix/tz.py +9 -0
- angr/procedures/posix/unlink.py +11 -0
- angr/procedures/posix/usleep.py +8 -0
- angr/procedures/posix/write.py +13 -0
- angr/procedures/procedure_dict.py +50 -0
- angr/procedures/stubs/CallReturn.py +13 -0
- angr/procedures/stubs/NoReturnUnconstrained.py +13 -0
- angr/procedures/stubs/Nop.py +7 -0
- angr/procedures/stubs/PathTerminator.py +9 -0
- angr/procedures/stubs/Redirect.py +18 -0
- angr/procedures/stubs/ReturnChar.py +11 -0
- angr/procedures/stubs/ReturnUnconstrained.py +24 -0
- angr/procedures/stubs/UnresolvableCallTarget.py +9 -0
- angr/procedures/stubs/UnresolvableJumpTarget.py +9 -0
- angr/procedures/stubs/UserHook.py +18 -0
- angr/procedures/stubs/__init__.py +3 -0
- angr/procedures/stubs/b64_decode.py +15 -0
- angr/procedures/stubs/caller.py +14 -0
- angr/procedures/stubs/crazy_scanf.py +20 -0
- angr/procedures/stubs/format_parser.py +669 -0
- angr/procedures/stubs/syscall_stub.py +24 -0
- angr/procedures/testing/__init__.py +3 -0
- angr/procedures/testing/manyargs.py +9 -0
- angr/procedures/testing/retreg.py +8 -0
- angr/procedures/tracer/__init__.py +4 -0
- angr/procedures/tracer/random.py +9 -0
- angr/procedures/tracer/receive.py +23 -0
- angr/procedures/tracer/transmit.py +26 -0
- angr/procedures/uclibc/__init__.py +3 -0
- angr/procedures/uclibc/__uClibc_main.py +10 -0
- angr/procedures/win32/EncodePointer.py +7 -0
- angr/procedures/win32/ExitProcess.py +9 -0
- angr/procedures/win32/GetCommandLine.py +12 -0
- angr/procedures/win32/GetCurrentProcessId.py +7 -0
- angr/procedures/win32/GetCurrentThreadId.py +7 -0
- angr/procedures/win32/GetLastInputInfo.py +40 -0
- angr/procedures/win32/GetModuleHandle.py +29 -0
- angr/procedures/win32/GetProcessAffinityMask.py +37 -0
- angr/procedures/win32/InterlockedExchange.py +15 -0
- angr/procedures/win32/IsProcessorFeaturePresent.py +7 -0
- angr/procedures/win32/VirtualAlloc.py +114 -0
- angr/procedures/win32/VirtualProtect.py +60 -0
- angr/procedures/win32/__init__.py +3 -0
- angr/procedures/win32/critical_section.py +12 -0
- angr/procedures/win32/dynamic_loading.py +104 -0
- angr/procedures/win32/file_handles.py +47 -0
- angr/procedures/win32/gethostbyname.py +12 -0
- angr/procedures/win32/heap.py +45 -0
- angr/procedures/win32/is_bad_ptr.py +26 -0
- angr/procedures/win32/local_storage.py +88 -0
- angr/procedures/win32/mutex.py +11 -0
- angr/procedures/win32/sim_time.py +135 -0
- angr/procedures/win32/system_paths.py +35 -0
- angr/procedures/win32_kernel/ExAllocatePool.py +13 -0
- angr/procedures/win32_kernel/ExFreePoolWithTag.py +8 -0
- angr/procedures/win32_kernel/__fastfail.py +15 -0
- angr/procedures/win32_kernel/__init__.py +3 -0
- angr/procedures/win_user32/__init__.py +0 -0
- angr/procedures/win_user32/chars.py +15 -0
- angr/procedures/win_user32/keyboard.py +14 -0
- angr/procedures/win_user32/messagebox.py +49 -0
- angr/project.py +860 -0
- angr/protos/__init__.py +19 -0
- angr/protos/cfg_pb2.py +42 -0
- angr/protos/function_pb2.py +38 -0
- angr/protos/primitives_pb2.py +59 -0
- angr/protos/variables_pb2.py +55 -0
- angr/protos/xrefs_pb2.py +36 -0
- angr/py.typed +1 -0
- angr/rustylib.cpython-311-darwin.so +0 -0
- angr/serializable.py +66 -0
- angr/sim_manager.py +971 -0
- angr/sim_options.py +436 -0
- angr/sim_procedure.py +626 -0
- angr/sim_state.py +926 -0
- angr/sim_state_options.py +403 -0
- angr/sim_type.py +4026 -0
- angr/sim_variable.py +470 -0
- angr/simos/__init__.py +47 -0
- angr/simos/cgc.py +153 -0
- angr/simos/javavm.py +458 -0
- angr/simos/linux.py +509 -0
- angr/simos/simos.py +444 -0
- angr/simos/snimmuc_nxp.py +149 -0
- angr/simos/userland.py +163 -0
- angr/simos/windows.py +615 -0
- angr/simos/xbox.py +32 -0
- angr/slicer.py +352 -0
- angr/state_hierarchy.py +262 -0
- angr/state_plugins/__init__.py +84 -0
- angr/state_plugins/callstack.py +478 -0
- angr/state_plugins/cgc.py +155 -0
- angr/state_plugins/debug_variables.py +192 -0
- angr/state_plugins/filesystem.py +463 -0
- angr/state_plugins/gdb.py +148 -0
- angr/state_plugins/globals.py +65 -0
- angr/state_plugins/heap/__init__.py +15 -0
- angr/state_plugins/heap/heap_base.py +128 -0
- angr/state_plugins/heap/heap_brk.py +136 -0
- angr/state_plugins/heap/heap_freelist.py +213 -0
- angr/state_plugins/heap/heap_libc.py +46 -0
- angr/state_plugins/heap/heap_ptmalloc.py +620 -0
- angr/state_plugins/heap/utils.py +22 -0
- angr/state_plugins/history.py +564 -0
- angr/state_plugins/inspect.py +375 -0
- angr/state_plugins/javavm_classloader.py +134 -0
- angr/state_plugins/jni_references.py +95 -0
- angr/state_plugins/libc.py +1263 -0
- angr/state_plugins/light_registers.py +168 -0
- angr/state_plugins/log.py +84 -0
- angr/state_plugins/loop_data.py +92 -0
- angr/state_plugins/plugin.py +176 -0
- angr/state_plugins/posix.py +703 -0
- angr/state_plugins/preconstrainer.py +196 -0
- angr/state_plugins/scratch.py +173 -0
- angr/state_plugins/sim_action.py +326 -0
- angr/state_plugins/sim_action_object.py +271 -0
- angr/state_plugins/sim_event.py +59 -0
- angr/state_plugins/solver.py +1128 -0
- angr/state_plugins/symbolizer.py +291 -0
- angr/state_plugins/trace_additions.py +738 -0
- angr/state_plugins/uc_manager.py +94 -0
- angr/state_plugins/unicorn_engine.py +1920 -0
- angr/state_plugins/view.py +340 -0
- angr/storage/__init__.py +15 -0
- angr/storage/file.py +1210 -0
- angr/storage/memory_mixins/__init__.py +317 -0
- angr/storage/memory_mixins/actions_mixin.py +72 -0
- angr/storage/memory_mixins/address_concretization_mixin.py +384 -0
- angr/storage/memory_mixins/bvv_conversion_mixin.py +73 -0
- angr/storage/memory_mixins/clouseau_mixin.py +137 -0
- angr/storage/memory_mixins/conditional_store_mixin.py +25 -0
- angr/storage/memory_mixins/convenient_mappings_mixin.py +256 -0
- angr/storage/memory_mixins/default_filler_mixin.py +144 -0
- angr/storage/memory_mixins/dirty_addrs_mixin.py +11 -0
- angr/storage/memory_mixins/hex_dumper_mixin.py +82 -0
- angr/storage/memory_mixins/javavm_memory_mixin.py +392 -0
- angr/storage/memory_mixins/keyvalue_memory_mixin.py +43 -0
- angr/storage/memory_mixins/label_merger_mixin.py +31 -0
- angr/storage/memory_mixins/memory_mixin.py +175 -0
- angr/storage/memory_mixins/multi_value_merger_mixin.py +79 -0
- angr/storage/memory_mixins/name_resolution_mixin.py +67 -0
- angr/storage/memory_mixins/paged_memory/__init__.py +0 -0
- angr/storage/memory_mixins/paged_memory/page_backer_mixins.py +266 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_mixin.py +743 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +65 -0
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +26 -0
- angr/storage/memory_mixins/paged_memory/pages/base.py +31 -0
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +341 -0
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +92 -0
- angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +55 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +338 -0
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +324 -0
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +419 -0
- angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +52 -0
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +529 -0
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +74 -0
- angr/storage/memory_mixins/regioned_memory/__init__.py +17 -0
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +36 -0
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +31 -0
- angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +9 -0
- angr/storage/memory_mixins/regioned_memory/region_data.py +246 -0
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +241 -0
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +119 -0
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +442 -0
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +69 -0
- angr/storage/memory_mixins/simple_interface_mixin.py +71 -0
- angr/storage/memory_mixins/simplification_mixin.py +15 -0
- angr/storage/memory_mixins/size_resolution_mixin.py +143 -0
- angr/storage/memory_mixins/slotted_memory.py +140 -0
- angr/storage/memory_mixins/smart_find_mixin.py +161 -0
- angr/storage/memory_mixins/symbolic_merger_mixin.py +16 -0
- angr/storage/memory_mixins/top_merger_mixin.py +25 -0
- angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
- angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
- angr/storage/memory_object.py +195 -0
- angr/tablespecs.py +91 -0
- angr/unicornlib.dylib +0 -0
- angr/utils/__init__.py +46 -0
- angr/utils/ail.py +176 -0
- angr/utils/algo.py +34 -0
- angr/utils/balancer.py +776 -0
- angr/utils/bits.py +46 -0
- angr/utils/constants.py +9 -0
- angr/utils/cowdict.py +63 -0
- angr/utils/cpp.py +17 -0
- angr/utils/doms.py +150 -0
- angr/utils/dynamic_dictlist.py +89 -0
- angr/utils/endness.py +18 -0
- angr/utils/enums_conv.py +97 -0
- angr/utils/env.py +12 -0
- angr/utils/formatting.py +128 -0
- angr/utils/funcid.py +244 -0
- angr/utils/graph.py +981 -0
- angr/utils/lazy_import.py +13 -0
- angr/utils/library.py +236 -0
- angr/utils/loader.py +55 -0
- angr/utils/mp.py +66 -0
- angr/utils/orderedset.py +74 -0
- angr/utils/ssa/__init__.py +455 -0
- angr/utils/ssa/tmp_uses_collector.py +23 -0
- angr/utils/ssa/vvar_uses_collector.py +36 -0
- angr/utils/strings.py +20 -0
- angr/utils/tagged_interval_map.py +112 -0
- angr/utils/timing.py +74 -0
- angr/utils/types.py +193 -0
- angr/utils/vex.py +11 -0
- angr/vaults.py +367 -0
- angr-9.2.192.dist-info/METADATA +112 -0
- angr-9.2.192.dist-info/RECORD +1442 -0
- angr-9.2.192.dist-info/WHEEL +6 -0
- angr-9.2.192.dist-info/entry_points.txt +2 -0
- angr-9.2.192.dist-info/licenses/LICENSE +27 -0
- angr-9.2.192.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2490 @@
|
|
|
1
|
+
# pylint:disable=wrong-import-position,wrong-import-order
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import enum
|
|
4
|
+
from typing import TYPE_CHECKING, Literal, cast
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
from collections import defaultdict, OrderedDict
|
|
7
|
+
import logging
|
|
8
|
+
import functools
|
|
9
|
+
import contextlib
|
|
10
|
+
|
|
11
|
+
import pyvex
|
|
12
|
+
import claripy
|
|
13
|
+
from archinfo.arch_arm import is_arm_arch
|
|
14
|
+
from claripy.annotation import UninitializedAnnotation
|
|
15
|
+
|
|
16
|
+
from angr import sim_options as o
|
|
17
|
+
from angr import BP, BP_BEFORE, BP_AFTER
|
|
18
|
+
from angr.misc.ux import once
|
|
19
|
+
from angr.concretization_strategies import SimConcretizationStrategyAny
|
|
20
|
+
from angr.knowledge_plugins.cfg import IndirectJump, IndirectJumpType
|
|
21
|
+
from angr.engines.vex.claripy import ccall
|
|
22
|
+
from angr.engines.light import SimEngineNostmtVEX, SpOffset, RegisterOffset
|
|
23
|
+
from angr.errors import AngrError, SimError
|
|
24
|
+
from angr.blade import Blade
|
|
25
|
+
from angr.annocfg import AnnotatedCFG
|
|
26
|
+
from angr.exploration_techniques.slicecutor import Slicecutor
|
|
27
|
+
from angr.exploration_techniques.local_loop_seer import LocalLoopSeer
|
|
28
|
+
from angr.exploration_techniques.explorer import Explorer
|
|
29
|
+
from angr.utils.constants import DEFAULT_STATEMENT
|
|
30
|
+
from angr.analyses.propagator.top_checker_mixin import ClaripyDataVEXEngineMixin
|
|
31
|
+
from angr.engines.vex.claripy.datalayer import value
|
|
32
|
+
from .resolver import IndirectJumpResolver
|
|
33
|
+
from .constant_value_manager import ConstantValueManager
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
from angr.engines import pcode
|
|
37
|
+
except ImportError:
|
|
38
|
+
pcode = None
|
|
39
|
+
|
|
40
|
+
if TYPE_CHECKING:
|
|
41
|
+
from angr.knowledge_plugins import Function
|
|
42
|
+
|
|
43
|
+
l = logging.getLogger(name=__name__)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class NotAJumpTableNotification(AngrError):
|
|
47
|
+
"""
|
|
48
|
+
Exception raised to indicate this is not (or does not appear to be) a jump table.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class UninitReadMeta:
|
|
53
|
+
"""
|
|
54
|
+
Uninitialized read remapping details.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
uninit_read_base = 0xC000000
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AddressTransformationTypes(int, enum.Enum):
|
|
61
|
+
"""
|
|
62
|
+
Address transformation operations.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
Assignment = 0
|
|
66
|
+
SignedExtension = 1
|
|
67
|
+
UnsignedExtension = 2
|
|
68
|
+
Truncation = 3
|
|
69
|
+
Or1 = 4
|
|
70
|
+
ShiftLeft = 5
|
|
71
|
+
ShiftRight = 6
|
|
72
|
+
Add = 7
|
|
73
|
+
Load = 8
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class AddressTransformation:
|
|
77
|
+
"""
|
|
78
|
+
Describe and record an address transformation operation.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, op: AddressTransformationTypes, operands: list, first_load: bool = False):
|
|
82
|
+
self.op = op
|
|
83
|
+
self.operands = operands
|
|
84
|
+
self.first_load = first_load
|
|
85
|
+
|
|
86
|
+
def __repr__(self):
|
|
87
|
+
return f"<Transformation: {self.op} {self.operands}>"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class AddressOperand:
|
|
91
|
+
"""
|
|
92
|
+
The class for the singleton class AddressSingleton. It represents the address being transformed before using as an
|
|
93
|
+
indirect jump target.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
def __repr__(self):
|
|
97
|
+
return "ADDR"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
AddressSingleton = AddressOperand()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class Tmp:
|
|
104
|
+
"""
|
|
105
|
+
For modeling Tmp variables.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
def __init__(self, tmp_idx):
|
|
109
|
+
self.tmp_idx = tmp_idx
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class JumpTargetBaseAddr:
|
|
113
|
+
"""
|
|
114
|
+
Model for jump targets and their data origin.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def __init__(
|
|
118
|
+
self, stmt_loc, stmt: pyvex.stmt.IRStmt, tmp: int, base_addr: int | None = None, tmp_1: int | None = None
|
|
119
|
+
):
|
|
120
|
+
self.stmt_loc = stmt_loc
|
|
121
|
+
self.stmt = stmt
|
|
122
|
+
self.tmp = tmp
|
|
123
|
+
self.tmp_1 = tmp_1
|
|
124
|
+
self.base_addr = base_addr
|
|
125
|
+
|
|
126
|
+
assert base_addr is not None or tmp_1 is not None
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def base_addr_available(self):
|
|
130
|
+
return self.base_addr is not None
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# Jump table pre-check
|
|
135
|
+
#
|
|
136
|
+
|
|
137
|
+
_x86_ct = ccall.data["X86"]["CondTypes"]
|
|
138
|
+
_amd64_ct = ccall.data["AMD64"]["CondTypes"]
|
|
139
|
+
EXPECTED_COND_TYPES = {
|
|
140
|
+
"X86": {
|
|
141
|
+
_x86_ct["CondB"],
|
|
142
|
+
_x86_ct["CondNB"],
|
|
143
|
+
_x86_ct["CondBE"],
|
|
144
|
+
_x86_ct["CondNBE"],
|
|
145
|
+
_x86_ct["CondL"],
|
|
146
|
+
_x86_ct["CondNL"],
|
|
147
|
+
_x86_ct["CondLE"],
|
|
148
|
+
_x86_ct["CondNLE"],
|
|
149
|
+
},
|
|
150
|
+
"AMD64": {
|
|
151
|
+
_amd64_ct["CondB"],
|
|
152
|
+
_amd64_ct["CondNB"],
|
|
153
|
+
_amd64_ct["CondBE"],
|
|
154
|
+
_amd64_ct["CondNBE"],
|
|
155
|
+
_amd64_ct["CondL"],
|
|
156
|
+
_amd64_ct["CondNL"],
|
|
157
|
+
_amd64_ct["CondLE"],
|
|
158
|
+
_amd64_ct["CondNLE"],
|
|
159
|
+
},
|
|
160
|
+
"ARM": {
|
|
161
|
+
ccall.ARMCondHS,
|
|
162
|
+
ccall.ARMCondLO,
|
|
163
|
+
ccall.ARMCondHI,
|
|
164
|
+
ccall.ARMCondLS,
|
|
165
|
+
ccall.ARMCondGE,
|
|
166
|
+
ccall.ARMCondLT,
|
|
167
|
+
ccall.ARMCondGT,
|
|
168
|
+
ccall.ARMCondLE,
|
|
169
|
+
},
|
|
170
|
+
"AARCH64": {
|
|
171
|
+
ccall.ARM64CondCS,
|
|
172
|
+
ccall.ARM64CondCC,
|
|
173
|
+
ccall.ARM64CondHI,
|
|
174
|
+
ccall.ARM64CondLS,
|
|
175
|
+
ccall.ARM64CondGE,
|
|
176
|
+
ccall.ARM64CondLT,
|
|
177
|
+
ccall.ARM64CondGT,
|
|
178
|
+
ccall.ARM64CondLE,
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class JumpTableProcessorState:
|
|
184
|
+
"""
|
|
185
|
+
The state used in JumpTableProcessor.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
__slots__ = (
|
|
189
|
+
"_registers",
|
|
190
|
+
"_stack",
|
|
191
|
+
"_tmpvar_source",
|
|
192
|
+
"arch",
|
|
193
|
+
"is_jumptable",
|
|
194
|
+
"regs_to_initialize",
|
|
195
|
+
"stmts_to_instrument",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
def __init__(self, arch):
|
|
199
|
+
self.arch = arch
|
|
200
|
+
|
|
201
|
+
self._registers = {}
|
|
202
|
+
self._stack = {}
|
|
203
|
+
self._tmpvar_source = {} # a mapping from temporary variables to their origins
|
|
204
|
+
|
|
205
|
+
self.is_jumptable: bool | None = None # is the current slice representing a jump table?
|
|
206
|
+
self.stmts_to_instrument = [] # Store/Put statements that we should instrument
|
|
207
|
+
self.regs_to_initialize = [] # registers that we should initialize
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
class RegOffsetAnnotation(claripy.Annotation):
|
|
211
|
+
"""
|
|
212
|
+
Register Offset annotation.
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
__slots__ = ("reg_offset",)
|
|
216
|
+
|
|
217
|
+
def __init__(self, reg_offset: RegisterOffset):
|
|
218
|
+
self.reg_offset = reg_offset
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def relocatable(self):
|
|
222
|
+
return False
|
|
223
|
+
|
|
224
|
+
@property
|
|
225
|
+
def eliminatable(self):
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
binop_handler = SimEngineNostmtVEX[JumpTableProcessorState, claripy.ast.BV, JumpTableProcessorState].binop_handler
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class JumpTableProcessor(
|
|
233
|
+
SimEngineNostmtVEX[JumpTableProcessorState, claripy.ast.BV, JumpTableProcessorState],
|
|
234
|
+
ClaripyDataVEXEngineMixin[JumpTableProcessorState, claripy.ast.BV, JumpTableProcessorState, None],
|
|
235
|
+
): # pylint:disable=abstract-method
|
|
236
|
+
"""
|
|
237
|
+
Implements a simple and stupid data dependency tracking for stack and register variables.
|
|
238
|
+
|
|
239
|
+
Also determines which statements to instrument during static execution of the slice later. For example, the
|
|
240
|
+
following example is not uncommon in non-optimized binaries::
|
|
241
|
+
|
|
242
|
+
mov [rbp+var_54], 1
|
|
243
|
+
loc_4051a6:
|
|
244
|
+
cmp [rbp+var_54], 6
|
|
245
|
+
ja loc_405412 (default)
|
|
246
|
+
loc_4051b0:
|
|
247
|
+
mov eax, [rbp+var_54]
|
|
248
|
+
mov rax, qword [rax*8+0x223a01]
|
|
249
|
+
jmp rax
|
|
250
|
+
|
|
251
|
+
We want to instrument the first instruction and replace the constant 1 with a symbolic variable, otherwise we will
|
|
252
|
+
not be able to recover all jump targets later in block 0x4051b0.
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
def __init__(self, project, indirect_jump_node_pred_addrs: set[int], bp_sp_diff=0x100):
|
|
256
|
+
super().__init__(project)
|
|
257
|
+
self._bp_sp_diff = bp_sp_diff # bp - sp
|
|
258
|
+
self._tsrc: set[Literal["const"] | tuple[int, int]] = (
|
|
259
|
+
set()
|
|
260
|
+
) # a scratch variable to store source information for values
|
|
261
|
+
self._indirect_jump_node_pred_addrs = indirect_jump_node_pred_addrs
|
|
262
|
+
|
|
263
|
+
self._SPOFFSET_BASE = claripy.BVS("SpOffset", self.project.arch.bits, explicit_name=True)
|
|
264
|
+
self._REGOFFSET_BASE: dict[int, claripy.ast.BV] = {}
|
|
265
|
+
|
|
266
|
+
def _process_block_end(self, stmt_result, whitelist):
|
|
267
|
+
return self.state
|
|
268
|
+
|
|
269
|
+
@staticmethod
|
|
270
|
+
def _is_spoffset(expr) -> bool:
|
|
271
|
+
return "SpOffset" in expr.variables
|
|
272
|
+
|
|
273
|
+
def _get_spoffset_expr(self, sp_offset: SpOffset) -> claripy.ast.BV:
|
|
274
|
+
return self._SPOFFSET_BASE.annotate(RegOffsetAnnotation(sp_offset))
|
|
275
|
+
|
|
276
|
+
@staticmethod
|
|
277
|
+
def _extract_spoffset_from_expr(expr: claripy.ast.Base) -> RegisterOffset | None:
|
|
278
|
+
if expr.op == "BVS":
|
|
279
|
+
for anno in expr.annotations:
|
|
280
|
+
if isinstance(anno, RegOffsetAnnotation):
|
|
281
|
+
return anno.reg_offset
|
|
282
|
+
elif expr.op == "__add__":
|
|
283
|
+
if len(expr.args) == 1:
|
|
284
|
+
return JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
285
|
+
if len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
286
|
+
sp_offset = JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
287
|
+
if sp_offset is not None:
|
|
288
|
+
delta = cast(claripy.ast.BV, expr.args[1]).concrete_value
|
|
289
|
+
sp_offset += delta
|
|
290
|
+
return sp_offset
|
|
291
|
+
elif expr.op == "__and__" and len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
292
|
+
# ignore all masking on SpOffsets
|
|
293
|
+
return JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
294
|
+
return None
|
|
295
|
+
|
|
296
|
+
@staticmethod
|
|
297
|
+
def _is_registeroffset(expr) -> bool:
|
|
298
|
+
return "RegisterOffset" in expr.variables
|
|
299
|
+
|
|
300
|
+
def _get_regoffset_expr(self, reg_offset: RegisterOffset, bits: int) -> claripy.ast.BV:
|
|
301
|
+
if bits not in self._REGOFFSET_BASE:
|
|
302
|
+
self._REGOFFSET_BASE[bits] = claripy.BVS("RegisterOffset", bits, explicit_name=True)
|
|
303
|
+
return self._REGOFFSET_BASE[bits].annotate(RegOffsetAnnotation(reg_offset))
|
|
304
|
+
|
|
305
|
+
@staticmethod
|
|
306
|
+
def _extract_regoffset_from_expr(expr: claripy.ast.Base) -> RegisterOffset | None:
|
|
307
|
+
if expr.op == "BVS":
|
|
308
|
+
for anno in expr.annotations:
|
|
309
|
+
if isinstance(anno, RegOffsetAnnotation):
|
|
310
|
+
return anno.reg_offset
|
|
311
|
+
elif expr.op == "__add__":
|
|
312
|
+
if len(expr.args) == 1:
|
|
313
|
+
return JumpTableProcessor._extract_regoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
314
|
+
if len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
315
|
+
reg_offset = JumpTableProcessor._extract_regoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
316
|
+
if reg_offset is not None:
|
|
317
|
+
delta = cast(claripy.ast.BV, expr.args[1]).concrete_value
|
|
318
|
+
reg_offset += delta
|
|
319
|
+
return reg_offset
|
|
320
|
+
elif expr.op == "__and__" and len(expr.args) == 2 and cast(claripy.ast.BV, expr.args[1]).op == "BVV":
|
|
321
|
+
# ignore all masking on SpOffsets
|
|
322
|
+
return JumpTableProcessor._extract_spoffset_from_expr(cast(claripy.ast.BV, expr.args[0]))
|
|
323
|
+
return None
|
|
324
|
+
|
|
325
|
+
def _handle_stmt_WrTmp(self, stmt):
|
|
326
|
+
self._tsrc = set()
|
|
327
|
+
|
|
328
|
+
self.tmps[stmt.tmp] = self._expr(stmt.data)
|
|
329
|
+
if self._tsrc:
|
|
330
|
+
self.state._tmpvar_source[stmt.tmp] = self._tsrc
|
|
331
|
+
|
|
332
|
+
def _handle_stmt_Put(self, stmt):
|
|
333
|
+
self._tsrc = set()
|
|
334
|
+
offset = stmt.offset
|
|
335
|
+
data = self._expr(stmt.data)
|
|
336
|
+
r = (self._tsrc, data) if self._tsrc is not None else ((self.block.addr, self.stmt_idx), data)
|
|
337
|
+
self.state._registers[offset] = r
|
|
338
|
+
|
|
339
|
+
def _handle_stmt_Store(self, stmt):
|
|
340
|
+
self._tsrc = set()
|
|
341
|
+
addr = self._expr(stmt.addr)
|
|
342
|
+
data = self._expr(stmt.data)
|
|
343
|
+
|
|
344
|
+
if addr is None:
|
|
345
|
+
return
|
|
346
|
+
|
|
347
|
+
if isinstance(addr, SpOffset):
|
|
348
|
+
self.state._stack[addr.offset] = ((self.block.addr, self.stmt_idx), data)
|
|
349
|
+
|
|
350
|
+
def _handle_expr_RdTmp(self, expr):
|
|
351
|
+
try:
|
|
352
|
+
v = self.tmps[expr.tmp]
|
|
353
|
+
except KeyError:
|
|
354
|
+
v = self._top(expr.result_size(self.tyenv))
|
|
355
|
+
if expr.tmp in self.state._tmpvar_source:
|
|
356
|
+
self._tsrc |= set(self.state._tmpvar_source[expr.tmp])
|
|
357
|
+
return v
|
|
358
|
+
|
|
359
|
+
def _handle_expr_Get(self, expr):
|
|
360
|
+
if expr.offset == self.arch.bp_offset:
|
|
361
|
+
v = self._get_spoffset_expr(SpOffset(self.arch.bits, self._bp_sp_diff))
|
|
362
|
+
elif expr.offset == self.arch.sp_offset:
|
|
363
|
+
v = self._get_spoffset_expr(SpOffset(self.arch.bits, 0))
|
|
364
|
+
else:
|
|
365
|
+
if expr.offset in self.state._registers:
|
|
366
|
+
self._tsrc |= set(self.state._registers[expr.offset][0])
|
|
367
|
+
v = self.state._registers[expr.offset][1]
|
|
368
|
+
else:
|
|
369
|
+
# the register does not exist
|
|
370
|
+
# we initialize it here
|
|
371
|
+
v = RegisterOffset(expr.result_size(self.tyenv), expr.offset, 0)
|
|
372
|
+
v = self._get_regoffset_expr(v, expr.result_size(self.tyenv))
|
|
373
|
+
src = (self.block.addr, self.stmt_idx)
|
|
374
|
+
self._tsrc.add(src)
|
|
375
|
+
self.state._registers[expr.offset] = ([src], v)
|
|
376
|
+
|
|
377
|
+
# make sure the size matches
|
|
378
|
+
# note that this is sometimes incorrect. for example, we do not differentiate between reads at ah and al...
|
|
379
|
+
# but it should be good enough for now (without switching state._registers to a real SimMemory, which will
|
|
380
|
+
# surely slow down stuff quite a bit)
|
|
381
|
+
if v is not None:
|
|
382
|
+
bits = expr.result_size(self.tyenv)
|
|
383
|
+
if v.size() > bits:
|
|
384
|
+
v = v[bits - 1 : 0]
|
|
385
|
+
elif v.size() < bits:
|
|
386
|
+
v = claripy.ZeroExt(bits - v.size(), v)
|
|
387
|
+
return v
|
|
388
|
+
|
|
389
|
+
def _handle_function(self, expr): # pylint:disable=unused-argument,no-self-use
|
|
390
|
+
return None # This analysis is not interprocedural
|
|
391
|
+
|
|
392
|
+
def _handle_expr_Load(self, expr):
|
|
393
|
+
addr = self._expr(expr.addr)
|
|
394
|
+
size = expr.result_size(self.tyenv) // 8
|
|
395
|
+
return self._do_load(addr, size)
|
|
396
|
+
|
|
397
|
+
def _handle_stmt_LoadG(self, stmt: pyvex.stmt.LoadG):
|
|
398
|
+
self._tsrc = set()
|
|
399
|
+
|
|
400
|
+
guard = self._expr(stmt.guard) != 0
|
|
401
|
+
iftrue = self._do_load(self._expr(stmt.addr), stmt.addr.result_size(self.tyenv) // 8)
|
|
402
|
+
iffalse = self._expr(stmt.alt)
|
|
403
|
+
result = claripy.If(guard, iftrue, iffalse)
|
|
404
|
+
self.tmps[stmt.dst] = result
|
|
405
|
+
if self._tsrc:
|
|
406
|
+
self.state._tmpvar_source[stmt.dst] = self._tsrc
|
|
407
|
+
|
|
408
|
+
def _handle_expr_Const(self, expr):
|
|
409
|
+
v = value(expr.con.type, expr.con.value)
|
|
410
|
+
self._tsrc.add("const")
|
|
411
|
+
if not isinstance(v, claripy.ast.BV):
|
|
412
|
+
return self._top(expr.result_size(self.tyenv))
|
|
413
|
+
return v
|
|
414
|
+
|
|
415
|
+
@binop_handler
|
|
416
|
+
def _handle_binop_And(self, expr):
|
|
417
|
+
arg0 = self._expr(expr.args[0])
|
|
418
|
+
if (
|
|
419
|
+
isinstance(arg0, claripy.ast.BV)
|
|
420
|
+
and self._is_registeroffset(arg0)
|
|
421
|
+
and isinstance(expr.args[1], pyvex.IRExpr.Const)
|
|
422
|
+
):
|
|
423
|
+
mask_value = expr.args[1].con.value
|
|
424
|
+
if mask_value in {1, 3, 7, 15, 31, 63, 127, 255}:
|
|
425
|
+
# 1cbbf108f44c8f4babde546d26425ca5340dccf878d306b90eb0fbec2f83ab51:0x40bd1b
|
|
426
|
+
self.state.is_jumptable = True
|
|
427
|
+
return arg0 & mask_value
|
|
428
|
+
return self._top(expr.result_size(self.tyenv))
|
|
429
|
+
|
|
430
|
+
@binop_handler
|
|
431
|
+
def _handle_binop_CmpLE(self, expr):
|
|
432
|
+
return self._handle_Comparison(*expr.args)
|
|
433
|
+
|
|
434
|
+
@binop_handler
|
|
435
|
+
def _handle_binop_CmpGE(self, expr):
|
|
436
|
+
return self._handle_Comparison(*expr.args)
|
|
437
|
+
|
|
438
|
+
@binop_handler
|
|
439
|
+
def _handle_binop_CmpLT(self, expr):
|
|
440
|
+
return self._handle_Comparison(*expr.args)
|
|
441
|
+
|
|
442
|
+
@binop_handler
|
|
443
|
+
def _handle_binop_CmpGT(self, expr):
|
|
444
|
+
return self._handle_Comparison(*expr.args)
|
|
445
|
+
|
|
446
|
+
def _handle_expr_CCall(self, expr):
|
|
447
|
+
if isinstance(expr.args[0], pyvex.IRExpr.Const):
|
|
448
|
+
cond_type_enum = expr.args[0].con.value
|
|
449
|
+
|
|
450
|
+
if self.arch.name in {"X86", "AMD64", "AARCH64"}:
|
|
451
|
+
if cond_type_enum in EXPECTED_COND_TYPES[self.arch.name]:
|
|
452
|
+
self._handle_Comparison(expr.args[2], expr.args[3])
|
|
453
|
+
elif is_arm_arch(self.arch):
|
|
454
|
+
if cond_type_enum in EXPECTED_COND_TYPES["ARM"]:
|
|
455
|
+
self._handle_Comparison(expr.args[2], expr.args[3])
|
|
456
|
+
else:
|
|
457
|
+
# other architectures
|
|
458
|
+
l.warning("Please fill in EXPECTED_COND_TYPES for %s.", self.arch.name)
|
|
459
|
+
self._handle_Comparison(expr.args[2], expr.args[3])
|
|
460
|
+
|
|
461
|
+
return self._top(expr.result_size(self.tyenv))
|
|
462
|
+
|
|
463
|
+
def _handle_expr_VECRET(self, expr):
|
|
464
|
+
return self._top(expr.result_size(self.tyenv))
|
|
465
|
+
|
|
466
|
+
def _handle_expr_GSPTR(self, expr):
|
|
467
|
+
return self._top(expr.result_size(self.tyenv))
|
|
468
|
+
|
|
469
|
+
def _handle_expr_GetI(self, expr):
|
|
470
|
+
return self._top(expr.result_size(self.tyenv))
|
|
471
|
+
|
|
472
|
+
def _handle_expr_ITE(self, expr):
|
|
473
|
+
return self._top(expr.result_size(self.tyenv))
|
|
474
|
+
|
|
475
|
+
def _handle_Comparison(self, arg0: pyvex.expr.IRExpr, arg1: pyvex.expr.IRExpr) -> claripy.ast.BV:
|
|
476
|
+
if self.block.addr not in self._indirect_jump_node_pred_addrs:
|
|
477
|
+
return self._top(1)
|
|
478
|
+
|
|
479
|
+
# found the comparison
|
|
480
|
+
arg0_src, arg1_src = None, None
|
|
481
|
+
|
|
482
|
+
if isinstance(arg0, pyvex.IRExpr.RdTmp):
|
|
483
|
+
if arg0.tmp in self.state._tmpvar_source:
|
|
484
|
+
arg0_src = self.state._tmpvar_source[arg0.tmp]
|
|
485
|
+
arg0_src = None if not arg0_src or len(arg0_src) > 1 else next(iter(arg0_src))
|
|
486
|
+
elif isinstance(arg0, pyvex.IRExpr.Const):
|
|
487
|
+
arg0_src = "const"
|
|
488
|
+
if isinstance(arg1, pyvex.IRExpr.RdTmp):
|
|
489
|
+
if arg1.tmp in self.state._tmpvar_source:
|
|
490
|
+
arg1_src = self.state._tmpvar_source[arg1.tmp]
|
|
491
|
+
arg1_src = None if not arg1_src or len(arg1_src) > 1 else next(iter(arg1_src))
|
|
492
|
+
elif isinstance(arg1, pyvex.IRExpr.Const):
|
|
493
|
+
arg1_src = "const"
|
|
494
|
+
|
|
495
|
+
if arg0_src == "const" and arg1_src == "const":
|
|
496
|
+
# comparison of two consts... there is nothing we can do
|
|
497
|
+
self.state.is_jumptable = True
|
|
498
|
+
return self._top(1)
|
|
499
|
+
if arg0_src not in {"const", None} and arg1_src not in {"const", None}:
|
|
500
|
+
# this is probably not a jump table
|
|
501
|
+
return self._top(1)
|
|
502
|
+
if arg1_src == "const":
|
|
503
|
+
# make sure arg0_src is const
|
|
504
|
+
arg0_src, arg1_src = arg1_src, arg0_src
|
|
505
|
+
|
|
506
|
+
self.state.is_jumptable = True
|
|
507
|
+
|
|
508
|
+
if arg0_src != "const":
|
|
509
|
+
# we failed during dependency tracking so arg0_src couldn't be determined
|
|
510
|
+
# but we will still try to resolve it as a jump table as a fall back
|
|
511
|
+
return self._top(1)
|
|
512
|
+
|
|
513
|
+
if isinstance(arg1_src, tuple):
|
|
514
|
+
arg1_src_stmt = self.project.factory.block(arg1_src[0], cross_insn_opt=True).vex.statements[arg1_src[1]]
|
|
515
|
+
if isinstance(arg1_src_stmt, pyvex.IRStmt.Store):
|
|
516
|
+
# Storing a constant/variable in memory
|
|
517
|
+
# We will need to overwrite it when executing the slice to guarantee the full recovery of jump table
|
|
518
|
+
# targets.
|
|
519
|
+
#
|
|
520
|
+
# Here is an example:
|
|
521
|
+
# mov [rbp+var_54], 1
|
|
522
|
+
# loc_4051a6:
|
|
523
|
+
# cmp [rbp+var_54], 6
|
|
524
|
+
# ja loc_405412 (default)
|
|
525
|
+
#
|
|
526
|
+
# Instead of writing 1 to [rbp+var_54], we want to write a symbolic variable there instead. Otherwise
|
|
527
|
+
# we will only recover the second jump target instead of all 7 targets.
|
|
528
|
+
self.state.stmts_to_instrument.append(("mem_write", *arg1_src))
|
|
529
|
+
elif isinstance(arg1_src_stmt, pyvex.IRStmt.WrTmp) and isinstance(arg1_src_stmt.data, pyvex.IRExpr.Load):
|
|
530
|
+
# Loading a constant/variable from memory (and later the value is stored in a register)
|
|
531
|
+
# Same as above, we will need to overwrite it when executing the slice to guarantee the full recovery
|
|
532
|
+
# of jump table targets.
|
|
533
|
+
#
|
|
534
|
+
# Here is an example:
|
|
535
|
+
# mov eax, [0x625a3c]
|
|
536
|
+
# cmp eax, 0x4
|
|
537
|
+
# ja 0x40899d (default)
|
|
538
|
+
# loc_408899:
|
|
539
|
+
# mov eax, eax
|
|
540
|
+
# mov rax, qword [rax*8+0x220741]
|
|
541
|
+
# jmp rax
|
|
542
|
+
#
|
|
543
|
+
self.state.stmts_to_instrument.append(("mem_read", *arg1_src))
|
|
544
|
+
elif isinstance(arg1_src_stmt, pyvex.IRStmt.Put):
|
|
545
|
+
# Storing a constant/variable in register
|
|
546
|
+
# Same as above...
|
|
547
|
+
#
|
|
548
|
+
# Here is an example:
|
|
549
|
+
# movzx eax, byte ptr [rax+12h]
|
|
550
|
+
# movzx eax, al
|
|
551
|
+
# cmp eax, 0xe
|
|
552
|
+
# ja 0x405b9f (default)
|
|
553
|
+
# loc_405b34:
|
|
554
|
+
# mov eax, eax
|
|
555
|
+
# mov rax, qword [rax*8+0x2231ae]
|
|
556
|
+
#
|
|
557
|
+
self.state.stmts_to_instrument.append(("reg_write", *arg1_src))
|
|
558
|
+
|
|
559
|
+
return self._top(1)
|
|
560
|
+
|
|
561
|
+
def _do_load(self, addr: claripy.ast.BV, size: int) -> claripy.ast.BV:
|
|
562
|
+
src = (self.block.addr, self.stmt_idx)
|
|
563
|
+
self._tsrc = {src}
|
|
564
|
+
|
|
565
|
+
if self._is_spoffset(addr):
|
|
566
|
+
spoffset = self._extract_spoffset_from_expr(addr)
|
|
567
|
+
if spoffset is not None and spoffset.offset in self.state._stack:
|
|
568
|
+
self._tsrc = {self.state._stack[spoffset.offset][0]}
|
|
569
|
+
return self.state._stack[spoffset.offset][1]
|
|
570
|
+
elif self._is_registeroffset(addr):
|
|
571
|
+
# Load data from a register, but this register hasn't been initialized at this point
|
|
572
|
+
# We will need to initialize this register during slice execution later
|
|
573
|
+
|
|
574
|
+
# Try to get where this register is first accessed
|
|
575
|
+
reg_offset = self._extract_regoffset_from_expr(addr)
|
|
576
|
+
if reg_offset is not None and reg_offset.reg in self.state._registers:
|
|
577
|
+
try:
|
|
578
|
+
source = next(iter(src for src in self.state._registers[reg_offset.reg][0] if src != "const"))
|
|
579
|
+
assert isinstance(source, tuple)
|
|
580
|
+
self.state.regs_to_initialize.append((*source, reg_offset.reg, reg_offset.bits))
|
|
581
|
+
except StopIteration:
|
|
582
|
+
# we don't need to initialize this register
|
|
583
|
+
# it might be caused by an incorrect analysis result
|
|
584
|
+
# e.g. PN-337140.bin 11e918 r0 comes from r4, r4 comes from r0@11e8c0, and r0@11e8c0 comes from
|
|
585
|
+
# function call sub_375c04. Since we do not analyze sub_375c04, we treat r0@11e918 as a constant 0.
|
|
586
|
+
pass
|
|
587
|
+
|
|
588
|
+
return self._top(size)
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
#
|
|
592
|
+
# State hooks
|
|
593
|
+
#
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
class StoreHook:
|
|
597
|
+
"""
|
|
598
|
+
Hook for memory stores.
|
|
599
|
+
"""
|
|
600
|
+
|
|
601
|
+
@staticmethod
|
|
602
|
+
def hook(state):
|
|
603
|
+
write_length = state.inspect.mem_write_length
|
|
604
|
+
if write_length is None:
|
|
605
|
+
write_length = len(state.inspect.mem_write_expr)
|
|
606
|
+
else:
|
|
607
|
+
write_length = write_length * state.arch.byte_width
|
|
608
|
+
state.inspect.mem_write_expr = claripy.BVS("instrumented_store", write_length)
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
class LoadHook:
|
|
612
|
+
"""
|
|
613
|
+
Hook for memory loads.
|
|
614
|
+
"""
|
|
615
|
+
|
|
616
|
+
def __init__(self):
|
|
617
|
+
self._var = None
|
|
618
|
+
|
|
619
|
+
def hook_before(self, state):
|
|
620
|
+
addr = state.inspect.mem_read_address
|
|
621
|
+
size = state.solver.eval(state.inspect.mem_read_length)
|
|
622
|
+
self._var = claripy.BVS("instrumented_load", size * 8)
|
|
623
|
+
state.memory.store(addr, self._var, endness=state.arch.memory_endness)
|
|
624
|
+
|
|
625
|
+
def hook_after(self, state):
|
|
626
|
+
state.inspect.mem_read_expr = self._var
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
class PutHook:
|
|
630
|
+
"""
|
|
631
|
+
Hook for register writes.
|
|
632
|
+
"""
|
|
633
|
+
|
|
634
|
+
@staticmethod
|
|
635
|
+
def hook(state):
|
|
636
|
+
state.inspect.reg_write_expr = claripy.BVS(
|
|
637
|
+
"instrumented_put", state.solver.eval(state.inspect.reg_write_length) * 8
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
class RegisterInitializerHook:
|
|
642
|
+
"""
|
|
643
|
+
Hook for register init.
|
|
644
|
+
"""
|
|
645
|
+
|
|
646
|
+
def __init__(self, reg_offset, reg_bits, initial_value):
|
|
647
|
+
self.reg_offset = reg_offset
|
|
648
|
+
self.reg_bits = reg_bits
|
|
649
|
+
self.value = initial_value
|
|
650
|
+
|
|
651
|
+
def hook(self, state):
|
|
652
|
+
state.registers.store(self.reg_offset, claripy.BVV(self.value, self.reg_bits))
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
class BSSHook:
|
|
656
|
+
"""
|
|
657
|
+
Hook for BSS read/write.
|
|
658
|
+
"""
|
|
659
|
+
|
|
660
|
+
def __init__(self, project, bss_regions):
|
|
661
|
+
self.project = project
|
|
662
|
+
self._bss_regions = bss_regions
|
|
663
|
+
self._written_addrs = set()
|
|
664
|
+
|
|
665
|
+
def bss_memory_read_hook(self, state):
|
|
666
|
+
if not self._bss_regions:
|
|
667
|
+
return
|
|
668
|
+
|
|
669
|
+
read_addr = state.inspect.mem_read_address
|
|
670
|
+
read_length = state.inspect.mem_read_length
|
|
671
|
+
|
|
672
|
+
if not isinstance(read_addr, int) and read_addr.symbolic:
|
|
673
|
+
# don't touch it
|
|
674
|
+
return
|
|
675
|
+
|
|
676
|
+
concrete_read_addr = state.solver.eval(read_addr)
|
|
677
|
+
concrete_read_length = state.solver.eval(read_length)
|
|
678
|
+
|
|
679
|
+
for start, size in self._bss_regions:
|
|
680
|
+
if start <= concrete_read_addr < start + size:
|
|
681
|
+
# this is a read from the .bss section
|
|
682
|
+
break
|
|
683
|
+
else:
|
|
684
|
+
return
|
|
685
|
+
|
|
686
|
+
if concrete_read_addr not in self._written_addrs:
|
|
687
|
+
# it was never written to before. we overwrite it with unconstrained bytes
|
|
688
|
+
for i in range(0, concrete_read_length, self.project.arch.bytes):
|
|
689
|
+
state.memory.store(
|
|
690
|
+
concrete_read_addr + i,
|
|
691
|
+
state.solver.Unconstrained("unconstrained", self.project.arch.bits),
|
|
692
|
+
endness=self.project.arch.memory_endness,
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
# job done :-)
|
|
696
|
+
|
|
697
|
+
def bss_memory_write_hook(self, state):
|
|
698
|
+
if not self._bss_regions:
|
|
699
|
+
return
|
|
700
|
+
|
|
701
|
+
write_addr = state.inspect.mem_write_address
|
|
702
|
+
|
|
703
|
+
if not isinstance(write_addr, int) and write_addr.symbolic:
|
|
704
|
+
return
|
|
705
|
+
|
|
706
|
+
concrete_write_addr = state.solver.eval(write_addr)
|
|
707
|
+
concrete_write_length = (
|
|
708
|
+
state.solver.eval(state.inspect.mem_write_length)
|
|
709
|
+
if state.inspect.mem_write_length is not None
|
|
710
|
+
else len(state.inspect.mem_write_expr) // state.arch.byte_width
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
for start, size in self._bss_regions:
|
|
714
|
+
if start <= concrete_write_addr < start + size:
|
|
715
|
+
# hit a BSS section
|
|
716
|
+
break
|
|
717
|
+
else:
|
|
718
|
+
return
|
|
719
|
+
|
|
720
|
+
if concrete_write_length > 1024:
|
|
721
|
+
l.warning("Writing more 1024 bytes to the BSS region, only considering the first 1024 bytes.")
|
|
722
|
+
concrete_write_length = 1024
|
|
723
|
+
|
|
724
|
+
for i in range(concrete_write_addr, concrete_write_length):
|
|
725
|
+
self._written_addrs.add(i)
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
class MIPSGPHook:
|
|
729
|
+
"""
|
|
730
|
+
Hooks all reads from and writes into the gp register for MIPS32 binaries.
|
|
731
|
+
"""
|
|
732
|
+
|
|
733
|
+
def __init__(self, gp_offset: int, gp: int):
|
|
734
|
+
self.gp_offset = gp_offset
|
|
735
|
+
self.gp = gp
|
|
736
|
+
|
|
737
|
+
def gp_register_read_hook(self, state):
|
|
738
|
+
read_offset = state.inspect.reg_read_offset
|
|
739
|
+
read_length = state.inspect.reg_read_length
|
|
740
|
+
if state.solver.eval(read_offset) == self.gp_offset and read_length == 4:
|
|
741
|
+
state.inspect.reg_read_expr = claripy.BVV(self.gp, size=32)
|
|
742
|
+
|
|
743
|
+
def gp_register_write_hook(self, state):
|
|
744
|
+
write_offset = state.inspect.reg_write_offset
|
|
745
|
+
write_length = state.inspect.reg_write_length
|
|
746
|
+
if state.solver.eval(write_offset) == self.gp_offset and write_length == 4:
|
|
747
|
+
state.inspect.reg_write_expr = claripy.BVV(self.gp, size=32)
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
#
|
|
751
|
+
# Main class
|
|
752
|
+
#
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
class JumpTableResolver(IndirectJumpResolver):
|
|
756
|
+
"""
|
|
757
|
+
A generic jump table resolver.
|
|
758
|
+
|
|
759
|
+
This is a fast jump table resolution. For performance concerns, we made the following assumptions:
|
|
760
|
+
- The final jump target comes from the memory.
|
|
761
|
+
- The final jump target must be directly read out of the memory, without any further modification or altering.
|
|
762
|
+
|
|
763
|
+
Progressively larger program slices will be analyzed to determine jump table location and size. If the size of the
|
|
764
|
+
table cannot be determined, a *guess* will be made based on how many entries in the table *appear* valid.
|
|
765
|
+
"""
|
|
766
|
+
|
|
767
|
+
def __init__(self, project, resolve_calls: bool = True):
|
|
768
|
+
super().__init__(project, timeless=False)
|
|
769
|
+
|
|
770
|
+
self.resolve_calls = resolve_calls
|
|
771
|
+
|
|
772
|
+
self._bss_regions = None
|
|
773
|
+
# the maximum number of resolved targets. Will be initialized from CFG.
|
|
774
|
+
self._max_targets = 0
|
|
775
|
+
|
|
776
|
+
# cached memory read addresses that are used to initialize uninitialized registers
|
|
777
|
+
# should be cleared before every symbolic execution run on the slice
|
|
778
|
+
self._cached_memread_addrs = {}
|
|
779
|
+
|
|
780
|
+
self._find_bss_region()
|
|
781
|
+
|
|
782
|
+
def filter(self, cfg, addr, func_addr, block, jumpkind):
|
|
783
|
+
if pcode is not None and isinstance(block.vex, pcode.lifter.IRSB): # type:ignore
|
|
784
|
+
if once("pcode__indirect_jump_resolver"):
|
|
785
|
+
l.warning("JumpTableResolver does not support P-Code IR yet; CFG may be incomplete.")
|
|
786
|
+
return False
|
|
787
|
+
|
|
788
|
+
if jumpkind == "Ijk_Boring":
|
|
789
|
+
return True
|
|
790
|
+
return bool(self.resolve_calls and jumpkind == "Ijk_Call")
|
|
791
|
+
|
|
792
|
+
def resolve(self, cfg, addr, func_addr, block, jumpkind, func_graph_complete: bool = True, **kwargs):
|
|
793
|
+
"""
|
|
794
|
+
Resolves jump tables.
|
|
795
|
+
|
|
796
|
+
:param cfg: A CFG instance.
|
|
797
|
+
:param int addr: IRSB address.
|
|
798
|
+
:param int func_addr: The function address.
|
|
799
|
+
:param pyvex.IRSB block: The IRSB.
|
|
800
|
+
:return: A bool indicating whether the indirect jump is resolved successfully, and a list of resolved targets
|
|
801
|
+
:rtype: tuple
|
|
802
|
+
"""
|
|
803
|
+
|
|
804
|
+
if not cfg.kb.functions.contains_addr(func_addr):
|
|
805
|
+
# fix for angr issue #3768
|
|
806
|
+
# the function must exist in the KB
|
|
807
|
+
return False, None
|
|
808
|
+
|
|
809
|
+
func: Function = cfg.kb.functions[func_addr]
|
|
810
|
+
self._max_targets = cfg._indirect_jump_target_limit
|
|
811
|
+
|
|
812
|
+
# this is an indirect call if (1) the instruction is a call, or (2) the instruction is a tail jump (we detect
|
|
813
|
+
# sp moving up to approximate)
|
|
814
|
+
potential_call_table = jumpkind == "Ijk_Call" or self._sp_moved_up(block) or len(func.block_addrs_set) <= 5
|
|
815
|
+
# we only perform full-function propagation for jump tables or call tables in really small functions
|
|
816
|
+
if not potential_call_table or len(func.block_addrs_set) <= 5:
|
|
817
|
+
cv_manager = ConstantValueManager(self.project, cfg.kb, func, addr)
|
|
818
|
+
else:
|
|
819
|
+
cv_manager = None
|
|
820
|
+
|
|
821
|
+
for slice_steps in range(1, 5):
|
|
822
|
+
# Perform a backward slicing from the jump target
|
|
823
|
+
# Important: Do not go across function call boundaries
|
|
824
|
+
b = Blade(
|
|
825
|
+
cfg.graph,
|
|
826
|
+
addr,
|
|
827
|
+
-1,
|
|
828
|
+
cfg=cfg,
|
|
829
|
+
project=self.project,
|
|
830
|
+
ignore_sp=False,
|
|
831
|
+
ignore_bp=False,
|
|
832
|
+
max_level=slice_steps,
|
|
833
|
+
base_state=self.base_state,
|
|
834
|
+
stop_at_calls=True,
|
|
835
|
+
cross_insn_opt=True,
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
l.debug("Try resolving %#x with a %d-level backward slice...", addr, slice_steps)
|
|
839
|
+
r, targets = self._resolve(
|
|
840
|
+
cfg, addr, func, b, cv_manager, potential_call_table=False, func_graph_complete=func_graph_complete
|
|
841
|
+
)
|
|
842
|
+
if r:
|
|
843
|
+
return r, targets
|
|
844
|
+
|
|
845
|
+
if potential_call_table:
|
|
846
|
+
b = Blade(
|
|
847
|
+
cfg.graph,
|
|
848
|
+
addr,
|
|
849
|
+
-1,
|
|
850
|
+
cfg=cfg,
|
|
851
|
+
project=self.project,
|
|
852
|
+
ignore_sp=False,
|
|
853
|
+
ignore_bp=False,
|
|
854
|
+
max_level=1,
|
|
855
|
+
base_state=self.base_state,
|
|
856
|
+
stop_at_calls=True,
|
|
857
|
+
cross_insn_opt=True,
|
|
858
|
+
)
|
|
859
|
+
return self._resolve(
|
|
860
|
+
cfg, addr, func, b, cv_manager, potential_call_table=True, func_graph_complete=func_graph_complete
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
return False, None
|
|
864
|
+
|
|
865
|
+
#
|
|
866
|
+
# Private methods
|
|
867
|
+
#
|
|
868
|
+
|
|
869
|
+
def _resolve(
|
|
870
|
+
self,
|
|
871
|
+
cfg,
|
|
872
|
+
addr: int,
|
|
873
|
+
func: Function,
|
|
874
|
+
b: Blade,
|
|
875
|
+
cv_manager: ConstantValueManager | None,
|
|
876
|
+
potential_call_table: bool = False,
|
|
877
|
+
func_graph_complete: bool = True,
|
|
878
|
+
) -> tuple[bool, Sequence[int] | None]:
|
|
879
|
+
"""
|
|
880
|
+
Internal method for resolving jump tables.
|
|
881
|
+
|
|
882
|
+
:param cfg: A CFG instance.
|
|
883
|
+
:param addr: Address of the block where the indirect jump is.
|
|
884
|
+
:param func: The Function instance.
|
|
885
|
+
:param b: The generated backward slice.
|
|
886
|
+
:return: A bool indicating whether the indirect jump is resolved successfully, and a list of
|
|
887
|
+
resolved targets.
|
|
888
|
+
"""
|
|
889
|
+
|
|
890
|
+
project = self.project # short-hand
|
|
891
|
+
func_addr = func.addr
|
|
892
|
+
is_arm = is_arm_arch(self.project.arch)
|
|
893
|
+
|
|
894
|
+
stmt_loc = (addr, DEFAULT_STATEMENT)
|
|
895
|
+
if stmt_loc not in b.slice:
|
|
896
|
+
return False, None
|
|
897
|
+
|
|
898
|
+
(
|
|
899
|
+
load_stmt_loc,
|
|
900
|
+
load_stmt,
|
|
901
|
+
load_size,
|
|
902
|
+
stmts_to_remove,
|
|
903
|
+
stmts_adding_base_addr,
|
|
904
|
+
transformations,
|
|
905
|
+
) = self._find_load_statement(b, stmt_loc)
|
|
906
|
+
ite_stmt, ite_stmt_loc = None, None
|
|
907
|
+
|
|
908
|
+
if load_stmt_loc is None:
|
|
909
|
+
# the load statement is not found
|
|
910
|
+
# maybe it's a typical ARM-style jump table like the following:
|
|
911
|
+
# SUB R3, R5, #34
|
|
912
|
+
# CMP R3, #28
|
|
913
|
+
# ADDLS PC, PC, R3,LSL#2
|
|
914
|
+
if is_arm:
|
|
915
|
+
ite_stmt, ite_stmt_loc, stmts_to_remove = self._find_load_pc_ite_statement(b, stmt_loc)
|
|
916
|
+
if ite_stmt is None:
|
|
917
|
+
l.debug("Could not find load statement in this slice")
|
|
918
|
+
return False, None
|
|
919
|
+
|
|
920
|
+
# more sanity checks
|
|
921
|
+
|
|
922
|
+
# for a typical jump table, the current block has only one predecessor, and the predecessor to the current
|
|
923
|
+
# block has two successors
|
|
924
|
+
# for a typical vtable call (or jump if at the end of a function), the block as two predecessors that form a
|
|
925
|
+
# diamond shape
|
|
926
|
+
curr_node = func.get_node(addr)
|
|
927
|
+
if curr_node is None or curr_node not in func.transition_graph:
|
|
928
|
+
l.debug("Could not find the node %#x in the function transition graph", addr)
|
|
929
|
+
return False, None
|
|
930
|
+
preds = list(func.transition_graph.predecessors(curr_node))
|
|
931
|
+
pred_endaddrs = {pred.addr + pred.size for pred in preds} # handle non-normalized CFGs
|
|
932
|
+
if func_graph_complete and not is_arm and not potential_call_table:
|
|
933
|
+
# on ARM you can do a single-block jump table...
|
|
934
|
+
if len(pred_endaddrs) == 1:
|
|
935
|
+
pred_succs = [succ for succ in func.transition_graph.successors(preds[0]) if succ.addr != preds[0].addr]
|
|
936
|
+
if len(pred_succs) != 2:
|
|
937
|
+
l.debug("Expect two successors to the single predecessor, found %d.", len(pred_succs))
|
|
938
|
+
return False, None
|
|
939
|
+
elif len(pred_endaddrs) == 2 and len(preds) == 2 and all(p in func.graph for p in preds):
|
|
940
|
+
pred_succs = set(
|
|
941
|
+
[succ for succ in func.graph.successors(preds[0]) if succ.addr != preds[0].addr]
|
|
942
|
+
+ [succ for succ in func.graph.successors(preds[1]) if succ.addr != preds[1].addr]
|
|
943
|
+
)
|
|
944
|
+
is_diamond = False
|
|
945
|
+
if len(pred_succs) == 2:
|
|
946
|
+
non_node_succ = next(iter(pred_succ for pred_succ in pred_succs if pred_succ is not curr_node))
|
|
947
|
+
while func.graph.out_degree[non_node_succ] == 1:
|
|
948
|
+
non_node_succ = next(iter(func.graph.successors(non_node_succ)))
|
|
949
|
+
if non_node_succ == curr_node:
|
|
950
|
+
is_diamond = True
|
|
951
|
+
break
|
|
952
|
+
if not is_diamond:
|
|
953
|
+
l.debug("Expect a diamond shape.")
|
|
954
|
+
return False, None
|
|
955
|
+
else:
|
|
956
|
+
l.debug("The predecessor-successor shape does not look like a jump table or a vtable jump/call.")
|
|
957
|
+
return False, None
|
|
958
|
+
|
|
959
|
+
try:
|
|
960
|
+
jump_target = self._try_resolve_single_constant_loads(load_stmt, cfg, addr)
|
|
961
|
+
except NotAJumpTableNotification:
|
|
962
|
+
return False, None
|
|
963
|
+
if jump_target is not None:
|
|
964
|
+
if self._is_target_valid(cfg, jump_target):
|
|
965
|
+
ij = cfg.indirect_jumps.get(addr, None)
|
|
966
|
+
if ij is not None:
|
|
967
|
+
ij.jumptable = False
|
|
968
|
+
ij.resolved_targets = {jump_target}
|
|
969
|
+
return True, [jump_target]
|
|
970
|
+
l.debug("Found single constant load, but it does not appear to be a valid target")
|
|
971
|
+
return False, None
|
|
972
|
+
|
|
973
|
+
# Well, we have a real jump table to resolve!
|
|
974
|
+
|
|
975
|
+
# skip all statements after the load statement
|
|
976
|
+
# We want to leave the final loaded value as symbolic, so we can
|
|
977
|
+
# get the full range of possibilities
|
|
978
|
+
b.slice.remove_nodes_from(stmts_to_remove)
|
|
979
|
+
|
|
980
|
+
stmts_to_instrument, regs_to_initialize = [], []
|
|
981
|
+
try:
|
|
982
|
+
stmts_to_instrument, regs_to_initialize = self._jumptable_precheck(b, {pred.addr for pred in preds})
|
|
983
|
+
l.debug(
|
|
984
|
+
"jumptable_precheck provides stmts_to_instrument = %s, regs_to_initialize = %s",
|
|
985
|
+
stmts_to_instrument,
|
|
986
|
+
regs_to_initialize,
|
|
987
|
+
)
|
|
988
|
+
except NotAJumpTableNotification:
|
|
989
|
+
if not potential_call_table and not is_arm:
|
|
990
|
+
l.debug("Indirect jump at %#x does not look like a jump table. Skip.", addr)
|
|
991
|
+
return False, None
|
|
992
|
+
|
|
993
|
+
# Debugging output
|
|
994
|
+
if l.level == logging.DEBUG:
|
|
995
|
+
self._dbg_repr_slice(b)
|
|
996
|
+
|
|
997
|
+
# Get all sources
|
|
998
|
+
sources = [n_ for n_ in b.slice.nodes() if b.slice.in_degree(n_) == 0]
|
|
999
|
+
|
|
1000
|
+
# Create the annotated CFG
|
|
1001
|
+
annotatedcfg = AnnotatedCFG(project, None, detect_loops=False)
|
|
1002
|
+
annotatedcfg.from_digraph(b.slice)
|
|
1003
|
+
|
|
1004
|
+
# pylint: disable=too-many-nested-blocks
|
|
1005
|
+
for block_addr, _ in sources:
|
|
1006
|
+
# Use slicecutor to execute each one, and get the address
|
|
1007
|
+
# We simply give up if any exception occurs on the way
|
|
1008
|
+
start_state = self._initial_state(block_addr, cfg, func_addr)
|
|
1009
|
+
|
|
1010
|
+
# instrument specified store/put/load statements
|
|
1011
|
+
self._instrument_statements(start_state, stmts_to_instrument, regs_to_initialize)
|
|
1012
|
+
|
|
1013
|
+
self._cached_memread_addrs.clear()
|
|
1014
|
+
init_registers_on_demand_bp = BP(when=BP_BEFORE, enabled=True, action=self._init_registers_on_demand)
|
|
1015
|
+
start_state.inspect.add_breakpoint("mem_read", init_registers_on_demand_bp)
|
|
1016
|
+
|
|
1017
|
+
# constant value manager
|
|
1018
|
+
if cv_manager is not None:
|
|
1019
|
+
constant_value_reg_read_bp = BP(when=BP_AFTER, enabled=True, action=cv_manager.reg_read_callback)
|
|
1020
|
+
start_state.inspect.add_breakpoint("reg_read", constant_value_reg_read_bp)
|
|
1021
|
+
|
|
1022
|
+
# use Any as the concretization strategy
|
|
1023
|
+
start_state.memory.read_strategies = [SimConcretizationStrategyAny()]
|
|
1024
|
+
start_state.memory.write_strategies = [SimConcretizationStrategyAny()]
|
|
1025
|
+
|
|
1026
|
+
# Create the slicecutor
|
|
1027
|
+
simgr = self.project.factory.simulation_manager(start_state, resilience=True)
|
|
1028
|
+
slicecutor = Slicecutor(annotatedcfg, force_taking_exit=True)
|
|
1029
|
+
simgr.use_technique(slicecutor)
|
|
1030
|
+
simgr.use_technique(LocalLoopSeer(bound=1))
|
|
1031
|
+
if load_stmt is not None:
|
|
1032
|
+
assert load_stmt_loc is not None
|
|
1033
|
+
explorer = Explorer(find=load_stmt_loc[0])
|
|
1034
|
+
elif ite_stmt is not None:
|
|
1035
|
+
assert ite_stmt_loc is not None
|
|
1036
|
+
explorer = Explorer(find=ite_stmt_loc[0])
|
|
1037
|
+
else:
|
|
1038
|
+
raise TypeError("Unsupported type of jump table.")
|
|
1039
|
+
simgr.use_technique(explorer)
|
|
1040
|
+
|
|
1041
|
+
# Run it!
|
|
1042
|
+
try:
|
|
1043
|
+
simgr.run()
|
|
1044
|
+
except KeyError as ex:
|
|
1045
|
+
# This is because the program slice is incomplete.
|
|
1046
|
+
# Blade will support more IRExprs and IRStmts in the future
|
|
1047
|
+
l.debug("KeyError occurred due to incomplete program slice.", exc_info=ex)
|
|
1048
|
+
continue
|
|
1049
|
+
|
|
1050
|
+
# Get the jumping targets
|
|
1051
|
+
for r in simgr.found:
|
|
1052
|
+
jt2, jt2_addr, jt2_entrysize, jt2_size = None, None, None, None
|
|
1053
|
+
if load_stmt is not None:
|
|
1054
|
+
ret = self._try_resolve_targets_load(
|
|
1055
|
+
r,
|
|
1056
|
+
addr,
|
|
1057
|
+
cfg,
|
|
1058
|
+
annotatedcfg,
|
|
1059
|
+
load_stmt,
|
|
1060
|
+
load_size,
|
|
1061
|
+
stmts_adding_base_addr,
|
|
1062
|
+
transformations,
|
|
1063
|
+
potential_call_table,
|
|
1064
|
+
)
|
|
1065
|
+
if ret is None:
|
|
1066
|
+
# Try the next state
|
|
1067
|
+
continue
|
|
1068
|
+
(
|
|
1069
|
+
jump_table,
|
|
1070
|
+
jumptable_addr,
|
|
1071
|
+
entry_size,
|
|
1072
|
+
jumptable_size,
|
|
1073
|
+
all_targets,
|
|
1074
|
+
sort,
|
|
1075
|
+
jt2,
|
|
1076
|
+
jt2_addr,
|
|
1077
|
+
jt2_entrysize,
|
|
1078
|
+
jt2_size,
|
|
1079
|
+
) = ret
|
|
1080
|
+
if sort == "jumptable":
|
|
1081
|
+
ij_type = IndirectJumpType.Jumptable_AddressLoadedFromMemory
|
|
1082
|
+
elif sort == "vtable":
|
|
1083
|
+
ij_type = IndirectJumpType.Vtable
|
|
1084
|
+
else:
|
|
1085
|
+
ij_type = IndirectJumpType.Unknown
|
|
1086
|
+
elif ite_stmt is not None:
|
|
1087
|
+
ret = self._try_resolve_targets_ite(r, addr, cfg, annotatedcfg, ite_stmt)
|
|
1088
|
+
if ret is None:
|
|
1089
|
+
# Try the next state
|
|
1090
|
+
continue
|
|
1091
|
+
jumptable_addr = None
|
|
1092
|
+
jump_table, jumptable_size, entry_size = ret
|
|
1093
|
+
all_targets = jump_table
|
|
1094
|
+
ij_type = IndirectJumpType.Jumptable_AddressComputed
|
|
1095
|
+
else:
|
|
1096
|
+
raise TypeError("Unsupported type of jump table.")
|
|
1097
|
+
|
|
1098
|
+
assert ret is not None
|
|
1099
|
+
|
|
1100
|
+
# finally, we filter jump targets according to the alignment of the architecture
|
|
1101
|
+
if is_arm_arch(self.project.arch):
|
|
1102
|
+
alignment = 4 if addr % 2 == 0 else 2
|
|
1103
|
+
else:
|
|
1104
|
+
alignment = self.project.arch.instruction_alignment
|
|
1105
|
+
if alignment != 1:
|
|
1106
|
+
if is_arm_arch(self.project.arch) and addr % 2 == 1:
|
|
1107
|
+
# Special logic for handling THUMB addresses
|
|
1108
|
+
all_targets = [t_ for t_ in all_targets if (t_ - 1) % alignment == 0]
|
|
1109
|
+
else:
|
|
1110
|
+
all_targets = [t_ for t_ in all_targets if t_ % alignment == 0]
|
|
1111
|
+
|
|
1112
|
+
l.info(
|
|
1113
|
+
"Jump table at %#x has %d targets: %s",
|
|
1114
|
+
addr,
|
|
1115
|
+
len(all_targets),
|
|
1116
|
+
", ".join([hex(a) for a in all_targets]),
|
|
1117
|
+
)
|
|
1118
|
+
|
|
1119
|
+
# write to the IndirectJump object in CFG
|
|
1120
|
+
ij: IndirectJump = cfg.indirect_jumps.get(addr, None)
|
|
1121
|
+
if ij is not None:
|
|
1122
|
+
if len(all_targets) > 1:
|
|
1123
|
+
# It can be considered a jump table only if there are more than one jump target
|
|
1124
|
+
if ij_type in {
|
|
1125
|
+
IndirectJumpType.Jumptable_AddressComputed,
|
|
1126
|
+
IndirectJumpType.Jumptable_AddressLoadedFromMemory,
|
|
1127
|
+
}:
|
|
1128
|
+
ij.jumptable = True
|
|
1129
|
+
else:
|
|
1130
|
+
ij.jumptable = False
|
|
1131
|
+
ij.add_jumptable(jumptable_addr, jumptable_size, entry_size, jump_table, is_primary=True)
|
|
1132
|
+
ij.resolved_targets = set(jump_table)
|
|
1133
|
+
ij.type = ij_type
|
|
1134
|
+
else:
|
|
1135
|
+
ij.jumptable = False
|
|
1136
|
+
ij.resolved_targets = set(jump_table)
|
|
1137
|
+
if jt2 is not None and jt2_addr is not None and jt2_size is not None and jt2_entrysize is not None:
|
|
1138
|
+
ij.add_jumptable(jt2_addr, jt2_size, jt2_entrysize, jt2, is_primary=False)
|
|
1139
|
+
|
|
1140
|
+
return True, all_targets
|
|
1141
|
+
|
|
1142
|
+
l.info("Could not resolve indirect jump %#x in function %#x.", addr, func_addr)
|
|
1143
|
+
return False, None
|
|
1144
|
+
|
|
1145
|
+
def _find_load_statement(self, b, stmt_loc: tuple[int, int]) -> tuple[
|
|
1146
|
+
tuple[int, int] | None,
|
|
1147
|
+
pyvex.stmt.IRStmt | None,
|
|
1148
|
+
int | None,
|
|
1149
|
+
list[tuple[int, int]],
|
|
1150
|
+
list[JumpTargetBaseAddr],
|
|
1151
|
+
OrderedDict[tuple[int, int], AddressTransformation],
|
|
1152
|
+
]:
|
|
1153
|
+
"""
|
|
1154
|
+
Find the location of the final Load statement that loads indirect jump targets from the jump table.
|
|
1155
|
+
"""
|
|
1156
|
+
|
|
1157
|
+
# pylint:disable=no-else-continue
|
|
1158
|
+
|
|
1159
|
+
# shorthand
|
|
1160
|
+
project = self.project
|
|
1161
|
+
|
|
1162
|
+
# initialization
|
|
1163
|
+
load_stmt_loc, load_stmt, load_size = None, None, None
|
|
1164
|
+
stmts_to_remove = [stmt_loc]
|
|
1165
|
+
stmts_adding_base_addr: list[JumpTargetBaseAddr] = []
|
|
1166
|
+
# All temporary variables that hold indirect addresses loaded out of the memory
|
|
1167
|
+
# Obviously, load_stmt.tmp must be here
|
|
1168
|
+
# if there are additional data transferring statements between the Load statement and the base-address-adding
|
|
1169
|
+
# statement, all_addr_holders will have more than one temporary variables
|
|
1170
|
+
#
|
|
1171
|
+
# Here is an example:
|
|
1172
|
+
#
|
|
1173
|
+
# IRSB 0x4c64c4
|
|
1174
|
+
# + 06 | t12 = LDle:I32(t7)
|
|
1175
|
+
# + 07 | t11 = 32Sto64(t12)
|
|
1176
|
+
# + 10 | t2 = Add64(0x0000000000571df0,t11)
|
|
1177
|
+
#
|
|
1178
|
+
# all_addr_holders will be {(0x4c64c4, 11): (AddressTransferringTypes.SignedExtension, 32, 64,),
|
|
1179
|
+
# (0x4c64c4, 12); (AddressTransferringTypes.Assignment,),
|
|
1180
|
+
# }
|
|
1181
|
+
transformations: dict[tuple[int, int], AddressTransformation] = OrderedDict()
|
|
1182
|
+
|
|
1183
|
+
initial_block_addr = stmt_loc[0]
|
|
1184
|
+
all_load_stmts = sorted(self._all_qualified_load_stmts_in_slice(b, stmt_loc[0]))
|
|
1185
|
+
|
|
1186
|
+
while True:
|
|
1187
|
+
preds = list(b.slice.predecessors(stmt_loc))
|
|
1188
|
+
if len(preds) != 1:
|
|
1189
|
+
break
|
|
1190
|
+
block_addr, stmt_idx = stmt_loc = preds[0]
|
|
1191
|
+
block = project.factory.block(block_addr, cross_insn_opt=True, backup_state=self.base_state).vex
|
|
1192
|
+
if stmt_idx == DEFAULT_STATEMENT:
|
|
1193
|
+
# it's the default exit. continue
|
|
1194
|
+
continue
|
|
1195
|
+
stmt = block.statements[stmt_idx]
|
|
1196
|
+
if isinstance(stmt, (pyvex.IRStmt.WrTmp, pyvex.IRStmt.Put)):
|
|
1197
|
+
if isinstance(stmt.data, (pyvex.IRExpr.Get, pyvex.IRExpr.RdTmp)):
|
|
1198
|
+
# data transferring
|
|
1199
|
+
stmts_to_remove.append(stmt_loc)
|
|
1200
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1201
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1202
|
+
AddressTransformationTypes.Assignment, [stmt.tmp, AddressSingleton]
|
|
1203
|
+
)
|
|
1204
|
+
continue
|
|
1205
|
+
if isinstance(stmt.data, pyvex.IRExpr.ITE):
|
|
1206
|
+
# data transferring
|
|
1207
|
+
# t16 = if (t43) ILGop_Ident32(LDle(t29)) else 0x0000c844
|
|
1208
|
+
# > t44 = ITE(t43,t16,0x0000c844)
|
|
1209
|
+
stmts_to_remove.append(stmt_loc)
|
|
1210
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1211
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1212
|
+
AddressTransformationTypes.Assignment, [stmt.tmp, AddressSingleton]
|
|
1213
|
+
)
|
|
1214
|
+
continue
|
|
1215
|
+
if isinstance(stmt.data, pyvex.IRExpr.Unop):
|
|
1216
|
+
if stmt.data.op == "Iop_32Sto64":
|
|
1217
|
+
# data transferring with conversion
|
|
1218
|
+
# t11 = 32Sto64(t12)
|
|
1219
|
+
stmts_to_remove.append(stmt_loc)
|
|
1220
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1221
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1222
|
+
AddressTransformationTypes.SignedExtension, [32, 64, AddressSingleton]
|
|
1223
|
+
)
|
|
1224
|
+
continue
|
|
1225
|
+
if stmt.data.op == "Iop_64to32":
|
|
1226
|
+
# data transferring with conversion
|
|
1227
|
+
# t24 = 64to32(t21)
|
|
1228
|
+
stmts_to_remove.append(stmt_loc)
|
|
1229
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1230
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1231
|
+
AddressTransformationTypes.Truncation, [64, 32, AddressSingleton]
|
|
1232
|
+
)
|
|
1233
|
+
continue
|
|
1234
|
+
if stmt.data.op == "Iop_32Uto64":
|
|
1235
|
+
# data transferring with conversion
|
|
1236
|
+
# t21 = 32Uto64(t22)
|
|
1237
|
+
stmts_to_remove.append(stmt_loc)
|
|
1238
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1239
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1240
|
+
AddressTransformationTypes.UnsignedExtension, [32, 64, AddressSingleton]
|
|
1241
|
+
)
|
|
1242
|
+
continue
|
|
1243
|
+
if stmt.data.op == "Iop_16Uto32":
|
|
1244
|
+
# data transferring with conversion
|
|
1245
|
+
stmts_to_remove.append(stmt_loc)
|
|
1246
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1247
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1248
|
+
AddressTransformationTypes.UnsignedExtension, [16, 32, AddressSingleton]
|
|
1249
|
+
)
|
|
1250
|
+
continue
|
|
1251
|
+
if stmt.data.op == "Iop_8Uto32":
|
|
1252
|
+
# data transferring with conversion
|
|
1253
|
+
stmts_to_remove.append(stmt_loc)
|
|
1254
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1255
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1256
|
+
AddressTransformationTypes.UnsignedExtension, [8, 32, AddressSingleton]
|
|
1257
|
+
)
|
|
1258
|
+
continue
|
|
1259
|
+
if stmt.data.op == "Iop_8Uto64":
|
|
1260
|
+
stmts_to_remove.append(stmt_loc)
|
|
1261
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
1262
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1263
|
+
AddressTransformationTypes.UnsignedExtension, [8, 64, AddressSingleton]
|
|
1264
|
+
)
|
|
1265
|
+
continue
|
|
1266
|
+
elif isinstance(stmt.data, pyvex.IRExpr.Binop):
|
|
1267
|
+
if stmt.data.op.startswith("Iop_Add"):
|
|
1268
|
+
# GitHub issue #1289, an S390X binary
|
|
1269
|
+
# jump_label = &jump_table + *(jump_table[index])
|
|
1270
|
+
# IRSB 0x4007c0
|
|
1271
|
+
# 00 | ------ IMark(0x4007c0, 4, 0) ------
|
|
1272
|
+
# + 01 | t0 = GET:I32(212)
|
|
1273
|
+
# + 02 | t1 = Add32(t0,0xffffffff)
|
|
1274
|
+
# 03 | PUT(352) = 0x0000000000000003
|
|
1275
|
+
# 04 | t13 = 32Sto64(t0)
|
|
1276
|
+
# 05 | t6 = t13
|
|
1277
|
+
# 06 | PUT(360) = t6
|
|
1278
|
+
# 07 | PUT(368) = 0xffffffffffffffff
|
|
1279
|
+
# 08 | PUT(376) = 0x0000000000000000
|
|
1280
|
+
# 09 | PUT(212) = t1
|
|
1281
|
+
# 10 | PUT(ia) = 0x00000000004007c4
|
|
1282
|
+
# 11 | ------ IMark(0x4007c4, 6, 0) ------
|
|
1283
|
+
# + 12 | t14 = 32Uto64(t1)
|
|
1284
|
+
# + 13 | t8 = t14
|
|
1285
|
+
# + 14 | t16 = CmpLE64U(t8,0x000000000000000b)
|
|
1286
|
+
# + 15 | t15 = 1Uto32(t16)
|
|
1287
|
+
# + 16 | t10 = t15
|
|
1288
|
+
# + 17 | t11 = CmpNE32(t10,0x00000000)
|
|
1289
|
+
# + 18 | if (t11) { PUT(offset=336) = 0x4007d4; Ijk_Boring }
|
|
1290
|
+
# Next: 0x4007ca
|
|
1291
|
+
#
|
|
1292
|
+
# IRSB 0x4007d4
|
|
1293
|
+
# 00 | ------ IMark(0x4007d4, 6, 0) ------
|
|
1294
|
+
# + 01 | t8 = GET:I64(r2)
|
|
1295
|
+
# + 02 | t7 = Shr64(t8,0x3d)
|
|
1296
|
+
# + 03 | t9 = Shl64(t8,0x03)
|
|
1297
|
+
# + 04 | t6 = Or64(t9,t7)
|
|
1298
|
+
# + 05 | t11 = And64(t6,0x00000007fffffff8)
|
|
1299
|
+
# 06 | ------ IMark(0x4007da, 6, 0) ------
|
|
1300
|
+
# 07 | PUT(r1) = 0x0000000000400a50
|
|
1301
|
+
# 08 | PUT(ia) = 0x00000000004007e0
|
|
1302
|
+
# 09 | ------ IMark(0x4007e0, 6, 0) ------
|
|
1303
|
+
# + 10 | t12 = Add64(0x0000000000400a50,t11)
|
|
1304
|
+
# + 11 | t16 = LDbe:I64(t12)
|
|
1305
|
+
# 12 | PUT(r2) = t16
|
|
1306
|
+
# 13 | ------ IMark(0x4007e6, 4, 0) ------
|
|
1307
|
+
# + 14 | t17 = Add64(0x0000000000400a50,t16)
|
|
1308
|
+
# + Next: t17
|
|
1309
|
+
#
|
|
1310
|
+
# Special case: a base address is added to the loaded offset before jumping to it.
|
|
1311
|
+
if isinstance(stmt.data.args[0], pyvex.IRExpr.Const) and isinstance(
|
|
1312
|
+
stmt.data.args[1], pyvex.IRExpr.RdTmp
|
|
1313
|
+
):
|
|
1314
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1315
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1316
|
+
AddressTransformationTypes.Add, [stmt.data.args[0].con.value, AddressSingleton]
|
|
1317
|
+
)
|
|
1318
|
+
# we no longer update stmts_adding_base_addr in this case because it's replaced by
|
|
1319
|
+
# transformations
|
|
1320
|
+
stmts_to_remove.append(stmt_loc)
|
|
1321
|
+
elif isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp) and isinstance(
|
|
1322
|
+
stmt.data.args[1], pyvex.IRExpr.Const
|
|
1323
|
+
):
|
|
1324
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1325
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1326
|
+
AddressTransformationTypes.Add, [AddressSingleton, stmt.data.args[1].con.value]
|
|
1327
|
+
)
|
|
1328
|
+
# we no longer update stmts_adding_base_addr in this case because it's replaced by
|
|
1329
|
+
# transformations
|
|
1330
|
+
stmts_to_remove.append(stmt_loc)
|
|
1331
|
+
elif isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp) and isinstance(
|
|
1332
|
+
stmt.data.args[1], pyvex.IRExpr.RdTmp
|
|
1333
|
+
):
|
|
1334
|
+
# one of the tmps must be holding a concrete value at this point. we will know this when
|
|
1335
|
+
# we perform constant propagation before running JumpTableResolver. this can act as an
|
|
1336
|
+
# indicator that we need to run constant propagation for this function.
|
|
1337
|
+
# for now, we don't support it :)
|
|
1338
|
+
# FIXME: Run constant propagation for the function when necessary. we can also remove
|
|
1339
|
+
# stmts_adding_base_addr and the surrounding logic then.
|
|
1340
|
+
# transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1341
|
+
# AddressTransferringTypes.Add,
|
|
1342
|
+
# [Tmp(stmt.data.args[0].tmp), Tmp(stmt.data.args[1].tmp)],
|
|
1343
|
+
# )
|
|
1344
|
+
stmts_adding_base_addr.append(
|
|
1345
|
+
JumpTargetBaseAddr(stmt_loc, stmt, stmt.data.args[0].tmp, tmp_1=stmt.data.args[1].tmp)
|
|
1346
|
+
)
|
|
1347
|
+
stmts_to_remove.append(stmt_loc)
|
|
1348
|
+
else:
|
|
1349
|
+
# not supported
|
|
1350
|
+
pass
|
|
1351
|
+
continue
|
|
1352
|
+
if stmt.data.op.startswith("Iop_Or"):
|
|
1353
|
+
# this is sometimes used in VEX statements in THUMB mode code to adjust the address to an odd
|
|
1354
|
+
# number
|
|
1355
|
+
# e.g.
|
|
1356
|
+
# IRSB 0x4b63
|
|
1357
|
+
# 00 | ------ IMark(0x4b62, 4, 1) ------
|
|
1358
|
+
# 01 | PUT(itstate) = 0x00000000
|
|
1359
|
+
# + 02 | t11 = GET:I32(r2)
|
|
1360
|
+
# + 03 | t10 = Shl32(t11,0x01)
|
|
1361
|
+
# + 04 | t9 = Add32(0x00004b66,t10)
|
|
1362
|
+
# + 05 | t8 = LDle:I16(t9)
|
|
1363
|
+
# + 06 | t7 = 16Uto32(t8)
|
|
1364
|
+
# + 07 | t14 = Shl32(t7,0x01)
|
|
1365
|
+
# + 08 | t13 = Add32(0x00004b66,t14)
|
|
1366
|
+
# + 09 | t12 = Or32(t13,0x00000001)
|
|
1367
|
+
# + Next: t12
|
|
1368
|
+
if (
|
|
1369
|
+
isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp)
|
|
1370
|
+
and isinstance(stmt.data.args[1], pyvex.IRExpr.Const)
|
|
1371
|
+
and stmt.data.args[1].con.value == 1
|
|
1372
|
+
):
|
|
1373
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1374
|
+
# great. here it is
|
|
1375
|
+
stmts_to_remove.append(stmt_loc)
|
|
1376
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1377
|
+
AddressTransformationTypes.Or1, [AddressSingleton]
|
|
1378
|
+
)
|
|
1379
|
+
continue
|
|
1380
|
+
elif stmt.data.op.startswith("Iop_Shl"):
|
|
1381
|
+
# this is sometimes used when dealing with TBx instructions in ARM code.
|
|
1382
|
+
# e.g.
|
|
1383
|
+
# IRSB 0x4b63
|
|
1384
|
+
# 00 | ------ IMark(0x4b62, 4, 1) ------
|
|
1385
|
+
# 01 | PUT(itstate) = 0x00000000
|
|
1386
|
+
# + 02 | t11 = GET:I32(r2)
|
|
1387
|
+
# + 03 | t10 = Shl32(t11,0x01)
|
|
1388
|
+
# + 04 | t9 = Add32(0x00004b66,t10)
|
|
1389
|
+
# + 05 | t8 = LDle:I16(t9)
|
|
1390
|
+
# + 06 | t7 = 16Uto32(t8)
|
|
1391
|
+
# + 07 | t14 = Shl32(t7,0x01)
|
|
1392
|
+
# + 08 | t13 = Add32(0x00004b66,t14)
|
|
1393
|
+
# + 09 | t12 = Or32(t13,0x00000001)
|
|
1394
|
+
# + Next: t12
|
|
1395
|
+
if isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp) and isinstance(
|
|
1396
|
+
stmt.data.args[1], pyvex.IRExpr.Const
|
|
1397
|
+
):
|
|
1398
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1399
|
+
# found it
|
|
1400
|
+
stmts_to_remove.append(stmt_loc)
|
|
1401
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1402
|
+
AddressTransformationTypes.ShiftLeft, [AddressSingleton, stmt.data.args[1].con.value]
|
|
1403
|
+
)
|
|
1404
|
+
continue
|
|
1405
|
+
# AArch64
|
|
1406
|
+
#
|
|
1407
|
+
# LDRB W0, [X20,W26,UXTW]
|
|
1408
|
+
# ADR X1, loc_11F85C
|
|
1409
|
+
# ADD X0, X1, W0,SXTB#2
|
|
1410
|
+
# BR X0
|
|
1411
|
+
#
|
|
1412
|
+
# IRSB 0x51f84c
|
|
1413
|
+
# + 00 | ------ IMark(0x51f84c, 4, 0) ------
|
|
1414
|
+
# + 01 | t8 = GET:I64(x26)
|
|
1415
|
+
# + 02 | t7 = 64to32(t8)
|
|
1416
|
+
# + 03 | t6 = 32Uto64(t7)
|
|
1417
|
+
# + 04 | t9 = GET:I64(x20)
|
|
1418
|
+
# + 05 | t5 = Add64(t9,t6)
|
|
1419
|
+
# + 06 | t11 = LDle:I8(t5)
|
|
1420
|
+
# + 07 | t10 = 8Uto64(t11)
|
|
1421
|
+
# + 08 | ------ IMark(0x51f850, 4, 0) ------
|
|
1422
|
+
# 09 | PUT(x1) = 0x000000000051f85c
|
|
1423
|
+
# + 10 | ------ IMark(0x51f854, 4, 0) ------
|
|
1424
|
+
# + 11 | t14 = Shl64(t10,0x38)
|
|
1425
|
+
# + 12 | t13 = Sar64(t14,0x38)
|
|
1426
|
+
# + 13 | t12 = Shl64(t13,0x02)
|
|
1427
|
+
# + 14 | t4 = Add64(0x000000000051f85c,t12)
|
|
1428
|
+
# 15 | PUT(x0) = t4
|
|
1429
|
+
# + 16 | ------ IMark(0x51f858, 4, 0) ------
|
|
1430
|
+
# + Next: t4
|
|
1431
|
+
elif (
|
|
1432
|
+
stmt.data.op.startswith("Iop_Sar")
|
|
1433
|
+
and isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp)
|
|
1434
|
+
and isinstance(stmt.data.args[1], pyvex.IRExpr.Const)
|
|
1435
|
+
):
|
|
1436
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1437
|
+
# found it
|
|
1438
|
+
stmts_to_remove.append(stmt_loc)
|
|
1439
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1440
|
+
AddressTransformationTypes.ShiftRight, [AddressSingleton, stmt.data.args[1].con.value]
|
|
1441
|
+
)
|
|
1442
|
+
continue
|
|
1443
|
+
elif isinstance(stmt.data, pyvex.IRExpr.Load):
|
|
1444
|
+
assert isinstance(stmt, pyvex.stmt.WrTmp)
|
|
1445
|
+
# Got it!
|
|
1446
|
+
load_stmt, load_stmt_loc, load_size = (
|
|
1447
|
+
stmt,
|
|
1448
|
+
stmt_loc,
|
|
1449
|
+
block.tyenv.sizeof(stmt.tmp) // self.project.arch.byte_width,
|
|
1450
|
+
)
|
|
1451
|
+
stmts_to_remove.append(stmt_loc)
|
|
1452
|
+
is_first_load_stmt = (
|
|
1453
|
+
True if not all_load_stmts else (stmt_loc == (initial_block_addr, all_load_stmts[0]))
|
|
1454
|
+
)
|
|
1455
|
+
transformations[(stmt_loc[0], stmt.tmp)] = AddressTransformation(
|
|
1456
|
+
AddressTransformationTypes.Load, [AddressSingleton, load_size], first_load=is_first_load_stmt
|
|
1457
|
+
)
|
|
1458
|
+
if not is_first_load_stmt:
|
|
1459
|
+
# This is not the first load statement in the block. more to go
|
|
1460
|
+
continue
|
|
1461
|
+
elif isinstance(stmt, pyvex.IRStmt.LoadG):
|
|
1462
|
+
# Got it!
|
|
1463
|
+
#
|
|
1464
|
+
# this is how an ARM jump table is translated to VEX
|
|
1465
|
+
# > t16 = if (t43) ILGop_Ident32(LDle(t29)) else 0x0000c844
|
|
1466
|
+
load_stmt, load_stmt_loc, load_size = (
|
|
1467
|
+
stmt,
|
|
1468
|
+
stmt_loc,
|
|
1469
|
+
block.tyenv.sizeof(stmt.dst) // self.project.arch.byte_width,
|
|
1470
|
+
)
|
|
1471
|
+
stmts_to_remove.append(stmt_loc)
|
|
1472
|
+
elif isinstance(stmt, pyvex.IRStmt.IMark):
|
|
1473
|
+
continue
|
|
1474
|
+
|
|
1475
|
+
break
|
|
1476
|
+
|
|
1477
|
+
return load_stmt_loc, load_stmt, load_size, stmts_to_remove, stmts_adding_base_addr, transformations
|
|
1478
|
+
|
|
1479
|
+
def _find_load_pc_ite_statement(self, b: Blade, stmt_loc: tuple[int, int]):
|
|
1480
|
+
"""
|
|
1481
|
+
Find the location of the final ITE statement that loads indirect jump targets into a tmp.
|
|
1482
|
+
|
|
1483
|
+
The slice looks like the following:
|
|
1484
|
+
|
|
1485
|
+
IRSB 0x41d0fc
|
|
1486
|
+
00 | ------ IMark(0x41d0fc, 4, 0) ------
|
|
1487
|
+
+ 01 | t0 = GET:I32(r5)
|
|
1488
|
+
+ 02 | t2 = Sub32(t0,0x00000022)
|
|
1489
|
+
03 | PUT(r3) = t2
|
|
1490
|
+
04 | ------ IMark(0x41d100, 4, 0) ------
|
|
1491
|
+
05 | PUT(cc_op) = 0x00000002
|
|
1492
|
+
06 | PUT(cc_dep1) = t2
|
|
1493
|
+
07 | PUT(cc_dep2) = 0x0000001c
|
|
1494
|
+
08 | PUT(cc_ndep) = 0x00000000
|
|
1495
|
+
09 | ------ IMark(0x41d104, 4, 0) ------
|
|
1496
|
+
+ 10 | t25 = CmpLE32U(t2,0x0000001c)
|
|
1497
|
+
11 | t24 = 1Uto32(t25)
|
|
1498
|
+
+ 12 | t8 = Shl32(t2,0x02)
|
|
1499
|
+
+ 13 | t10 = Add32(0x0041d10c,t8)
|
|
1500
|
+
+ 14 | t26 = ITE(t25,t10,0x0041d104) <---- this is the statement that we are looking for. Note that
|
|
1501
|
+
0x0041d104 *must* be ignored since it is a side effect generated
|
|
1502
|
+
by the VEX ARM lifter
|
|
1503
|
+
15 | PUT(pc) = t26
|
|
1504
|
+
16 | t21 = Xor32(t24,0x00000001)
|
|
1505
|
+
17 | t27 = 32to1(t21)
|
|
1506
|
+
18 | if (t27) { PUT(offset=68) = 0x41d108; Ijk_Boring }
|
|
1507
|
+
+ Next: t26
|
|
1508
|
+
|
|
1509
|
+
:param b: The Blade instance, which comes with the slice.
|
|
1510
|
+
:param stmt_loc: The location of the final statement.
|
|
1511
|
+
:return:
|
|
1512
|
+
"""
|
|
1513
|
+
|
|
1514
|
+
project = self.project
|
|
1515
|
+
ite_stmt, ite_stmt_loc = None, None
|
|
1516
|
+
stmts_to_remove = [stmt_loc]
|
|
1517
|
+
|
|
1518
|
+
while True:
|
|
1519
|
+
preds = list(b.slice.predecessors(stmt_loc))
|
|
1520
|
+
if len(preds) != 1:
|
|
1521
|
+
break
|
|
1522
|
+
block_addr, stmt_idx = stmt_loc = preds[0]
|
|
1523
|
+
stmts_to_remove.append(stmt_loc)
|
|
1524
|
+
block = project.factory.block(block_addr, cross_insn_opt=True).vex
|
|
1525
|
+
if stmt_idx == DEFAULT_STATEMENT:
|
|
1526
|
+
# we should not reach the default exit (which belongs to a predecessor block)
|
|
1527
|
+
break
|
|
1528
|
+
if not isinstance(block.next, pyvex.IRExpr.RdTmp):
|
|
1529
|
+
# next must be an RdTmp
|
|
1530
|
+
break
|
|
1531
|
+
stmt = block.statements[stmt_idx]
|
|
1532
|
+
if (
|
|
1533
|
+
isinstance(stmt, pyvex.IRStmt.WrTmp)
|
|
1534
|
+
and stmt.tmp == block.next.tmp
|
|
1535
|
+
and isinstance(stmt.data, pyvex.IRExpr.ITE)
|
|
1536
|
+
):
|
|
1537
|
+
# yes!
|
|
1538
|
+
ite_stmt, ite_stmt_loc = stmt, stmt_loc
|
|
1539
|
+
break
|
|
1540
|
+
|
|
1541
|
+
return ite_stmt, ite_stmt_loc, stmts_to_remove
|
|
1542
|
+
|
|
1543
|
+
def _jumptable_precheck(self, b, indirect_jump_node_pred_addrs):
|
|
1544
|
+
"""
|
|
1545
|
+
Perform a pre-check on the slice to determine whether it is a jump table or not. Please refer to the docstring
|
|
1546
|
+
of JumpTableProcessor for how precheck and statement instrumentation works. A NotAJumpTableNotification
|
|
1547
|
+
exception will be raised if the slice fails this precheck.
|
|
1548
|
+
|
|
1549
|
+
:param b: The statement slice generated by Blade.
|
|
1550
|
+
:return: A list of statements to instrument, and a list of registers to initialize.
|
|
1551
|
+
:rtype: tuple of lists
|
|
1552
|
+
"""
|
|
1553
|
+
|
|
1554
|
+
# pylint:disable=no-else-continue
|
|
1555
|
+
|
|
1556
|
+
engine = JumpTableProcessor(self.project, indirect_jump_node_pred_addrs)
|
|
1557
|
+
|
|
1558
|
+
sources = [n for n in b.slice.nodes() if b.slice.in_degree(n) == 0]
|
|
1559
|
+
|
|
1560
|
+
annotatedcfg = AnnotatedCFG(self.project, None, detect_loops=False)
|
|
1561
|
+
annotatedcfg.from_digraph(b.slice)
|
|
1562
|
+
|
|
1563
|
+
for src in sources:
|
|
1564
|
+
state = JumpTableProcessorState(self.project.arch)
|
|
1565
|
+
traced = {src[0]}
|
|
1566
|
+
while src is not None:
|
|
1567
|
+
state._tmpvar_source.clear()
|
|
1568
|
+
block_addr, _ = src
|
|
1569
|
+
|
|
1570
|
+
block = self.project.factory.block(block_addr, cross_insn_opt=True, backup_state=self.base_state)
|
|
1571
|
+
stmt_whitelist = annotatedcfg.get_whitelisted_statements(block_addr)
|
|
1572
|
+
assert isinstance(stmt_whitelist, list)
|
|
1573
|
+
try:
|
|
1574
|
+
engine.process(
|
|
1575
|
+
state, block=block, whitelist=set(stmt_whitelist) if stmt_whitelist is not None else None
|
|
1576
|
+
)
|
|
1577
|
+
except (claripy.ClaripyError, SimError, AngrError):
|
|
1578
|
+
# anything can happen
|
|
1579
|
+
break
|
|
1580
|
+
|
|
1581
|
+
if state.is_jumptable:
|
|
1582
|
+
return state.stmts_to_instrument, state.regs_to_initialize
|
|
1583
|
+
if state.is_jumptable is False:
|
|
1584
|
+
raise NotAJumpTableNotification
|
|
1585
|
+
|
|
1586
|
+
# find the next block
|
|
1587
|
+
src = None
|
|
1588
|
+
for idx in reversed(stmt_whitelist):
|
|
1589
|
+
loc = (block_addr, idx)
|
|
1590
|
+
successors = list(b.slice.successors(loc))
|
|
1591
|
+
if len(successors) == 1:
|
|
1592
|
+
block_addr_ = successors[0][0]
|
|
1593
|
+
if block_addr_ not in traced:
|
|
1594
|
+
src = successors[0]
|
|
1595
|
+
traced.add(block_addr_)
|
|
1596
|
+
break
|
|
1597
|
+
|
|
1598
|
+
raise NotAJumpTableNotification
|
|
1599
|
+
|
|
1600
|
+
@staticmethod
|
|
1601
|
+
def _try_resolve_single_constant_loads(load_stmt, cfg, addr):
|
|
1602
|
+
"""
|
|
1603
|
+
Resolve cases where only a single constant load is required to resolve the indirect jump. Strictly speaking, it
|
|
1604
|
+
is not a jump table, but we resolve it here anyway.
|
|
1605
|
+
|
|
1606
|
+
:param load_stmt: The pyvex.IRStmt.Load statement that loads an address.
|
|
1607
|
+
:param cfg: The CFG instance.
|
|
1608
|
+
:param int addr: Address of the jump table block.
|
|
1609
|
+
:return: A jump target, or None if it cannot be resolved.
|
|
1610
|
+
:rtype: int or None
|
|
1611
|
+
"""
|
|
1612
|
+
|
|
1613
|
+
# If we're just reading a constant, don't bother with the rest of this mess!
|
|
1614
|
+
if isinstance(load_stmt, pyvex.IRStmt.WrTmp):
|
|
1615
|
+
assert isinstance(load_stmt.data, pyvex.IRExpr.Load)
|
|
1616
|
+
if isinstance(load_stmt.data.addr, pyvex.IRExpr.Const):
|
|
1617
|
+
# It's directly loading from a constant address
|
|
1618
|
+
# e.g.,
|
|
1619
|
+
# ldr r0, =main+1
|
|
1620
|
+
# blx r0
|
|
1621
|
+
# It's not a jump table, but we resolve it anyway
|
|
1622
|
+
jump_target_addr = load_stmt.data.addr.con.value
|
|
1623
|
+
jump_target = cfg._fast_memory_load_pointer(jump_target_addr)
|
|
1624
|
+
if jump_target is None:
|
|
1625
|
+
l.info(
|
|
1626
|
+
"Constant indirect jump %#x points outside of loaded memory to %#08x", addr, jump_target_addr
|
|
1627
|
+
)
|
|
1628
|
+
raise NotAJumpTableNotification
|
|
1629
|
+
|
|
1630
|
+
l.info("Resolved constant indirect jump from %#08x to %#08x", addr, jump_target_addr)
|
|
1631
|
+
return jump_target
|
|
1632
|
+
|
|
1633
|
+
elif isinstance(load_stmt, pyvex.IRStmt.LoadG) and isinstance(load_stmt.addr, pyvex.IRExpr.Const):
|
|
1634
|
+
# It's directly loading from a constant address
|
|
1635
|
+
# e.g.,
|
|
1636
|
+
# 4352c SUB R1, R11, #0x1000
|
|
1637
|
+
# 43530 LDRHI R3, =loc_45450
|
|
1638
|
+
# ...
|
|
1639
|
+
# 43540 MOV PC, R3
|
|
1640
|
+
#
|
|
1641
|
+
# It's not a jump table, but we resolve it anyway
|
|
1642
|
+
# Note that this block has two branches: One goes to 45450, the other one goes to whatever the original
|
|
1643
|
+
# value of R3 is. Some intensive data-flow analysis is required in this case.
|
|
1644
|
+
jump_target_addr = load_stmt.addr.con.value
|
|
1645
|
+
jump_target = cfg._fast_memory_load_pointer(jump_target_addr)
|
|
1646
|
+
l.info("Resolved constant indirect jump from %#08x to %#08x", addr, jump_target_addr)
|
|
1647
|
+
return jump_target
|
|
1648
|
+
|
|
1649
|
+
return None
|
|
1650
|
+
|
|
1651
|
+
def _try_resolve_targets_load(
|
|
1652
|
+
self,
|
|
1653
|
+
r,
|
|
1654
|
+
addr,
|
|
1655
|
+
cfg,
|
|
1656
|
+
annotatedcfg,
|
|
1657
|
+
load_stmt,
|
|
1658
|
+
load_size,
|
|
1659
|
+
stmts_adding_base_addr,
|
|
1660
|
+
transformations: dict[tuple[int, int], AddressTransformation],
|
|
1661
|
+
potential_call_table: bool = False,
|
|
1662
|
+
):
|
|
1663
|
+
"""
|
|
1664
|
+
Try loading all jump targets from a jump table or a vtable.
|
|
1665
|
+
"""
|
|
1666
|
+
|
|
1667
|
+
# shorthand
|
|
1668
|
+
project = self.project
|
|
1669
|
+
|
|
1670
|
+
try:
|
|
1671
|
+
whitelist = annotatedcfg.get_whitelisted_statements(r.addr)
|
|
1672
|
+
last_stmt = annotatedcfg.get_last_statement_index(r.addr)
|
|
1673
|
+
succ = project.factory.successors(r, whitelist=whitelist, last_stmt=last_stmt)
|
|
1674
|
+
except (AngrError, SimError):
|
|
1675
|
+
# oops there are errors
|
|
1676
|
+
l.debug("Cannot get jump successor states from a path that has reached the target. Skip it.")
|
|
1677
|
+
return None
|
|
1678
|
+
|
|
1679
|
+
all_states = succ.flat_successors + succ.unconstrained_successors
|
|
1680
|
+
if not all_states:
|
|
1681
|
+
l.debug("Slicecutor failed to execute the program slice. No output state is available.")
|
|
1682
|
+
return None
|
|
1683
|
+
|
|
1684
|
+
state = all_states[0] # Just take the first state
|
|
1685
|
+
self._cached_memread_addrs.clear() # clear the cache to save some memory (and avoid confusion when debugging)
|
|
1686
|
+
|
|
1687
|
+
# Parse the memory load statement and get the memory address of where the jump table is stored
|
|
1688
|
+
jumptable_addr = self._parse_load_statement(load_stmt, state)
|
|
1689
|
+
if jumptable_addr is None:
|
|
1690
|
+
return None
|
|
1691
|
+
|
|
1692
|
+
# sanity check and necessary pre-processing
|
|
1693
|
+
jump_base_addr = None
|
|
1694
|
+
if stmts_adding_base_addr:
|
|
1695
|
+
if len(stmts_adding_base_addr) == 1:
|
|
1696
|
+
jump_base_addr = stmts_adding_base_addr[0]
|
|
1697
|
+
if jump_base_addr.base_addr_available:
|
|
1698
|
+
addr_holders = {(jump_base_addr.stmt_loc[0], jump_base_addr.tmp)}
|
|
1699
|
+
else:
|
|
1700
|
+
addr_holders = {
|
|
1701
|
+
(jump_base_addr.stmt_loc[0], jump_base_addr.tmp),
|
|
1702
|
+
(jump_base_addr.stmt_loc[0], jump_base_addr.tmp_1),
|
|
1703
|
+
}
|
|
1704
|
+
if len(set(transformations.keys()).intersection(addr_holders)) != 1:
|
|
1705
|
+
# for some reason it's trying to add a base address onto a different temporary variable that we
|
|
1706
|
+
# are not aware of. skip.
|
|
1707
|
+
return None
|
|
1708
|
+
|
|
1709
|
+
if not jump_base_addr.base_addr_available:
|
|
1710
|
+
# we need to decide which tmp is the address holder and which tmp holds the base address
|
|
1711
|
+
addr_holder = next(iter(set(transformations.keys()).intersection(addr_holders)))
|
|
1712
|
+
if jump_base_addr.tmp_1 == addr_holder[1]:
|
|
1713
|
+
# swap the two tmps
|
|
1714
|
+
jump_base_addr.tmp, jump_base_addr.tmp_1 = jump_base_addr.tmp_1, jump_base_addr.tmp
|
|
1715
|
+
# Load the concrete base address
|
|
1716
|
+
with contextlib.suppress(SimError):
|
|
1717
|
+
# silently eat the claripy exception
|
|
1718
|
+
jump_base_addr.base_addr = state.solver.eval(state.scratch.temps[jump_base_addr.tmp_1])
|
|
1719
|
+
else:
|
|
1720
|
+
# We do not support the cases where the base address involves more than one addition.
|
|
1721
|
+
# One such case exists in libc-2.27.so shipped with Ubuntu x86 where esi is used as the address of the
|
|
1722
|
+
# data region.
|
|
1723
|
+
#
|
|
1724
|
+
# .text:00047316 mov eax, esi
|
|
1725
|
+
# .text:00047318 mov esi, [ebp+data_region_ptr]
|
|
1726
|
+
# .text:0004731E movsx eax, al
|
|
1727
|
+
# .text:00047321 movzx eax, byte ptr [esi+eax-603A0h]
|
|
1728
|
+
# .text:00047329 mov eax, ds:(jpt_47337 - 1D8000h)[esi+eax*4] ; switch 32 cases
|
|
1729
|
+
# .text:00047330 lea eax, (loc_47033 - 1D8000h)[esi+eax] ; jumptable 00047337 cases 0-13,27-31
|
|
1730
|
+
# .text:00047337 jmp eax ; switch
|
|
1731
|
+
#
|
|
1732
|
+
# the proper solution requires angr to correctly determine that esi is the beginning address of the data
|
|
1733
|
+
# region (in this case, 0x1d8000). we give up in such cases until we can reasonably perform a
|
|
1734
|
+
# full-function data propagation before performing jump table recovery.
|
|
1735
|
+
l.debug("Multiple statements adding bases, not supported yet") # FIXME: Just check the addresses?
|
|
1736
|
+
|
|
1737
|
+
if jumptable_addr.has_annotation_type(claripy.RegionAnnotation):
|
|
1738
|
+
return None
|
|
1739
|
+
|
|
1740
|
+
all_targets = []
|
|
1741
|
+
jump_table = []
|
|
1742
|
+
|
|
1743
|
+
if jumptable_addr.op == "BVV":
|
|
1744
|
+
stride = 0
|
|
1745
|
+
else:
|
|
1746
|
+
try:
|
|
1747
|
+
jumptable_si = claripy.backends.vsa.simplify(jumptable_addr)
|
|
1748
|
+
si_annotation = jumptable_si.get_annotation(claripy.annotation.StridedIntervalAnnotation)
|
|
1749
|
+
stride = si_annotation.stride if si_annotation is not None else 0
|
|
1750
|
+
except claripy.ClaripyError:
|
|
1751
|
+
return None
|
|
1752
|
+
|
|
1753
|
+
# we may resolve a vtable (in C, e.g., the IO_JUMPS_FUNC in libc), but the stride of this load is usually 1
|
|
1754
|
+
# while the read statement reads a word size at a time.
|
|
1755
|
+
# we use this to differentiate between traditional jump tables (where each entry is some blocks that belong to
|
|
1756
|
+
# the current function) and vtables (where each entry is a function).
|
|
1757
|
+
if stride < load_size:
|
|
1758
|
+
stride = load_size
|
|
1759
|
+
total_cases = jumptable_addr.cardinality // load_size
|
|
1760
|
+
sort = "vtable" # it's probably a vtable!
|
|
1761
|
+
else:
|
|
1762
|
+
total_cases = jumptable_addr.cardinality
|
|
1763
|
+
sort = "jumptable"
|
|
1764
|
+
|
|
1765
|
+
assert self._max_targets is not None
|
|
1766
|
+
if total_cases > self._max_targets:
|
|
1767
|
+
if (
|
|
1768
|
+
potential_call_table
|
|
1769
|
+
and sort == "jumptable"
|
|
1770
|
+
and stride * 8 == state.arch.bits
|
|
1771
|
+
and jumptable_addr.op == "__add__"
|
|
1772
|
+
):
|
|
1773
|
+
# Undetermined table size. Take a guess based on target plausibility.
|
|
1774
|
+
table_base_addr = None
|
|
1775
|
+
for arg in jumptable_addr.args:
|
|
1776
|
+
assert isinstance(arg, (claripy.ast.BV, claripy.ast.FP, claripy.ast.Bool))
|
|
1777
|
+
if arg.concrete:
|
|
1778
|
+
table_base_addr = state.solver.eval(arg)
|
|
1779
|
+
break
|
|
1780
|
+
|
|
1781
|
+
if table_base_addr is not None:
|
|
1782
|
+
addr = table_base_addr
|
|
1783
|
+
# FIXME: May want to support NULL targets for handlers that are not filled in / placeholders
|
|
1784
|
+
# FIXME: Try negative offsets too? (this would be unusual)
|
|
1785
|
+
l.debug("Inspecting table at %#x for plausible targets...", addr)
|
|
1786
|
+
for i in range(self._max_targets):
|
|
1787
|
+
target = cfg._fast_memory_load_pointer(addr, size=load_size)
|
|
1788
|
+
if target is None or not self._is_jumptarget_legal(target):
|
|
1789
|
+
break
|
|
1790
|
+
l.debug("- %#x[%d] -> %#x", table_base_addr, i, target)
|
|
1791
|
+
jump_table.append(target)
|
|
1792
|
+
addr += stride
|
|
1793
|
+
num_targets = len(jump_table)
|
|
1794
|
+
if num_targets == 0:
|
|
1795
|
+
l.debug("Didn't find any plausible targets in suspected jump table %#x", table_base_addr)
|
|
1796
|
+
elif num_targets == self._max_targets:
|
|
1797
|
+
l.debug(
|
|
1798
|
+
"Reached maximum number of targets (%d) while scanning jump table %#x. It might not be "
|
|
1799
|
+
"a jump table, or the limit might be too low.",
|
|
1800
|
+
num_targets,
|
|
1801
|
+
table_base_addr,
|
|
1802
|
+
)
|
|
1803
|
+
else:
|
|
1804
|
+
l.debug("Table at %#x has %d plausible targets", table_base_addr, num_targets)
|
|
1805
|
+
return (
|
|
1806
|
+
jump_table,
|
|
1807
|
+
table_base_addr,
|
|
1808
|
+
load_size,
|
|
1809
|
+
num_targets * load_size,
|
|
1810
|
+
jump_table,
|
|
1811
|
+
sort,
|
|
1812
|
+
None,
|
|
1813
|
+
None,
|
|
1814
|
+
None,
|
|
1815
|
+
None,
|
|
1816
|
+
)
|
|
1817
|
+
|
|
1818
|
+
# We resolved too many targets for this indirect jump. Something might have gone wrong.
|
|
1819
|
+
l.debug(
|
|
1820
|
+
"%d targets are resolved for the indirect jump at %#x. It may not be a jump table. Try the "
|
|
1821
|
+
"next source, if there is any.",
|
|
1822
|
+
total_cases,
|
|
1823
|
+
addr,
|
|
1824
|
+
)
|
|
1825
|
+
return None
|
|
1826
|
+
|
|
1827
|
+
# Or alternatively, we can ask user, which is meh...
|
|
1828
|
+
#
|
|
1829
|
+
# jump_base_addr = int(raw_input("please give me the jump base addr: "), 16)
|
|
1830
|
+
# total_cases = int(raw_input("please give me the total cases: "))
|
|
1831
|
+
# jump_target = state.solver.SI(bits=64, lower_bound=jump_base_addr, upper_bound=jump_base_addr +
|
|
1832
|
+
# (total_cases - 1) * 8, stride=8)
|
|
1833
|
+
|
|
1834
|
+
min_jumptable_addr = state.solver.min(jumptable_addr)
|
|
1835
|
+
max_jumptable_addr = state.solver.max(jumptable_addr)
|
|
1836
|
+
|
|
1837
|
+
# Both the min jump target and the max jump target should be within a mapped memory region
|
|
1838
|
+
# i.e., we shouldn't be jumping to the stack or somewhere unmapped
|
|
1839
|
+
if not (
|
|
1840
|
+
(
|
|
1841
|
+
project.loader.find_segment_containing(min_jumptable_addr)
|
|
1842
|
+
and project.loader.find_segment_containing(max_jumptable_addr)
|
|
1843
|
+
)
|
|
1844
|
+
or (
|
|
1845
|
+
project.loader.find_section_containing(min_jumptable_addr)
|
|
1846
|
+
and project.loader.find_section_containing(max_jumptable_addr)
|
|
1847
|
+
)
|
|
1848
|
+
):
|
|
1849
|
+
l.debug(
|
|
1850
|
+
"Jump table %#x might have jump targets outside mapped memory regions. "
|
|
1851
|
+
"Continue to resolve it from the next data source.",
|
|
1852
|
+
addr,
|
|
1853
|
+
)
|
|
1854
|
+
return None
|
|
1855
|
+
|
|
1856
|
+
# Load the jump table from memory
|
|
1857
|
+
should_skip = False
|
|
1858
|
+
for idx, a in enumerate(range(min_jumptable_addr, max_jumptable_addr + 1, stride)):
|
|
1859
|
+
if idx % 100 == 0 and idx != 0:
|
|
1860
|
+
l.debug("%d targets have been resolved for the indirect jump at %#x...", idx, addr)
|
|
1861
|
+
if idx >= total_cases:
|
|
1862
|
+
break
|
|
1863
|
+
target = cfg._fast_memory_load_pointer(a, size=load_size)
|
|
1864
|
+
if target is None:
|
|
1865
|
+
l.debug("Cannot load pointer from address %#x. Skip.", a)
|
|
1866
|
+
should_skip = True
|
|
1867
|
+
break
|
|
1868
|
+
all_targets.append(target)
|
|
1869
|
+
if should_skip:
|
|
1870
|
+
return None
|
|
1871
|
+
|
|
1872
|
+
# Adjust entries inside the jump table
|
|
1873
|
+
mask = (2**self.project.arch.bits) - 1
|
|
1874
|
+
transformation_list = list(reversed([v for v in transformations.values() if not v.first_load]))
|
|
1875
|
+
jt_2nd_memloads: dict[int, int] = {}
|
|
1876
|
+
if transformation_list:
|
|
1877
|
+
|
|
1878
|
+
def handle_signed_ext(a):
|
|
1879
|
+
return (a | 0xFFFFFFFF00000000) if a >= 0x80000000 else a
|
|
1880
|
+
|
|
1881
|
+
def handle_unsigned_ext(a):
|
|
1882
|
+
return a
|
|
1883
|
+
|
|
1884
|
+
def handle_trunc_64_32(a):
|
|
1885
|
+
return a & 0xFFFFFFFF
|
|
1886
|
+
|
|
1887
|
+
def handle_or1(a):
|
|
1888
|
+
return a | 1
|
|
1889
|
+
|
|
1890
|
+
def handle_lshift(num_bits, a):
|
|
1891
|
+
return a << num_bits
|
|
1892
|
+
|
|
1893
|
+
def handle_rshift(num_bits, a):
|
|
1894
|
+
return a >> num_bits
|
|
1895
|
+
|
|
1896
|
+
def handle_add(con, a):
|
|
1897
|
+
return (a + con) & mask
|
|
1898
|
+
|
|
1899
|
+
def handle_load(size, a):
|
|
1900
|
+
if a not in jt_2nd_memloads:
|
|
1901
|
+
jt_2nd_memloads[a] = size
|
|
1902
|
+
else:
|
|
1903
|
+
jt_2nd_memloads[a] = max(jt_2nd_memloads[a], size)
|
|
1904
|
+
return cfg._fast_memory_load_pointer(a, size=size)
|
|
1905
|
+
|
|
1906
|
+
invert_conversion_ops = []
|
|
1907
|
+
for tran in transformation_list:
|
|
1908
|
+
tran_op, args = tran.op, tran.operands
|
|
1909
|
+
if tran_op is AddressTransformationTypes.SignedExtension:
|
|
1910
|
+
if args == [32, 64, AddressSingleton]:
|
|
1911
|
+
lam = handle_signed_ext
|
|
1912
|
+
else:
|
|
1913
|
+
raise NotImplementedError("Unsupported signed extension operation.")
|
|
1914
|
+
elif tran_op is AddressTransformationTypes.UnsignedExtension:
|
|
1915
|
+
lam = handle_unsigned_ext
|
|
1916
|
+
elif tran_op is AddressTransformationTypes.Truncation:
|
|
1917
|
+
if args == [64, 32, AddressSingleton]:
|
|
1918
|
+
lam = handle_trunc_64_32
|
|
1919
|
+
else:
|
|
1920
|
+
raise NotImplementedError("Unsupported truncation operation.")
|
|
1921
|
+
elif tran_op is AddressTransformationTypes.Or1:
|
|
1922
|
+
lam = handle_or1
|
|
1923
|
+
elif tran_op is AddressTransformationTypes.ShiftLeft:
|
|
1924
|
+
lam = functools.partial(
|
|
1925
|
+
handle_lshift, next(iter(arg for arg in args if arg is not AddressSingleton))
|
|
1926
|
+
)
|
|
1927
|
+
elif tran_op is AddressTransformationTypes.ShiftRight:
|
|
1928
|
+
lam = functools.partial(
|
|
1929
|
+
handle_rshift, next(iter(arg for arg in args if arg is not AddressSingleton))
|
|
1930
|
+
)
|
|
1931
|
+
elif tran_op is AddressTransformationTypes.Add:
|
|
1932
|
+
add_arg = next(iter(arg for arg in args if arg is not AddressSingleton))
|
|
1933
|
+
if not isinstance(add_arg, int):
|
|
1934
|
+
# unsupported cases (Tmp, for example). abort
|
|
1935
|
+
return None
|
|
1936
|
+
lam = functools.partial(handle_add, add_arg)
|
|
1937
|
+
elif tran_op is AddressTransformationTypes.Load:
|
|
1938
|
+
lam = functools.partial(handle_load, args[1])
|
|
1939
|
+
elif tran_op is AddressTransformationTypes.Assignment:
|
|
1940
|
+
continue
|
|
1941
|
+
else:
|
|
1942
|
+
raise NotImplementedError("Unsupported transformation operation.")
|
|
1943
|
+
invert_conversion_ops.append(lam)
|
|
1944
|
+
all_targets_copy = all_targets
|
|
1945
|
+
all_targets = []
|
|
1946
|
+
for target_ in all_targets_copy:
|
|
1947
|
+
for lam in invert_conversion_ops:
|
|
1948
|
+
target_ = lam(target_)
|
|
1949
|
+
if target_ is None:
|
|
1950
|
+
# transformation failed. abort
|
|
1951
|
+
return None
|
|
1952
|
+
all_targets.append(target_)
|
|
1953
|
+
if None in all_targets:
|
|
1954
|
+
return None
|
|
1955
|
+
if len(stmts_adding_base_addr) == 1:
|
|
1956
|
+
stmt_adding_base_addr = stmts_adding_base_addr[0]
|
|
1957
|
+
base_addr = stmt_adding_base_addr.base_addr
|
|
1958
|
+
all_targets = [(target + base_addr) & mask for target in all_targets]
|
|
1959
|
+
|
|
1960
|
+
# special case for ARM: if the source block is in THUMB mode, all jump targets should be in THUMB mode, too
|
|
1961
|
+
if is_arm_arch(self.project.arch) and (addr & 1) == 1:
|
|
1962
|
+
all_targets = [target | 1 for target in all_targets]
|
|
1963
|
+
|
|
1964
|
+
if len(all_targets) == 0:
|
|
1965
|
+
l.debug("Could not recover jump table")
|
|
1966
|
+
return None
|
|
1967
|
+
|
|
1968
|
+
# there might be a secondary jumptable
|
|
1969
|
+
jt_2nd = self._get_secondary_jumptable_from_transformations(transformation_list)
|
|
1970
|
+
jt_2nd_entries: list[int] | None = None
|
|
1971
|
+
jt_2nd_baseaddr: int | None = None
|
|
1972
|
+
jt_2nd_entrysize: int | None = None
|
|
1973
|
+
jt_2nd_size: int | None = None
|
|
1974
|
+
if jt_2nd is not None and jt_2nd_memloads:
|
|
1975
|
+
# determine the size of the secondary jump table
|
|
1976
|
+
jt_2nd_baseaddr, jt_2nd_entrysize = jt_2nd
|
|
1977
|
+
if jt_2nd_baseaddr in jt_2nd_memloads:
|
|
1978
|
+
jt_2nd_size = max(jt_2nd_memloads) - jt_2nd_baseaddr + jt_2nd_entrysize
|
|
1979
|
+
if jt_2nd_size % jt_2nd_entrysize == 0:
|
|
1980
|
+
jt_2nd_entrycount = jt_2nd_size // jt_2nd_entrysize
|
|
1981
|
+
if jt_2nd_entrycount <= len(all_targets):
|
|
1982
|
+
# we found it!
|
|
1983
|
+
jt_2nd_entries = []
|
|
1984
|
+
for i in range(jt_2nd_entrycount):
|
|
1985
|
+
target = cfg._fast_memory_load_pointer(
|
|
1986
|
+
jt_2nd_baseaddr + i * jt_2nd_entrysize,
|
|
1987
|
+
size=jt_2nd_entrysize,
|
|
1988
|
+
)
|
|
1989
|
+
if target is None:
|
|
1990
|
+
break
|
|
1991
|
+
jt_2nd_entries.append(target)
|
|
1992
|
+
|
|
1993
|
+
# Finally... all targets are ready
|
|
1994
|
+
illegal_target_found = False
|
|
1995
|
+
for target in all_targets:
|
|
1996
|
+
# if the total number of targets is suspicious (it usually implies a failure in applying the
|
|
1997
|
+
# constraints), check if all jump targets are legal
|
|
1998
|
+
if len(all_targets) in {1, 0x100, 0x10000} and not self._is_jumptarget_legal(target):
|
|
1999
|
+
l.info(
|
|
2000
|
+
"Jump target %#x is probably illegal. Try to resolve indirect jump at %#x from the next source.",
|
|
2001
|
+
target,
|
|
2002
|
+
addr,
|
|
2003
|
+
)
|
|
2004
|
+
illegal_target_found = True
|
|
2005
|
+
break
|
|
2006
|
+
jump_table.append(target)
|
|
2007
|
+
if illegal_target_found:
|
|
2008
|
+
return None
|
|
2009
|
+
|
|
2010
|
+
return (
|
|
2011
|
+
jump_table,
|
|
2012
|
+
min_jumptable_addr,
|
|
2013
|
+
load_size,
|
|
2014
|
+
total_cases * load_size,
|
|
2015
|
+
all_targets,
|
|
2016
|
+
sort,
|
|
2017
|
+
jt_2nd_entries,
|
|
2018
|
+
jt_2nd_baseaddr,
|
|
2019
|
+
jt_2nd_entrysize,
|
|
2020
|
+
jt_2nd_size,
|
|
2021
|
+
)
|
|
2022
|
+
|
|
2023
|
+
def _try_resolve_targets_ite(
|
|
2024
|
+
self, r, addr, cfg, annotatedcfg, ite_stmt: pyvex.IRStmt.WrTmp
|
|
2025
|
+
): # pylint:disable=unused-argument
|
|
2026
|
+
"""
|
|
2027
|
+
Try loading all jump targets from parsing an ITE block.
|
|
2028
|
+
"""
|
|
2029
|
+
project = self.project
|
|
2030
|
+
|
|
2031
|
+
try:
|
|
2032
|
+
whitelist = annotatedcfg.get_whitelisted_statements(r.addr)
|
|
2033
|
+
last_stmt = annotatedcfg.get_last_statement_index(r.addr)
|
|
2034
|
+
succ = project.factory.successors(r, whitelist=whitelist, last_stmt=last_stmt)
|
|
2035
|
+
except (AngrError, SimError):
|
|
2036
|
+
# oops there are errors
|
|
2037
|
+
l.warning("Cannot get jump successor states from a path that has reached the target. Skip it.")
|
|
2038
|
+
return None
|
|
2039
|
+
|
|
2040
|
+
all_states = succ.flat_successors + succ.unconstrained_successors
|
|
2041
|
+
if not all_states:
|
|
2042
|
+
l.warning("Slicecutor failed to execute the program slice. No output state is available.")
|
|
2043
|
+
return None
|
|
2044
|
+
|
|
2045
|
+
state = all_states[0] # Just take the first state
|
|
2046
|
+
temps = state.scratch.temps
|
|
2047
|
+
if not isinstance(ite_stmt.data, pyvex.IRExpr.ITE):
|
|
2048
|
+
return None
|
|
2049
|
+
# load the default
|
|
2050
|
+
if not isinstance(ite_stmt.data.iffalse, pyvex.IRExpr.Const):
|
|
2051
|
+
return None
|
|
2052
|
+
# ite_stmt.data.iffalse.con.value is garbage introduced by the VEX ARM lifter and should be ignored
|
|
2053
|
+
if not isinstance(ite_stmt.data.iftrue, pyvex.IRExpr.RdTmp):
|
|
2054
|
+
return None
|
|
2055
|
+
if not isinstance(ite_stmt.data.cond, pyvex.IRExpr.RdTmp):
|
|
2056
|
+
return None
|
|
2057
|
+
cond = temps[ite_stmt.data.cond.tmp]
|
|
2058
|
+
# apply the constraint
|
|
2059
|
+
state.add_constraints(cond == 1)
|
|
2060
|
+
# load the target
|
|
2061
|
+
target_expr = temps[ite_stmt.data.iftrue.tmp]
|
|
2062
|
+
try:
|
|
2063
|
+
jump_table = state.solver.eval_upto(target_expr, self._max_targets + 1)
|
|
2064
|
+
except SimError:
|
|
2065
|
+
return None
|
|
2066
|
+
entry_size = len(target_expr) // self.project.arch.byte_width
|
|
2067
|
+
|
|
2068
|
+
if len(jump_table) == self._max_targets + 1:
|
|
2069
|
+
# so many targets! failed
|
|
2070
|
+
return None
|
|
2071
|
+
|
|
2072
|
+
return jump_table, len(jump_table), entry_size
|
|
2073
|
+
|
|
2074
|
+
@staticmethod
|
|
2075
|
+
def _instrument_statements(state, stmts_to_instrument, regs_to_initialize):
|
|
2076
|
+
"""
|
|
2077
|
+
Hook statements as specified in stmts_to_instrument and overwrite values loaded in those statements.
|
|
2078
|
+
|
|
2079
|
+
:param SimState state: The program state to insert hooks to.
|
|
2080
|
+
:param list stmts_to_instrument: A list of statements to instrument.
|
|
2081
|
+
:param list regs_to_initialize: A list of registers to initialize.
|
|
2082
|
+
:return: None
|
|
2083
|
+
"""
|
|
2084
|
+
|
|
2085
|
+
for sort, block_addr, stmt_idx in stmts_to_instrument:
|
|
2086
|
+
l.debug("Add a %s hook to overwrite memory/register values at %#x:%d.", sort, block_addr, stmt_idx)
|
|
2087
|
+
if sort == "mem_write":
|
|
2088
|
+
bp = BP(
|
|
2089
|
+
when=BP_BEFORE,
|
|
2090
|
+
enabled=True,
|
|
2091
|
+
action=StoreHook.hook,
|
|
2092
|
+
condition=lambda _s, a=block_addr, idx=stmt_idx: _s.scratch.bbl_addr == a
|
|
2093
|
+
and _s.scratch.stmt_idx == idx,
|
|
2094
|
+
)
|
|
2095
|
+
state.inspect.add_breakpoint("mem_write", bp)
|
|
2096
|
+
elif sort == "mem_read":
|
|
2097
|
+
hook = LoadHook()
|
|
2098
|
+
bp0 = BP(
|
|
2099
|
+
when=BP_BEFORE,
|
|
2100
|
+
enabled=True,
|
|
2101
|
+
action=hook.hook_before,
|
|
2102
|
+
condition=lambda _s, a=block_addr, idx=stmt_idx: _s.scratch.bbl_addr == a
|
|
2103
|
+
and _s.scratch.stmt_idx == idx,
|
|
2104
|
+
)
|
|
2105
|
+
state.inspect.add_breakpoint("mem_read", bp0)
|
|
2106
|
+
bp1 = BP(
|
|
2107
|
+
when=BP_AFTER,
|
|
2108
|
+
enabled=True,
|
|
2109
|
+
action=hook.hook_after,
|
|
2110
|
+
condition=lambda _s, a=block_addr, idx=stmt_idx: _s.scratch.bbl_addr == a
|
|
2111
|
+
and _s.scratch.stmt_idx == idx,
|
|
2112
|
+
)
|
|
2113
|
+
state.inspect.add_breakpoint("mem_read", bp1)
|
|
2114
|
+
elif sort == "reg_write":
|
|
2115
|
+
bp = BP(
|
|
2116
|
+
when=BP_BEFORE,
|
|
2117
|
+
enabled=True,
|
|
2118
|
+
action=PutHook.hook,
|
|
2119
|
+
condition=lambda _s, a=block_addr, idx=stmt_idx: _s.scratch.bbl_addr == a
|
|
2120
|
+
and _s.scratch.stmt_idx == idx,
|
|
2121
|
+
)
|
|
2122
|
+
state.inspect.add_breakpoint("reg_write", bp)
|
|
2123
|
+
else:
|
|
2124
|
+
raise NotImplementedError(f"Unsupported sort {sort} in stmts_to_instrument.")
|
|
2125
|
+
|
|
2126
|
+
reg_val = 0x13370000
|
|
2127
|
+
|
|
2128
|
+
def bp_condition(block_addr, stmt_idx, _s):
|
|
2129
|
+
return _s.scratch.bbl_addr == block_addr and _s.inspect.statement == stmt_idx
|
|
2130
|
+
|
|
2131
|
+
for block_addr, stmt_idx, reg_offset, reg_bits in regs_to_initialize:
|
|
2132
|
+
l.debug(
|
|
2133
|
+
"Add a hook to initialize register %s at %x:%d.",
|
|
2134
|
+
state.arch.translate_register_name(reg_offset, size=reg_bits),
|
|
2135
|
+
block_addr,
|
|
2136
|
+
stmt_idx,
|
|
2137
|
+
)
|
|
2138
|
+
bp = BP(
|
|
2139
|
+
when=BP_BEFORE,
|
|
2140
|
+
enabled=True,
|
|
2141
|
+
action=RegisterInitializerHook(reg_offset, reg_bits, reg_val).hook,
|
|
2142
|
+
condition=functools.partial(bp_condition, block_addr, stmt_idx),
|
|
2143
|
+
)
|
|
2144
|
+
state.inspect.add_breakpoint("statement", bp)
|
|
2145
|
+
reg_val += 16
|
|
2146
|
+
|
|
2147
|
+
def _find_bss_region(self):
|
|
2148
|
+
self._bss_regions = []
|
|
2149
|
+
|
|
2150
|
+
# TODO: support other sections other than '.bss'.
|
|
2151
|
+
# TODO: this is very hackish. fix it after the chaos.
|
|
2152
|
+
for section in self.project.loader.main_object.sections:
|
|
2153
|
+
if section.name == ".bss":
|
|
2154
|
+
self._bss_regions.append((section.vaddr, section.memsize))
|
|
2155
|
+
break
|
|
2156
|
+
|
|
2157
|
+
def _init_registers_on_demand(self, state):
|
|
2158
|
+
# for uninitialized read using a register as the source address, we replace them in memory on demand
|
|
2159
|
+
read_addr = state.inspect.mem_read_address
|
|
2160
|
+
cond = state.inspect.mem_read_condition
|
|
2161
|
+
|
|
2162
|
+
if not isinstance(read_addr, int) and read_addr.has_annotation_type(UninitializedAnnotation) and cond is None:
|
|
2163
|
+
# if this AST has been initialized before, just use the cached addr
|
|
2164
|
+
cached_addr = self._cached_memread_addrs.get(read_addr, None)
|
|
2165
|
+
if cached_addr is not None:
|
|
2166
|
+
state.inspect.mem_read_address = cached_addr
|
|
2167
|
+
return
|
|
2168
|
+
|
|
2169
|
+
read_length = state.inspect.mem_read_length
|
|
2170
|
+
if not isinstance(read_length, int):
|
|
2171
|
+
read_length = read_length.args[3] # max
|
|
2172
|
+
if read_length > 16:
|
|
2173
|
+
return
|
|
2174
|
+
new_read_addr = claripy.BVV(UninitReadMeta.uninit_read_base, state.arch.bits)
|
|
2175
|
+
UninitReadMeta.uninit_read_base += read_length
|
|
2176
|
+
|
|
2177
|
+
# replace the expression in registers
|
|
2178
|
+
state.registers.replace_all(read_addr, new_read_addr)
|
|
2179
|
+
|
|
2180
|
+
# extra caution: if this read_addr AST comes up again in the future, we want to replace it with the same
|
|
2181
|
+
# address again.
|
|
2182
|
+
self._cached_memread_addrs[read_addr] = new_read_addr
|
|
2183
|
+
|
|
2184
|
+
state.inspect.mem_read_address = new_read_addr
|
|
2185
|
+
|
|
2186
|
+
# job done :-)
|
|
2187
|
+
|
|
2188
|
+
def _dbg_repr_slice(self, blade, in_slice_stmts_only=False):
|
|
2189
|
+
stmts = defaultdict(set)
|
|
2190
|
+
|
|
2191
|
+
for addr, stmt_idx in sorted(blade.slice.nodes()):
|
|
2192
|
+
stmts[addr].add(stmt_idx)
|
|
2193
|
+
|
|
2194
|
+
for addr in sorted(stmts.keys()):
|
|
2195
|
+
stmt_ids = stmts[addr]
|
|
2196
|
+
irsb = self.project.factory.block(addr, cross_insn_opt=True, backup_state=self.base_state).vex
|
|
2197
|
+
|
|
2198
|
+
print(" ####")
|
|
2199
|
+
print(f" #### Block {addr:#x}")
|
|
2200
|
+
print(" ####")
|
|
2201
|
+
|
|
2202
|
+
for i, stmt in enumerate(irsb.statements):
|
|
2203
|
+
stmt_taken = i in stmt_ids
|
|
2204
|
+
display = stmt_taken if in_slice_stmts_only else True
|
|
2205
|
+
if display:
|
|
2206
|
+
s = (
|
|
2207
|
+
f"{'+' if stmt_taken else ' '} {addr:x}:{i:02d} | "
|
|
2208
|
+
f"{stmt.pp_str(arch=self.project.arch, tyenv=irsb.tyenv)} "
|
|
2209
|
+
)
|
|
2210
|
+
if stmt_taken:
|
|
2211
|
+
s += f"IN: {blade.slice.in_degree((addr, i))}"
|
|
2212
|
+
print(s)
|
|
2213
|
+
|
|
2214
|
+
# the default exit
|
|
2215
|
+
default_exit_taken = DEFAULT_STATEMENT in stmt_ids
|
|
2216
|
+
s = "{} {:x}:default | PUT({}) = {}; {}".format(
|
|
2217
|
+
"+" if default_exit_taken else " ", addr, irsb.offsIP, irsb.next, irsb.jumpkind
|
|
2218
|
+
)
|
|
2219
|
+
print(s)
|
|
2220
|
+
|
|
2221
|
+
def _initial_state(self, block_addr, cfg, func_addr: int):
|
|
2222
|
+
add_options = {
|
|
2223
|
+
o.DO_RET_EMULATION,
|
|
2224
|
+
o.TRUE_RET_EMULATION_GUARD,
|
|
2225
|
+
o.AVOID_MULTIVALUED_READS,
|
|
2226
|
+
# Keep IP symbolic to avoid unnecessary concretization
|
|
2227
|
+
o.KEEP_IP_SYMBOLIC,
|
|
2228
|
+
o.NO_IP_CONCRETIZATION,
|
|
2229
|
+
# be quiet!!!!!!
|
|
2230
|
+
o.SYMBOL_FILL_UNCONSTRAINED_REGISTERS,
|
|
2231
|
+
o.SYMBOL_FILL_UNCONSTRAINED_MEMORY,
|
|
2232
|
+
}
|
|
2233
|
+
state = self.project.factory.blank_state(
|
|
2234
|
+
addr=block_addr,
|
|
2235
|
+
mode="static",
|
|
2236
|
+
add_options=add_options,
|
|
2237
|
+
remove_options={
|
|
2238
|
+
o.CGC_ZERO_FILL_UNCONSTRAINED_MEMORY,
|
|
2239
|
+
o.UNINITIALIZED_ACCESS_AWARENESS,
|
|
2240
|
+
}
|
|
2241
|
+
| o.refs,
|
|
2242
|
+
)
|
|
2243
|
+
state.regs._sp = 0x7FFF_FFF0
|
|
2244
|
+
|
|
2245
|
+
# any read from an uninitialized segment should be unconstrained
|
|
2246
|
+
if self._bss_regions:
|
|
2247
|
+
bss_hook = BSSHook(self.project, self._bss_regions)
|
|
2248
|
+
bss_memory_write_bp = BP(when=BP_AFTER, enabled=True, action=bss_hook.bss_memory_write_hook)
|
|
2249
|
+
state.inspect.add_breakpoint("mem_write", bss_memory_write_bp)
|
|
2250
|
+
bss_memory_read_bp = BP(when=BP_BEFORE, enabled=True, action=bss_hook.bss_memory_read_hook)
|
|
2251
|
+
state.inspect.add_breakpoint("mem_read", bss_memory_read_bp)
|
|
2252
|
+
|
|
2253
|
+
if self.project.arch.name == "MIPS32":
|
|
2254
|
+
try:
|
|
2255
|
+
func = cfg.kb.functions.get_by_addr(func_addr)
|
|
2256
|
+
if func.info and "gp" in func.info:
|
|
2257
|
+
state.regs._gp = func.info["gp"]
|
|
2258
|
+
except KeyError:
|
|
2259
|
+
pass
|
|
2260
|
+
|
|
2261
|
+
# instrument all reads from gp and all writes to gp
|
|
2262
|
+
gp = None
|
|
2263
|
+
try:
|
|
2264
|
+
func = cfg.kb.functions.get_by_addr(func_addr)
|
|
2265
|
+
if func.info and "gp" in func.info:
|
|
2266
|
+
gp = func.info["gp"]
|
|
2267
|
+
except KeyError:
|
|
2268
|
+
pass
|
|
2269
|
+
if gp is not None:
|
|
2270
|
+
mips_gp_hook = MIPSGPHook(self.project.arch.registers["gp"][0], gp)
|
|
2271
|
+
mips_gp_read_bp = BP(when=BP_AFTER, enabled=True, action=mips_gp_hook.gp_register_read_hook)
|
|
2272
|
+
mips_gp_write_bp = BP(when=BP_AFTER, enabled=True, action=mips_gp_hook.gp_register_write_hook)
|
|
2273
|
+
state.inspect.add_breakpoint("reg_read", mips_gp_read_bp)
|
|
2274
|
+
state.inspect.add_breakpoint("reg_write", mips_gp_write_bp)
|
|
2275
|
+
|
|
2276
|
+
# FIXME:
|
|
2277
|
+
# this is a hack: for certain architectures, we do not initialize the base pointer, since the jump table on
|
|
2278
|
+
# those architectures may use the bp register to store value
|
|
2279
|
+
if self.project.arch.name not in {"S390X"}:
|
|
2280
|
+
state.regs.bp = state.arch.initial_sp + 0x2000
|
|
2281
|
+
|
|
2282
|
+
return state
|
|
2283
|
+
|
|
2284
|
+
@staticmethod
|
|
2285
|
+
def _parse_load_statement(load_stmt, state):
|
|
2286
|
+
"""
|
|
2287
|
+
Parse a memory load VEX statement and get the jump target addresses.
|
|
2288
|
+
|
|
2289
|
+
:param load_stmt: The VEX statement for loading the jump target addresses.
|
|
2290
|
+
:param state: The SimState instance (in static mode).
|
|
2291
|
+
:return: An abstract value (or a concrete value) representing the jump target addresses. Return None
|
|
2292
|
+
if we fail to parse the statement.
|
|
2293
|
+
"""
|
|
2294
|
+
|
|
2295
|
+
# The jump table address is stored in a tmp. In this case, we find the jump-target loading tmp.
|
|
2296
|
+
load_addr_tmp = None
|
|
2297
|
+
|
|
2298
|
+
if isinstance(load_stmt, pyvex.IRStmt.WrTmp):
|
|
2299
|
+
assert isinstance(load_stmt.data, pyvex.IRExpr.Load)
|
|
2300
|
+
if isinstance(load_stmt.data.addr, pyvex.IRExpr.RdTmp):
|
|
2301
|
+
load_addr_tmp = load_stmt.data.addr.tmp
|
|
2302
|
+
elif isinstance(load_stmt.data.addr, pyvex.IRExpr.Const):
|
|
2303
|
+
# It's directly loading from a constant address
|
|
2304
|
+
# e.g.,
|
|
2305
|
+
# ldr r0, =main+1
|
|
2306
|
+
# blx r0
|
|
2307
|
+
# It's not a jump table, but we resolve it anyway
|
|
2308
|
+
jump_target_addr = load_stmt.data.addr.con.value
|
|
2309
|
+
return claripy.BVV(jump_target_addr, state.arch.bits)
|
|
2310
|
+
elif isinstance(load_stmt, pyvex.IRStmt.LoadG):
|
|
2311
|
+
if isinstance(load_stmt.addr, pyvex.IRExpr.RdTmp):
|
|
2312
|
+
load_addr_tmp = load_stmt.addr.tmp
|
|
2313
|
+
elif isinstance(load_stmt.addr, pyvex.IRExpr.Const):
|
|
2314
|
+
# It's directly loading from a constant address
|
|
2315
|
+
# e.g.,
|
|
2316
|
+
# 4352c SUB R1, R11, #0x1000
|
|
2317
|
+
# 43530 LDRHI R3, =loc_45450
|
|
2318
|
+
# ...
|
|
2319
|
+
# 43540 MOV PC, R3
|
|
2320
|
+
#
|
|
2321
|
+
# It's not a jump table, but we resolve it anyway
|
|
2322
|
+
# Note that this block has two branches: One goes to 45450, the other one goes to whatever the original
|
|
2323
|
+
# value of R3 is. Some intensive data-flow analysis is required in this case.
|
|
2324
|
+
jump_target_addr = load_stmt.addr.con.value
|
|
2325
|
+
return claripy.BVV(jump_target_addr, state.arch.bits)
|
|
2326
|
+
else:
|
|
2327
|
+
raise TypeError(f"Unsupported address loading statement type {type(load_stmt)}.")
|
|
2328
|
+
|
|
2329
|
+
if state.scratch.temps[load_addr_tmp] is None:
|
|
2330
|
+
# the tmp variable is not there... umm...
|
|
2331
|
+
return None
|
|
2332
|
+
|
|
2333
|
+
jump_addr = state.scratch.temps[load_addr_tmp]
|
|
2334
|
+
|
|
2335
|
+
if isinstance(load_stmt, pyvex.IRStmt.LoadG) and not isinstance(load_stmt.guard, pyvex.IRExpr.Const):
|
|
2336
|
+
# LoadG comes with a guard. We should apply this guard to the load expression
|
|
2337
|
+
assert isinstance(load_stmt.guard, pyvex.expr.RdTmp)
|
|
2338
|
+
guard_tmp = load_stmt.guard.tmp
|
|
2339
|
+
guard = state.scratch.temps[guard_tmp] != 0
|
|
2340
|
+
try:
|
|
2341
|
+
jump_addr = state.memory._apply_condition_to_symbolic_addr(jump_addr, guard)
|
|
2342
|
+
except Exception: # pylint: disable=broad-except
|
|
2343
|
+
l.exception("Error computing jump table address!")
|
|
2344
|
+
return None
|
|
2345
|
+
return jump_addr
|
|
2346
|
+
|
|
2347
|
+
def _get_secondary_jumptable_from_transformations(
|
|
2348
|
+
self, transformations: list[AddressTransformation]
|
|
2349
|
+
) -> tuple[int, int] | None:
|
|
2350
|
+
"""
|
|
2351
|
+
Find the potential secondary "jump table" from a list of transformations.
|
|
2352
|
+
|
|
2353
|
+
:param transformations: A list of address transformations.
|
|
2354
|
+
:return: A tuple of [jump_table_addr, entry_size] if a secondary jump table is found. None otherwise.
|
|
2355
|
+
"""
|
|
2356
|
+
|
|
2357
|
+
# find all add-(add-)load sequence
|
|
2358
|
+
|
|
2359
|
+
for i in range(len(transformations) - 1):
|
|
2360
|
+
prev_tran = transformations[i - 1] if i - 1 >= 0 else None
|
|
2361
|
+
tran = transformations[i]
|
|
2362
|
+
if not (
|
|
2363
|
+
tran.op == AddressTransformationTypes.Add
|
|
2364
|
+
and (prev_tran is None or prev_tran.op != AddressTransformationTypes.Add)
|
|
2365
|
+
):
|
|
2366
|
+
continue
|
|
2367
|
+
next_tran = transformations[i + 1]
|
|
2368
|
+
add_tran, load_tran = None, None
|
|
2369
|
+
if next_tran.op == AddressTransformationTypes.Load:
|
|
2370
|
+
add_tran = None
|
|
2371
|
+
load_tran = next_tran
|
|
2372
|
+
elif next_tran.op == AddressTransformationTypes.Add:
|
|
2373
|
+
next2_tran = transformations[i + 2] if i + 2 < len(transformations) else None
|
|
2374
|
+
if next2_tran is not None and next2_tran.op == AddressTransformationTypes.Load:
|
|
2375
|
+
add_tran = next_tran
|
|
2376
|
+
load_tran = next2_tran
|
|
2377
|
+
|
|
2378
|
+
if load_tran is None:
|
|
2379
|
+
continue
|
|
2380
|
+
# we have found an add-(add-)load sequence
|
|
2381
|
+
jumptable_base_addr = None
|
|
2382
|
+
if isinstance(tran.operands[0], AddressOperand) and isinstance(tran.operands[1], int):
|
|
2383
|
+
jumptable_base_addr = tran.operands[1]
|
|
2384
|
+
elif isinstance(tran.operands[1], AddressOperand) and isinstance(tran.operands[0], int):
|
|
2385
|
+
jumptable_base_addr = tran.operands[0]
|
|
2386
|
+
else:
|
|
2387
|
+
# unsupported first add
|
|
2388
|
+
continue
|
|
2389
|
+
|
|
2390
|
+
if add_tran is not None:
|
|
2391
|
+
mask = (1 << self.project.arch.bits) - 1
|
|
2392
|
+
if isinstance(add_tran.operands[0], AddressOperand) and isinstance(add_tran.operands[1], int):
|
|
2393
|
+
jumptable_base_addr = (jumptable_base_addr + add_tran.operands[1]) & mask
|
|
2394
|
+
elif isinstance(add_tran.operands[1], AddressOperand) and isinstance(add_tran.operands[0], int):
|
|
2395
|
+
jumptable_base_addr = (jumptable_base_addr + add_tran.operands[0]) & mask
|
|
2396
|
+
else:
|
|
2397
|
+
# unsupported second add
|
|
2398
|
+
continue
|
|
2399
|
+
|
|
2400
|
+
load_size = load_tran.operands[1]
|
|
2401
|
+
# we have a potential secondary jump table!
|
|
2402
|
+
return jumptable_base_addr, load_size
|
|
2403
|
+
return None
|
|
2404
|
+
|
|
2405
|
+
def _sp_moved_up(self, block) -> bool:
|
|
2406
|
+
"""
|
|
2407
|
+
Examine if the stack pointer moves up (if any values are popped out of the stack) within a single block.
|
|
2408
|
+
"""
|
|
2409
|
+
|
|
2410
|
+
spt = self.project.analyses.StackPointerTracker(
|
|
2411
|
+
None, {self.project.arch.sp_offset}, block=block, track_memory=False
|
|
2412
|
+
)
|
|
2413
|
+
offset_after = spt.offset_after(block.addr, self.project.arch.sp_offset)
|
|
2414
|
+
return offset_after is not None and offset_after > 0
|
|
2415
|
+
|
|
2416
|
+
def _is_jumptarget_legal(self, target):
|
|
2417
|
+
try:
|
|
2418
|
+
vex_block = self.project.factory.block(target, cross_insn_opt=True).vex_nostmt
|
|
2419
|
+
except (AngrError, SimError):
|
|
2420
|
+
return False
|
|
2421
|
+
if vex_block.jumpkind == "Ijk_NoDecode":
|
|
2422
|
+
return False
|
|
2423
|
+
return vex_block.size != 0
|
|
2424
|
+
|
|
2425
|
+
def _is_address_mapped(self, addr: int) -> bool:
|
|
2426
|
+
return (
|
|
2427
|
+
self.project.loader.find_segment_containing(addr) is not None
|
|
2428
|
+
or self.project.loader.find_section_containing(addr) is not None
|
|
2429
|
+
)
|
|
2430
|
+
|
|
2431
|
+
def _all_qualified_load_stmts_in_slice(self, b: Blade, addr: int) -> list[int]:
|
|
2432
|
+
"""
|
|
2433
|
+
Recognize all qualified load statements in a slice. A qualified load statements refers to those that are
|
|
2434
|
+
loading jump targets (or jump offsets) from a jump table, or loading jump table offsets from a jump-table
|
|
2435
|
+
offset table.
|
|
2436
|
+
|
|
2437
|
+
:param b: The Blade object.
|
|
2438
|
+
:param addr: Address of the last block.
|
|
2439
|
+
:return: A list of qualified load statement IDs.
|
|
2440
|
+
"""
|
|
2441
|
+
|
|
2442
|
+
stmt_ids = []
|
|
2443
|
+
for block_addr, stmt_id in b.slice.nodes:
|
|
2444
|
+
if block_addr == addr and stmt_id != DEFAULT_STATEMENT:
|
|
2445
|
+
stmt_ids.append(stmt_id)
|
|
2446
|
+
|
|
2447
|
+
if not stmt_ids:
|
|
2448
|
+
return []
|
|
2449
|
+
stmt_ids = sorted(stmt_ids)
|
|
2450
|
+
qualified_load_stmt_ids = []
|
|
2451
|
+
load_stmt_ids = []
|
|
2452
|
+
block = self.project.factory.block(addr, cross_insn_opt=True, backup_state=self.base_state).vex
|
|
2453
|
+
tmp_values = {}
|
|
2454
|
+
mask = (2**self.project.arch.bits) - 1
|
|
2455
|
+
for stmt_id in stmt_ids:
|
|
2456
|
+
stmt = block.statements[stmt_id]
|
|
2457
|
+
if isinstance(stmt, pyvex.IRStmt.WrTmp):
|
|
2458
|
+
if isinstance(stmt.data, pyvex.IRExpr.Const):
|
|
2459
|
+
tmp_values[stmt.tmp] = stmt.data.con.value
|
|
2460
|
+
elif isinstance(stmt.data, pyvex.IRExpr.Binop) and stmt.data.op.startswith("Iop_Add"):
|
|
2461
|
+
op0 = None
|
|
2462
|
+
if isinstance(stmt.data.args[0], pyvex.IRExpr.RdTmp):
|
|
2463
|
+
op0 = tmp_values.get(stmt.data.args[0].tmp, None)
|
|
2464
|
+
elif isinstance(stmt.data.args[0], pyvex.IRExpr.Const):
|
|
2465
|
+
op0 = stmt.data.args[0].con.value
|
|
2466
|
+
op1 = None
|
|
2467
|
+
if isinstance(stmt.data.args[1], pyvex.IRExpr.RdTmp):
|
|
2468
|
+
op1 = tmp_values.get(stmt.data.args[1].tmp, None)
|
|
2469
|
+
elif isinstance(stmt.data.args[1], pyvex.IRExpr.Const):
|
|
2470
|
+
op1 = stmt.data.args[1].con.value
|
|
2471
|
+
if isinstance(op1, int) and not isinstance(op0, int):
|
|
2472
|
+
op0, op1 = op1, op0
|
|
2473
|
+
if isinstance(op0, int):
|
|
2474
|
+
if op1 is None:
|
|
2475
|
+
tmp_values[stmt.tmp] = ("+", op0, op1)
|
|
2476
|
+
elif isinstance(op1, int):
|
|
2477
|
+
tmp_values[stmt.tmp] = (op0 + op1) & mask
|
|
2478
|
+
elif isinstance(op1, tuple) and op1[0] == "+":
|
|
2479
|
+
tmp_values[stmt.tmp] = ("+", (op0 + op1[1]) & mask, op1[2])
|
|
2480
|
+
elif isinstance(stmt.data, pyvex.IRExpr.Load) and isinstance(stmt.data.addr, pyvex.IRExpr.RdTmp):
|
|
2481
|
+
# is this load statement loading from a static address + an offset?
|
|
2482
|
+
v = tmp_values.get(stmt.data.addr.tmp, None)
|
|
2483
|
+
if isinstance(v, tuple) and v[0] == "+" and v[2] is None and self._is_address_mapped(v[1]):
|
|
2484
|
+
qualified_load_stmt_ids.append(stmt_id)
|
|
2485
|
+
load_stmt_ids.append(stmt_id)
|
|
2486
|
+
if qualified_load_stmt_ids and len(qualified_load_stmt_ids) <= 2:
|
|
2487
|
+
return qualified_load_stmt_ids
|
|
2488
|
+
if load_stmt_ids:
|
|
2489
|
+
return [load_stmt_ids[-1]]
|
|
2490
|
+
return []
|