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,2900 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
import logging
|
|
4
|
+
import re
|
|
5
|
+
import string
|
|
6
|
+
import struct
|
|
7
|
+
from collections import defaultdict
|
|
8
|
+
from itertools import count
|
|
9
|
+
|
|
10
|
+
import capstone
|
|
11
|
+
import cle
|
|
12
|
+
import networkx
|
|
13
|
+
import pyvex
|
|
14
|
+
|
|
15
|
+
from angr.analyses import AnalysesHub
|
|
16
|
+
from . import Analysis
|
|
17
|
+
from .cfg.cfg_emulated import CFGEmulated
|
|
18
|
+
from .ddg import DDG
|
|
19
|
+
from .cfg.cfg_fast import CFGFast
|
|
20
|
+
from angr.codenode import CodeNode
|
|
21
|
+
from angr.knowledge_plugins.cfg.memory_data import MemoryDataSort
|
|
22
|
+
from angr.knowledge_plugins.functions import Function
|
|
23
|
+
from angr.knowledge_base import KnowledgeBase
|
|
24
|
+
from angr.sim_variable import SimMemoryVariable, SimTemporaryVariable
|
|
25
|
+
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
from .cfg import CFGNode
|
|
28
|
+
|
|
29
|
+
l = logging.getLogger(name=__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# Exceptions
|
|
34
|
+
#
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class BinaryError(Exception):
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class InstructionError(BinaryError):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ReassemblerFailureNotice(BinaryError):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
#
|
|
50
|
+
# Constants
|
|
51
|
+
#
|
|
52
|
+
|
|
53
|
+
OP_TYPE_REG = 1
|
|
54
|
+
OP_TYPE_IMM = 2
|
|
55
|
+
OP_TYPE_MEM = 3
|
|
56
|
+
OP_TYPE_RAW = 4
|
|
57
|
+
|
|
58
|
+
OP_TYPE_MAP = {
|
|
59
|
+
OP_TYPE_REG: "REG",
|
|
60
|
+
OP_TYPE_IMM: "IMM",
|
|
61
|
+
OP_TYPE_MEM: "MEM",
|
|
62
|
+
OP_TYPE_RAW: "RAW",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
CAPSTONE_OP_TYPE_MAP = {
|
|
66
|
+
"X86": {
|
|
67
|
+
capstone.x86.X86_OP_REG: OP_TYPE_REG,
|
|
68
|
+
capstone.x86.X86_OP_IMM: OP_TYPE_IMM,
|
|
69
|
+
capstone.x86.X86_OP_MEM: OP_TYPE_MEM,
|
|
70
|
+
},
|
|
71
|
+
"AMD64": {
|
|
72
|
+
capstone.x86.X86_OP_REG: OP_TYPE_REG,
|
|
73
|
+
capstone.x86.X86_OP_IMM: OP_TYPE_IMM,
|
|
74
|
+
capstone.x86.X86_OP_MEM: OP_TYPE_MEM,
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
CAPSTONE_REG_MAP = {
|
|
79
|
+
# will be filled up by fill_reg_map()
|
|
80
|
+
"X86": {},
|
|
81
|
+
"AMD64": {},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# Utils
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def string_escape(s):
|
|
88
|
+
if isinstance(s, bytes):
|
|
89
|
+
s = "".join(chr(i) for i in s)
|
|
90
|
+
|
|
91
|
+
s = s.encode("unicode_escape").decode("utf-8")
|
|
92
|
+
|
|
93
|
+
s = s.replace("\\'", "'")
|
|
94
|
+
return s.replace('"', '\\"')
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def fill_reg_map():
|
|
98
|
+
# TODO: Support more architectures
|
|
99
|
+
for attr in dir(capstone.x86):
|
|
100
|
+
if attr.startswith("X86_REG_"):
|
|
101
|
+
reg_name = attr[8:]
|
|
102
|
+
reg_offset = getattr(capstone.x86, attr)
|
|
103
|
+
CAPSTONE_REG_MAP["X86"][reg_offset] = reg_name.lower()
|
|
104
|
+
|
|
105
|
+
for attr in dir(capstone.x86):
|
|
106
|
+
if attr.startswith("X86_REG_"):
|
|
107
|
+
reg_name = attr[8:]
|
|
108
|
+
reg_offset = getattr(capstone.x86, attr)
|
|
109
|
+
CAPSTONE_REG_MAP["AMD64"][reg_offset] = reg_name.lower()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def split_operands(s):
|
|
113
|
+
operands = []
|
|
114
|
+
operand = ""
|
|
115
|
+
in_parenthesis = False
|
|
116
|
+
for i, c in enumerate(s):
|
|
117
|
+
if in_parenthesis and c == ")":
|
|
118
|
+
in_parenthesis = False
|
|
119
|
+
if c == "(":
|
|
120
|
+
in_parenthesis = True
|
|
121
|
+
if not in_parenthesis and c == "," and (i == len(s) - 1 or s[i + 1] == " "):
|
|
122
|
+
operands.append(operand)
|
|
123
|
+
operand = ""
|
|
124
|
+
continue
|
|
125
|
+
operand += c
|
|
126
|
+
|
|
127
|
+
if operand:
|
|
128
|
+
operands.append(operand)
|
|
129
|
+
|
|
130
|
+
return operands
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def is_hex(s):
|
|
134
|
+
try:
|
|
135
|
+
int(s, 16)
|
|
136
|
+
return True
|
|
137
|
+
except ValueError:
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
fill_reg_map()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class Label:
|
|
145
|
+
g_label_ctr = count()
|
|
146
|
+
|
|
147
|
+
def __init__(self, binary, name, original_addr=None):
|
|
148
|
+
self.binary = binary
|
|
149
|
+
self.name = name
|
|
150
|
+
|
|
151
|
+
self.assigned = False
|
|
152
|
+
|
|
153
|
+
self.var_size = None
|
|
154
|
+
|
|
155
|
+
if self.name is None:
|
|
156
|
+
self.name = f"label_{next(Label.g_label_ctr)}"
|
|
157
|
+
|
|
158
|
+
self.original_addr = original_addr
|
|
159
|
+
self.base_addr = None
|
|
160
|
+
|
|
161
|
+
#
|
|
162
|
+
# Overridden predefined methods
|
|
163
|
+
#
|
|
164
|
+
|
|
165
|
+
def __str__(self):
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
:return:
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
# if self.var_size is not None:
|
|
172
|
+
# s = ".type {name},@object\n.comm {name},{size},{size}".format(name=self.name, size=self.var_size)
|
|
173
|
+
# else:
|
|
174
|
+
return f".{self.name}:"
|
|
175
|
+
|
|
176
|
+
def __hash__(self):
|
|
177
|
+
return hash(self.name)
|
|
178
|
+
|
|
179
|
+
def __eq__(self, other):
|
|
180
|
+
return self.name == other.name
|
|
181
|
+
|
|
182
|
+
#
|
|
183
|
+
# Properties
|
|
184
|
+
#
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def operand_str(self):
|
|
188
|
+
if self.base_addr is None:
|
|
189
|
+
return f".{self.name}"
|
|
190
|
+
offset = self.offset
|
|
191
|
+
sign = "+" if offset >= 0 else "-"
|
|
192
|
+
offset = abs(offset)
|
|
193
|
+
return f".{self.name}{sign}{offset}"
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def offset(self):
|
|
197
|
+
if self.base_addr is None:
|
|
198
|
+
return 0
|
|
199
|
+
return self.original_addr - self.base_addr
|
|
200
|
+
|
|
201
|
+
#
|
|
202
|
+
# Static methods
|
|
203
|
+
#
|
|
204
|
+
|
|
205
|
+
@staticmethod
|
|
206
|
+
def new_label(binary, name=None, function_name=None, original_addr=None, data_label=False):
|
|
207
|
+
if function_name is not None:
|
|
208
|
+
return FunctionLabel(binary, function_name, original_addr)
|
|
209
|
+
if data_label:
|
|
210
|
+
return DataLabel(binary, original_addr)
|
|
211
|
+
return Label(binary, name, original_addr=original_addr)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class DataLabel(Label):
|
|
215
|
+
def __init__(self, binary, original_addr, name=None):
|
|
216
|
+
Label.__init__(self, binary, name, original_addr=original_addr)
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def operand_str(self):
|
|
220
|
+
if self.base_addr is None:
|
|
221
|
+
return self.name
|
|
222
|
+
offset = self.offset
|
|
223
|
+
sign = "+" if offset >= 0 else "-"
|
|
224
|
+
offset = abs(offset)
|
|
225
|
+
return f"({self.name}{sign}{offset})"
|
|
226
|
+
|
|
227
|
+
def __str__(self):
|
|
228
|
+
# if self.var_size is not None:
|
|
229
|
+
# s = ".comm {name},{size},{size}".format(name=self.name, size=self.var_size)
|
|
230
|
+
# else:
|
|
231
|
+
return f"{self.name}:"
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class FunctionLabel(Label):
|
|
235
|
+
def __init__(self, binary, function_name, original_addr, plt=False):
|
|
236
|
+
Label.__init__(self, binary, function_name, original_addr=original_addr)
|
|
237
|
+
|
|
238
|
+
self.plt = plt
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def function_name(self):
|
|
242
|
+
return self.name
|
|
243
|
+
|
|
244
|
+
@property
|
|
245
|
+
def operand_str(self):
|
|
246
|
+
return self.name
|
|
247
|
+
|
|
248
|
+
def __str__(self):
|
|
249
|
+
return ("\t.globl {func_name}\n" + "\t.type {func_name}, @function\n" + "{func_name}:").format(
|
|
250
|
+
func_name=self.function_name
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class ObjectLabel(Label):
|
|
255
|
+
def __init__(self, binary, symbol_name, original_addr, plt=False):
|
|
256
|
+
Label.__init__(self, binary, symbol_name, original_addr=original_addr)
|
|
257
|
+
|
|
258
|
+
self.plt = plt
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def symbol_name(self):
|
|
262
|
+
return self.name
|
|
263
|
+
|
|
264
|
+
@property
|
|
265
|
+
def operand_str(self):
|
|
266
|
+
return self.name
|
|
267
|
+
|
|
268
|
+
def __str__(self):
|
|
269
|
+
return ("\t.globl {symbol_name}\n" + "\t.type {symbol_name}, @object\n" + "{symbol_name}:").format(
|
|
270
|
+
symbol_name=self.symbol_name
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
class NotypeLabel(Label):
|
|
275
|
+
def __init__(self, binary, symbol_name, original_addr, plt=False):
|
|
276
|
+
Label.__init__(self, binary, symbol_name, original_addr=original_addr)
|
|
277
|
+
|
|
278
|
+
self.plt = plt
|
|
279
|
+
|
|
280
|
+
@property
|
|
281
|
+
def symbol_name(self):
|
|
282
|
+
return self.name
|
|
283
|
+
|
|
284
|
+
@property
|
|
285
|
+
def operand_str(self):
|
|
286
|
+
return self.name
|
|
287
|
+
|
|
288
|
+
def __str__(self):
|
|
289
|
+
return ("\t.globl {symbol_name}\n" + "\t.type {symbol_name}, @notype\n" + "{symbol_name}:").format(
|
|
290
|
+
symbol_name=self.symbol_name
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class SymbolManager:
|
|
295
|
+
"""
|
|
296
|
+
SymbolManager manages all symbols in the binary.
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
def __init__(self, binary, cfg):
|
|
300
|
+
"""
|
|
301
|
+
Constructor.
|
|
302
|
+
|
|
303
|
+
:param Reassembler binary: The Binary analysis instance.
|
|
304
|
+
:param angr.analyses.CFG cfg: The CFG analysis instance.
|
|
305
|
+
:return: None
|
|
306
|
+
"""
|
|
307
|
+
|
|
308
|
+
self.binary = binary
|
|
309
|
+
self.project = binary.project
|
|
310
|
+
self.cfg = cfg
|
|
311
|
+
|
|
312
|
+
self.addr_to_label = defaultdict(list)
|
|
313
|
+
self.symbol_names = set() # deduplicate symbol names
|
|
314
|
+
|
|
315
|
+
def get_unique_symbol_name(self, symbol_name):
|
|
316
|
+
if symbol_name not in self.symbol_names:
|
|
317
|
+
self.symbol_names.add(symbol_name)
|
|
318
|
+
return symbol_name
|
|
319
|
+
|
|
320
|
+
i = 0
|
|
321
|
+
while True:
|
|
322
|
+
name = f"{symbol_name}_{i}"
|
|
323
|
+
if name not in self.symbol_names:
|
|
324
|
+
self.symbol_names.add(name)
|
|
325
|
+
return name
|
|
326
|
+
i += 1
|
|
327
|
+
|
|
328
|
+
def new_label(self, addr, name=None, is_function=None, force=False):
|
|
329
|
+
if force:
|
|
330
|
+
if self.binary.main_nonexecutable_regions_contain(addr):
|
|
331
|
+
label = DataLabel(self.binary, addr, name=name)
|
|
332
|
+
else:
|
|
333
|
+
label = Label.new_label(self.binary, name=name, original_addr=addr)
|
|
334
|
+
self.addr_to_label[addr].append(label)
|
|
335
|
+
return label
|
|
336
|
+
|
|
337
|
+
if addr in self.addr_to_label:
|
|
338
|
+
return self.addr_to_label[addr][0]
|
|
339
|
+
|
|
340
|
+
# Check if the address points to a function by checking the plt of main binary
|
|
341
|
+
reverse_plt = self.project.loader.main_object.reverse_plt
|
|
342
|
+
|
|
343
|
+
if addr in reverse_plt:
|
|
344
|
+
# It's a PLT entry!
|
|
345
|
+
label = FunctionLabel(self.binary, reverse_plt[addr], addr, plt=True)
|
|
346
|
+
elif addr is not None and self.project.loader.find_symbol(addr) is not None:
|
|
347
|
+
# It's an extern symbol
|
|
348
|
+
symbol = self.project.loader.find_symbol(addr)
|
|
349
|
+
if symbol.owner is self.project.loader.main_object:
|
|
350
|
+
symbol_name = symbol.name
|
|
351
|
+
if "@" in symbol_name:
|
|
352
|
+
symbol_name = symbol_name[: symbol_name.index("@")]
|
|
353
|
+
|
|
354
|
+
# check the type...
|
|
355
|
+
if symbol.type == cle.SymbolType.TYPE_FUNCTION:
|
|
356
|
+
# it's a function!
|
|
357
|
+
unique_symbol_name = self.get_unique_symbol_name(symbol_name)
|
|
358
|
+
label = FunctionLabel(self.binary, unique_symbol_name, addr)
|
|
359
|
+
elif symbol.type == cle.SymbolType.TYPE_OBJECT:
|
|
360
|
+
# it's an object
|
|
361
|
+
unique_symbol_name = self.get_unique_symbol_name(symbol_name)
|
|
362
|
+
label = ObjectLabel(self.binary, unique_symbol_name, addr)
|
|
363
|
+
elif symbol.type == cle.SymbolType.TYPE_NONE:
|
|
364
|
+
# notype
|
|
365
|
+
unique_symbol_name = self.get_unique_symbol_name(symbol_name)
|
|
366
|
+
label = NotypeLabel(self.binary, unique_symbol_name, addr)
|
|
367
|
+
elif symbol.type == cle.SymbolType.TYPE_SECTION:
|
|
368
|
+
# section label
|
|
369
|
+
# use a normal label instead
|
|
370
|
+
if not name:
|
|
371
|
+
# handle empty names
|
|
372
|
+
name = None
|
|
373
|
+
label = Label.new_label(self.binary, name=name, original_addr=addr)
|
|
374
|
+
else:
|
|
375
|
+
raise Exception(f"Unsupported symbol type {symbol.type}. Bug Fish about it!")
|
|
376
|
+
|
|
377
|
+
else:
|
|
378
|
+
raise Exception(
|
|
379
|
+
f"the symbol {symbol.name} is not owned by the main object. Try reload the project with"
|
|
380
|
+
'"auto_load_libs=False". If that does not solve the issue, please report to GitHub.'
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
elif (addr is not None and addr in self.cfg.functions) or is_function:
|
|
384
|
+
# It's a function identified by angr's CFG recovery
|
|
385
|
+
|
|
386
|
+
if is_function and name is not None:
|
|
387
|
+
function_name = name
|
|
388
|
+
else:
|
|
389
|
+
function_name = self.cfg.functions[addr].name
|
|
390
|
+
|
|
391
|
+
# special function name for entry point
|
|
392
|
+
if addr == self.project.entry:
|
|
393
|
+
function_name = "_start"
|
|
394
|
+
|
|
395
|
+
label = FunctionLabel(self.binary, function_name, addr)
|
|
396
|
+
elif addr is not None and self.binary.main_nonexecutable_regions_contain(addr):
|
|
397
|
+
label = DataLabel(self.binary, addr)
|
|
398
|
+
else:
|
|
399
|
+
label = Label.new_label(self.binary, name=name, original_addr=addr)
|
|
400
|
+
|
|
401
|
+
if addr is not None:
|
|
402
|
+
self.addr_to_label[addr].append(label)
|
|
403
|
+
|
|
404
|
+
return label
|
|
405
|
+
|
|
406
|
+
def label_got(self, addr, label):
|
|
407
|
+
"""
|
|
408
|
+
Mark a certain label as assigned (to an instruction or a block of data).
|
|
409
|
+
|
|
410
|
+
:param int addr: The address of the label.
|
|
411
|
+
:param angr.analyses.reassembler.Label label:
|
|
412
|
+
The label that is just assigned.
|
|
413
|
+
:return: None
|
|
414
|
+
"""
|
|
415
|
+
|
|
416
|
+
if label in self.addr_to_label[addr]:
|
|
417
|
+
label.assigned = True
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
class Operand:
|
|
421
|
+
def __init__(
|
|
422
|
+
self, binary, insn_addr, insn_size, capstone_operand, operand_str, mnemonic, operand_offset, syntax=None
|
|
423
|
+
):
|
|
424
|
+
"""
|
|
425
|
+
Constructor.
|
|
426
|
+
|
|
427
|
+
:param Reassembler binary: The Binary analysis.
|
|
428
|
+
:param int insn_addr: Address of the instruction.
|
|
429
|
+
:param capstone_operand:
|
|
430
|
+
:param str operand_str: the string representation of this operand
|
|
431
|
+
:param str mnemonic: Mnemonic of the instruction that this operand belongs to.
|
|
432
|
+
:param int operand_offset: offset of the operand into the instruction.
|
|
433
|
+
:param str syntax: Provide a way to override the default syntax coming from `binary`.
|
|
434
|
+
:return: None
|
|
435
|
+
"""
|
|
436
|
+
|
|
437
|
+
self.binary = binary
|
|
438
|
+
self.project = binary.project
|
|
439
|
+
self.insn_addr = insn_addr
|
|
440
|
+
self.insn_size = insn_size
|
|
441
|
+
self.operand_str = operand_str
|
|
442
|
+
self.mnemonic = mnemonic
|
|
443
|
+
self.operand_offset = operand_offset
|
|
444
|
+
self.syntax = self.binary.syntax if syntax is None else syntax
|
|
445
|
+
self.type = None
|
|
446
|
+
self.size = capstone_operand.size
|
|
447
|
+
|
|
448
|
+
# IMM
|
|
449
|
+
self.is_coderef = None
|
|
450
|
+
self.is_dataref = None
|
|
451
|
+
self.label = None
|
|
452
|
+
self.label_offset = 0
|
|
453
|
+
|
|
454
|
+
# MEM
|
|
455
|
+
self.base = None
|
|
456
|
+
self.index = None
|
|
457
|
+
self.scale = None
|
|
458
|
+
self.disp = None
|
|
459
|
+
|
|
460
|
+
# RAW
|
|
461
|
+
self.raw_asm = None
|
|
462
|
+
|
|
463
|
+
self.disp_is_coderef = None
|
|
464
|
+
self.disp_is_dataref = None
|
|
465
|
+
self.disp_label = None
|
|
466
|
+
self.disp_label_offset = 0
|
|
467
|
+
|
|
468
|
+
self._initialize(capstone_operand)
|
|
469
|
+
|
|
470
|
+
#
|
|
471
|
+
# Public methods
|
|
472
|
+
#
|
|
473
|
+
|
|
474
|
+
def assembly(self):
|
|
475
|
+
if self.type == OP_TYPE_IMM and self.label:
|
|
476
|
+
if self.label_offset > 0:
|
|
477
|
+
return f"{self.label.operand_str} + {self.label_offset}"
|
|
478
|
+
if self.label_offset < 0:
|
|
479
|
+
return f"{self.label.operand_str} - {abs(self.label_offset)}"
|
|
480
|
+
return self.label.operand_str
|
|
481
|
+
|
|
482
|
+
if self.type == OP_TYPE_MEM:
|
|
483
|
+
disp = ""
|
|
484
|
+
if self.disp:
|
|
485
|
+
if self.disp_label:
|
|
486
|
+
if self.disp_label_offset > 0:
|
|
487
|
+
disp = f"{self.disp_label.operand_str} + {self.disp_label_offset}"
|
|
488
|
+
elif self.disp_label_offset < 0:
|
|
489
|
+
disp = f"{self.disp_label.operand_str} - {abs(self.disp_label_offset)}"
|
|
490
|
+
else:
|
|
491
|
+
disp = self.disp_label.operand_str
|
|
492
|
+
else:
|
|
493
|
+
disp = f"{self.disp}"
|
|
494
|
+
|
|
495
|
+
base = ""
|
|
496
|
+
if self.base:
|
|
497
|
+
base = CAPSTONE_REG_MAP[self.project.arch.name][self.base]
|
|
498
|
+
|
|
499
|
+
if self.syntax == "at&t":
|
|
500
|
+
# displacement(base, index, scale)
|
|
501
|
+
base = f"%{base}" if base else ""
|
|
502
|
+
|
|
503
|
+
if "*" in self.operand_str and disp:
|
|
504
|
+
# absolute memory address
|
|
505
|
+
disp = "*" + disp
|
|
506
|
+
|
|
507
|
+
if self.index:
|
|
508
|
+
s = f"{disp}({base}, %{CAPSTONE_REG_MAP[self.project.arch.name][self.index]}, {self.scale})"
|
|
509
|
+
elif self.base: # not self.index
|
|
510
|
+
s = f"{disp}({base})"
|
|
511
|
+
else:
|
|
512
|
+
s = disp
|
|
513
|
+
|
|
514
|
+
return s
|
|
515
|
+
|
|
516
|
+
s = []
|
|
517
|
+
if base:
|
|
518
|
+
s.append(base)
|
|
519
|
+
|
|
520
|
+
if self.index and self.scale:
|
|
521
|
+
if s:
|
|
522
|
+
s.append("+")
|
|
523
|
+
s.append(f"({CAPSTONE_REG_MAP[self.project.arch.name][self.index]} * {self.scale})")
|
|
524
|
+
|
|
525
|
+
if disp:
|
|
526
|
+
if disp.startswith("-"):
|
|
527
|
+
s.append("-")
|
|
528
|
+
s.append(disp[1:])
|
|
529
|
+
else:
|
|
530
|
+
if s:
|
|
531
|
+
s.append("+")
|
|
532
|
+
s.append(disp)
|
|
533
|
+
|
|
534
|
+
asm = " ".join(s)
|
|
535
|
+
|
|
536
|
+
# we need to specify the size here
|
|
537
|
+
if self.size == 16:
|
|
538
|
+
asm = f"xmmword ptr [{asm}]"
|
|
539
|
+
elif self.size == 10:
|
|
540
|
+
asm = f"xword ptr [{asm}]"
|
|
541
|
+
elif self.size == 8:
|
|
542
|
+
asm = f"qword ptr [{asm}]"
|
|
543
|
+
elif self.size == 4:
|
|
544
|
+
asm = f"dword ptr [{asm}]"
|
|
545
|
+
elif self.size == 2:
|
|
546
|
+
asm = f"word ptr [{asm}]"
|
|
547
|
+
elif self.size == 1:
|
|
548
|
+
asm = f"byte ptr [{asm}]"
|
|
549
|
+
else:
|
|
550
|
+
raise BinaryError(f'Unsupported memory operand size for operand "{self.operand_str}"')
|
|
551
|
+
|
|
552
|
+
return asm
|
|
553
|
+
|
|
554
|
+
if self.type == OP_TYPE_RAW:
|
|
555
|
+
return self.raw_asm
|
|
556
|
+
|
|
557
|
+
# Nothing special
|
|
558
|
+
return None
|
|
559
|
+
|
|
560
|
+
#
|
|
561
|
+
# Overridden predefined methods
|
|
562
|
+
#
|
|
563
|
+
|
|
564
|
+
def __str__(self):
|
|
565
|
+
"""
|
|
566
|
+
|
|
567
|
+
:return:
|
|
568
|
+
"""
|
|
569
|
+
|
|
570
|
+
op_type = OP_TYPE_MAP[self.type]
|
|
571
|
+
|
|
572
|
+
ref_type = ""
|
|
573
|
+
if self.is_coderef:
|
|
574
|
+
ref_type = "CODEREF"
|
|
575
|
+
elif self.is_dataref:
|
|
576
|
+
ref_type = "DATAREF"
|
|
577
|
+
|
|
578
|
+
if ref_type:
|
|
579
|
+
return f"{op_type} <{ref_type}>"
|
|
580
|
+
return op_type
|
|
581
|
+
|
|
582
|
+
#
|
|
583
|
+
# Properties
|
|
584
|
+
#
|
|
585
|
+
|
|
586
|
+
@property
|
|
587
|
+
def is_immediate(self):
|
|
588
|
+
return self.type == OP_TYPE_IMM
|
|
589
|
+
|
|
590
|
+
@property
|
|
591
|
+
def symbolized(self):
|
|
592
|
+
return self.label is not None or self.disp_label is not None
|
|
593
|
+
|
|
594
|
+
#
|
|
595
|
+
# Private methods
|
|
596
|
+
#
|
|
597
|
+
|
|
598
|
+
def _initialize(self, capstone_operand):
|
|
599
|
+
arch_name = self.project.arch.name
|
|
600
|
+
self.type = CAPSTONE_OP_TYPE_MAP[arch_name][capstone_operand.type]
|
|
601
|
+
|
|
602
|
+
if self.type == OP_TYPE_IMM:
|
|
603
|
+
# Check if this is a reference to code
|
|
604
|
+
imm = capstone_operand.imm
|
|
605
|
+
|
|
606
|
+
self.is_coderef, self.is_dataref, baseaddr = self._imm_to_ptr(imm, self.type, self.mnemonic)
|
|
607
|
+
|
|
608
|
+
if self.is_coderef or self.is_dataref:
|
|
609
|
+
self.label = self.binary.symbol_manager.new_label(addr=baseaddr)
|
|
610
|
+
self.label_offset = imm - baseaddr
|
|
611
|
+
|
|
612
|
+
if self.mnemonic.startswith("j") or self.mnemonic.startswith("loop"):
|
|
613
|
+
sort = "jump"
|
|
614
|
+
elif self.mnemonic.startswith("call"):
|
|
615
|
+
sort = "call"
|
|
616
|
+
else:
|
|
617
|
+
sort = "absolute"
|
|
618
|
+
self.binary.register_instruction_reference(self.insn_addr, imm, sort, self.operand_offset)
|
|
619
|
+
|
|
620
|
+
elif self.type == OP_TYPE_MEM:
|
|
621
|
+
self.base = capstone_operand.mem.base
|
|
622
|
+
self.index = capstone_operand.mem.index
|
|
623
|
+
self.scale = capstone_operand.mem.scale
|
|
624
|
+
self.disp = capstone_operand.mem.disp
|
|
625
|
+
|
|
626
|
+
if self.binary.project.arch.name == "AMD64" and CAPSTONE_REG_MAP["AMD64"][self.base] == "rip":
|
|
627
|
+
# rip-relative addressing
|
|
628
|
+
self.disp += self.insn_addr + self.insn_size
|
|
629
|
+
|
|
630
|
+
self.disp_is_coderef, self.disp_is_dataref, baseaddr = self._imm_to_ptr(self.disp, self.type, self.mnemonic)
|
|
631
|
+
|
|
632
|
+
if self.disp_is_coderef or self.disp_is_dataref:
|
|
633
|
+
self.disp_label = self.binary.symbol_manager.new_label(addr=baseaddr)
|
|
634
|
+
self.disp_label_offset = self.disp - baseaddr
|
|
635
|
+
|
|
636
|
+
self.binary.register_instruction_reference(self.insn_addr, self.disp, "absolute", self.operand_offset)
|
|
637
|
+
|
|
638
|
+
def _imm_to_ptr(self, imm, operand_type, mnemonic): # pylint:disable=no-self-use,unused-argument
|
|
639
|
+
"""
|
|
640
|
+
Try to classify an immediate as a pointer.
|
|
641
|
+
|
|
642
|
+
:param int imm: The immediate to test.
|
|
643
|
+
:param int operand_type: Operand type of this operand, can either be IMM or MEM.
|
|
644
|
+
:param str mnemonic: Mnemonic of the instruction that this operand belongs to.
|
|
645
|
+
:return: A tuple of (is code reference, is data reference, base address, offset)
|
|
646
|
+
:rtype: tuple
|
|
647
|
+
"""
|
|
648
|
+
|
|
649
|
+
is_coderef, is_dataref = False, False
|
|
650
|
+
baseaddr = None
|
|
651
|
+
|
|
652
|
+
if (
|
|
653
|
+
not is_coderef
|
|
654
|
+
and not is_dataref
|
|
655
|
+
and self.binary.main_executable_regions_contain(imm)
|
|
656
|
+
# does it point to the beginning of an instruction?
|
|
657
|
+
and imm in self.binary.all_insn_addrs
|
|
658
|
+
):
|
|
659
|
+
is_coderef = True
|
|
660
|
+
baseaddr = imm
|
|
661
|
+
|
|
662
|
+
if not is_coderef and not is_dataref and self.binary.main_nonexecutable_regions_contain(imm):
|
|
663
|
+
is_dataref = True
|
|
664
|
+
baseaddr = imm
|
|
665
|
+
|
|
666
|
+
if not is_coderef and not is_dataref:
|
|
667
|
+
tolerance_before = 1024 if operand_type == OP_TYPE_MEM else 64
|
|
668
|
+
contains_, baseaddr_ = self.binary.main_nonexecutable_region_limbos_contain(
|
|
669
|
+
imm, tolerance_before=tolerance_before, tolerance_after=1024
|
|
670
|
+
)
|
|
671
|
+
if contains_:
|
|
672
|
+
is_dataref = True
|
|
673
|
+
baseaddr = baseaddr_
|
|
674
|
+
|
|
675
|
+
if not contains_:
|
|
676
|
+
contains_, baseaddr_ = self.binary.main_executable_region_limbos_contain(imm)
|
|
677
|
+
if contains_:
|
|
678
|
+
is_coderef = True
|
|
679
|
+
baseaddr = baseaddr_
|
|
680
|
+
|
|
681
|
+
return (is_coderef, is_dataref, baseaddr)
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
class Instruction:
|
|
685
|
+
"""
|
|
686
|
+
High-level representation of an instruction in the binary
|
|
687
|
+
"""
|
|
688
|
+
|
|
689
|
+
def __init__(self, binary, addr, size, insn_bytes, capstone_instr):
|
|
690
|
+
"""
|
|
691
|
+
|
|
692
|
+
:param Reassembler binary: The Binary analysis
|
|
693
|
+
:param int addr: Address of the instruction
|
|
694
|
+
:param int size: Size of the instruction
|
|
695
|
+
:param str insn_bytes: Instruction bytes
|
|
696
|
+
:param capstone_instr: Capstone Instr object.
|
|
697
|
+
:return: None
|
|
698
|
+
"""
|
|
699
|
+
|
|
700
|
+
self.binary = binary
|
|
701
|
+
self.project = binary.project
|
|
702
|
+
self.addr = addr
|
|
703
|
+
self.size = size
|
|
704
|
+
self.bytes = insn_bytes
|
|
705
|
+
|
|
706
|
+
self.mnemonic = capstone_instr.mnemonic
|
|
707
|
+
self.op_str = capstone_instr.op_str
|
|
708
|
+
self.capstone_operand_types = [operand.type for operand in capstone_instr.operands]
|
|
709
|
+
|
|
710
|
+
self.operands = []
|
|
711
|
+
|
|
712
|
+
self.labels = []
|
|
713
|
+
|
|
714
|
+
operand_offsets = []
|
|
715
|
+
for operand in capstone_instr.operands:
|
|
716
|
+
if operand.type == capstone.CS_OP_IMM:
|
|
717
|
+
operand_offsets.append(capstone_instr.imm_offset)
|
|
718
|
+
elif operand.type == capstone.CS_OP_MEM:
|
|
719
|
+
operand_offsets.append(capstone_instr.disp_offset)
|
|
720
|
+
else:
|
|
721
|
+
operand_offsets.append(0)
|
|
722
|
+
|
|
723
|
+
if self.addr is not None:
|
|
724
|
+
self._initialize(capstone_instr.operands, operand_offsets)
|
|
725
|
+
|
|
726
|
+
#
|
|
727
|
+
# Overridden predefined instructions
|
|
728
|
+
#
|
|
729
|
+
def __str__(self):
|
|
730
|
+
"""
|
|
731
|
+
|
|
732
|
+
:return:
|
|
733
|
+
"""
|
|
734
|
+
|
|
735
|
+
return self.assembly(comments=True, symbolized=False)
|
|
736
|
+
|
|
737
|
+
#
|
|
738
|
+
# Public methods
|
|
739
|
+
#
|
|
740
|
+
|
|
741
|
+
def assign_labels(self):
|
|
742
|
+
if self.addr in self.binary.symbol_manager.addr_to_label:
|
|
743
|
+
labels = self.binary.symbol_manager.addr_to_label[self.addr]
|
|
744
|
+
for label in labels:
|
|
745
|
+
if label not in self.labels:
|
|
746
|
+
self.labels.append(label)
|
|
747
|
+
|
|
748
|
+
def dbg_comments(self):
|
|
749
|
+
operands = ", ".join([str(operand) for operand in self.operands])
|
|
750
|
+
capstone_str = f"{self.addr:#08x}:\t{self.mnemonic}\t{self.op_str}"
|
|
751
|
+
return f"\t# {capstone_str} [{operands}]"
|
|
752
|
+
|
|
753
|
+
def assembly(self, comments=False, symbolized=True):
|
|
754
|
+
"""
|
|
755
|
+
|
|
756
|
+
:return:
|
|
757
|
+
"""
|
|
758
|
+
|
|
759
|
+
dbg_comments = self.dbg_comments() if comments else ""
|
|
760
|
+
|
|
761
|
+
labels = "\n".join([str(lbl) for lbl in self.labels])
|
|
762
|
+
|
|
763
|
+
inserted_asm_before_label = ""
|
|
764
|
+
if self.addr in self.binary.inserted_asm_before_label:
|
|
765
|
+
# put all assembly code there
|
|
766
|
+
if comments:
|
|
767
|
+
inserted_asm_before_label += "\t# Inserted assembly code (before label):\n"
|
|
768
|
+
inserted_asm_before_label = "\n".join(self.binary.inserted_asm_before_label[self.addr])
|
|
769
|
+
inserted_asm_before_label += "\n"
|
|
770
|
+
|
|
771
|
+
inserted_asm_after_label = ""
|
|
772
|
+
if self.addr in self.binary.inserted_asm_after_label:
|
|
773
|
+
# put all assembly code there
|
|
774
|
+
if comments:
|
|
775
|
+
inserted_asm_after_label += "\t# Inserted assembly code (after label):\n"
|
|
776
|
+
inserted_asm_after_label = "\n".join(self.binary.inserted_asm_after_label[self.addr])
|
|
777
|
+
inserted_asm_after_label += "\n"
|
|
778
|
+
|
|
779
|
+
not_symbolized = f"\t{self.mnemonic}\t{self.op_str}"
|
|
780
|
+
if not symbolized:
|
|
781
|
+
asm = not_symbolized
|
|
782
|
+
|
|
783
|
+
elif not any((operand.symbolized or operand.type == OP_TYPE_RAW) for operand in self.operands):
|
|
784
|
+
# No label is involved
|
|
785
|
+
asm = not_symbolized
|
|
786
|
+
|
|
787
|
+
elif not self.operands:
|
|
788
|
+
# There is no operand
|
|
789
|
+
asm = not_symbolized
|
|
790
|
+
|
|
791
|
+
else:
|
|
792
|
+
# Now it's the tricky part. capstone doesn't give us anyway to print individual operand. We gotta parse it
|
|
793
|
+
# by ourselves
|
|
794
|
+
# Remove the address
|
|
795
|
+
# capstone_str = capstone_str[capstone_str.find('\t') + 1 : ]
|
|
796
|
+
|
|
797
|
+
all_operands = [operand.operand_str for operand in self.operands]
|
|
798
|
+
mnemonic = self.mnemonic
|
|
799
|
+
|
|
800
|
+
for i, op in enumerate(self.operands):
|
|
801
|
+
op_asm = op.assembly()
|
|
802
|
+
if op_asm is not None:
|
|
803
|
+
if op.type in (OP_TYPE_IMM, OP_TYPE_MEM, OP_TYPE_RAW):
|
|
804
|
+
all_operands[i] = op_asm
|
|
805
|
+
else:
|
|
806
|
+
raise BinaryError(f"Unsupported operand type {op.type}.")
|
|
807
|
+
|
|
808
|
+
if op.type != OP_TYPE_RAW and self.capstone_operand_types[i] == capstone.CS_OP_IMM:
|
|
809
|
+
if mnemonic.startswith(("j", "call", "loop")):
|
|
810
|
+
pass
|
|
811
|
+
else:
|
|
812
|
+
# mark the size of the variable
|
|
813
|
+
if op.is_dataref:
|
|
814
|
+
op.label.var_size = op.size
|
|
815
|
+
if self.binary.syntax == "at&t":
|
|
816
|
+
all_operands[i] = "$" + all_operands[i]
|
|
817
|
+
else:
|
|
818
|
+
all_operands[i] = "OFFSET FLAT:" + all_operands[i]
|
|
819
|
+
|
|
820
|
+
asm = "\t{}{}".format(mnemonic, "\t" + ", ".join(all_operands))
|
|
821
|
+
|
|
822
|
+
if self.addr in self.binary._removed_instructions:
|
|
823
|
+
contents = [dbg_comments, inserted_asm_before_label, labels, inserted_asm_after_label]
|
|
824
|
+
else:
|
|
825
|
+
contents = [dbg_comments, inserted_asm_before_label, labels, inserted_asm_after_label, asm]
|
|
826
|
+
contents = [a for a in contents if a]
|
|
827
|
+
|
|
828
|
+
return "\n".join(contents)
|
|
829
|
+
|
|
830
|
+
#
|
|
831
|
+
# Private methods
|
|
832
|
+
#
|
|
833
|
+
|
|
834
|
+
def _initialize(self, capstone_operands, operand_offsets):
|
|
835
|
+
"""
|
|
836
|
+
Initialize this object
|
|
837
|
+
|
|
838
|
+
:return: None
|
|
839
|
+
"""
|
|
840
|
+
|
|
841
|
+
if self.addr is None:
|
|
842
|
+
raise InstructionError("self.addr must be specified")
|
|
843
|
+
|
|
844
|
+
self._initialize_operands(capstone_operands, operand_offsets)
|
|
845
|
+
|
|
846
|
+
def _initialize_operands(self, capstone_operands, operand_offsets):
|
|
847
|
+
"""
|
|
848
|
+
|
|
849
|
+
:return:
|
|
850
|
+
"""
|
|
851
|
+
|
|
852
|
+
all_operands = split_operands(self.op_str)
|
|
853
|
+
capstone_operands = capstone_operands[
|
|
854
|
+
-len(all_operands) :
|
|
855
|
+
] # sometimes there are more operands than expected...
|
|
856
|
+
operand_offsets = operand_offsets[-len(all_operands) :]
|
|
857
|
+
|
|
858
|
+
for operand, operand_str, offset in zip(capstone_operands, all_operands, operand_offsets):
|
|
859
|
+
self.operands.append(
|
|
860
|
+
Operand(self.binary, self.addr, self.size, operand, operand_str, self.mnemonic, offset)
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
class BasicBlock:
|
|
865
|
+
"""
|
|
866
|
+
BasicBlock represents a basic block in the binary.
|
|
867
|
+
"""
|
|
868
|
+
|
|
869
|
+
def __init__(self, binary, addr, size, x86_getpc_retsite: bool = False):
|
|
870
|
+
"""
|
|
871
|
+
Constructor.
|
|
872
|
+
|
|
873
|
+
:param Reassembler binary: The Binary analysis.
|
|
874
|
+
:param int addr: Address of the block
|
|
875
|
+
:param int size: Size of the block
|
|
876
|
+
:return: None
|
|
877
|
+
"""
|
|
878
|
+
|
|
879
|
+
self.binary = binary
|
|
880
|
+
self.project = binary.project
|
|
881
|
+
|
|
882
|
+
self.addr = addr
|
|
883
|
+
self.size = size
|
|
884
|
+
self.x86_getpc_retsite = x86_getpc_retsite
|
|
885
|
+
|
|
886
|
+
self.instructions = []
|
|
887
|
+
|
|
888
|
+
self._initialize()
|
|
889
|
+
|
|
890
|
+
#
|
|
891
|
+
# Overridden predefined methods
|
|
892
|
+
#
|
|
893
|
+
|
|
894
|
+
def __str__(self):
|
|
895
|
+
"""
|
|
896
|
+
Return a linear representation of all instructions in this block.
|
|
897
|
+
:return:
|
|
898
|
+
"""
|
|
899
|
+
|
|
900
|
+
return self.assembly(symbolized=False)
|
|
901
|
+
|
|
902
|
+
def __repr__(self):
|
|
903
|
+
return f"<BasicBlock {self.addr:#08x}>"
|
|
904
|
+
|
|
905
|
+
#
|
|
906
|
+
# Public methods
|
|
907
|
+
#
|
|
908
|
+
|
|
909
|
+
def assign_labels(self):
|
|
910
|
+
for ins in self.instructions:
|
|
911
|
+
ins.assign_labels()
|
|
912
|
+
|
|
913
|
+
def assembly(self, comments=False, symbolized=True):
|
|
914
|
+
return "\n".join([ins.assembly(comments=comments, symbolized=symbolized) for ins in self.instructions])
|
|
915
|
+
|
|
916
|
+
def instruction_addresses(self):
|
|
917
|
+
return sorted([(ins.addr, ins.size) for ins in self.instructions], key=lambda x: x[0])
|
|
918
|
+
|
|
919
|
+
#
|
|
920
|
+
# Private methods
|
|
921
|
+
#
|
|
922
|
+
|
|
923
|
+
def _initialize(self):
|
|
924
|
+
"""
|
|
925
|
+
|
|
926
|
+
:return:
|
|
927
|
+
"""
|
|
928
|
+
|
|
929
|
+
# re-lifting
|
|
930
|
+
block = self.project.factory.fresh_block(self.addr, self.size)
|
|
931
|
+
capstone_obj = block.capstone
|
|
932
|
+
|
|
933
|
+
# Fill in instructions
|
|
934
|
+
for idx, instr in enumerate(capstone_obj.insns):
|
|
935
|
+
# special handling for X86 PIE binaries
|
|
936
|
+
instruction = Instruction(self.binary, instr.address, instr.size, None, instr)
|
|
937
|
+
|
|
938
|
+
if self.x86_getpc_retsite and idx == 0:
|
|
939
|
+
if (
|
|
940
|
+
self.binary.syntax == "at&t"
|
|
941
|
+
and instr.mnemonic == "addl"
|
|
942
|
+
and instr.operands[1].type == capstone.CS_OP_REG
|
|
943
|
+
and instr.operands[0].type == capstone.CS_OP_IMM
|
|
944
|
+
):
|
|
945
|
+
instruction.operands[0].type = OP_TYPE_RAW
|
|
946
|
+
instruction.operands[0].raw_asm = "$_GLOBAL_OFFSET_TABLE_"
|
|
947
|
+
elif (
|
|
948
|
+
self.binary.syntax == "intel"
|
|
949
|
+
and instr.mnemonic == "add"
|
|
950
|
+
and instr.operands[0].type == capstone.CS_OP_REG
|
|
951
|
+
and instr.operands[1].type == capstone.CS_OP_IMM
|
|
952
|
+
):
|
|
953
|
+
instruction.operands[1].type = OP_TYPE_RAW
|
|
954
|
+
instruction.operands[1].raw_asm = "OFFSET FLAG:_GLOBAL_OFFSET_TABLE_"
|
|
955
|
+
|
|
956
|
+
self.instructions.append(instruction)
|
|
957
|
+
|
|
958
|
+
self.instructions = sorted(self.instructions, key=lambda x: x.addr)
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
class Procedure:
|
|
962
|
+
"""
|
|
963
|
+
Procedure in the binary.
|
|
964
|
+
"""
|
|
965
|
+
|
|
966
|
+
def __init__(self, binary, function=None, addr=None, size=None, name=None, section=".text", asm_code=None):
|
|
967
|
+
"""
|
|
968
|
+
Constructor.
|
|
969
|
+
|
|
970
|
+
:param Reassembler binary: The Binary analysis.
|
|
971
|
+
:param angr.knowledge.Function function: The function it represents
|
|
972
|
+
:param int addr: Address of the function. Not required if `function` is provided.
|
|
973
|
+
:param int size: Size of the function. Not required if `function` is provided.
|
|
974
|
+
:param str section: Which section this function comes from.
|
|
975
|
+
:return: None
|
|
976
|
+
"""
|
|
977
|
+
|
|
978
|
+
self.binary = binary
|
|
979
|
+
self.project = binary.project
|
|
980
|
+
|
|
981
|
+
if function is None:
|
|
982
|
+
self.addr = addr
|
|
983
|
+
self.size = size
|
|
984
|
+
|
|
985
|
+
self.function = None
|
|
986
|
+
self._name = name
|
|
987
|
+
|
|
988
|
+
else:
|
|
989
|
+
self.addr = function.addr
|
|
990
|
+
self.size = None # FIXME:
|
|
991
|
+
|
|
992
|
+
self.function = function
|
|
993
|
+
self._name = function.name
|
|
994
|
+
|
|
995
|
+
self.asm_code = asm_code
|
|
996
|
+
self.section = section
|
|
997
|
+
|
|
998
|
+
self.blocks = []
|
|
999
|
+
|
|
1000
|
+
self._initialize()
|
|
1001
|
+
|
|
1002
|
+
#
|
|
1003
|
+
# Attributes
|
|
1004
|
+
#
|
|
1005
|
+
|
|
1006
|
+
@property
|
|
1007
|
+
def name(self):
|
|
1008
|
+
"""
|
|
1009
|
+
Get function name from the labels of the very first block.
|
|
1010
|
+
:return: Function name if there is any, None otherwise
|
|
1011
|
+
:rtype: string
|
|
1012
|
+
"""
|
|
1013
|
+
|
|
1014
|
+
if self._name is not None:
|
|
1015
|
+
return self._name
|
|
1016
|
+
|
|
1017
|
+
if not self.blocks:
|
|
1018
|
+
return None
|
|
1019
|
+
|
|
1020
|
+
if not self.blocks[0].instructions:
|
|
1021
|
+
return None
|
|
1022
|
+
|
|
1023
|
+
if not self.blocks[0].instructions[0].labels:
|
|
1024
|
+
return None
|
|
1025
|
+
|
|
1026
|
+
lbl = self.blocks[0].instructions[0].labels[0]
|
|
1027
|
+
|
|
1028
|
+
if isinstance(lbl, FunctionLabel):
|
|
1029
|
+
return lbl.function_name
|
|
1030
|
+
|
|
1031
|
+
return None
|
|
1032
|
+
|
|
1033
|
+
@property
|
|
1034
|
+
def is_plt(self):
|
|
1035
|
+
"""
|
|
1036
|
+
If this function is a PLT entry or not.
|
|
1037
|
+
:return: True if this function is a PLT entry, False otherwise
|
|
1038
|
+
:rtype: bool
|
|
1039
|
+
"""
|
|
1040
|
+
|
|
1041
|
+
if self.section == ".plt":
|
|
1042
|
+
return True
|
|
1043
|
+
|
|
1044
|
+
if not self.blocks:
|
|
1045
|
+
return False
|
|
1046
|
+
|
|
1047
|
+
initial_block = next((b for b in self.blocks if b.addr == self.addr), None)
|
|
1048
|
+
if initial_block is None:
|
|
1049
|
+
return False
|
|
1050
|
+
|
|
1051
|
+
if not initial_block.instructions:
|
|
1052
|
+
return False
|
|
1053
|
+
|
|
1054
|
+
if not initial_block.instructions[0].labels:
|
|
1055
|
+
return False
|
|
1056
|
+
|
|
1057
|
+
lbl = initial_block.instructions[0].labels[0]
|
|
1058
|
+
|
|
1059
|
+
if isinstance(lbl, FunctionLabel):
|
|
1060
|
+
return lbl.plt
|
|
1061
|
+
|
|
1062
|
+
return False
|
|
1063
|
+
|
|
1064
|
+
#
|
|
1065
|
+
# Overridden predefined methods
|
|
1066
|
+
#
|
|
1067
|
+
def __str__(self):
|
|
1068
|
+
"""
|
|
1069
|
+
Output all instructions of the current procedure
|
|
1070
|
+
:return:
|
|
1071
|
+
"""
|
|
1072
|
+
|
|
1073
|
+
return self.assembly(symbolized=False)
|
|
1074
|
+
|
|
1075
|
+
#
|
|
1076
|
+
# Public methods
|
|
1077
|
+
#
|
|
1078
|
+
|
|
1079
|
+
def assign_labels(self):
|
|
1080
|
+
for block in self.blocks:
|
|
1081
|
+
block.assign_labels()
|
|
1082
|
+
|
|
1083
|
+
def assembly(self, comments=False, symbolized=True):
|
|
1084
|
+
"""
|
|
1085
|
+
Get the assembly manifest of the procedure.
|
|
1086
|
+
|
|
1087
|
+
:param comments:
|
|
1088
|
+
:param symbolized:
|
|
1089
|
+
:return: A list of tuples (address, basic block assembly), ordered by basic block addresses
|
|
1090
|
+
:rtype: list
|
|
1091
|
+
"""
|
|
1092
|
+
|
|
1093
|
+
assembly = []
|
|
1094
|
+
|
|
1095
|
+
header = f"\t.section\t{self.section}\n\t.align\t{self.binary.section_alignment(self.section)}\n"
|
|
1096
|
+
procedure_name = f"{self.addr:#x}" if self.addr is not None else self._name
|
|
1097
|
+
header += f"\t#Procedure {procedure_name}\n"
|
|
1098
|
+
|
|
1099
|
+
if self._output_function_label:
|
|
1100
|
+
if self.addr:
|
|
1101
|
+
function_label = self.binary.symbol_manager.new_label(self.addr)
|
|
1102
|
+
else:
|
|
1103
|
+
function_label = self.binary.symbol_manager.new_label(None, name=procedure_name, is_function=True)
|
|
1104
|
+
header += str(function_label) + "\n"
|
|
1105
|
+
|
|
1106
|
+
assembly.append((self.addr, header))
|
|
1107
|
+
|
|
1108
|
+
if self.asm_code:
|
|
1109
|
+
s = self.asm_code
|
|
1110
|
+
assembly.append((self.addr, s))
|
|
1111
|
+
elif self.blocks:
|
|
1112
|
+
b: BasicBlock
|
|
1113
|
+
for b in sorted(self.blocks, key=lambda x: x.addr):
|
|
1114
|
+
s = b.assembly(comments=comments, symbolized=symbolized)
|
|
1115
|
+
assembly.append((b.addr, s))
|
|
1116
|
+
|
|
1117
|
+
return assembly
|
|
1118
|
+
|
|
1119
|
+
def instruction_addresses(self):
|
|
1120
|
+
"""
|
|
1121
|
+
Get all instruction addresses in the binary.
|
|
1122
|
+
|
|
1123
|
+
:return: A list of sorted instruction addresses.
|
|
1124
|
+
:rtype: list
|
|
1125
|
+
"""
|
|
1126
|
+
|
|
1127
|
+
addrs = []
|
|
1128
|
+
b: BasicBlock
|
|
1129
|
+
for b in sorted(self.blocks, key=lambda x: x.addr):
|
|
1130
|
+
addrs.extend(b.instruction_addresses())
|
|
1131
|
+
|
|
1132
|
+
return sorted(set(addrs), key=lambda x: x[0])
|
|
1133
|
+
|
|
1134
|
+
#
|
|
1135
|
+
# Private methods
|
|
1136
|
+
#
|
|
1137
|
+
|
|
1138
|
+
def _initialize(self):
|
|
1139
|
+
if self.function is None:
|
|
1140
|
+
if not self.asm_code:
|
|
1141
|
+
raise BinaryError(
|
|
1142
|
+
"Unsupported procedure type. You must either specify a angr.knowledge.Function "
|
|
1143
|
+
"object, or specify assembly code."
|
|
1144
|
+
)
|
|
1145
|
+
|
|
1146
|
+
else:
|
|
1147
|
+
x86_getpc_retsites = set()
|
|
1148
|
+
if self.project.arch.name == "X86" and "pc_reg" in self.function.info:
|
|
1149
|
+
# this is an x86-PIC function that calls a get_pc thunk
|
|
1150
|
+
# we need to fix the "add e{a,b,c}x, offset" instruction right after the get_pc call
|
|
1151
|
+
# first let's identify which function is the get_pc function
|
|
1152
|
+
for src, dst, _data in self.function.transition_graph.edges(data=True):
|
|
1153
|
+
if isinstance(src, CodeNode) and isinstance(dst, Function) and "get_pc" in dst.info:
|
|
1154
|
+
# found it!
|
|
1155
|
+
x86_getpc_retsites.add(src.addr + src.size)
|
|
1156
|
+
for block_addr in self.function.block_addrs:
|
|
1157
|
+
b = BasicBlock(
|
|
1158
|
+
self.binary,
|
|
1159
|
+
block_addr,
|
|
1160
|
+
self.function._block_sizes[block_addr],
|
|
1161
|
+
x86_getpc_retsite=block_addr in x86_getpc_retsites,
|
|
1162
|
+
)
|
|
1163
|
+
self.blocks.append(b)
|
|
1164
|
+
|
|
1165
|
+
self.blocks = sorted(self.blocks, key=lambda x: x.addr)
|
|
1166
|
+
|
|
1167
|
+
@property
|
|
1168
|
+
def _output_function_label(self):
|
|
1169
|
+
"""
|
|
1170
|
+
Determines if we want to output the function label in assembly. We output the function label only when the
|
|
1171
|
+
original instruction does not output the function label.
|
|
1172
|
+
|
|
1173
|
+
:return: True if we should output the function label, False otherwise.
|
|
1174
|
+
:rtype: bool
|
|
1175
|
+
"""
|
|
1176
|
+
|
|
1177
|
+
if self.asm_code:
|
|
1178
|
+
return True
|
|
1179
|
+
if not self.blocks:
|
|
1180
|
+
return True
|
|
1181
|
+
|
|
1182
|
+
the_block = next((b for b in self.blocks if b.addr == self.addr), None)
|
|
1183
|
+
if the_block is None:
|
|
1184
|
+
return True
|
|
1185
|
+
if not the_block.instructions:
|
|
1186
|
+
return True
|
|
1187
|
+
return bool(not the_block.instructions[0].labels)
|
|
1188
|
+
|
|
1189
|
+
|
|
1190
|
+
class ProcedureChunk(Procedure):
|
|
1191
|
+
"""
|
|
1192
|
+
Procedure chunk.
|
|
1193
|
+
"""
|
|
1194
|
+
|
|
1195
|
+
def __init__(self, project, addr, size):
|
|
1196
|
+
"""
|
|
1197
|
+
Constructor.
|
|
1198
|
+
|
|
1199
|
+
:param project:
|
|
1200
|
+
:param addr:
|
|
1201
|
+
:param size:
|
|
1202
|
+
:return:
|
|
1203
|
+
"""
|
|
1204
|
+
|
|
1205
|
+
Procedure.__init__(self, project, addr=addr, size=size)
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
class Data:
|
|
1209
|
+
def __init__(
|
|
1210
|
+
self,
|
|
1211
|
+
binary,
|
|
1212
|
+
memory_data=None,
|
|
1213
|
+
section=None,
|
|
1214
|
+
section_name=None,
|
|
1215
|
+
name=None,
|
|
1216
|
+
size=None,
|
|
1217
|
+
sort=None,
|
|
1218
|
+
addr=None,
|
|
1219
|
+
initial_content=None,
|
|
1220
|
+
):
|
|
1221
|
+
self.binary = binary
|
|
1222
|
+
self.project = binary.project
|
|
1223
|
+
self.memory_data = memory_data
|
|
1224
|
+
self.section = section
|
|
1225
|
+
self.section_name = section.name if section else section_name
|
|
1226
|
+
|
|
1227
|
+
self.addr = addr
|
|
1228
|
+
self.name = name
|
|
1229
|
+
self.size = size
|
|
1230
|
+
self.sort = sort
|
|
1231
|
+
self._initial_content = initial_content # only used by patcherex
|
|
1232
|
+
|
|
1233
|
+
self._content = None
|
|
1234
|
+
|
|
1235
|
+
self.labels = [] # a list of tuples like (address, label)
|
|
1236
|
+
self.end_labels = [] # a list of labels only show up at the end of this memory data entry. mostly because the
|
|
1237
|
+
# data block after this one is removed for some reason. only assigned by other methods.
|
|
1238
|
+
|
|
1239
|
+
self.null_terminated = None
|
|
1240
|
+
|
|
1241
|
+
self.skip = False
|
|
1242
|
+
|
|
1243
|
+
self._initialize()
|
|
1244
|
+
|
|
1245
|
+
def __repr__(self):
|
|
1246
|
+
return f"<DataItem {self.sort}@{self.addr:#08x}, {self.size} bytes>"
|
|
1247
|
+
|
|
1248
|
+
@property
|
|
1249
|
+
def content(self):
|
|
1250
|
+
return self._content
|
|
1251
|
+
|
|
1252
|
+
@content.setter
|
|
1253
|
+
def content(self, v):
|
|
1254
|
+
self._content = v
|
|
1255
|
+
|
|
1256
|
+
def shrink(self, new_size):
|
|
1257
|
+
"""
|
|
1258
|
+
Reduce the size of this block
|
|
1259
|
+
|
|
1260
|
+
:param int new_size: The new size
|
|
1261
|
+
:return: None
|
|
1262
|
+
"""
|
|
1263
|
+
self.size = new_size
|
|
1264
|
+
|
|
1265
|
+
if self.sort == MemoryDataSort.String:
|
|
1266
|
+
self.null_terminated = False # string without the null byte terminator
|
|
1267
|
+
self._content[0] = self._content[0][: self.size]
|
|
1268
|
+
|
|
1269
|
+
elif self.sort == MemoryDataSort.PointerArray:
|
|
1270
|
+
pointer_size = self.binary.project.arch.bytes
|
|
1271
|
+
|
|
1272
|
+
if self.size % pointer_size != 0:
|
|
1273
|
+
# it's not aligned?
|
|
1274
|
+
raise BinaryError("Fails at Data.shrink()")
|
|
1275
|
+
|
|
1276
|
+
pointers = self.size // pointer_size
|
|
1277
|
+
self._content = self._content[:pointers]
|
|
1278
|
+
|
|
1279
|
+
else:
|
|
1280
|
+
# unknown
|
|
1281
|
+
self._content = [self._content[0][: self.size]]
|
|
1282
|
+
|
|
1283
|
+
def desymbolize(self):
|
|
1284
|
+
"""
|
|
1285
|
+
We believe this was a pointer and symbolized it before. Now we want to desymbolize it.
|
|
1286
|
+
|
|
1287
|
+
The following actions are performed:
|
|
1288
|
+
- Reload content from memory
|
|
1289
|
+
- Mark the sort as 'unknown'
|
|
1290
|
+
|
|
1291
|
+
:return: None
|
|
1292
|
+
"""
|
|
1293
|
+
|
|
1294
|
+
self.sort = MemoryDataSort.Unknown
|
|
1295
|
+
content = self.binary.fast_memory_load(self.addr, self.size, bytes)
|
|
1296
|
+
self.content = [content]
|
|
1297
|
+
|
|
1298
|
+
def assign_labels(self):
|
|
1299
|
+
# TODO: What if it's not aligned for some sort of data, like pointer array?
|
|
1300
|
+
|
|
1301
|
+
if self.addr is None:
|
|
1302
|
+
# this piece of data comes from a patch, not from the original binary
|
|
1303
|
+
return
|
|
1304
|
+
|
|
1305
|
+
# Put labels to self.labels
|
|
1306
|
+
for i in range(self.size):
|
|
1307
|
+
addr = self.addr + i
|
|
1308
|
+
if addr in self.binary.symbol_manager.addr_to_label:
|
|
1309
|
+
labels = self.binary.symbol_manager.addr_to_label[addr]
|
|
1310
|
+
|
|
1311
|
+
for label in labels:
|
|
1312
|
+
if self.sort == MemoryDataSort.PointerArray and addr % (self.project.arch.bytes) != 0:
|
|
1313
|
+
# we need to modify the base address of the label
|
|
1314
|
+
base_addr = addr - (addr % (self.project.arch.bytes))
|
|
1315
|
+
label.base_addr = base_addr
|
|
1316
|
+
tpl = (base_addr, label)
|
|
1317
|
+
if tpl not in self.labels:
|
|
1318
|
+
self.labels.append(tpl)
|
|
1319
|
+
else:
|
|
1320
|
+
tpl = (addr, label)
|
|
1321
|
+
if tpl not in self.labels:
|
|
1322
|
+
self.labels.append(tpl)
|
|
1323
|
+
|
|
1324
|
+
def assembly(self, comments=False, symbolized=True):
|
|
1325
|
+
s = ""
|
|
1326
|
+
|
|
1327
|
+
if comments:
|
|
1328
|
+
if self.addr is not None:
|
|
1329
|
+
s += f"\t# data @ {self.addr:#08x}\n"
|
|
1330
|
+
else:
|
|
1331
|
+
s += f"\t# data ({self.name})\n"
|
|
1332
|
+
|
|
1333
|
+
if self.skip:
|
|
1334
|
+
return s
|
|
1335
|
+
|
|
1336
|
+
if self.sort == MemoryDataSort.String:
|
|
1337
|
+
if symbolized:
|
|
1338
|
+
ss = []
|
|
1339
|
+
last_pos = 0
|
|
1340
|
+
for i, tpl in enumerate(self.labels):
|
|
1341
|
+
addr, lbl = tpl
|
|
1342
|
+
|
|
1343
|
+
# split the string
|
|
1344
|
+
pos = addr - self.addr
|
|
1345
|
+
# endpos = self.labels[i + 1][0] - self.addr + 1 if i < len(self.labels) - 1 else self.size
|
|
1346
|
+
string_piece = self.content[0][last_pos:pos]
|
|
1347
|
+
|
|
1348
|
+
last_pos = pos
|
|
1349
|
+
|
|
1350
|
+
# null at the end in true case
|
|
1351
|
+
directive = ".asciz" if i == len(self.labels) - 1 and pos == self.size else ".ascii"
|
|
1352
|
+
|
|
1353
|
+
if string_piece:
|
|
1354
|
+
ss.append(f'\t{directive} "{string_escape(string_piece)}"')
|
|
1355
|
+
ss.append(f"{lbl!s}")
|
|
1356
|
+
|
|
1357
|
+
if last_pos <= self.size - 1:
|
|
1358
|
+
string_piece = self.content[0][last_pos:]
|
|
1359
|
+
directive = ".ascii" if self.null_terminated is False else ".asciz"
|
|
1360
|
+
|
|
1361
|
+
ss.append(f'\t{directive} "{string_escape(string_piece)}"')
|
|
1362
|
+
|
|
1363
|
+
s += "\n".join(ss)
|
|
1364
|
+
else:
|
|
1365
|
+
directive = ".ascii" if self.null_terminated is False else ".asciz"
|
|
1366
|
+
s += f'\t.{directive} "{string_escape(self.content[0])}"'
|
|
1367
|
+
s += "\n"
|
|
1368
|
+
|
|
1369
|
+
elif self.sort == MemoryDataSort.PointerArray:
|
|
1370
|
+
if self.binary.project.arch.bits == 32:
|
|
1371
|
+
directive = ".long"
|
|
1372
|
+
elif self.binary.project.arch.bits == 64:
|
|
1373
|
+
directive = ".quad"
|
|
1374
|
+
else:
|
|
1375
|
+
raise BinaryError("Unsupported pointer size %d", self.binary.project.arch.bits)
|
|
1376
|
+
|
|
1377
|
+
if symbolized:
|
|
1378
|
+
addr_to_labels = {}
|
|
1379
|
+
for k, v in self.labels:
|
|
1380
|
+
if k not in addr_to_labels:
|
|
1381
|
+
addr_to_labels[k] = []
|
|
1382
|
+
addr_to_labels[k].append(v)
|
|
1383
|
+
|
|
1384
|
+
i = 0
|
|
1385
|
+
if self.name is not None:
|
|
1386
|
+
s += f"{self.name}:\n"
|
|
1387
|
+
for symbolized_label in self.content:
|
|
1388
|
+
if self.addr is not None and (self.addr + i) in addr_to_labels:
|
|
1389
|
+
for label in addr_to_labels[self.addr + i]:
|
|
1390
|
+
s += f"{label!s}\n"
|
|
1391
|
+
elif self.addr is not None and (self.addr + i) in self.binary.symbol_manager.addr_to_label:
|
|
1392
|
+
labels = self.binary.symbol_manager.addr_to_label[self.addr + i]
|
|
1393
|
+
for label in labels:
|
|
1394
|
+
s += f"{label!s}\n"
|
|
1395
|
+
i += self.project.arch.bytes
|
|
1396
|
+
|
|
1397
|
+
if isinstance(symbolized_label, int):
|
|
1398
|
+
s += f"\t{directive} {symbolized_label}\n"
|
|
1399
|
+
else:
|
|
1400
|
+
s += f"\t{directive} {symbolized_label.operand_str}\n"
|
|
1401
|
+
|
|
1402
|
+
else:
|
|
1403
|
+
for label in self.content:
|
|
1404
|
+
s += f"\t{directive} {label.operand_str}\n"
|
|
1405
|
+
|
|
1406
|
+
elif self.sort == MemoryDataSort.SegmentBoundary:
|
|
1407
|
+
if symbolized:
|
|
1408
|
+
for _, label in self.labels:
|
|
1409
|
+
s += f"\t{label!s}\n"
|
|
1410
|
+
|
|
1411
|
+
elif self.sort == MemoryDataSort.Integer:
|
|
1412
|
+
# display it as bytes only when there are references pointing to the middle
|
|
1413
|
+
content = []
|
|
1414
|
+
|
|
1415
|
+
if self.size == 1:
|
|
1416
|
+
directive = ".byte"
|
|
1417
|
+
fmt_str = "B"
|
|
1418
|
+
elif self.size == 2:
|
|
1419
|
+
directive = ".short"
|
|
1420
|
+
fmt_str = "<H"
|
|
1421
|
+
elif self.size == 4:
|
|
1422
|
+
directive = ".long"
|
|
1423
|
+
fmt_str = "<I"
|
|
1424
|
+
elif self.size == 8:
|
|
1425
|
+
directive = ".quad"
|
|
1426
|
+
fmt_str = "<Q"
|
|
1427
|
+
else:
|
|
1428
|
+
# we'll have to display it as a bunch of bytes
|
|
1429
|
+
directive = None
|
|
1430
|
+
fmt_str = None
|
|
1431
|
+
|
|
1432
|
+
if symbolized:
|
|
1433
|
+
addr_to_labels = {}
|
|
1434
|
+
for k, v in self.labels:
|
|
1435
|
+
if k not in addr_to_labels:
|
|
1436
|
+
addr_to_labels[k] = []
|
|
1437
|
+
addr_to_labels[k].append(v)
|
|
1438
|
+
|
|
1439
|
+
show_integer = False
|
|
1440
|
+
if len(addr_to_labels) == 0 or (
|
|
1441
|
+
(
|
|
1442
|
+
len(addr_to_labels) == 1
|
|
1443
|
+
and self.addr is not None
|
|
1444
|
+
and next(iter(addr_to_labels.keys())) == self.addr
|
|
1445
|
+
)
|
|
1446
|
+
or (self.addr is None and next(iter(addr_to_labels.keys())) == 0)
|
|
1447
|
+
):
|
|
1448
|
+
show_integer = True
|
|
1449
|
+
|
|
1450
|
+
if directive is not None and show_integer:
|
|
1451
|
+
# nice, we should display it as an integer
|
|
1452
|
+
if addr_to_labels:
|
|
1453
|
+
for label in next(iter(addr_to_labels.values())):
|
|
1454
|
+
content += [f"{label!s}"]
|
|
1455
|
+
|
|
1456
|
+
integer = struct.unpack(fmt_str, self.content[0])[0]
|
|
1457
|
+
content += [
|
|
1458
|
+
"\t{directive} {integer}".format(
|
|
1459
|
+
directive=directive,
|
|
1460
|
+
integer=f"{integer:#x}",
|
|
1461
|
+
)
|
|
1462
|
+
]
|
|
1463
|
+
|
|
1464
|
+
else:
|
|
1465
|
+
# display it as bytes...
|
|
1466
|
+
addr = self.addr if self.addr is not None else 0
|
|
1467
|
+
for piece in self.content:
|
|
1468
|
+
for c in piece:
|
|
1469
|
+
if addr in addr_to_labels:
|
|
1470
|
+
for label in addr_to_labels[addr]:
|
|
1471
|
+
content += [f"{label!s}"]
|
|
1472
|
+
addr += 1
|
|
1473
|
+
|
|
1474
|
+
content += [f"\t.byte {c}"]
|
|
1475
|
+
|
|
1476
|
+
else:
|
|
1477
|
+
integer = struct.unpack(fmt_str, self.content[0])[0]
|
|
1478
|
+
content += [
|
|
1479
|
+
"\t{directive} {integer}".format(
|
|
1480
|
+
directive=directive,
|
|
1481
|
+
integer=f"{integer:#x}",
|
|
1482
|
+
)
|
|
1483
|
+
]
|
|
1484
|
+
|
|
1485
|
+
s += "\n".join(content)
|
|
1486
|
+
s += "\n"
|
|
1487
|
+
|
|
1488
|
+
elif self.sort == MemoryDataSort.FloatingPoint:
|
|
1489
|
+
# we have to display it as bytes...
|
|
1490
|
+
# TODO: switch to "ten byes" whenever time permits
|
|
1491
|
+
content = []
|
|
1492
|
+
|
|
1493
|
+
if symbolized:
|
|
1494
|
+
addr_to_labels = {}
|
|
1495
|
+
for k, v in self.labels:
|
|
1496
|
+
if k not in addr_to_labels:
|
|
1497
|
+
addr_to_labels[k] = []
|
|
1498
|
+
addr_to_labels[k].append(v)
|
|
1499
|
+
|
|
1500
|
+
addr = self.addr if self.addr is not None else 0
|
|
1501
|
+
for piece in self.content:
|
|
1502
|
+
for c in piece:
|
|
1503
|
+
if addr in addr_to_labels:
|
|
1504
|
+
for label in addr_to_labels[addr]:
|
|
1505
|
+
content += [f"{label!s}"]
|
|
1506
|
+
addr += 1
|
|
1507
|
+
|
|
1508
|
+
content += [f"\t.byte {c}"]
|
|
1509
|
+
else:
|
|
1510
|
+
for piece in self.content:
|
|
1511
|
+
content += [f"\t.byte {c}" for c in piece]
|
|
1512
|
+
|
|
1513
|
+
s += "\n".join(content)
|
|
1514
|
+
s += "\n"
|
|
1515
|
+
|
|
1516
|
+
else:
|
|
1517
|
+
content = []
|
|
1518
|
+
|
|
1519
|
+
if symbolized:
|
|
1520
|
+
addr_to_labels = {}
|
|
1521
|
+
for k, v in self.labels:
|
|
1522
|
+
if k not in addr_to_labels:
|
|
1523
|
+
addr_to_labels[k] = []
|
|
1524
|
+
addr_to_labels[k].append(v)
|
|
1525
|
+
|
|
1526
|
+
addr = self.addr if self.addr is not None else 0
|
|
1527
|
+
for piece in self.content:
|
|
1528
|
+
for c in piece:
|
|
1529
|
+
if addr in addr_to_labels:
|
|
1530
|
+
for label in addr_to_labels[addr]:
|
|
1531
|
+
content += [f"{label!s}"]
|
|
1532
|
+
addr += 1
|
|
1533
|
+
|
|
1534
|
+
content += [f"\t.byte {c}"]
|
|
1535
|
+
else:
|
|
1536
|
+
for piece in self.content:
|
|
1537
|
+
content += [f"\t.byte {c}" for c in piece]
|
|
1538
|
+
|
|
1539
|
+
s += "\n".join(content)
|
|
1540
|
+
s += "\n"
|
|
1541
|
+
|
|
1542
|
+
if self.end_labels:
|
|
1543
|
+
for label in self.end_labels:
|
|
1544
|
+
s += f"{label}\n"
|
|
1545
|
+
|
|
1546
|
+
return s.strip("\n")
|
|
1547
|
+
|
|
1548
|
+
#
|
|
1549
|
+
# Private methods
|
|
1550
|
+
#
|
|
1551
|
+
|
|
1552
|
+
def _initialize(self):
|
|
1553
|
+
if self.memory_data is None:
|
|
1554
|
+
if self.size is None or (self._initial_content is None and self.sort is None):
|
|
1555
|
+
raise BinaryError("You must at least specify size, initial_content, and sort.")
|
|
1556
|
+
|
|
1557
|
+
if self.sort == MemoryDataSort.PointerArray:
|
|
1558
|
+
lbl = DataLabel(self.binary, -1, name=self.name)
|
|
1559
|
+
self.labels.append((0, lbl))
|
|
1560
|
+
|
|
1561
|
+
# symbolize the pointer array
|
|
1562
|
+
|
|
1563
|
+
self._content = []
|
|
1564
|
+
|
|
1565
|
+
fmt_str = ""
|
|
1566
|
+
if self.project.arch.memory_endness == "Iend_LE":
|
|
1567
|
+
fmt_str += "<"
|
|
1568
|
+
else:
|
|
1569
|
+
fmt_str += ">"
|
|
1570
|
+
if self.project.arch.bits == 32:
|
|
1571
|
+
fmt_str += "I"
|
|
1572
|
+
pointer_size = 4
|
|
1573
|
+
else:
|
|
1574
|
+
fmt_str += "Q"
|
|
1575
|
+
pointer_size = 8
|
|
1576
|
+
|
|
1577
|
+
for i in range(0, len(self._initial_content), pointer_size):
|
|
1578
|
+
addr_str = self._initial_content[i : i + pointer_size]
|
|
1579
|
+
addr = struct.unpack(fmt_str, addr_str)[0]
|
|
1580
|
+
if addr != 0 and (
|
|
1581
|
+
self.binary.main_executable_regions_contain(addr)
|
|
1582
|
+
or self.binary.main_nonexecutable_regions_contain(addr)
|
|
1583
|
+
):
|
|
1584
|
+
label = self.binary.symbol_manager.new_label(addr)
|
|
1585
|
+
else:
|
|
1586
|
+
# it might be a pointer pointing to the binary base address or something
|
|
1587
|
+
# just keep it as it is
|
|
1588
|
+
# TODO: some more delicate logic should be applied here. For example, if the pointer is very
|
|
1589
|
+
# TODO: close to the beginning of .text, but after reassembling, it might be pointing to
|
|
1590
|
+
# TODO: somewhere inside .text. In this case we'd like to fix up the reference and make it
|
|
1591
|
+
# TODO: point to the beginning of .text minus an offset, instead of keeping the original header.
|
|
1592
|
+
label = addr
|
|
1593
|
+
self._content.append(label)
|
|
1594
|
+
|
|
1595
|
+
elif self.sort in {MemoryDataSort.String, MemoryDataSort.Unknown, MemoryDataSort.Integer}:
|
|
1596
|
+
lbl = DataLabel(self.binary, -1, name=self.name)
|
|
1597
|
+
self.labels.append((0, lbl))
|
|
1598
|
+
|
|
1599
|
+
self._content = [self._initial_content]
|
|
1600
|
+
|
|
1601
|
+
elif self.sort == MemoryDataSort.SegmentBoundary:
|
|
1602
|
+
label = self.binary.symbol_manager.new_label(self.addr)
|
|
1603
|
+
self.labels.append((self.addr, label))
|
|
1604
|
+
self._content = []
|
|
1605
|
+
|
|
1606
|
+
else:
|
|
1607
|
+
raise BinaryError(f'Unsupported data sort "{self.sort}"')
|
|
1608
|
+
|
|
1609
|
+
else:
|
|
1610
|
+
self.addr = self.memory_data.address
|
|
1611
|
+
self.size = self.memory_data.size
|
|
1612
|
+
self.sort = self.memory_data.sort
|
|
1613
|
+
|
|
1614
|
+
# Symbolize the content
|
|
1615
|
+
if self.sort == MemoryDataSort.PointerArray:
|
|
1616
|
+
# read out the address
|
|
1617
|
+
pointer_size = self.project.arch.bytes
|
|
1618
|
+
pointers = self.size // pointer_size
|
|
1619
|
+
|
|
1620
|
+
self._content = []
|
|
1621
|
+
for i in range(pointers):
|
|
1622
|
+
addr = self.binary.fast_memory_load(
|
|
1623
|
+
self.addr + i * pointer_size, pointer_size, int, endness=self.project.arch.memory_endness
|
|
1624
|
+
)
|
|
1625
|
+
if addr is None:
|
|
1626
|
+
continue
|
|
1627
|
+
obj = self.project.loader.find_object_containing(addr)
|
|
1628
|
+
if obj is self.project.loader.main_object:
|
|
1629
|
+
# a dynamic pointer
|
|
1630
|
+
if self.binary.main_executable_regions_contain(
|
|
1631
|
+
addr
|
|
1632
|
+
) or self.binary.main_nonexecutable_regions_contain(addr):
|
|
1633
|
+
label = self.binary.symbol_manager.new_label(addr)
|
|
1634
|
+
self._content.append(label)
|
|
1635
|
+
|
|
1636
|
+
self.binary.register_data_reference(self.addr + i * pointer_size, addr)
|
|
1637
|
+
|
|
1638
|
+
else:
|
|
1639
|
+
# it's a pointer pointing to a segment, but not any section. keep it as it is
|
|
1640
|
+
self._content.append(addr)
|
|
1641
|
+
else:
|
|
1642
|
+
# it's a static pointer. we should use the original pointer value.
|
|
1643
|
+
self._content.append(addr)
|
|
1644
|
+
|
|
1645
|
+
elif self.sort == MemoryDataSort.String:
|
|
1646
|
+
data = self.binary.fast_memory_load(self.addr, self.size, bytes)
|
|
1647
|
+
if data[-1] == 0:
|
|
1648
|
+
self.null_terminated = True
|
|
1649
|
+
data = data[:-1] # remove the null-byte. we'll use .asciz for it instead.
|
|
1650
|
+
else:
|
|
1651
|
+
self.null_terminated = False
|
|
1652
|
+
|
|
1653
|
+
self._content = [data]
|
|
1654
|
+
|
|
1655
|
+
elif self.sort == MemoryDataSort.Integer:
|
|
1656
|
+
data = self.binary.fast_memory_load(self.addr, self.size, bytes)
|
|
1657
|
+
self._content = [data]
|
|
1658
|
+
|
|
1659
|
+
elif self.sort == MemoryDataSort.SegmentBoundary:
|
|
1660
|
+
label = self.binary.symbol_manager.new_label(self.addr)
|
|
1661
|
+
self.labels.append((self.addr, label))
|
|
1662
|
+
|
|
1663
|
+
self._content = []
|
|
1664
|
+
|
|
1665
|
+
elif self.sort == MemoryDataSort.FloatingPoint:
|
|
1666
|
+
# floating-point integers
|
|
1667
|
+
# Python has some trouble in dealing with floating point numbers
|
|
1668
|
+
# just store them as bytes
|
|
1669
|
+
data = self.binary.fast_memory_load(self.addr, self.size, bytes)
|
|
1670
|
+
self._content = [data]
|
|
1671
|
+
|
|
1672
|
+
else:
|
|
1673
|
+
# other sorts
|
|
1674
|
+
content = self.binary.fast_memory_load(self.addr, self.size, bytes)
|
|
1675
|
+
if content is not None:
|
|
1676
|
+
self._content = [content]
|
|
1677
|
+
else:
|
|
1678
|
+
self._content = []
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
class Relocation:
|
|
1682
|
+
def __init__(self, addr, ref_addr, sort):
|
|
1683
|
+
self.addr = addr
|
|
1684
|
+
self.ref_addr = ref_addr
|
|
1685
|
+
self.sort = sort
|
|
1686
|
+
|
|
1687
|
+
def __repr__(self):
|
|
1688
|
+
return f"<Reloc {self.sort} {self.addr:#x} ({self.ref_addr:#x})>"
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
class Reassembler(Analysis):
|
|
1692
|
+
"""
|
|
1693
|
+
High-level representation of a binary with a linear representation of all instructions and data regions. After
|
|
1694
|
+
calling "symbolize", it essentially acts as a binary reassembler.
|
|
1695
|
+
|
|
1696
|
+
Tested on CGC, x86 and x86-64 binaries.
|
|
1697
|
+
|
|
1698
|
+
Disclaimer: The reassembler is an empirical solution. Don't be surprised if it does not work on some binaries.
|
|
1699
|
+
"""
|
|
1700
|
+
|
|
1701
|
+
def __init__(self, syntax="intel", remove_cgc_attachments=True, log_relocations=True):
|
|
1702
|
+
self.syntax = syntax
|
|
1703
|
+
self._remove_cgc_attachments = remove_cgc_attachments
|
|
1704
|
+
|
|
1705
|
+
self.symbol_manager = None
|
|
1706
|
+
self.cfg = None
|
|
1707
|
+
self._cgc_attachments_removed = False
|
|
1708
|
+
self.log_relocations = log_relocations
|
|
1709
|
+
|
|
1710
|
+
self.procedures = []
|
|
1711
|
+
self.data = []
|
|
1712
|
+
|
|
1713
|
+
self.extra_rodata = []
|
|
1714
|
+
self.extra_data = []
|
|
1715
|
+
|
|
1716
|
+
self._main_executable_regions = None
|
|
1717
|
+
self._main_nonexecutable_regions = None
|
|
1718
|
+
|
|
1719
|
+
self._symbolization_needed = True
|
|
1720
|
+
|
|
1721
|
+
# section names to alignments
|
|
1722
|
+
self._section_alignments = {}
|
|
1723
|
+
|
|
1724
|
+
# all instruction addresses
|
|
1725
|
+
self.all_insn_addrs = set()
|
|
1726
|
+
|
|
1727
|
+
self._relocations = []
|
|
1728
|
+
|
|
1729
|
+
self._inserted_asm_before_label = defaultdict(list)
|
|
1730
|
+
self._inserted_asm_after_label = defaultdict(list)
|
|
1731
|
+
self._removed_instructions = set()
|
|
1732
|
+
self._extra_memory_regions = [(0x4347C000, 0x4347C000 + 0x1000)]
|
|
1733
|
+
|
|
1734
|
+
self._initialize()
|
|
1735
|
+
|
|
1736
|
+
#
|
|
1737
|
+
# Overridden predefined methods
|
|
1738
|
+
#
|
|
1739
|
+
|
|
1740
|
+
def __str__(self):
|
|
1741
|
+
"""
|
|
1742
|
+
Return a linear representation of all instructions in the binary
|
|
1743
|
+
:return:
|
|
1744
|
+
"""
|
|
1745
|
+
|
|
1746
|
+
return "\n".join([str(proc) for proc in self.procedures])
|
|
1747
|
+
|
|
1748
|
+
#
|
|
1749
|
+
# Properties
|
|
1750
|
+
#
|
|
1751
|
+
@property
|
|
1752
|
+
def instructions(self):
|
|
1753
|
+
"""
|
|
1754
|
+
Get a list of all instructions in the binary
|
|
1755
|
+
|
|
1756
|
+
:return: A list of (address, instruction)
|
|
1757
|
+
:rtype: tuple
|
|
1758
|
+
"""
|
|
1759
|
+
|
|
1760
|
+
raise NotImplementedError
|
|
1761
|
+
|
|
1762
|
+
@property
|
|
1763
|
+
def relocations(self):
|
|
1764
|
+
return self._relocations
|
|
1765
|
+
|
|
1766
|
+
@property
|
|
1767
|
+
def inserted_asm_before_label(self):
|
|
1768
|
+
return self._inserted_asm_before_label
|
|
1769
|
+
|
|
1770
|
+
@property
|
|
1771
|
+
def inserted_asm_after_label(self):
|
|
1772
|
+
return self._inserted_asm_after_label
|
|
1773
|
+
|
|
1774
|
+
@property
|
|
1775
|
+
def main_executable_regions(self):
|
|
1776
|
+
"""
|
|
1777
|
+
|
|
1778
|
+
:return:
|
|
1779
|
+
"""
|
|
1780
|
+
|
|
1781
|
+
if self._main_executable_regions is None:
|
|
1782
|
+
self._main_executable_regions = []
|
|
1783
|
+
|
|
1784
|
+
obj = self.project.loader.main_object
|
|
1785
|
+
|
|
1786
|
+
if obj.sections:
|
|
1787
|
+
for sec in obj.sections:
|
|
1788
|
+
if sec.is_executable:
|
|
1789
|
+
min_addr = sec.min_addr
|
|
1790
|
+
max_addr = sec.max_addr + 1
|
|
1791
|
+
if max_addr <= min_addr or min_addr == 0:
|
|
1792
|
+
continue
|
|
1793
|
+
self._main_executable_regions.append((min_addr, max_addr))
|
|
1794
|
+
|
|
1795
|
+
else:
|
|
1796
|
+
for seg in obj.segments:
|
|
1797
|
+
if seg.is_executable:
|
|
1798
|
+
min_addr = seg.min_addr
|
|
1799
|
+
max_addr = seg.max_addr + 1
|
|
1800
|
+
self._main_executable_regions.append((min_addr, max_addr))
|
|
1801
|
+
|
|
1802
|
+
return self._main_executable_regions
|
|
1803
|
+
|
|
1804
|
+
@property
|
|
1805
|
+
def main_nonexecutable_regions(self):
|
|
1806
|
+
"""
|
|
1807
|
+
|
|
1808
|
+
:return:
|
|
1809
|
+
"""
|
|
1810
|
+
|
|
1811
|
+
if self._main_nonexecutable_regions is None:
|
|
1812
|
+
self._main_nonexecutable_regions = []
|
|
1813
|
+
|
|
1814
|
+
obj = self.project.loader.main_object
|
|
1815
|
+
|
|
1816
|
+
if obj.sections:
|
|
1817
|
+
for sec in obj.sections:
|
|
1818
|
+
if sec.name in {".eh_frame", ".eh_frame_hdr"}:
|
|
1819
|
+
# hack for ELF binaries...
|
|
1820
|
+
continue
|
|
1821
|
+
if not sec.is_executable:
|
|
1822
|
+
min_addr = sec.min_addr
|
|
1823
|
+
max_addr = sec.max_addr + 1
|
|
1824
|
+
if max_addr <= min_addr or min_addr == 0:
|
|
1825
|
+
continue
|
|
1826
|
+
self._main_nonexecutable_regions.append((min_addr, max_addr))
|
|
1827
|
+
|
|
1828
|
+
else:
|
|
1829
|
+
for seg in obj.segments:
|
|
1830
|
+
if not seg.is_executable:
|
|
1831
|
+
min_addr = seg.min_addr
|
|
1832
|
+
max_addr = seg.max_addr + 1
|
|
1833
|
+
self._main_nonexecutable_regions.append((min_addr, max_addr))
|
|
1834
|
+
|
|
1835
|
+
return self._main_nonexecutable_regions
|
|
1836
|
+
|
|
1837
|
+
#
|
|
1838
|
+
# Public methods
|
|
1839
|
+
#
|
|
1840
|
+
|
|
1841
|
+
def section_alignment(self, section_name):
|
|
1842
|
+
"""
|
|
1843
|
+
Get the alignment for the specific section. If the section is not found, 16 is used as default.
|
|
1844
|
+
|
|
1845
|
+
:param str section_name: The section.
|
|
1846
|
+
:return: The alignment in bytes.
|
|
1847
|
+
:rtype: int
|
|
1848
|
+
"""
|
|
1849
|
+
|
|
1850
|
+
return self._section_alignments.get(section_name, 16)
|
|
1851
|
+
|
|
1852
|
+
def main_executable_regions_contain(self, addr):
|
|
1853
|
+
"""
|
|
1854
|
+
|
|
1855
|
+
:param addr:
|
|
1856
|
+
:return:
|
|
1857
|
+
"""
|
|
1858
|
+
return any(start <= addr < end for start, end in self.main_executable_regions)
|
|
1859
|
+
|
|
1860
|
+
def main_executable_region_limbos_contain(self, addr):
|
|
1861
|
+
"""
|
|
1862
|
+
Sometimes there exists a pointer that points to a few bytes before the beginning of a section, or a few bytes
|
|
1863
|
+
after the beginning of the section. We take care of that here.
|
|
1864
|
+
|
|
1865
|
+
:param int addr: The address to check.
|
|
1866
|
+
:return: A 2-tuple of (bool, the closest base address)
|
|
1867
|
+
:rtype: tuple
|
|
1868
|
+
"""
|
|
1869
|
+
|
|
1870
|
+
TOLERANCE = 64
|
|
1871
|
+
|
|
1872
|
+
closest_region = None
|
|
1873
|
+
least_limbo = None
|
|
1874
|
+
|
|
1875
|
+
for start, end in self.main_executable_regions:
|
|
1876
|
+
if start - TOLERANCE <= addr < start and (least_limbo is None or start - addr < least_limbo):
|
|
1877
|
+
closest_region = (True, start)
|
|
1878
|
+
least_limbo = start - addr
|
|
1879
|
+
if end <= addr < end + TOLERANCE and (least_limbo is None or addr - end < least_limbo):
|
|
1880
|
+
closest_region = (True, end)
|
|
1881
|
+
least_limbo = addr - end
|
|
1882
|
+
|
|
1883
|
+
if closest_region is not None:
|
|
1884
|
+
return closest_region
|
|
1885
|
+
return (False, None)
|
|
1886
|
+
|
|
1887
|
+
def main_nonexecutable_regions_contain(self, addr):
|
|
1888
|
+
"""
|
|
1889
|
+
|
|
1890
|
+
:param int addr: The address to check.
|
|
1891
|
+
:return: True if the address is inside a non-executable region, False otherwise.
|
|
1892
|
+
:rtype: bool
|
|
1893
|
+
"""
|
|
1894
|
+
return any(start <= addr < end for start, end in self.main_nonexecutable_regions)
|
|
1895
|
+
|
|
1896
|
+
def main_nonexecutable_region_limbos_contain(self, addr, tolerance_before=64, tolerance_after=64):
|
|
1897
|
+
"""
|
|
1898
|
+
Sometimes there exists a pointer that points to a few bytes before the beginning of a section, or a few bytes
|
|
1899
|
+
after the beginning of the section. We take care of that here.
|
|
1900
|
+
|
|
1901
|
+
:param int addr: The address to check.
|
|
1902
|
+
:return: A 2-tuple of (bool, the closest base address)
|
|
1903
|
+
:rtype: tuple
|
|
1904
|
+
"""
|
|
1905
|
+
|
|
1906
|
+
closest_region = None
|
|
1907
|
+
least_limbo = None
|
|
1908
|
+
|
|
1909
|
+
for start, end in self.main_nonexecutable_regions:
|
|
1910
|
+
if (start - tolerance_before <= addr < start) and (least_limbo is None or start - addr < least_limbo):
|
|
1911
|
+
closest_region = (True, start)
|
|
1912
|
+
least_limbo = start - addr
|
|
1913
|
+
if (end <= addr < end + tolerance_after) and (least_limbo is None or addr - end < least_limbo):
|
|
1914
|
+
closest_region = (True, end)
|
|
1915
|
+
least_limbo = addr - end
|
|
1916
|
+
|
|
1917
|
+
if closest_region is not None:
|
|
1918
|
+
return closest_region
|
|
1919
|
+
return False, None
|
|
1920
|
+
|
|
1921
|
+
def register_instruction_reference(self, insn_addr, ref_addr, sort, operand_offset):
|
|
1922
|
+
if not self.log_relocations:
|
|
1923
|
+
return
|
|
1924
|
+
|
|
1925
|
+
addr = insn_addr + operand_offset
|
|
1926
|
+
r = Relocation(addr, ref_addr, sort)
|
|
1927
|
+
|
|
1928
|
+
self._relocations.append(r)
|
|
1929
|
+
|
|
1930
|
+
def register_data_reference(self, data_addr, ref_addr):
|
|
1931
|
+
if not self.log_relocations:
|
|
1932
|
+
return
|
|
1933
|
+
|
|
1934
|
+
r = Relocation(data_addr, ref_addr, "absolute")
|
|
1935
|
+
|
|
1936
|
+
self._relocations.append(r)
|
|
1937
|
+
|
|
1938
|
+
def add_label(self, name, addr):
|
|
1939
|
+
"""
|
|
1940
|
+
Add a new label to the symbol manager.
|
|
1941
|
+
|
|
1942
|
+
:param str name: Name of the label.
|
|
1943
|
+
:param int addr: Address of the label.
|
|
1944
|
+
:return: None
|
|
1945
|
+
"""
|
|
1946
|
+
|
|
1947
|
+
# set the label
|
|
1948
|
+
self._symbolization_needed = True
|
|
1949
|
+
|
|
1950
|
+
self.symbol_manager.new_label(addr, name=name, force=True)
|
|
1951
|
+
|
|
1952
|
+
def insert_asm(self, addr, asm_code, before_label=False):
|
|
1953
|
+
"""
|
|
1954
|
+
Insert some assembly code at the specific address. There must be an instruction starting at that address.
|
|
1955
|
+
|
|
1956
|
+
:param int addr: Address of insertion
|
|
1957
|
+
:param str asm_code: The assembly code to insert
|
|
1958
|
+
:return: None
|
|
1959
|
+
"""
|
|
1960
|
+
|
|
1961
|
+
if before_label:
|
|
1962
|
+
self._inserted_asm_before_label[addr].append(asm_code)
|
|
1963
|
+
else:
|
|
1964
|
+
self._inserted_asm_after_label[addr].append(asm_code)
|
|
1965
|
+
|
|
1966
|
+
def append_procedure(self, name, asm_code):
|
|
1967
|
+
"""
|
|
1968
|
+
Add a new procedure with specific name and assembly code.
|
|
1969
|
+
|
|
1970
|
+
:param str name: The name of the new procedure.
|
|
1971
|
+
:param str asm_code: The assembly code of the procedure
|
|
1972
|
+
:return: None
|
|
1973
|
+
"""
|
|
1974
|
+
|
|
1975
|
+
proc = Procedure(self, name=name, asm_code=asm_code)
|
|
1976
|
+
self.procedures.append(proc)
|
|
1977
|
+
|
|
1978
|
+
def append_data(
|
|
1979
|
+
self, name, initial_content, size, readonly=False, sort="unknown"
|
|
1980
|
+
): # pylint:disable=unused-argument
|
|
1981
|
+
"""
|
|
1982
|
+
Append a new data entry into the binary with specific name, content, and size.
|
|
1983
|
+
|
|
1984
|
+
:param str name: Name of the data entry. Will be used as the label.
|
|
1985
|
+
:param bytes initial_content: The initial content of the data entry.
|
|
1986
|
+
:param int size: Size of the data entry.
|
|
1987
|
+
:param bool readonly: If the data entry belongs to the readonly region.
|
|
1988
|
+
:param str sort: Type of the data.
|
|
1989
|
+
:return: None
|
|
1990
|
+
"""
|
|
1991
|
+
|
|
1992
|
+
section_name = ".rodata" if readonly else ".data"
|
|
1993
|
+
|
|
1994
|
+
if initial_content is None:
|
|
1995
|
+
initial_content = b""
|
|
1996
|
+
initial_content = initial_content.ljust(size, b"\x00")
|
|
1997
|
+
data = Data(
|
|
1998
|
+
self,
|
|
1999
|
+
memory_data=None,
|
|
2000
|
+
section_name=section_name,
|
|
2001
|
+
name=name,
|
|
2002
|
+
initial_content=initial_content,
|
|
2003
|
+
size=size,
|
|
2004
|
+
sort=sort,
|
|
2005
|
+
)
|
|
2006
|
+
|
|
2007
|
+
if section_name == ".rodata":
|
|
2008
|
+
self.extra_rodata.append(data)
|
|
2009
|
+
else:
|
|
2010
|
+
self.extra_data.append(data)
|
|
2011
|
+
|
|
2012
|
+
def remove_instruction(self, ins_addr):
|
|
2013
|
+
"""
|
|
2014
|
+
|
|
2015
|
+
:param ins_addr:
|
|
2016
|
+
:return:
|
|
2017
|
+
"""
|
|
2018
|
+
|
|
2019
|
+
self._removed_instructions.add(ins_addr)
|
|
2020
|
+
|
|
2021
|
+
def randomize_procedures(self):
|
|
2022
|
+
"""
|
|
2023
|
+
|
|
2024
|
+
:return:
|
|
2025
|
+
"""
|
|
2026
|
+
|
|
2027
|
+
raise NotImplementedError
|
|
2028
|
+
|
|
2029
|
+
def symbolize(self):
|
|
2030
|
+
# clear the flag
|
|
2031
|
+
self._symbolization_needed = False
|
|
2032
|
+
|
|
2033
|
+
# sanity checks
|
|
2034
|
+
# if self._has_integer_used_as_pointers():
|
|
2035
|
+
# raise ReassemblerFailureNotice('Integer-used-as-pointer detected. Reassembler will not work safely on '
|
|
2036
|
+
# 'this binary. Ping Fish if you believe the detection is wrong.'
|
|
2037
|
+
# )
|
|
2038
|
+
|
|
2039
|
+
for proc in self.procedures:
|
|
2040
|
+
proc.assign_labels()
|
|
2041
|
+
|
|
2042
|
+
for data in self.data:
|
|
2043
|
+
data.assign_labels()
|
|
2044
|
+
|
|
2045
|
+
# Get all instruction addresses, and modify those labels pointing to the middle of an instruction
|
|
2046
|
+
insn_addrs = []
|
|
2047
|
+
proc: Procedure
|
|
2048
|
+
for proc in self.procedures:
|
|
2049
|
+
insn_addrs.extend(proc.instruction_addresses())
|
|
2050
|
+
# just to be safe
|
|
2051
|
+
insn_addrs = sorted(set(insn_addrs), key=lambda x: x[0])
|
|
2052
|
+
|
|
2053
|
+
pos = 0
|
|
2054
|
+
|
|
2055
|
+
changed_labels = []
|
|
2056
|
+
|
|
2057
|
+
for label_addr in sorted(self.symbol_manager.addr_to_label.keys()):
|
|
2058
|
+
while pos < len(insn_addrs) and label_addr > insn_addrs[pos][0]:
|
|
2059
|
+
pos += 1
|
|
2060
|
+
|
|
2061
|
+
if pos >= len(insn_addrs):
|
|
2062
|
+
break
|
|
2063
|
+
|
|
2064
|
+
if pos == 0:
|
|
2065
|
+
continue
|
|
2066
|
+
|
|
2067
|
+
insn_addr, insn_size = insn_addrs[pos - 1]
|
|
2068
|
+
|
|
2069
|
+
if insn_addr < label_addr < insn_addr + insn_size:
|
|
2070
|
+
# this label should be converted to something like 0x8000040+1
|
|
2071
|
+
labels = self.symbol_manager.addr_to_label[label_addr]
|
|
2072
|
+
for label in labels:
|
|
2073
|
+
label.base_addr = insn_addrs[pos][0]
|
|
2074
|
+
changed_labels.append(label)
|
|
2075
|
+
|
|
2076
|
+
for label in changed_labels:
|
|
2077
|
+
self.symbol_manager.addr_to_label[label.original_addr].remove(label)
|
|
2078
|
+
if not self.symbol_manager.addr_to_label[label.original_addr]:
|
|
2079
|
+
del self.symbol_manager.addr_to_label[label.original_addr]
|
|
2080
|
+
self.symbol_manager.addr_to_label[label.base_addr].append(label)
|
|
2081
|
+
|
|
2082
|
+
if changed_labels:
|
|
2083
|
+
for proc in self.procedures:
|
|
2084
|
+
proc.assign_labels()
|
|
2085
|
+
|
|
2086
|
+
def assembly(self, comments=False, symbolized=True):
|
|
2087
|
+
if symbolized and self._symbolization_needed:
|
|
2088
|
+
self.symbolize()
|
|
2089
|
+
|
|
2090
|
+
if self._remove_cgc_attachments:
|
|
2091
|
+
self._cgc_attachments_removed = self.remove_cgc_attachments()
|
|
2092
|
+
|
|
2093
|
+
s = ""
|
|
2094
|
+
|
|
2095
|
+
if self.syntax == "intel":
|
|
2096
|
+
s += "\t.intel_syntax noprefix\n"
|
|
2097
|
+
|
|
2098
|
+
all_assembly_lines = []
|
|
2099
|
+
|
|
2100
|
+
addr_and_assembly = []
|
|
2101
|
+
for proc in self.procedures:
|
|
2102
|
+
addr_and_assembly.extend(proc.assembly(comments=comments, symbolized=symbolized))
|
|
2103
|
+
# sort it by the address - must be a stable sort!
|
|
2104
|
+
addr_and_assembly = sorted(addr_and_assembly, key=lambda x: x[0] if x[0] is not None else -1)
|
|
2105
|
+
all_assembly_lines.extend(line for _, line in addr_and_assembly)
|
|
2106
|
+
|
|
2107
|
+
last_section = None
|
|
2108
|
+
|
|
2109
|
+
if self._cgc_attachments_removed:
|
|
2110
|
+
all_data = self.data + self.extra_rodata + self.extra_data
|
|
2111
|
+
else:
|
|
2112
|
+
# to reduce memory usage, we put extra data in front of the original data in binary
|
|
2113
|
+
all_data = self.extra_data + self.data + self.extra_rodata
|
|
2114
|
+
|
|
2115
|
+
for data in all_data:
|
|
2116
|
+
if last_section is None or data.section_name != last_section:
|
|
2117
|
+
last_section = data.section_name
|
|
2118
|
+
all_assembly_lines.append(
|
|
2119
|
+
"\t.section {section}\n\t.align {alignment}".format(
|
|
2120
|
+
section=(last_section if last_section != ".init_array" else ".data"),
|
|
2121
|
+
alignment=self.section_alignment(last_section),
|
|
2122
|
+
)
|
|
2123
|
+
)
|
|
2124
|
+
all_assembly_lines.append(data.assembly(comments=comments, symbolized=symbolized))
|
|
2125
|
+
|
|
2126
|
+
s += "\n".join(all_assembly_lines)
|
|
2127
|
+
|
|
2128
|
+
return s
|
|
2129
|
+
|
|
2130
|
+
def remove_cgc_attachments(self):
|
|
2131
|
+
"""
|
|
2132
|
+
Remove CGC attachments.
|
|
2133
|
+
|
|
2134
|
+
:return: True if CGC attachments are found and removed, False otherwise
|
|
2135
|
+
:rtype: bool
|
|
2136
|
+
"""
|
|
2137
|
+
|
|
2138
|
+
cgc_package_list = None
|
|
2139
|
+
cgc_extended_application = None
|
|
2140
|
+
|
|
2141
|
+
for data in self.data:
|
|
2142
|
+
if data.sort == "cgc-package-list":
|
|
2143
|
+
cgc_package_list = data
|
|
2144
|
+
elif data.sort == "cgc-extended-application":
|
|
2145
|
+
cgc_extended_application = data
|
|
2146
|
+
|
|
2147
|
+
if not cgc_package_list or not cgc_extended_application:
|
|
2148
|
+
return False
|
|
2149
|
+
|
|
2150
|
+
if cgc_package_list.skip or cgc_extended_application.skip:
|
|
2151
|
+
# they have already been removed
|
|
2152
|
+
# so we still return True to indicate that CGC attachments have been removed
|
|
2153
|
+
return True
|
|
2154
|
+
|
|
2155
|
+
# there is a single function referencing them
|
|
2156
|
+
cgcpl_memory_data = self.cfg.memory_data.get(cgc_package_list.addr, None)
|
|
2157
|
+
cgcea_memory_data = self.cfg.memory_data.get(cgc_extended_application.addr, None)
|
|
2158
|
+
refs = self.cfg.kb.xrefs
|
|
2159
|
+
|
|
2160
|
+
if cgcpl_memory_data is None or cgcea_memory_data is None:
|
|
2161
|
+
return False
|
|
2162
|
+
|
|
2163
|
+
if len(refs.get_xrefs_by_dst(cgcpl_memory_data.addr)) != 1:
|
|
2164
|
+
return False
|
|
2165
|
+
if len(refs.get_xrefs_by_dst(cgcea_memory_data.addr)) != 1:
|
|
2166
|
+
return False
|
|
2167
|
+
|
|
2168
|
+
# check if the irsb addresses are the same
|
|
2169
|
+
if (
|
|
2170
|
+
next(iter(refs.get_xrefs_by_dst(cgcpl_memory_data.addr))).block_addr
|
|
2171
|
+
!= next(iter(refs.get_xrefs_by_dst(cgcea_memory_data.addr))).block_addr
|
|
2172
|
+
):
|
|
2173
|
+
return False
|
|
2174
|
+
|
|
2175
|
+
insn_addr = next(iter(refs.get_xrefs_by_dst(cgcpl_memory_data.addr))).ins_addr
|
|
2176
|
+
# get the basic block
|
|
2177
|
+
cfg_node = self.cfg.model.get_any_node(insn_addr, anyaddr=True)
|
|
2178
|
+
if not cfg_node:
|
|
2179
|
+
return False
|
|
2180
|
+
|
|
2181
|
+
func_addr = cfg_node.function_address
|
|
2182
|
+
|
|
2183
|
+
# this function should be calling another function
|
|
2184
|
+
sub_func_addr = None
|
|
2185
|
+
if func_addr not in self.cfg.functions:
|
|
2186
|
+
return False
|
|
2187
|
+
function = self.cfg.functions[func_addr]
|
|
2188
|
+
# traverse the graph and make sure there is only one call edge
|
|
2189
|
+
calling_targets = []
|
|
2190
|
+
for _, dst, data in function.transition_graph.edges(data=True):
|
|
2191
|
+
if "type" in data and data["type"] == "call":
|
|
2192
|
+
calling_targets.append(dst.addr)
|
|
2193
|
+
|
|
2194
|
+
if len(calling_targets) != 1:
|
|
2195
|
+
return False
|
|
2196
|
+
|
|
2197
|
+
sub_func_addr = calling_targets[0]
|
|
2198
|
+
|
|
2199
|
+
# alright. We want to nop this function, as well as the subfunction
|
|
2200
|
+
proc = next((p for p in self.procedures if p.addr == func_addr), None)
|
|
2201
|
+
if proc is None:
|
|
2202
|
+
return False
|
|
2203
|
+
|
|
2204
|
+
subproc = next((p for p in self.procedures if p.addr == sub_func_addr), None)
|
|
2205
|
+
if subproc is None:
|
|
2206
|
+
return False
|
|
2207
|
+
|
|
2208
|
+
# if those two data entries have any label, we should properly modify them
|
|
2209
|
+
# at this point, we are fairly confident that none of those labels are direct data references to either package
|
|
2210
|
+
# list or extended application
|
|
2211
|
+
has_label = True
|
|
2212
|
+
lowest_address = min(cgc_package_list.addr, cgc_extended_application.addr)
|
|
2213
|
+
for obj in (cgc_package_list, cgc_extended_application):
|
|
2214
|
+
labels = obj.labels
|
|
2215
|
+
for addr, label in labels:
|
|
2216
|
+
if addr != lowest_address:
|
|
2217
|
+
label.base_addr = lowest_address
|
|
2218
|
+
|
|
2219
|
+
if has_label:
|
|
2220
|
+
# is there any memory data entry that ends right at the lowest address?
|
|
2221
|
+
data = next((d for d in self.data if d.addr is not None and d.addr + d.size == lowest_address), None)
|
|
2222
|
+
if data is None:
|
|
2223
|
+
# since there is no gap between memory data entries (we guarantee that), this can only be that no other
|
|
2224
|
+
# data resides in the same memory region that CGC attachments are in
|
|
2225
|
+
pass
|
|
2226
|
+
else:
|
|
2227
|
+
lbl = self.symbol_manager.addr_to_label[lowest_address][0]
|
|
2228
|
+
if lbl not in data.end_labels:
|
|
2229
|
+
data.end_labels.append(lbl)
|
|
2230
|
+
|
|
2231
|
+
# practically nop the function
|
|
2232
|
+
proc.asm_code = "\tret\n"
|
|
2233
|
+
subproc.asm_code = "\tret\n"
|
|
2234
|
+
|
|
2235
|
+
# remove those two data entries
|
|
2236
|
+
cgc_package_list.skip = True
|
|
2237
|
+
cgc_extended_application.skip = True
|
|
2238
|
+
|
|
2239
|
+
l.info("CGC attachments are removed.")
|
|
2240
|
+
|
|
2241
|
+
return True
|
|
2242
|
+
|
|
2243
|
+
def remove_unnecessary_stuff(self):
|
|
2244
|
+
"""
|
|
2245
|
+
Remove unnecessary functions and data
|
|
2246
|
+
|
|
2247
|
+
:return: None
|
|
2248
|
+
"""
|
|
2249
|
+
|
|
2250
|
+
# determine if the binary is compiled against glibc
|
|
2251
|
+
is_glibc = False
|
|
2252
|
+
for dep in self.project.loader.main_object.deps:
|
|
2253
|
+
if dep.lower() in {"libc.so.6", "libc.so"}:
|
|
2254
|
+
is_glibc = True
|
|
2255
|
+
break
|
|
2256
|
+
if is_glibc:
|
|
2257
|
+
self.remove_unnecessary_stuff_glibc()
|
|
2258
|
+
|
|
2259
|
+
def remove_unnecessary_stuff_glibc(self):
|
|
2260
|
+
glibc_functions_blacklist = {
|
|
2261
|
+
"_start",
|
|
2262
|
+
"init",
|
|
2263
|
+
"_init",
|
|
2264
|
+
"fini",
|
|
2265
|
+
"_fini",
|
|
2266
|
+
"__gmon_start__",
|
|
2267
|
+
"__do_global_dtors_aux",
|
|
2268
|
+
"frame_dummy",
|
|
2269
|
+
"atexit",
|
|
2270
|
+
"deregister_tm_clones",
|
|
2271
|
+
"register_tm_clones",
|
|
2272
|
+
"__x86.get_pc_thunk.bx",
|
|
2273
|
+
"__libc_csu_init",
|
|
2274
|
+
"__libc_csu_fini",
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
glibc_data_blacklist = {
|
|
2278
|
+
"__TMC_END__",
|
|
2279
|
+
"_GLOBAL_OFFSET_TABLE_",
|
|
2280
|
+
"__JCR_END__",
|
|
2281
|
+
"__dso_handle",
|
|
2282
|
+
"__init_array_start",
|
|
2283
|
+
"__init_array_end",
|
|
2284
|
+
#
|
|
2285
|
+
"stdout",
|
|
2286
|
+
"stderr",
|
|
2287
|
+
"stdin",
|
|
2288
|
+
"program_invocation_short_",
|
|
2289
|
+
"program_invocation_short_name",
|
|
2290
|
+
"program_invocation_name",
|
|
2291
|
+
"__progname_full",
|
|
2292
|
+
"_IO_stdin_used",
|
|
2293
|
+
"obstack_alloc_failed_hand",
|
|
2294
|
+
"optind",
|
|
2295
|
+
"optarg",
|
|
2296
|
+
"__progname",
|
|
2297
|
+
"_environ",
|
|
2298
|
+
"environ",
|
|
2299
|
+
"__environ",
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
glibc_references_blacklist = {
|
|
2303
|
+
"frame_dummy",
|
|
2304
|
+
"__do_global_dtors_aux",
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
self.procedures = [p for p in self.procedures if p.name not in glibc_functions_blacklist and not p.is_plt]
|
|
2308
|
+
|
|
2309
|
+
# special handling for _init_proc
|
|
2310
|
+
try:
|
|
2311
|
+
init_func = self.cfg.functions["init"]
|
|
2312
|
+
callees = [
|
|
2313
|
+
node
|
|
2314
|
+
for node in init_func.transition_graph.nodes()
|
|
2315
|
+
if isinstance(node, Function) and node.addr != self.cfg._unresolvable_call_target_addr
|
|
2316
|
+
]
|
|
2317
|
+
# special handling for GCC-generated X86 PIE binaries
|
|
2318
|
+
non_getpc_callees = [callee for callee in callees if "get_pc" not in callee.info]
|
|
2319
|
+
if len(non_getpc_callees) == 1:
|
|
2320
|
+
# we found the _init_proc
|
|
2321
|
+
_init_proc = non_getpc_callees[0]
|
|
2322
|
+
self.procedures = [p for p in self.procedures if p.addr != _init_proc.addr]
|
|
2323
|
+
except KeyError:
|
|
2324
|
+
pass
|
|
2325
|
+
|
|
2326
|
+
self.data = [d for d in self.data if not any(lbl.name in glibc_data_blacklist for _, lbl in d.labels)]
|
|
2327
|
+
|
|
2328
|
+
for d in self.data:
|
|
2329
|
+
if d.sort == MemoryDataSort.PointerArray:
|
|
2330
|
+
for i in range(len(d.content)):
|
|
2331
|
+
ptr = d.content[i]
|
|
2332
|
+
if isinstance(ptr, Label) and ptr.name in glibc_references_blacklist:
|
|
2333
|
+
d.content[i] = 0
|
|
2334
|
+
elif d.sort == MemoryDataSort.SegmentBoundary and d.labels:
|
|
2335
|
+
new_labels = []
|
|
2336
|
+
for rebased_addr, label in d.labels:
|
|
2337
|
+
# check if this label belongs to a removed function
|
|
2338
|
+
if (
|
|
2339
|
+
self.cfg.functions.contains_addr(rebased_addr)
|
|
2340
|
+
and self.cfg.functions[rebased_addr].name in glibc_functions_blacklist
|
|
2341
|
+
):
|
|
2342
|
+
# we need to remove this label...
|
|
2343
|
+
continue
|
|
2344
|
+
new_labels.append((rebased_addr, label))
|
|
2345
|
+
d.labels = new_labels
|
|
2346
|
+
|
|
2347
|
+
#
|
|
2348
|
+
# Private methods
|
|
2349
|
+
#
|
|
2350
|
+
|
|
2351
|
+
def _initialize(self):
|
|
2352
|
+
"""
|
|
2353
|
+
Initialize the binary.
|
|
2354
|
+
|
|
2355
|
+
:return: None
|
|
2356
|
+
"""
|
|
2357
|
+
|
|
2358
|
+
# figure out section alignments
|
|
2359
|
+
for section in self.project.loader.main_object.sections:
|
|
2360
|
+
in_segment = False
|
|
2361
|
+
for segment in self.project.loader.main_object.segments:
|
|
2362
|
+
segment_addr = segment.vaddr
|
|
2363
|
+
if segment_addr <= section.vaddr < segment_addr + segment.memsize:
|
|
2364
|
+
in_segment = True
|
|
2365
|
+
break
|
|
2366
|
+
if not in_segment:
|
|
2367
|
+
continue
|
|
2368
|
+
|
|
2369
|
+
# calculate alignments
|
|
2370
|
+
if section.vaddr % 0x20 == 0:
|
|
2371
|
+
alignment = 0x20
|
|
2372
|
+
elif section.vaddr % 0x10 == 0:
|
|
2373
|
+
alignment = 0x10
|
|
2374
|
+
elif section.vaddr % 0x8 == 0:
|
|
2375
|
+
alignment = 0x8
|
|
2376
|
+
elif section.vaddr % 0x4 == 0:
|
|
2377
|
+
alignment = 0x4
|
|
2378
|
+
else:
|
|
2379
|
+
alignment = 2
|
|
2380
|
+
|
|
2381
|
+
self._section_alignments[section.name] = alignment
|
|
2382
|
+
|
|
2383
|
+
l.debug("Generating CFG...")
|
|
2384
|
+
cfg = self.project.analyses[CFGFast].prep()(
|
|
2385
|
+
normalize=True,
|
|
2386
|
+
resolve_indirect_jumps=True,
|
|
2387
|
+
data_references=True,
|
|
2388
|
+
extra_memory_regions=self._extra_memory_regions,
|
|
2389
|
+
data_type_guessing_handlers=[
|
|
2390
|
+
self._sequence_handler,
|
|
2391
|
+
self._cgc_extended_application_handler,
|
|
2392
|
+
self._unknown_data_size_handler,
|
|
2393
|
+
],
|
|
2394
|
+
)
|
|
2395
|
+
|
|
2396
|
+
self.cfg = cfg
|
|
2397
|
+
|
|
2398
|
+
old_capstone_syntax = self.project.arch.capstone_x86_syntax
|
|
2399
|
+
if old_capstone_syntax is None:
|
|
2400
|
+
old_capstone_syntax = "intel"
|
|
2401
|
+
|
|
2402
|
+
if self.syntax == "at&t":
|
|
2403
|
+
# switch capstone to AT&T style
|
|
2404
|
+
self.project.arch.capstone_x86_syntax = "at&t"
|
|
2405
|
+
# clear the block cache in lifter!
|
|
2406
|
+
self.project.factory.default_engine.clear_cache()
|
|
2407
|
+
|
|
2408
|
+
# initialize symbol manager
|
|
2409
|
+
self.symbol_manager = SymbolManager(self, cfg)
|
|
2410
|
+
|
|
2411
|
+
# collect address of all instructions
|
|
2412
|
+
l.debug("Collecting instruction addresses...")
|
|
2413
|
+
for cfg_node in self.cfg.model.nodes():
|
|
2414
|
+
self.all_insn_addrs |= set(cfg_node.instruction_addrs)
|
|
2415
|
+
|
|
2416
|
+
# Functions
|
|
2417
|
+
|
|
2418
|
+
l.debug("Creating functions...")
|
|
2419
|
+
for f in cfg.kb.functions.values():
|
|
2420
|
+
# Skip all SimProcedures
|
|
2421
|
+
if self.project.is_hooked(f.addr) or self.project.simos.is_syscall_addr(f.addr):
|
|
2422
|
+
continue
|
|
2423
|
+
|
|
2424
|
+
# Check which section the start address belongs to
|
|
2425
|
+
section = next(
|
|
2426
|
+
iter(
|
|
2427
|
+
sec.name
|
|
2428
|
+
for sec in self.project.loader.main_object.sections
|
|
2429
|
+
if f.addr >= sec.vaddr and f.addr < sec.vaddr + sec.memsize
|
|
2430
|
+
),
|
|
2431
|
+
".text",
|
|
2432
|
+
)
|
|
2433
|
+
|
|
2434
|
+
if section in {".got", ".plt", "init", "fini", ".init", ".fini"}:
|
|
2435
|
+
continue
|
|
2436
|
+
|
|
2437
|
+
procedure = Procedure(self, function=f, section=section)
|
|
2438
|
+
self.procedures.append(procedure)
|
|
2439
|
+
|
|
2440
|
+
self.procedures = sorted(self.procedures, key=lambda x: x.addr)
|
|
2441
|
+
|
|
2442
|
+
# Data
|
|
2443
|
+
|
|
2444
|
+
has_sections = len(self.project.loader.main_object.sections) > 0
|
|
2445
|
+
|
|
2446
|
+
l.debug("Creating data entries...")
|
|
2447
|
+
for addr, memory_data in cfg._memory_data.items():
|
|
2448
|
+
if memory_data.sort in ("code reference",):
|
|
2449
|
+
continue
|
|
2450
|
+
|
|
2451
|
+
if memory_data.sort == "string":
|
|
2452
|
+
# it might be the CGC package list
|
|
2453
|
+
new_sort, new_size = self._cgc_package_list_identifier(memory_data.address, memory_data.size)
|
|
2454
|
+
if new_sort is not None:
|
|
2455
|
+
# oh we got it!
|
|
2456
|
+
memory_data = memory_data.copy()
|
|
2457
|
+
memory_data.sort = new_sort
|
|
2458
|
+
|
|
2459
|
+
if has_sections:
|
|
2460
|
+
# Check which section the start address belongs to
|
|
2461
|
+
section = next(
|
|
2462
|
+
iter(
|
|
2463
|
+
sec
|
|
2464
|
+
for sec in self.project.loader.main_object.sections
|
|
2465
|
+
if sec.vaddr <= addr < sec.vaddr + sec.memsize
|
|
2466
|
+
),
|
|
2467
|
+
None,
|
|
2468
|
+
)
|
|
2469
|
+
|
|
2470
|
+
if section is not None and section.name not in (".note.gnu.build-id",): # ignore certain section names
|
|
2471
|
+
data = Data(self, memory_data, section=section)
|
|
2472
|
+
self.data.append(data)
|
|
2473
|
+
elif memory_data.sort == "segment-boundary":
|
|
2474
|
+
# it just points to the end of the segment or a section
|
|
2475
|
+
section = next(
|
|
2476
|
+
iter(
|
|
2477
|
+
sec for sec in self.project.loader.main_object.sections if addr == sec.vaddr + sec.memsize
|
|
2478
|
+
),
|
|
2479
|
+
None,
|
|
2480
|
+
)
|
|
2481
|
+
if section is not None:
|
|
2482
|
+
data = Data(self, memory_data, section=section)
|
|
2483
|
+
self.data.append(data)
|
|
2484
|
+
|
|
2485
|
+
else:
|
|
2486
|
+
# data = Data(self, memory_data, section_name='.data')
|
|
2487
|
+
# the data is not really within any existing section. weird. ignored it.
|
|
2488
|
+
pass
|
|
2489
|
+
else:
|
|
2490
|
+
# the binary does not have any section
|
|
2491
|
+
# we use segment information instead
|
|
2492
|
+
# TODO: this logic needs reviewing
|
|
2493
|
+
segment = next(
|
|
2494
|
+
iter(
|
|
2495
|
+
seg
|
|
2496
|
+
for seg in self.project.loader.main_object.segments
|
|
2497
|
+
if seg.vaddr <= addr <= seg.vaddr + seg.memsize
|
|
2498
|
+
),
|
|
2499
|
+
None,
|
|
2500
|
+
)
|
|
2501
|
+
|
|
2502
|
+
if segment is not None:
|
|
2503
|
+
data = Data(self, memory_data, section_name=".data")
|
|
2504
|
+
self.data.append(data)
|
|
2505
|
+
|
|
2506
|
+
# remove all data that belong to GCC-specific sections
|
|
2507
|
+
section_names_to_ignore = {
|
|
2508
|
+
".init",
|
|
2509
|
+
".fini",
|
|
2510
|
+
".fini_array",
|
|
2511
|
+
".jcr",
|
|
2512
|
+
".dynamic",
|
|
2513
|
+
".got",
|
|
2514
|
+
".got.plt",
|
|
2515
|
+
".eh_frame_hdr",
|
|
2516
|
+
".eh_frame",
|
|
2517
|
+
".rel.dyn",
|
|
2518
|
+
".rel.plt",
|
|
2519
|
+
".rela.dyn",
|
|
2520
|
+
".rela.plt",
|
|
2521
|
+
".dynstr",
|
|
2522
|
+
".dynsym",
|
|
2523
|
+
".interp",
|
|
2524
|
+
".note.ABI-tag",
|
|
2525
|
+
".note.gnu.build-id",
|
|
2526
|
+
".gnu.hash",
|
|
2527
|
+
".gnu.version",
|
|
2528
|
+
".gnu.version_r",
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
# make sure there are always memory data entries pointing at the end of sections
|
|
2532
|
+
all_data_addrs = {d.addr for d in self.data}
|
|
2533
|
+
all_procedure_addrs = {f.addr for f in self.procedures}
|
|
2534
|
+
all_addrs = all_data_addrs | all_procedure_addrs
|
|
2535
|
+
|
|
2536
|
+
if has_sections:
|
|
2537
|
+
for section in self.project.loader.main_object.sections:
|
|
2538
|
+
if section.name in section_names_to_ignore:
|
|
2539
|
+
# skip all sections that are CGC specific
|
|
2540
|
+
continue
|
|
2541
|
+
|
|
2542
|
+
# make sure this section is not empty
|
|
2543
|
+
if section.memsize == 0:
|
|
2544
|
+
continue
|
|
2545
|
+
|
|
2546
|
+
# make sure this section is inside a segment
|
|
2547
|
+
for segment in self.project.loader.main_object.segments:
|
|
2548
|
+
segment_start = segment.vaddr
|
|
2549
|
+
segment_end = segment_start + segment.memsize
|
|
2550
|
+
if segment_start <= section.vaddr < segment_end:
|
|
2551
|
+
break
|
|
2552
|
+
else:
|
|
2553
|
+
# this section is not mapped into memory
|
|
2554
|
+
continue
|
|
2555
|
+
|
|
2556
|
+
section_boundary_addr = section.vaddr + section.memsize
|
|
2557
|
+
if section_boundary_addr not in all_addrs:
|
|
2558
|
+
data = Data(
|
|
2559
|
+
self, addr=section_boundary_addr, size=0, sort="segment-boundary", section_name=section.name
|
|
2560
|
+
)
|
|
2561
|
+
self.data.append(data)
|
|
2562
|
+
# add the address to all_data_addrs so we don't end up adding another boundary in
|
|
2563
|
+
all_data_addrs.add(section_boundary_addr)
|
|
2564
|
+
|
|
2565
|
+
self.data = sorted(self.data, key=lambda x: x.addr)
|
|
2566
|
+
|
|
2567
|
+
data_indices_to_remove = set()
|
|
2568
|
+
|
|
2569
|
+
# Go through data entry list and refine them
|
|
2570
|
+
for i, data in enumerate(self.data):
|
|
2571
|
+
if i in data_indices_to_remove:
|
|
2572
|
+
continue
|
|
2573
|
+
|
|
2574
|
+
# process the overlapping ones
|
|
2575
|
+
if i < len(self.data) - 1 and data.addr + data.size > self.data[i + 1].addr:
|
|
2576
|
+
# they are overlapping :-(
|
|
2577
|
+
|
|
2578
|
+
# TODO: make sure new_size makes sense
|
|
2579
|
+
new_size = self.data[i + 1].addr - data.addr
|
|
2580
|
+
|
|
2581
|
+
# there are cases that legit data is misclassified as pointers
|
|
2582
|
+
# we are able to detect some of them here
|
|
2583
|
+
if data.sort == "pointer-array":
|
|
2584
|
+
pointer_size = self.project.arch.bytes
|
|
2585
|
+
if new_size % pointer_size != 0:
|
|
2586
|
+
# the self.data[i+1] cannot be pointed to by a pointer
|
|
2587
|
+
# remove that guy later
|
|
2588
|
+
data_indices_to_remove.add(i + 1)
|
|
2589
|
+
# mark the source as a non-pointer
|
|
2590
|
+
# apparently the original Reassembleable Disassembler paper cannot get this case
|
|
2591
|
+
source_addr = self.data[i + 1].memory_data.pointer_addr
|
|
2592
|
+
if source_addr is not None:
|
|
2593
|
+
# find the original data
|
|
2594
|
+
original_data = next(
|
|
2595
|
+
(d for d in self.data if d.addr <= source_addr < d.addr + d.size), None
|
|
2596
|
+
)
|
|
2597
|
+
if original_data is not None:
|
|
2598
|
+
original_data.desymbolize()
|
|
2599
|
+
|
|
2600
|
+
continue
|
|
2601
|
+
|
|
2602
|
+
data.shrink(new_size)
|
|
2603
|
+
|
|
2604
|
+
# process those ones whose type is unknown
|
|
2605
|
+
if data.sort == "unknown" and data.size == 0:
|
|
2606
|
+
# increase its size until reaching the next item
|
|
2607
|
+
|
|
2608
|
+
if i + 1 == len(self.data):
|
|
2609
|
+
if data.section is None:
|
|
2610
|
+
continue
|
|
2611
|
+
data.size = data.section.vaddr + data.section.memsize - data.addr
|
|
2612
|
+
else:
|
|
2613
|
+
data.size = self.data[i + 1].addr - data.addr
|
|
2614
|
+
|
|
2615
|
+
for i in sorted(data_indices_to_remove, reverse=True):
|
|
2616
|
+
self.data = self.data[:i] + self.data[i + 1 :]
|
|
2617
|
+
|
|
2618
|
+
# CGC-specific data filtering
|
|
2619
|
+
self.data = [d for d in self.data if d.section_name not in section_names_to_ignore]
|
|
2620
|
+
|
|
2621
|
+
# restore capstone X86 syntax at the end
|
|
2622
|
+
if self.project.arch.capstone_x86_syntax != old_capstone_syntax:
|
|
2623
|
+
self.project.arch.capstone_x86_syntax = old_capstone_syntax
|
|
2624
|
+
self.project.factory.default_engine.clear_cache()
|
|
2625
|
+
|
|
2626
|
+
l.debug("Initialized.")
|
|
2627
|
+
|
|
2628
|
+
def _is_sequence(self, cfg, addr, size):
|
|
2629
|
+
data = self.fast_memory_load(addr, size, bytes)
|
|
2630
|
+
if data is None:
|
|
2631
|
+
return False
|
|
2632
|
+
ints = list(data)
|
|
2633
|
+
if len({(i - j) for i, j in zip(ints, ints[1:])}) == 1:
|
|
2634
|
+
# arithmetic progression
|
|
2635
|
+
# backoff: it should not be ending with a pointer
|
|
2636
|
+
closest_aligned_addr = (addr + size - 1) & 0xFFFFFFFC
|
|
2637
|
+
ptr = self.fast_memory_load(closest_aligned_addr, 4, int, endness=self.project.arch.memory_endness)
|
|
2638
|
+
if ptr is None:
|
|
2639
|
+
return False
|
|
2640
|
+
return not self._is_pointer(cfg, ptr)
|
|
2641
|
+
return False
|
|
2642
|
+
|
|
2643
|
+
def _is_pointer(self, cfg, ptr):
|
|
2644
|
+
return bool(
|
|
2645
|
+
cfg.project.loader.find_section_containing(ptr) is not None
|
|
2646
|
+
or cfg.project.loader.find_segment_containing(ptr) is not None
|
|
2647
|
+
or (self._extra_memory_regions and next((a < ptr < b for a, b in self._extra_memory_regions), None))
|
|
2648
|
+
)
|
|
2649
|
+
|
|
2650
|
+
def _sequence_handler(self, cfg, irsb, irsb_addr, stmt_idx, data_addr, max_size): # pylint:disable=unused-argument
|
|
2651
|
+
"""
|
|
2652
|
+
Find sequences in binary data.
|
|
2653
|
+
|
|
2654
|
+
:param angr.analyses.CFG cfg: The control flow graph.
|
|
2655
|
+
:param pyvex.IRSB irsb: The IRSB object.
|
|
2656
|
+
:param int irsb_addr: Address of the block.
|
|
2657
|
+
:param int stmt_idx: Statement ID.
|
|
2658
|
+
:param int data_addr: Address of the data in memory.
|
|
2659
|
+
:param int max_size: Maximum size possible.
|
|
2660
|
+
:return: A 2-tuple of data type and size.
|
|
2661
|
+
:rtype: tuple
|
|
2662
|
+
"""
|
|
2663
|
+
|
|
2664
|
+
if not self._is_sequence(cfg, data_addr, 5):
|
|
2665
|
+
# fail-fast
|
|
2666
|
+
return None, None
|
|
2667
|
+
|
|
2668
|
+
sequence_max_size = min(256, max_size)
|
|
2669
|
+
|
|
2670
|
+
for i in range(5, min(256, max_size)):
|
|
2671
|
+
if not self._is_sequence(cfg, data_addr, i):
|
|
2672
|
+
return "sequence", i - 1
|
|
2673
|
+
|
|
2674
|
+
return "sequence", sequence_max_size
|
|
2675
|
+
|
|
2676
|
+
def _cgc_package_list_identifier(self, data_addr, data_size):
|
|
2677
|
+
"""
|
|
2678
|
+
Identifies the CGC package list associated with the CGC binary.
|
|
2679
|
+
|
|
2680
|
+
:param int data_addr: Address of the data in memory.
|
|
2681
|
+
:param int data_size: Maximum size possible.
|
|
2682
|
+
:return: A 2-tuple of data type and size.
|
|
2683
|
+
:rtype: tuple
|
|
2684
|
+
"""
|
|
2685
|
+
|
|
2686
|
+
if data_size < 100:
|
|
2687
|
+
return None, None
|
|
2688
|
+
|
|
2689
|
+
data = self.fast_memory_load(data_addr, data_size, str)
|
|
2690
|
+
|
|
2691
|
+
if data[:10] != "The DECREE":
|
|
2692
|
+
return None, None
|
|
2693
|
+
|
|
2694
|
+
if not all(i in string.printable for i in data):
|
|
2695
|
+
return None, None
|
|
2696
|
+
|
|
2697
|
+
if not re.match(r"The DECREE packages used in the creation of this challenge binary were:", data):
|
|
2698
|
+
return None, None
|
|
2699
|
+
|
|
2700
|
+
return "cgc-package-list", data_size
|
|
2701
|
+
|
|
2702
|
+
def _cgc_extended_application_handler(
|
|
2703
|
+
self, cfg, irsb, irsb_addr, stmt_idx, data_addr, max_size
|
|
2704
|
+
): # pylint:disable=unused-argument
|
|
2705
|
+
"""
|
|
2706
|
+
Identifies the extended application (a PDF file) associated with the CGC binary.
|
|
2707
|
+
|
|
2708
|
+
:param angr.analyses.CFG cfg: The control flow graph.
|
|
2709
|
+
:param pyvex.IRSB irsb: The IRSB object.
|
|
2710
|
+
:param int irsb_addr: Address of the block.
|
|
2711
|
+
:param int stmt_idx: Statement ID.
|
|
2712
|
+
:param int data_addr: Address of the data in memory.
|
|
2713
|
+
:param int max_size: Maximum size possible.
|
|
2714
|
+
:return: A 2-tuple of data type and size.
|
|
2715
|
+
:rtype: tuple
|
|
2716
|
+
"""
|
|
2717
|
+
|
|
2718
|
+
if max_size < 100:
|
|
2719
|
+
return None, None
|
|
2720
|
+
|
|
2721
|
+
data = self.fast_memory_load(data_addr, 20, bytes)
|
|
2722
|
+
|
|
2723
|
+
if data is not None and data[:4] != b"The ":
|
|
2724
|
+
return None, None
|
|
2725
|
+
|
|
2726
|
+
# read everything in
|
|
2727
|
+
data = self.fast_memory_load(data_addr, max_size, str)
|
|
2728
|
+
|
|
2729
|
+
m = re.match(r"The ([\d]+) byte CGC Extended Application follows.", data)
|
|
2730
|
+
if not m:
|
|
2731
|
+
return None, None
|
|
2732
|
+
pdf_size = int(m.group(1))
|
|
2733
|
+
|
|
2734
|
+
if "%PDF" not in data:
|
|
2735
|
+
return None, None
|
|
2736
|
+
if "%%EOF" not in data:
|
|
2737
|
+
return None, None
|
|
2738
|
+
|
|
2739
|
+
pdf_data = data[data.index("%PDF") : data.index("%%EOF") + 6]
|
|
2740
|
+
|
|
2741
|
+
if len(pdf_data) != pdf_size:
|
|
2742
|
+
return None, None
|
|
2743
|
+
|
|
2744
|
+
return "cgc-extended-application", max_size
|
|
2745
|
+
|
|
2746
|
+
def _unknown_data_size_handler(
|
|
2747
|
+
self, cfg, irsb, irsb_addr, stmt_idx, data_addr, max_size
|
|
2748
|
+
): # pylint:disable=unused-argument
|
|
2749
|
+
"""
|
|
2750
|
+
Return the maximum number of bytes until a potential pointer or a potential sequence is found.
|
|
2751
|
+
|
|
2752
|
+
:param angr.analyses.CFG cfg: The control flow graph.
|
|
2753
|
+
:param pyvex.IRSB irsb: The IRSB object.
|
|
2754
|
+
:param int irsb_addr: Address of the block.
|
|
2755
|
+
:param int stmt_idx: Statement ID.
|
|
2756
|
+
:param int data_addr: Address of the data in memory.
|
|
2757
|
+
:param int max_size: Maximum size possible.
|
|
2758
|
+
:return: A 2-tuple of data type and size.
|
|
2759
|
+
:rtype: tuple
|
|
2760
|
+
"""
|
|
2761
|
+
|
|
2762
|
+
sequence_offset = None
|
|
2763
|
+
|
|
2764
|
+
for offset in range(1, max_size):
|
|
2765
|
+
if self._is_sequence(cfg, data_addr + offset, 5):
|
|
2766
|
+
# a potential sequence is found
|
|
2767
|
+
sequence_offset = offset
|
|
2768
|
+
break
|
|
2769
|
+
|
|
2770
|
+
if sequence_offset is not None:
|
|
2771
|
+
if self.project.arch.bits == 32:
|
|
2772
|
+
max_size = min(max_size, sequence_offset)
|
|
2773
|
+
elif self.project.arch.bits == 64:
|
|
2774
|
+
max_size = min(max_size, sequence_offset + 5) # high 5 bytes might be all zeros...
|
|
2775
|
+
|
|
2776
|
+
ptr_size = cfg.project.arch.bytes
|
|
2777
|
+
|
|
2778
|
+
size = None
|
|
2779
|
+
|
|
2780
|
+
for offset in range(1, max_size - ptr_size + 1):
|
|
2781
|
+
ptr = self.fast_memory_load(data_addr + offset, ptr_size, int, endness=cfg.project.arch.memory_endness)
|
|
2782
|
+
if self._is_pointer(cfg, ptr):
|
|
2783
|
+
size = offset
|
|
2784
|
+
break
|
|
2785
|
+
|
|
2786
|
+
if size is not None:
|
|
2787
|
+
return "unknown", size
|
|
2788
|
+
if sequence_offset is not None:
|
|
2789
|
+
return "unknown", sequence_offset
|
|
2790
|
+
return None, None
|
|
2791
|
+
|
|
2792
|
+
def _has_integer_used_as_pointers(self):
|
|
2793
|
+
"""
|
|
2794
|
+
Test if there is any (suspicious) pointer decryption in the code.
|
|
2795
|
+
|
|
2796
|
+
:return: True if there is any pointer decryption, False otherwise.
|
|
2797
|
+
:rtype: bool
|
|
2798
|
+
"""
|
|
2799
|
+
|
|
2800
|
+
# check all integer accesses and see if there is any integer being used as a pointer later, but it wasn't
|
|
2801
|
+
# classified as a pointer reference
|
|
2802
|
+
|
|
2803
|
+
# we only care about unknown memory data that are 4 bytes long, and is directly referenced from an IRSB
|
|
2804
|
+
candidates = [
|
|
2805
|
+
i
|
|
2806
|
+
for i in self.cfg.memory_data.values()
|
|
2807
|
+
if i.sort in ("unknown", "integer") and i.size == self.project.arch.bytes and i.irsb_addr is not None
|
|
2808
|
+
]
|
|
2809
|
+
|
|
2810
|
+
if not candidates:
|
|
2811
|
+
return False
|
|
2812
|
+
|
|
2813
|
+
for candidate in candidates:
|
|
2814
|
+
# if the candidate is in .bss, we don't care about it
|
|
2815
|
+
sec = self.cfg.project.loader.find_section_containing(candidate.address)
|
|
2816
|
+
if sec.name in (".bss", ".got.plt"):
|
|
2817
|
+
continue
|
|
2818
|
+
|
|
2819
|
+
# execute the single basic block and see how the value is used
|
|
2820
|
+
base_graph = networkx.DiGraph()
|
|
2821
|
+
candidate_node: CFGNode = self.cfg.model.get_any_node(candidate.irsb_addr)
|
|
2822
|
+
if candidate_node is None:
|
|
2823
|
+
continue
|
|
2824
|
+
base_graph.add_node(candidate_node)
|
|
2825
|
+
tmp_kb = KnowledgeBase(self.project)
|
|
2826
|
+
cfg = self.project.analyses[CFGEmulated].prep(kb=tmp_kb)(
|
|
2827
|
+
starts=(candidate.irsb_addr,), keep_state=True, base_graph=base_graph
|
|
2828
|
+
)
|
|
2829
|
+
candidate_irsb = cfg.get_any_irsb(candidate.irsb_addr)
|
|
2830
|
+
ddg = self.project.analyses[DDG].prep(kb=tmp_kb)(cfg=cfg)
|
|
2831
|
+
|
|
2832
|
+
mem_var_node = None
|
|
2833
|
+
for node in ddg.simplified_data_graph.nodes():
|
|
2834
|
+
if isinstance(node.variable, SimMemoryVariable) and node.location.ins_addr == candidate.insn_addr:
|
|
2835
|
+
# found it!
|
|
2836
|
+
mem_var_node = node
|
|
2837
|
+
break
|
|
2838
|
+
else:
|
|
2839
|
+
# mem_var_node is not found
|
|
2840
|
+
continue
|
|
2841
|
+
|
|
2842
|
+
# get a sub graph
|
|
2843
|
+
subgraph = ddg.data_sub_graph(
|
|
2844
|
+
mem_var_node,
|
|
2845
|
+
simplified=False,
|
|
2846
|
+
killing_edges=False,
|
|
2847
|
+
excluding_types={"mem_addr"},
|
|
2848
|
+
)
|
|
2849
|
+
|
|
2850
|
+
# is it used as a memory address anywhere?
|
|
2851
|
+
# TODO:
|
|
2852
|
+
|
|
2853
|
+
# is it used as a jump target?
|
|
2854
|
+
next_tmp = None
|
|
2855
|
+
if isinstance(candidate_irsb.irsb.next, pyvex.IRExpr.RdTmp):
|
|
2856
|
+
next_tmp = candidate_irsb.irsb.next.tmp
|
|
2857
|
+
|
|
2858
|
+
if next_tmp is not None:
|
|
2859
|
+
next_tmp_node = next(
|
|
2860
|
+
(
|
|
2861
|
+
node
|
|
2862
|
+
for node in subgraph.nodes()
|
|
2863
|
+
if isinstance(node.variable, SimTemporaryVariable) and node.variable.tmp_id == next_tmp
|
|
2864
|
+
),
|
|
2865
|
+
None,
|
|
2866
|
+
)
|
|
2867
|
+
if next_tmp_node is not None:
|
|
2868
|
+
# ouch it's used as a jump target
|
|
2869
|
+
return True
|
|
2870
|
+
|
|
2871
|
+
return False
|
|
2872
|
+
|
|
2873
|
+
def fast_memory_load(self, addr, size, data_type, endness="Iend_LE"):
|
|
2874
|
+
"""
|
|
2875
|
+
Load memory bytes from loader's memory backend.
|
|
2876
|
+
|
|
2877
|
+
:param int addr: The address to begin memory loading.
|
|
2878
|
+
:param int size: Size in bytes.
|
|
2879
|
+
:param data_type: Type of the data.
|
|
2880
|
+
:param str endness: Endianness of this memory load.
|
|
2881
|
+
:return: Data read out of the memory.
|
|
2882
|
+
:rtype: int or bytes or str or None
|
|
2883
|
+
"""
|
|
2884
|
+
|
|
2885
|
+
if data_type is int:
|
|
2886
|
+
try:
|
|
2887
|
+
return self.project.loader.memory.unpack_word(addr, size=size, endness=endness)
|
|
2888
|
+
except KeyError:
|
|
2889
|
+
return None
|
|
2890
|
+
|
|
2891
|
+
try:
|
|
2892
|
+
data = self.project.loader.memory.load(addr, size)
|
|
2893
|
+
if data_type is str:
|
|
2894
|
+
return "".join(chr(i) for i in data)
|
|
2895
|
+
return data
|
|
2896
|
+
except KeyError:
|
|
2897
|
+
return None
|
|
2898
|
+
|
|
2899
|
+
|
|
2900
|
+
AnalysesHub.register_default("Reassembler", Reassembler)
|