angr 9.2.103__py3-none-macosx_11_0_arm64.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.
Potentially problematic release.
This version of angr might be problematic. Click here for more details.
- angr/__init__.py +153 -0
- angr/__main__.py +59 -0
- angr/analyses/__init__.py +46 -0
- angr/analyses/analysis.py +359 -0
- angr/analyses/backward_slice.py +691 -0
- angr/analyses/binary_optimizer.py +683 -0
- angr/analyses/bindiff.py +1251 -0
- angr/analyses/boyscout.py +77 -0
- angr/analyses/callee_cleanup_finder.py +75 -0
- angr/analyses/calling_convention.py +956 -0
- angr/analyses/cdg.py +197 -0
- angr/analyses/cfg/__init__.py +11 -0
- angr/analyses/cfg/cfb.py +436 -0
- angr/analyses/cfg/cfg.py +73 -0
- angr/analyses/cfg/cfg_arch_options.py +82 -0
- angr/analyses/cfg/cfg_base.py +2917 -0
- angr/analyses/cfg/cfg_emulated.py +3570 -0
- angr/analyses/cfg/cfg_fast.py +5053 -0
- angr/analyses/cfg/cfg_fast_soot.py +669 -0
- angr/analyses/cfg/cfg_job_base.py +204 -0
- angr/analyses/cfg/indirect_jump_resolvers/__init__.py +8 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_elf_got.py +63 -0
- angr/analyses/cfg/indirect_jump_resolvers/amd64_pe_iat.py +52 -0
- angr/analyses/cfg/indirect_jump_resolvers/arm_elf_fast.py +151 -0
- angr/analyses/cfg/indirect_jump_resolvers/const_resolver.py +141 -0
- angr/analyses/cfg/indirect_jump_resolvers/default_resolvers.py +68 -0
- angr/analyses/cfg/indirect_jump_resolvers/jumptable.py +2368 -0
- angr/analyses/cfg/indirect_jump_resolvers/mips_elf_fast.py +517 -0
- angr/analyses/cfg/indirect_jump_resolvers/propagator_utils.py +26 -0
- angr/analyses/cfg/indirect_jump_resolvers/resolver.py +74 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_elf_pic_plt.py +93 -0
- angr/analyses/cfg/indirect_jump_resolvers/x86_pe_iat.py +51 -0
- angr/analyses/cfg_slice_to_sink/__init__.py +2 -0
- angr/analyses/cfg_slice_to_sink/cfg_slice_to_sink.py +117 -0
- angr/analyses/cfg_slice_to_sink/graph.py +84 -0
- angr/analyses/cfg_slice_to_sink/transitions.py +25 -0
- angr/analyses/class_identifier.py +62 -0
- angr/analyses/code_tagging.py +123 -0
- angr/analyses/complete_calling_conventions.py +424 -0
- angr/analyses/congruency_check.py +384 -0
- angr/analyses/data_dep/__init__.py +2 -0
- angr/analyses/data_dep/data_dependency_analysis.py +605 -0
- angr/analyses/data_dep/dep_nodes.py +170 -0
- angr/analyses/data_dep/sim_act_location.py +46 -0
- angr/analyses/datagraph_meta.py +105 -0
- angr/analyses/ddg.py +1695 -0
- angr/analyses/decompiler/__init__.py +13 -0
- angr/analyses/decompiler/ail_simplifier.py +1408 -0
- angr/analyses/decompiler/ailgraph_walker.py +48 -0
- angr/analyses/decompiler/block_io_finder.py +293 -0
- angr/analyses/decompiler/block_similarity.py +188 -0
- angr/analyses/decompiler/block_simplifier.py +434 -0
- angr/analyses/decompiler/call_counter.py +43 -0
- angr/analyses/decompiler/callsite_maker.py +403 -0
- angr/analyses/decompiler/ccall_rewriters/__init__.py +6 -0
- angr/analyses/decompiler/ccall_rewriters/amd64_ccalls.py +489 -0
- angr/analyses/decompiler/ccall_rewriters/rewriter_base.py +19 -0
- angr/analyses/decompiler/clinic.py +2166 -0
- angr/analyses/decompiler/condition_processor.py +1184 -0
- angr/analyses/decompiler/decompilation_cache.py +38 -0
- angr/analyses/decompiler/decompilation_options.py +274 -0
- angr/analyses/decompiler/decompiler.py +544 -0
- angr/analyses/decompiler/empty_node_remover.py +211 -0
- angr/analyses/decompiler/expression_counters.py +76 -0
- angr/analyses/decompiler/expression_narrower.py +92 -0
- angr/analyses/decompiler/goto_manager.py +73 -0
- angr/analyses/decompiler/graph_region.py +413 -0
- angr/analyses/decompiler/jump_target_collector.py +36 -0
- angr/analyses/decompiler/jumptable_entry_condition_rewriter.py +66 -0
- angr/analyses/decompiler/optimization_passes/__init__.py +108 -0
- angr/analyses/decompiler/optimization_passes/base_ptr_save_simplifier.py +144 -0
- angr/analyses/decompiler/optimization_passes/code_motion.py +360 -0
- angr/analyses/decompiler/optimization_passes/const_derefs.py +265 -0
- angr/analyses/decompiler/optimization_passes/cross_jump_reverter.py +108 -0
- angr/analyses/decompiler/optimization_passes/deadblock_remover.py +73 -0
- angr/analyses/decompiler/optimization_passes/div_simplifier.py +391 -0
- angr/analyses/decompiler/optimization_passes/engine_base.py +303 -0
- angr/analyses/decompiler/optimization_passes/expr_op_swapper.py +136 -0
- angr/analyses/decompiler/optimization_passes/flip_boolean_cmp.py +91 -0
- angr/analyses/decompiler/optimization_passes/inlined_string_transformation_simplifier.py +386 -0
- angr/analyses/decompiler/optimization_passes/ite_expr_converter.py +226 -0
- angr/analyses/decompiler/optimization_passes/ite_region_converter.py +189 -0
- angr/analyses/decompiler/optimization_passes/lowered_switch_simplifier.py +757 -0
- angr/analyses/decompiler/optimization_passes/mod_simplifier.py +86 -0
- angr/analyses/decompiler/optimization_passes/multi_simplifier.py +227 -0
- angr/analyses/decompiler/optimization_passes/optimization_pass.py +397 -0
- angr/analyses/decompiler/optimization_passes/register_save_area_simplifier.py +198 -0
- angr/analyses/decompiler/optimization_passes/ret_addr_save_simplifier.py +172 -0
- angr/analyses/decompiler/optimization_passes/ret_deduplicator.py +219 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_base.py +448 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_high.py +57 -0
- angr/analyses/decompiler/optimization_passes/return_duplicator_low.py +121 -0
- angr/analyses/decompiler/optimization_passes/spilled_register_finder.py +18 -0
- angr/analyses/decompiler/optimization_passes/stack_canary_simplifier.py +293 -0
- angr/analyses/decompiler/optimization_passes/switch_default_case_duplicator.py +110 -0
- angr/analyses/decompiler/optimization_passes/win_stack_canary_simplifier.py +281 -0
- angr/analyses/decompiler/optimization_passes/x86_gcc_getpc_simplifier.py +87 -0
- angr/analyses/decompiler/peephole_optimizations/__init__.py +69 -0
- angr/analyses/decompiler/peephole_optimizations/a_div_const_add_a_mul_n_div_const.py +38 -0
- angr/analyses/decompiler/peephole_optimizations/a_mul_const_div_shr_const.py +38 -0
- angr/analyses/decompiler/peephole_optimizations/a_shl_const_sub_a.py +31 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div.py +25 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_div_const_mul_const.py +56 -0
- angr/analyses/decompiler/peephole_optimizations/a_sub_a_sub_n.py +19 -0
- angr/analyses/decompiler/peephole_optimizations/arm_cmpf.py +235 -0
- angr/analyses/decompiler/peephole_optimizations/base.py +120 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_add_n.py +33 -0
- angr/analyses/decompiler/peephole_optimizations/basepointeroffset_and_mask.py +35 -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 +131 -0
- angr/analyses/decompiler/peephole_optimizations/cmpord_rewriter.py +72 -0
- angr/analyses/decompiler/peephole_optimizations/coalesce_same_cascading_ifs.py +27 -0
- angr/analyses/decompiler/peephole_optimizations/const_mull_a_shift.py +91 -0
- angr/analyses/decompiler/peephole_optimizations/constant_derefs.py +43 -0
- angr/analyses/decompiler/peephole_optimizations/conv_a_sub0_shr_and.py +70 -0
- angr/analyses/decompiler/peephole_optimizations/conv_shl_shr.py +51 -0
- angr/analyses/decompiler/peephole_optimizations/eager_eval.py +225 -0
- angr/analyses/decompiler/peephole_optimizations/extended_byte_and_mask.py +55 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy.py +146 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_strcpy_consolidation.py +102 -0
- angr/analyses/decompiler/peephole_optimizations/inlined_wstrcpy.py +159 -0
- angr/analyses/decompiler/peephole_optimizations/invert_negated_logical_conjuction_disjunction.py +50 -0
- angr/analyses/decompiler/peephole_optimizations/one_sub_bool.py +33 -0
- angr/analyses/decompiler/peephole_optimizations/remove_cascading_conversions.py +19 -0
- angr/analyses/decompiler/peephole_optimizations/remove_empty_if_body.py +45 -0
- angr/analyses/decompiler/peephole_optimizations/remove_noop_conversions.py +26 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_bitmasks.py +48 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_conversions.py +160 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_branch.py +29 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_ite_comparisons.py +54 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_nots.py +17 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_reinterprets.py +43 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts.py +44 -0
- angr/analyses/decompiler/peephole_optimizations/remove_redundant_shifts_around_comparators.py +40 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_bit_extractions.py +85 -0
- angr/analyses/decompiler/peephole_optimizations/rewrite_mips_gp_loads.py +47 -0
- angr/analyses/decompiler/peephole_optimizations/rol_ror.py +77 -0
- angr/analyses/decompiler/peephole_optimizations/sar_to_signed_div.py +105 -0
- angr/analyses/decompiler/peephole_optimizations/simplify_pc_relative_loads.py +37 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_cond_to_boolexpr.py +52 -0
- angr/analyses/decompiler/peephole_optimizations/single_bit_xor.py +26 -0
- angr/analyses/decompiler/peephole_optimizations/tidy_stack_addr.py +133 -0
- angr/analyses/decompiler/redundant_label_remover.py +116 -0
- angr/analyses/decompiler/region_identifier.py +1098 -0
- angr/analyses/decompiler/region_simplifiers/__init__.py +1 -0
- angr/analyses/decompiler/region_simplifiers/cascading_cond_transformer.py +93 -0
- angr/analyses/decompiler/region_simplifiers/cascading_ifs.py +81 -0
- angr/analyses/decompiler/region_simplifiers/expr_folding.py +606 -0
- angr/analyses/decompiler/region_simplifiers/goto.py +177 -0
- angr/analyses/decompiler/region_simplifiers/if_.py +142 -0
- angr/analyses/decompiler/region_simplifiers/ifelse.py +90 -0
- angr/analyses/decompiler/region_simplifiers/loop.py +135 -0
- angr/analyses/decompiler/region_simplifiers/node_address_finder.py +23 -0
- angr/analyses/decompiler/region_simplifiers/region_simplifier.py +211 -0
- angr/analyses/decompiler/region_simplifiers/switch_cluster_simplifier.py +644 -0
- angr/analyses/decompiler/region_simplifiers/switch_expr_simplifier.py +83 -0
- angr/analyses/decompiler/region_walker.py +23 -0
- angr/analyses/decompiler/return_maker.py +70 -0
- angr/analyses/decompiler/seq_to_blocks.py +19 -0
- angr/analyses/decompiler/sequence_walker.py +235 -0
- angr/analyses/decompiler/structured_codegen/__init__.py +10 -0
- angr/analyses/decompiler/structured_codegen/base.py +132 -0
- angr/analyses/decompiler/structured_codegen/c.py +3811 -0
- angr/analyses/decompiler/structured_codegen/dummy.py +14 -0
- angr/analyses/decompiler/structured_codegen/dwarf_import.py +186 -0
- angr/analyses/decompiler/structuring/__init__.py +15 -0
- angr/analyses/decompiler/structuring/dream.py +1225 -0
- angr/analyses/decompiler/structuring/phoenix.py +2546 -0
- angr/analyses/decompiler/structuring/recursive_structurer.py +186 -0
- angr/analyses/decompiler/structuring/structurer_base.py +954 -0
- angr/analyses/decompiler/structuring/structurer_nodes.py +414 -0
- angr/analyses/decompiler/utils.py +787 -0
- angr/analyses/disassembly.py +1302 -0
- angr/analyses/disassembly_utils.py +104 -0
- angr/analyses/dominance_frontier.py +39 -0
- angr/analyses/find_objects_static.py +203 -0
- angr/analyses/flirt.py +185 -0
- angr/analyses/forward_analysis/__init__.py +2 -0
- angr/analyses/forward_analysis/forward_analysis.py +527 -0
- angr/analyses/forward_analysis/job_info.py +64 -0
- angr/analyses/forward_analysis/visitors/__init__.py +4 -0
- angr/analyses/forward_analysis/visitors/call_graph.py +28 -0
- angr/analyses/forward_analysis/visitors/function_graph.py +85 -0
- angr/analyses/forward_analysis/visitors/graph.py +250 -0
- angr/analyses/forward_analysis/visitors/loop.py +28 -0
- angr/analyses/forward_analysis/visitors/single_node_graph.py +38 -0
- angr/analyses/identifier/__init__.py +1 -0
- angr/analyses/identifier/custom_callable.py +138 -0
- angr/analyses/identifier/errors.py +9 -0
- angr/analyses/identifier/func.py +57 -0
- angr/analyses/identifier/functions/__init__.py +36 -0
- angr/analyses/identifier/functions/atoi.py +75 -0
- angr/analyses/identifier/functions/based_atoi.py +128 -0
- angr/analyses/identifier/functions/fdprintf.py +122 -0
- angr/analyses/identifier/functions/free.py +64 -0
- angr/analyses/identifier/functions/int2str.py +302 -0
- angr/analyses/identifier/functions/malloc.py +113 -0
- angr/analyses/identifier/functions/memcmp.py +69 -0
- angr/analyses/identifier/functions/memcpy.py +89 -0
- angr/analyses/identifier/functions/memset.py +43 -0
- angr/analyses/identifier/functions/printf.py +122 -0
- angr/analyses/identifier/functions/recv_until.py +315 -0
- angr/analyses/identifier/functions/skip_calloc.py +72 -0
- angr/analyses/identifier/functions/skip_realloc.py +99 -0
- angr/analyses/identifier/functions/skip_recv_n.py +107 -0
- angr/analyses/identifier/functions/snprintf.py +114 -0
- angr/analyses/identifier/functions/sprintf.py +115 -0
- angr/analyses/identifier/functions/strcasecmp.py +32 -0
- angr/analyses/identifier/functions/strcmp.py +112 -0
- angr/analyses/identifier/functions/strcpy.py +43 -0
- angr/analyses/identifier/functions/strlen.py +26 -0
- angr/analyses/identifier/functions/strncmp.py +103 -0
- angr/analyses/identifier/functions/strncpy.py +65 -0
- angr/analyses/identifier/functions/strtol.py +91 -0
- angr/analyses/identifier/identify.py +848 -0
- angr/analyses/identifier/runner.py +359 -0
- angr/analyses/init_finder.py +264 -0
- angr/analyses/loop_analysis.py +353 -0
- angr/analyses/loopfinder.py +174 -0
- angr/analyses/propagator/__init__.py +1 -0
- angr/analyses/propagator/engine_ail.py +1560 -0
- angr/analyses/propagator/engine_base.py +53 -0
- angr/analyses/propagator/engine_vex.py +328 -0
- angr/analyses/propagator/outdated_definition_walker.py +158 -0
- angr/analyses/propagator/propagator.py +422 -0
- angr/analyses/propagator/tmpvar_finder.py +17 -0
- angr/analyses/propagator/top_checker_mixin.py +14 -0
- angr/analyses/propagator/values.py +116 -0
- angr/analyses/propagator/vex_vars.py +67 -0
- angr/analyses/proximity_graph.py +452 -0
- angr/analyses/reaching_definitions/__init__.py +65 -0
- angr/analyses/reaching_definitions/call_trace.py +72 -0
- angr/analyses/reaching_definitions/dep_graph.py +392 -0
- angr/analyses/reaching_definitions/engine_ail.py +1172 -0
- angr/analyses/reaching_definitions/engine_vex.py +1102 -0
- angr/analyses/reaching_definitions/external_codeloc.py +0 -0
- angr/analyses/reaching_definitions/function_handler.py +603 -0
- angr/analyses/reaching_definitions/heap_allocator.py +69 -0
- angr/analyses/reaching_definitions/rd_initializer.py +235 -0
- angr/analyses/reaching_definitions/rd_state.py +613 -0
- angr/analyses/reaching_definitions/reaching_definitions.py +594 -0
- angr/analyses/reaching_definitions/subject.py +64 -0
- angr/analyses/reassembler.py +2970 -0
- angr/analyses/soot_class_hierarchy.py +283 -0
- angr/analyses/stack_pointer_tracker.py +832 -0
- angr/analyses/static_hooker.py +51 -0
- angr/analyses/typehoon/__init__.py +1 -0
- angr/analyses/typehoon/dfa.py +108 -0
- angr/analyses/typehoon/lifter.py +91 -0
- angr/analyses/typehoon/simple_solver.py +1258 -0
- angr/analyses/typehoon/translator.py +242 -0
- angr/analyses/typehoon/typeconsts.py +294 -0
- angr/analyses/typehoon/typehoon.py +239 -0
- angr/analyses/typehoon/typevars.py +565 -0
- angr/analyses/typehoon/variance.py +10 -0
- angr/analyses/variable_recovery/__init__.py +2 -0
- angr/analyses/variable_recovery/annotations.py +57 -0
- angr/analyses/variable_recovery/engine_ail.py +746 -0
- angr/analyses/variable_recovery/engine_base.py +962 -0
- angr/analyses/variable_recovery/engine_vex.py +580 -0
- angr/analyses/variable_recovery/irsb_scanner.py +131 -0
- angr/analyses/variable_recovery/variable_recovery.py +552 -0
- angr/analyses/variable_recovery/variable_recovery_base.py +452 -0
- angr/analyses/variable_recovery/variable_recovery_fast.py +589 -0
- angr/analyses/veritesting.py +635 -0
- angr/analyses/vfg.py +1945 -0
- angr/analyses/vsa_ddg.py +423 -0
- angr/analyses/vtable.py +92 -0
- angr/analyses/xrefs.py +263 -0
- angr/angrdb/__init__.py +9 -0
- angr/angrdb/db.py +208 -0
- angr/angrdb/models.py +183 -0
- angr/angrdb/serializers/__init__.py +2 -0
- angr/angrdb/serializers/cfg_model.py +41 -0
- angr/angrdb/serializers/comments.py +59 -0
- angr/angrdb/serializers/funcs.py +60 -0
- angr/angrdb/serializers/kb.py +110 -0
- angr/angrdb/serializers/labels.py +58 -0
- angr/angrdb/serializers/loader.py +81 -0
- angr/angrdb/serializers/structured_code.py +128 -0
- angr/angrdb/serializers/variables.py +58 -0
- angr/angrdb/serializers/xrefs.py +48 -0
- angr/annocfg.py +320 -0
- angr/blade.py +430 -0
- angr/block.py +506 -0
- angr/callable.py +162 -0
- angr/calling_conventions.py +2383 -0
- angr/code_location.py +168 -0
- angr/codenode.py +140 -0
- angr/concretization_strategies/__init__.py +97 -0
- angr/concretization_strategies/any.py +15 -0
- angr/concretization_strategies/any_named.py +32 -0
- angr/concretization_strategies/controlled_data.py +54 -0
- angr/concretization_strategies/eval.py +18 -0
- angr/concretization_strategies/logging.py +32 -0
- angr/concretization_strategies/max.py +24 -0
- angr/concretization_strategies/nonzero.py +14 -0
- angr/concretization_strategies/nonzero_range.py +20 -0
- angr/concretization_strategies/norepeats.py +35 -0
- angr/concretization_strategies/norepeats_range.py +35 -0
- angr/concretization_strategies/range.py +17 -0
- angr/concretization_strategies/signed_add.py +24 -0
- angr/concretization_strategies/single.py +12 -0
- angr/concretization_strategies/solutions.py +18 -0
- angr/concretization_strategies/unlimited_range.py +15 -0
- angr/distributed/__init__.py +3 -0
- angr/distributed/server.py +198 -0
- angr/distributed/worker.py +183 -0
- angr/engines/__init__.py +41 -0
- angr/engines/concrete.py +178 -0
- angr/engines/engine.py +212 -0
- angr/engines/failure.py +27 -0
- angr/engines/hook.py +67 -0
- angr/engines/light/__init__.py +2 -0
- angr/engines/light/data.py +715 -0
- angr/engines/light/engine.py +1441 -0
- angr/engines/pcode/__init__.py +2 -0
- angr/engines/pcode/behavior.py +995 -0
- angr/engines/pcode/cc.py +123 -0
- angr/engines/pcode/emulate.py +446 -0
- angr/engines/pcode/engine.py +256 -0
- angr/engines/pcode/lifter.py +1423 -0
- angr/engines/procedure.py +71 -0
- angr/engines/soot/__init__.py +1 -0
- angr/engines/soot/engine.py +415 -0
- angr/engines/soot/exceptions.py +14 -0
- angr/engines/soot/expressions/__init__.py +56 -0
- angr/engines/soot/expressions/arrayref.py +21 -0
- angr/engines/soot/expressions/base.py +22 -0
- angr/engines/soot/expressions/binop.py +27 -0
- angr/engines/soot/expressions/cast.py +21 -0
- angr/engines/soot/expressions/condition.py +34 -0
- angr/engines/soot/expressions/constants.py +45 -0
- angr/engines/soot/expressions/instanceOf.py +11 -0
- angr/engines/soot/expressions/instancefieldref.py +7 -0
- angr/engines/soot/expressions/invoke.py +117 -0
- angr/engines/soot/expressions/length.py +7 -0
- angr/engines/soot/expressions/local.py +7 -0
- angr/engines/soot/expressions/new.py +15 -0
- angr/engines/soot/expressions/newArray.py +51 -0
- angr/engines/soot/expressions/newMultiArray.py +84 -0
- angr/engines/soot/expressions/paramref.py +7 -0
- angr/engines/soot/expressions/phi.py +29 -0
- angr/engines/soot/expressions/staticfieldref.py +7 -0
- angr/engines/soot/expressions/thisref.py +6 -0
- angr/engines/soot/expressions/unsupported.py +6 -0
- angr/engines/soot/field_dispatcher.py +49 -0
- angr/engines/soot/method_dispatcher.py +49 -0
- angr/engines/soot/statements/__init__.py +30 -0
- angr/engines/soot/statements/assign.py +29 -0
- angr/engines/soot/statements/base.py +80 -0
- angr/engines/soot/statements/goto.py +11 -0
- angr/engines/soot/statements/identity.py +14 -0
- angr/engines/soot/statements/if_.py +16 -0
- angr/engines/soot/statements/invoke.py +11 -0
- angr/engines/soot/statements/return_.py +19 -0
- angr/engines/soot/statements/switch.py +38 -0
- angr/engines/soot/statements/throw.py +12 -0
- angr/engines/soot/values/__init__.py +24 -0
- angr/engines/soot/values/arrayref.py +124 -0
- angr/engines/soot/values/base.py +4 -0
- angr/engines/soot/values/constants.py +17 -0
- angr/engines/soot/values/instancefieldref.py +42 -0
- angr/engines/soot/values/local.py +17 -0
- angr/engines/soot/values/paramref.py +17 -0
- angr/engines/soot/values/staticfieldref.py +37 -0
- angr/engines/soot/values/strref.py +37 -0
- angr/engines/soot/values/thisref.py +148 -0
- angr/engines/successors.py +540 -0
- angr/engines/syscall.py +53 -0
- angr/engines/unicorn.py +483 -0
- angr/engines/vex/__init__.py +4 -0
- angr/engines/vex/claripy/__init__.py +1 -0
- angr/engines/vex/claripy/ccall.py +2097 -0
- angr/engines/vex/claripy/datalayer.py +149 -0
- angr/engines/vex/claripy/irop.py +1279 -0
- angr/engines/vex/heavy/__init__.py +5 -0
- angr/engines/vex/heavy/actions.py +237 -0
- angr/engines/vex/heavy/concretizers.py +394 -0
- angr/engines/vex/heavy/dirty.py +467 -0
- angr/engines/vex/heavy/heavy.py +379 -0
- angr/engines/vex/heavy/inspect.py +51 -0
- angr/engines/vex/heavy/resilience.py +85 -0
- angr/engines/vex/heavy/super_fastpath.py +34 -0
- angr/engines/vex/lifter.py +424 -0
- angr/engines/vex/light/__init__.py +3 -0
- angr/engines/vex/light/light.py +555 -0
- angr/engines/vex/light/resilience.py +73 -0
- angr/engines/vex/light/slicing.py +51 -0
- angr/errors.py +604 -0
- angr/exploration_techniques/__init__.py +176 -0
- angr/exploration_techniques/bucketizer.py +96 -0
- angr/exploration_techniques/common.py +56 -0
- angr/exploration_techniques/dfs.py +34 -0
- angr/exploration_techniques/director.py +523 -0
- angr/exploration_techniques/driller_core.py +102 -0
- angr/exploration_techniques/explorer.py +146 -0
- angr/exploration_techniques/lengthlimiter.py +20 -0
- angr/exploration_techniques/local_loop_seer.py +64 -0
- angr/exploration_techniques/loop_seer.py +239 -0
- angr/exploration_techniques/manual_mergepoint.py +80 -0
- angr/exploration_techniques/memory_watcher.py +40 -0
- angr/exploration_techniques/oppologist.py +93 -0
- angr/exploration_techniques/slicecutor.py +115 -0
- angr/exploration_techniques/spiller.py +282 -0
- angr/exploration_techniques/spiller_db.py +27 -0
- angr/exploration_techniques/stochastic.py +57 -0
- angr/exploration_techniques/suggestions.py +156 -0
- angr/exploration_techniques/symbion.py +78 -0
- angr/exploration_techniques/tech_builder.py +47 -0
- angr/exploration_techniques/threading.py +77 -0
- angr/exploration_techniques/timeout.py +31 -0
- angr/exploration_techniques/tracer.py +1101 -0
- angr/exploration_techniques/unique.py +104 -0
- angr/exploration_techniques/veritesting.py +36 -0
- angr/factory.py +385 -0
- angr/flirt/__init__.py +126 -0
- angr/flirt/build_sig.py +316 -0
- angr/graph_utils.py +0 -0
- angr/keyed_region.py +532 -0
- angr/knowledge_base/__init__.py +1 -0
- angr/knowledge_base/knowledge_base.py +145 -0
- angr/knowledge_plugins/__init__.py +18 -0
- angr/knowledge_plugins/callsite_prototypes.py +52 -0
- angr/knowledge_plugins/cfg/__init__.py +16 -0
- angr/knowledge_plugins/cfg/cfg_manager.py +94 -0
- angr/knowledge_plugins/cfg/cfg_model.py +1057 -0
- angr/knowledge_plugins/cfg/cfg_node.py +541 -0
- angr/knowledge_plugins/cfg/indirect_jump.py +67 -0
- angr/knowledge_plugins/cfg/memory_data.py +156 -0
- angr/knowledge_plugins/comments.py +15 -0
- angr/knowledge_plugins/custom_strings.py +37 -0
- angr/knowledge_plugins/data.py +21 -0
- angr/knowledge_plugins/debug_variables.py +221 -0
- angr/knowledge_plugins/functions/__init__.py +2 -0
- angr/knowledge_plugins/functions/function.py +1694 -0
- angr/knowledge_plugins/functions/function_manager.py +501 -0
- angr/knowledge_plugins/functions/function_parser.py +295 -0
- angr/knowledge_plugins/functions/soot_function.py +131 -0
- angr/knowledge_plugins/indirect_jumps.py +34 -0
- angr/knowledge_plugins/key_definitions/__init__.py +16 -0
- angr/knowledge_plugins/key_definitions/atoms.py +314 -0
- angr/knowledge_plugins/key_definitions/constants.py +23 -0
- angr/knowledge_plugins/key_definitions/definition.py +217 -0
- angr/knowledge_plugins/key_definitions/environment.py +92 -0
- angr/knowledge_plugins/key_definitions/heap_address.py +32 -0
- angr/knowledge_plugins/key_definitions/key_definition_manager.py +81 -0
- angr/knowledge_plugins/key_definitions/live_definitions.py +1074 -0
- angr/knowledge_plugins/key_definitions/liveness.py +170 -0
- angr/knowledge_plugins/key_definitions/rd_model.py +176 -0
- angr/knowledge_plugins/key_definitions/tag.py +77 -0
- angr/knowledge_plugins/key_definitions/undefined.py +67 -0
- angr/knowledge_plugins/key_definitions/unknown_size.py +83 -0
- angr/knowledge_plugins/key_definitions/uses.py +180 -0
- angr/knowledge_plugins/labels.py +109 -0
- angr/knowledge_plugins/patches.py +125 -0
- angr/knowledge_plugins/plugin.py +23 -0
- angr/knowledge_plugins/propagations/__init__.py +2 -0
- angr/knowledge_plugins/propagations/prop_value.py +193 -0
- angr/knowledge_plugins/propagations/propagation_manager.py +60 -0
- angr/knowledge_plugins/propagations/propagation_model.py +74 -0
- angr/knowledge_plugins/propagations/states.py +1064 -0
- angr/knowledge_plugins/structured_code/__init__.py +1 -0
- angr/knowledge_plugins/structured_code/manager.py +59 -0
- angr/knowledge_plugins/sync/__init__.py +1 -0
- angr/knowledge_plugins/sync/sync_controller.py +329 -0
- angr/knowledge_plugins/types.py +87 -0
- angr/knowledge_plugins/variables/__init__.py +1 -0
- angr/knowledge_plugins/variables/variable_access.py +114 -0
- angr/knowledge_plugins/variables/variable_manager.py +1191 -0
- angr/knowledge_plugins/xrefs/__init__.py +3 -0
- angr/knowledge_plugins/xrefs/xref.py +157 -0
- angr/knowledge_plugins/xrefs/xref_manager.py +122 -0
- angr/knowledge_plugins/xrefs/xref_types.py +13 -0
- angr/lib/angr_native.dylib +0 -0
- angr/misc/__init__.py +8 -0
- angr/misc/ansi.py +46 -0
- angr/misc/autoimport.py +89 -0
- angr/misc/bug_report.py +125 -0
- angr/misc/hookset.py +106 -0
- angr/misc/import_hooks.py +63 -0
- angr/misc/loggers.py +130 -0
- angr/misc/picklable_lock.py +45 -0
- angr/misc/plugins.py +291 -0
- angr/misc/range.py +21 -0
- angr/misc/testing.py +23 -0
- angr/misc/ux.py +31 -0
- angr/misc/weakpatch.py +58 -0
- angr/procedures/__init__.py +2 -0
- angr/procedures/advapi32/__init__.py +0 -0
- angr/procedures/cgc/__init__.py +3 -0
- angr/procedures/cgc/_terminate.py +10 -0
- angr/procedures/cgc/allocate.py +76 -0
- angr/procedures/cgc/deallocate.py +59 -0
- angr/procedures/cgc/fdwait.py +62 -0
- angr/procedures/cgc/random.py +60 -0
- angr/procedures/cgc/receive.py +91 -0
- angr/procedures/cgc/transmit.py +63 -0
- angr/procedures/definitions/__init__.py +784 -0
- angr/procedures/definitions/cgc.py +19 -0
- angr/procedures/definitions/glibc.py +8384 -0
- angr/procedures/definitions/gnulib.py +35 -0
- angr/procedures/definitions/libstdcpp.py +20 -0
- angr/procedures/definitions/linux_kernel.py +6167 -0
- angr/procedures/definitions/linux_loader.py +6 -0
- angr/procedures/definitions/msvcr.py +15 -0
- angr/procedures/definitions/parse_syscalls_from_local_system.py +49 -0
- angr/procedures/definitions/parse_win32json.py +2556 -0
- angr/procedures/definitions/types_win32.py +34481 -0
- angr/procedures/definitions/wdk_api-ms-win-dx-d3dkmt-l1-1-4.py +44 -0
- angr/procedures/definitions/wdk_api-ms-win-dx-d3dkmt-l1-1-6.py +40 -0
- angr/procedures/definitions/wdk_clfs.py +154 -0
- angr/procedures/definitions/wdk_fltmgr.py +570 -0
- angr/procedures/definitions/wdk_fwpkclnt.py +44 -0
- angr/procedures/definitions/wdk_fwpuclnt.py +330 -0
- angr/procedures/definitions/wdk_gdi32.py +380 -0
- angr/procedures/definitions/wdk_hal.py +92 -0
- angr/procedures/definitions/wdk_ksecdd.py +76 -0
- angr/procedures/definitions/wdk_ndis.py +252 -0
- angr/procedures/definitions/wdk_ntoskrnl.py +3463 -0
- angr/procedures/definitions/wdk_offreg.py +86 -0
- angr/procedures/definitions/wdk_pshed.py +50 -0
- angr/procedures/definitions/wdk_secur32.py +54 -0
- angr/procedures/definitions/wdk_vhfum.py +48 -0
- angr/procedures/definitions/win32_aclui.py +44 -0
- angr/procedures/definitions/win32_activeds.py +82 -0
- angr/procedures/definitions/win32_advapi32.py +1698 -0
- angr/procedures/definitions/win32_advpack.py +138 -0
- angr/procedures/definitions/win32_amsi.py +52 -0
- angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-1.py +58 -0
- angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-3.py +48 -0
- angr/procedures/definitions/win32_api-ms-win-appmodel-runtime-l1-1-6.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-apiquery-l2-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-backgroundtask-l1-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-comm-l1-1-1.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-comm-l1-1-2.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-enclave-l1-1-1.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-core-errorhandling-l1-1-3.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-featurestaging-l1-1-0.py +48 -0
- angr/procedures/definitions/win32_api-ms-win-core-featurestaging-l1-1-1.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-file-fromapp-l1-1-0.py +60 -0
- angr/procedures/definitions/win32_api-ms-win-core-handle-l1-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-ioring-l1-1-0.py +62 -0
- angr/procedures/definitions/win32_api-ms-win-core-marshal-l1-1-0.py +46 -0
- angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-3.py +46 -0
- angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-4.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-5.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-6.py +46 -0
- angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-7.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-core-memory-l1-1-8.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-core-path-l1-1-0.py +82 -0
- angr/procedures/definitions/win32_api-ms-win-core-psm-appnotify-l1-1-0.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-core-psm-appnotify-l1-1-1.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-core-realtime-l1-1-1.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-core-realtime-l1-1-2.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-core-slapi-l1-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-state-helpers-l1-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-synch-l1-2-0.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-3.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-4.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-core-sysinfo-l1-2-6.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-core-util-l1-1-1.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-error-l1-1-0.py +43 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-error-l1-1-1.py +37 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-l1-1-0.py +39 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-registration-l1-1-0.py +23 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-robuffer-l1-1-0.py +23 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-roparameterizediid-l1-1-0.py +27 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-string-l1-1-0.py +75 -0
- angr/procedures/definitions/win32_api-ms-win-core-winrt-string-l1-1-1.py +23 -0
- angr/procedures/definitions/win32_api-ms-win-core-wow64-l1-1-1.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-devices-query-l1-1-0.py +56 -0
- angr/procedures/definitions/win32_api-ms-win-devices-query-l1-1-1.py +48 -0
- angr/procedures/definitions/win32_api-ms-win-dx-d3dkmt-l1-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-gaming-deviceinformation-l1-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-gaming-expandedresources-l1-1-0.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-0.py +52 -0
- angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-1.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-2.py +52 -0
- angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-3.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-gaming-tcui-l1-1-4.py +54 -0
- angr/procedures/definitions/win32_api-ms-win-mm-misc-l1-1-1.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-net-isolation-l1-1-0.py +54 -0
- angr/procedures/definitions/win32_api-ms-win-security-base-l1-2-2.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-security-isolatedcontainer-l1-1-0.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-security-isolatedcontainer-l1-1-1.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-3.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-4.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-service-core-l1-1-5.py +42 -0
- angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-0.py +44 -0
- angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-1.py +50 -0
- angr/procedures/definitions/win32_api-ms-win-shcore-scaling-l1-1-2.py +40 -0
- angr/procedures/definitions/win32_api-ms-win-shcore-stream-winrt-l1-1-0.py +27 -0
- angr/procedures/definitions/win32_api-ms-win-wsl-api-l1-1-0.py +52 -0
- angr/procedures/definitions/win32_apphelp.py +40 -0
- angr/procedures/definitions/win32_authz.py +104 -0
- angr/procedures/definitions/win32_avicap32.py +46 -0
- angr/procedures/definitions/win32_avifil32.py +158 -0
- angr/procedures/definitions/win32_avrt.py +66 -0
- angr/procedures/definitions/win32_bcp47mrm.py +42 -0
- angr/procedures/definitions/win32_bcrypt.py +144 -0
- angr/procedures/definitions/win32_bcryptprimitives.py +42 -0
- angr/procedures/definitions/win32_bluetoothapis.py +120 -0
- angr/procedures/definitions/win32_bthprops.py +33 -0
- angr/procedures/definitions/win32_bthprops_cpl.py +50 -0
- angr/procedures/definitions/win32_cabinet.py +82 -0
- angr/procedures/definitions/win32_certadm.py +74 -0
- angr/procedures/definitions/win32_certpoleng.py +54 -0
- angr/procedures/definitions/win32_cfgmgr32.py +516 -0
- angr/procedures/definitions/win32_chakra.py +212 -0
- angr/procedures/definitions/win32_cldapi.py +110 -0
- angr/procedures/definitions/win32_clfsw32.py +156 -0
- angr/procedures/definitions/win32_clusapi.py +598 -0
- angr/procedures/definitions/win32_comctl32.py +268 -0
- angr/procedures/definitions/win32_comdlg32.py +80 -0
- angr/procedures/definitions/win32_compstui.py +46 -0
- angr/procedures/definitions/win32_computecore.py +146 -0
- angr/procedures/definitions/win32_computenetwork.py +124 -0
- angr/procedures/definitions/win32_computestorage.py +62 -0
- angr/procedures/definitions/win32_comsvcs.py +52 -0
- angr/procedures/definitions/win32_coremessaging.py +23 -0
- angr/procedures/definitions/win32_credui.py +76 -0
- angr/procedures/definitions/win32_crypt32.py +496 -0
- angr/procedures/definitions/win32_cryptnet.py +48 -0
- angr/procedures/definitions/win32_cryptui.py +58 -0
- angr/procedures/definitions/win32_cryptxml.py +76 -0
- angr/procedures/definitions/win32_cscapi.py +46 -0
- angr/procedures/definitions/win32_d2d1.py +64 -0
- angr/procedures/definitions/win32_d3d10.py +92 -0
- angr/procedures/definitions/win32_d3d10_1.py +42 -0
- angr/procedures/definitions/win32_d3d11.py +44 -0
- angr/procedures/definitions/win32_d3d12.py +54 -0
- angr/procedures/definitions/win32_d3d9.py +60 -0
- angr/procedures/definitions/win32_d3dcompiler_47.py +90 -0
- angr/procedures/definitions/win32_d3dcsx.py +56 -0
- angr/procedures/definitions/win32_davclnt.py +74 -0
- angr/procedures/definitions/win32_dbgeng.py +46 -0
- angr/procedures/definitions/win32_dbghelp.py +476 -0
- angr/procedures/definitions/win32_dbgmodel.py +40 -0
- angr/procedures/definitions/win32_dciman32.py +78 -0
- angr/procedures/definitions/win32_dcomp.py +62 -0
- angr/procedures/definitions/win32_ddraw.py +52 -0
- angr/procedures/definitions/win32_deviceaccess.py +40 -0
- angr/procedures/definitions/win32_dflayout.py +40 -0
- angr/procedures/definitions/win32_dhcpcsvc.py +68 -0
- angr/procedures/definitions/win32_dhcpcsvc6.py +50 -0
- angr/procedures/definitions/win32_dhcpsapi.py +430 -0
- angr/procedures/definitions/win32_diagnosticdataquery.py +108 -0
- angr/procedures/definitions/win32_dinput8.py +40 -0
- angr/procedures/definitions/win32_directml.py +42 -0
- angr/procedures/definitions/win32_dmprocessxmlfiltered.py +40 -0
- angr/procedures/definitions/win32_dnsapi.py +166 -0
- angr/procedures/definitions/win32_drt.py +70 -0
- angr/procedures/definitions/win32_drtprov.py +56 -0
- angr/procedures/definitions/win32_drttransport.py +42 -0
- angr/procedures/definitions/win32_dsound.py +58 -0
- angr/procedures/definitions/win32_dsparse.py +76 -0
- angr/procedures/definitions/win32_dsprop.py +52 -0
- angr/procedures/definitions/win32_dssec.py +46 -0
- angr/procedures/definitions/win32_dsuiext.py +46 -0
- angr/procedures/definitions/win32_dwmapi.py +100 -0
- angr/procedures/definitions/win32_dwrite.py +40 -0
- angr/procedures/definitions/win32_dxcompiler.py +42 -0
- angr/procedures/definitions/win32_dxcore.py +40 -0
- angr/procedures/definitions/win32_dxgi.py +50 -0
- angr/procedures/definitions/win32_dxva2.py +114 -0
- angr/procedures/definitions/win32_eappcfg.py +66 -0
- angr/procedures/definitions/win32_eappprxy.py +74 -0
- angr/procedures/definitions/win32_efswrt.py +42 -0
- angr/procedures/definitions/win32_elscore.py +48 -0
- angr/procedures/definitions/win32_esent.py +496 -0
- angr/procedures/definitions/win32_evr.py +52 -0
- angr/procedures/definitions/win32_faultrep.py +46 -0
- angr/procedures/definitions/win32_fhsvcctl.py +52 -0
- angr/procedures/definitions/win32_firewallapi.py +44 -0
- angr/procedures/definitions/win32_fltlib.py +94 -0
- angr/procedures/definitions/win32_fontsub.py +42 -0
- angr/procedures/definitions/win32_forceinline.py +44 -0
- angr/procedures/definitions/win32_fwpuclnt.py +422 -0
- angr/procedures/definitions/win32_fxsutility.py +42 -0
- angr/procedures/definitions/win32_gdi32.py +900 -0
- angr/procedures/definitions/win32_gdiplus.py +1296 -0
- angr/procedures/definitions/win32_glu32.py +142 -0
- angr/procedures/definitions/win32_gpedit.py +50 -0
- angr/procedures/definitions/win32_hhctrl_ocx.py +42 -0
- angr/procedures/definitions/win32_hid.py +128 -0
- angr/procedures/definitions/win32_hlink.py +94 -0
- angr/procedures/definitions/win32_hrtfapo.py +40 -0
- angr/procedures/definitions/win32_httpapi.py +124 -0
- angr/procedures/definitions/win32_icm32.py +80 -0
- angr/procedures/definitions/win32_icmui.py +42 -0
- angr/procedures/definitions/win32_icu.py +2088 -0
- angr/procedures/definitions/win32_ieframe.py +96 -0
- angr/procedures/definitions/win32_imagehlp.py +90 -0
- angr/procedures/definitions/win32_imgutil.py +56 -0
- angr/procedures/definitions/win32_imm32.py +202 -0
- angr/procedures/definitions/win32_infocardapi.py +72 -0
- angr/procedures/definitions/win32_inkobjcore.py +92 -0
- angr/procedures/definitions/win32_iphlpapi.py +440 -0
- angr/procedures/definitions/win32_iscsidsc.py +196 -0
- angr/procedures/definitions/win32_isolatedwindowsenvironmentutils.py +42 -0
- angr/procedures/definitions/win32_kernel32.py +3199 -0
- angr/procedures/definitions/win32_kernelbase.py +50 -0
- angr/procedures/definitions/win32_keycredmgr.py +46 -0
- angr/procedures/definitions/win32_ksproxy_ax.py +50 -0
- angr/procedures/definitions/win32_ksuser.py +54 -0
- angr/procedures/definitions/win32_ktmw32.py +116 -0
- angr/procedures/definitions/win32_licenseprotection.py +42 -0
- angr/procedures/definitions/win32_loadperf.py +62 -0
- angr/procedures/definitions/win32_magnification.py +76 -0
- angr/procedures/definitions/win32_mapi32.py +170 -0
- angr/procedures/definitions/win32_mdmlocalmanagement.py +44 -0
- angr/procedures/definitions/win32_mdmregistration.py +68 -0
- angr/procedures/definitions/win32_mf.py +162 -0
- angr/procedures/definitions/win32_mfcore.py +42 -0
- angr/procedures/definitions/win32_mfplat.py +328 -0
- angr/procedures/definitions/win32_mfplay.py +40 -0
- angr/procedures/definitions/win32_mfreadwrite.py +48 -0
- angr/procedures/definitions/win32_mfsensorgroup.py +58 -0
- angr/procedures/definitions/win32_mfsrcsnk.py +42 -0
- angr/procedures/definitions/win32_mgmtapi.py +56 -0
- angr/procedures/definitions/win32_mi.py +40 -0
- angr/procedures/definitions/win32_mmdevapi.py +40 -0
- angr/procedures/definitions/win32_mpr.py +132 -0
- angr/procedures/definitions/win32_mprapi.py +262 -0
- angr/procedures/definitions/win32_mqrt.py +106 -0
- angr/procedures/definitions/win32_mrmsupport.py +92 -0
- angr/procedures/definitions/win32_msacm32.py +122 -0
- angr/procedures/definitions/win32_msajapi.py +1132 -0
- angr/procedures/definitions/win32_mscms.py +196 -0
- angr/procedures/definitions/win32_mscoree.py +92 -0
- angr/procedures/definitions/win32_msctfmonitor.py +44 -0
- angr/procedures/definitions/win32_msdelta.py +70 -0
- angr/procedures/definitions/win32_msdmo.py +60 -0
- angr/procedures/definitions/win32_msdrm.py +206 -0
- angr/procedures/definitions/win32_msi.py +566 -0
- angr/procedures/definitions/win32_msimg32.py +44 -0
- angr/procedures/definitions/win32_mspatcha.py +70 -0
- angr/procedures/definitions/win32_mspatchc.py +56 -0
- angr/procedures/definitions/win32_msports.py +52 -0
- angr/procedures/definitions/win32_msrating.py +76 -0
- angr/procedures/definitions/win32_mssign32.py +58 -0
- angr/procedures/definitions/win32_mstask.py +42 -0
- angr/procedures/definitions/win32_msvfw32.py +124 -0
- angr/procedures/definitions/win32_mswsock.py +70 -0
- angr/procedures/definitions/win32_mtxdm.py +40 -0
- angr/procedures/definitions/win32_ncrypt.py +116 -0
- angr/procedures/definitions/win32_ndfapi.py +70 -0
- angr/procedures/definitions/win32_netapi32.py +450 -0
- angr/procedures/definitions/win32_netsh.py +54 -0
- angr/procedures/definitions/win32_netshell.py +42 -0
- angr/procedures/definitions/win32_newdev.py +60 -0
- angr/procedures/definitions/win32_ninput.py +98 -0
- angr/procedures/definitions/win32_normaliz.py +42 -0
- angr/procedures/definitions/win32_ntdll.py +185 -0
- angr/procedures/definitions/win32_ntdllk.py +40 -0
- angr/procedures/definitions/win32_ntdsapi.py +200 -0
- angr/procedures/definitions/win32_ntlanman.py +58 -0
- angr/procedures/definitions/win32_odbc32.py +406 -0
- angr/procedures/definitions/win32_odbcbcp.py +92 -0
- angr/procedures/definitions/win32_ole32.py +672 -0
- angr/procedures/definitions/win32_oleacc.py +72 -0
- angr/procedures/definitions/win32_oleaut32.py +848 -0
- angr/procedures/definitions/win32_oledlg.py +84 -0
- angr/procedures/definitions/win32_ondemandconnroutehelper.py +48 -0
- angr/procedures/definitions/win32_opengl32.py +748 -0
- angr/procedures/definitions/win32_opmxbox.py +44 -0
- angr/procedures/definitions/win32_p2p.py +254 -0
- angr/procedures/definitions/win32_p2pgraph.py +112 -0
- angr/procedures/definitions/win32_pdh.py +234 -0
- angr/procedures/definitions/win32_peerdist.py +94 -0
- angr/procedures/definitions/win32_powrprof.py +206 -0
- angr/procedures/definitions/win32_prntvpt.py +60 -0
- angr/procedures/definitions/win32_projectedfslib.py +76 -0
- angr/procedures/definitions/win32_propsys.py +474 -0
- angr/procedures/definitions/win32_psapi.py +92 -0
- angr/procedures/definitions/win32_quartz.py +42 -0
- angr/procedures/definitions/win32_query.py +46 -0
- angr/procedures/definitions/win32_qwave.py +60 -0
- angr/procedures/definitions/win32_rasapi32.py +206 -0
- angr/procedures/definitions/win32_rasdlg.py +50 -0
- angr/procedures/definitions/win32_resutils.py +278 -0
- angr/procedures/definitions/win32_rometadata.py +23 -0
- angr/procedures/definitions/win32_rpcns4.py +160 -0
- angr/procedures/definitions/win32_rpcproxy.py +46 -0
- angr/procedures/definitions/win32_rpcrt4.py +932 -0
- angr/procedures/definitions/win32_rstrtmgr.py +60 -0
- angr/procedures/definitions/win32_rtm.py +190 -0
- angr/procedures/definitions/win32_rtutils.py +120 -0
- angr/procedures/definitions/win32_rtworkq.py +104 -0
- angr/procedures/definitions/win32_sas.py +40 -0
- angr/procedures/definitions/win32_scarddlg.py +48 -0
- angr/procedures/definitions/win32_schannel.py +56 -0
- angr/procedures/definitions/win32_sechost.py +42 -0
- angr/procedures/definitions/win32_secur32.py +216 -0
- angr/procedures/definitions/win32_sensapi.py +44 -0
- angr/procedures/definitions/win32_sensorsutilsv2.py +118 -0
- angr/procedures/definitions/win32_setupapi.py +706 -0
- angr/procedures/definitions/win32_sfc.py +50 -0
- angr/procedures/definitions/win32_shdocvw.py +44 -0
- angr/procedures/definitions/win32_shell32.py +526 -0
- angr/procedures/definitions/win32_shlwapi.py +758 -0
- angr/procedures/definitions/win32_slc.py +102 -0
- angr/procedures/definitions/win32_slcext.py +46 -0
- angr/procedures/definitions/win32_slwga.py +40 -0
- angr/procedures/definitions/win32_snmpapi.py +90 -0
- angr/procedures/definitions/win32_spoolss.py +90 -0
- angr/procedures/definitions/win32_srclient.py +40 -0
- angr/procedures/definitions/win32_srpapi.py +60 -0
- angr/procedures/definitions/win32_sspicli.py +52 -0
- angr/procedures/definitions/win32_sti.py +40 -0
- angr/procedures/definitions/win32_t2embed.py +66 -0
- angr/procedures/definitions/win32_tapi32.py +536 -0
- angr/procedures/definitions/win32_tbs.py +66 -0
- angr/procedures/definitions/win32_tdh.py +92 -0
- angr/procedures/definitions/win32_tokenbinding.py +58 -0
- angr/procedures/definitions/win32_traffic.py +78 -0
- angr/procedures/definitions/win32_txfw32.py +56 -0
- angr/procedures/definitions/win32_ualapi.py +46 -0
- angr/procedures/definitions/win32_uiautomationcore.py +234 -0
- angr/procedures/definitions/win32_urlmon.py +192 -0
- angr/procedures/definitions/win32_user32.py +1565 -0
- angr/procedures/definitions/win32_userenv.py +126 -0
- angr/procedures/definitions/win32_usp10.py +118 -0
- angr/procedures/definitions/win32_uxtheme.py +192 -0
- angr/procedures/definitions/win32_verifier.py +40 -0
- angr/procedures/definitions/win32_version.py +66 -0
- angr/procedures/definitions/win32_vertdll.py +52 -0
- angr/procedures/definitions/win32_virtdisk.py +96 -0
- angr/procedures/definitions/win32_vmdevicehost.py +64 -0
- angr/procedures/definitions/win32_vmsavedstatedumpprovider.py +124 -0
- angr/procedures/definitions/win32_vssapi.py +40 -0
- angr/procedures/definitions/win32_wcmapi.py +48 -0
- angr/procedures/definitions/win32_wdsbp.py +52 -0
- angr/procedures/definitions/win32_wdsclientapi.py +112 -0
- angr/procedures/definitions/win32_wdsmc.py +50 -0
- angr/procedures/definitions/win32_wdspxe.py +100 -0
- angr/procedures/definitions/win32_wdstptc.py +64 -0
- angr/procedures/definitions/win32_webauthn.py +64 -0
- angr/procedures/definitions/win32_webservices.py +424 -0
- angr/procedures/definitions/win32_websocket.py +64 -0
- angr/procedures/definitions/win32_wecapi.py +68 -0
- angr/procedures/definitions/win32_wer.py +80 -0
- angr/procedures/definitions/win32_wevtapi.py +108 -0
- angr/procedures/definitions/win32_winbio.py +146 -0
- angr/procedures/definitions/win32_windows_ai_machinelearning.py +40 -0
- angr/procedures/definitions/win32_windows_data_pdf.py +23 -0
- angr/procedures/definitions/win32_windows_media_mediacontrol.py +54 -0
- angr/procedures/definitions/win32_windows_networking.py +40 -0
- angr/procedures/definitions/win32_windows_ui_xaml.py +42 -0
- angr/procedures/definitions/win32_windowscodecs.py +56 -0
- angr/procedures/definitions/win32_winfax.py +150 -0
- angr/procedures/definitions/win32_winhttp.py +150 -0
- angr/procedures/definitions/win32_winhvemulation.py +46 -0
- angr/procedures/definitions/win32_winhvplatform.py +170 -0
- angr/procedures/definitions/win32_wininet.py +630 -0
- angr/procedures/definitions/win32_winml.py +40 -0
- angr/procedures/definitions/win32_winmm.py +390 -0
- angr/procedures/definitions/win32_winscard.py +178 -0
- angr/procedures/definitions/win32_winspool.py +363 -0
- angr/procedures/definitions/win32_winspool_drv.py +382 -0
- angr/procedures/definitions/win32_wintrust.py +158 -0
- angr/procedures/definitions/win32_winusb.py +106 -0
- angr/procedures/definitions/win32_wlanapi.py +158 -0
- angr/procedures/definitions/win32_wlanui.py +40 -0
- angr/procedures/definitions/win32_wldap32.py +524 -0
- angr/procedures/definitions/win32_wldp.py +56 -0
- angr/procedures/definitions/win32_wmvcore.py +60 -0
- angr/procedures/definitions/win32_wnvapi.py +42 -0
- angr/procedures/definitions/win32_wofutil.py +60 -0
- angr/procedures/definitions/win32_ws2_32.py +358 -0
- angr/procedures/definitions/win32_wscapi.py +50 -0
- angr/procedures/definitions/win32_wsclient.py +44 -0
- angr/procedures/definitions/win32_wsdapi.py +102 -0
- angr/procedures/definitions/win32_wsmsvc.py +104 -0
- angr/procedures/definitions/win32_wsnmp32.py +136 -0
- angr/procedures/definitions/win32_wtsapi32.py +164 -0
- angr/procedures/definitions/win32_xaudio2_8.py +46 -0
- angr/procedures/definitions/win32_xinput1_4.py +52 -0
- angr/procedures/definitions/win32_xinputuap.py +35 -0
- angr/procedures/definitions/win32_xmllite.py +50 -0
- angr/procedures/definitions/win32_xolehlp.py +46 -0
- angr/procedures/definitions/win32_xpsprint.py +42 -0
- angr/procedures/glibc/__ctype_b_loc.py +22 -0
- angr/procedures/glibc/__ctype_tolower_loc.py +22 -0
- angr/procedures/glibc/__ctype_toupper_loc.py +22 -0
- angr/procedures/glibc/__errno_location.py +6 -0
- angr/procedures/glibc/__init__.py +3 -0
- angr/procedures/glibc/__libc_init.py +36 -0
- angr/procedures/glibc/__libc_start_main.py +294 -0
- angr/procedures/glibc/dynamic_loading.py +19 -0
- angr/procedures/glibc/scanf.py +10 -0
- angr/procedures/glibc/sscanf.py +5 -0
- angr/procedures/gnulib/__init__.py +3 -0
- angr/procedures/gnulib/xalloc_die.py +13 -0
- angr/procedures/gnulib/xstrtol_fatal.py +13 -0
- angr/procedures/java/__init__.py +38 -0
- angr/procedures/java/unconstrained.py +64 -0
- angr/procedures/java_io/__init__.py +0 -0
- angr/procedures/java_io/read.py +11 -0
- angr/procedures/java_io/write.py +16 -0
- angr/procedures/java_jni/__init__.py +475 -0
- angr/procedures/java_jni/array_operations.py +309 -0
- angr/procedures/java_jni/class_and_interface_operations.py +31 -0
- angr/procedures/java_jni/field_access.py +176 -0
- angr/procedures/java_jni/global_and_local_refs.py +56 -0
- angr/procedures/java_jni/method_calls.py +364 -0
- angr/procedures/java_jni/not_implemented.py +25 -0
- angr/procedures/java_jni/object_operations.py +95 -0
- angr/procedures/java_jni/string_operations.py +86 -0
- angr/procedures/java_jni/version_information.py +11 -0
- angr/procedures/java_lang/__init__.py +0 -0
- angr/procedures/java_lang/character.py +31 -0
- angr/procedures/java_lang/double.py +24 -0
- angr/procedures/java_lang/exit.py +12 -0
- angr/procedures/java_lang/getsimplename.py +15 -0
- angr/procedures/java_lang/integer.py +42 -0
- angr/procedures/java_lang/load_library.py +8 -0
- angr/procedures/java_lang/math.py +14 -0
- angr/procedures/java_lang/string.py +78 -0
- angr/procedures/java_lang/stringbuilder.py +43 -0
- angr/procedures/java_lang/system.py +17 -0
- angr/procedures/java_util/__init__.py +0 -0
- angr/procedures/java_util/collection.py +34 -0
- angr/procedures/java_util/iterator.py +45 -0
- angr/procedures/java_util/list.py +98 -0
- angr/procedures/java_util/map.py +132 -0
- angr/procedures/java_util/random.py +11 -0
- angr/procedures/java_util/scanner_nextline.py +22 -0
- angr/procedures/libc/__init__.py +3 -0
- angr/procedures/libc/abort.py +8 -0
- angr/procedures/libc/access.py +10 -0
- angr/procedures/libc/atoi.py +14 -0
- angr/procedures/libc/atol.py +12 -0
- angr/procedures/libc/calloc.py +7 -0
- angr/procedures/libc/closelog.py +9 -0
- angr/procedures/libc/err.py +13 -0
- angr/procedures/libc/error.py +55 -0
- angr/procedures/libc/exit.py +10 -0
- angr/procedures/libc/fclose.py +20 -0
- angr/procedures/libc/feof.py +19 -0
- angr/procedures/libc/fflush.py +15 -0
- angr/procedures/libc/fgetc.py +24 -0
- angr/procedures/libc/fgets.py +68 -0
- angr/procedures/libc/fopen.py +64 -0
- angr/procedures/libc/fprintf.py +24 -0
- angr/procedures/libc/fputc.py +22 -0
- angr/procedures/libc/fputs.py +23 -0
- angr/procedures/libc/fread.py +22 -0
- angr/procedures/libc/free.py +8 -0
- angr/procedures/libc/fscanf.py +20 -0
- angr/procedures/libc/fseek.py +32 -0
- angr/procedures/libc/ftell.py +21 -0
- angr/procedures/libc/fwrite.py +18 -0
- angr/procedures/libc/getchar.py +13 -0
- angr/procedures/libc/getdelim.py +96 -0
- angr/procedures/libc/getegid.py +7 -0
- angr/procedures/libc/geteuid.py +7 -0
- angr/procedures/libc/getgid.py +7 -0
- angr/procedures/libc/gets.py +66 -0
- angr/procedures/libc/getuid.py +7 -0
- angr/procedures/libc/malloc.py +11 -0
- angr/procedures/libc/memcmp.py +69 -0
- angr/procedures/libc/memcpy.py +37 -0
- angr/procedures/libc/memset.py +69 -0
- angr/procedures/libc/openlog.py +9 -0
- angr/procedures/libc/perror.py +12 -0
- angr/procedures/libc/printf.py +33 -0
- angr/procedures/libc/putchar.py +12 -0
- angr/procedures/libc/puts.py +16 -0
- angr/procedures/libc/rand.py +7 -0
- angr/procedures/libc/realloc.py +7 -0
- angr/procedures/libc/rewind.py +11 -0
- angr/procedures/libc/scanf.py +20 -0
- angr/procedures/libc/setbuf.py +8 -0
- angr/procedures/libc/setvbuf.py +6 -0
- angr/procedures/libc/snprintf.py +33 -0
- angr/procedures/libc/sprintf.py +22 -0
- angr/procedures/libc/srand.py +6 -0
- angr/procedures/libc/sscanf.py +13 -0
- angr/procedures/libc/stpcpy.py +18 -0
- angr/procedures/libc/strcat.py +13 -0
- angr/procedures/libc/strchr.py +44 -0
- angr/procedures/libc/strcmp.py +28 -0
- angr/procedures/libc/strcpy.py +13 -0
- angr/procedures/libc/strlen.py +99 -0
- angr/procedures/libc/strncat.py +18 -0
- angr/procedures/libc/strncmp.py +180 -0
- angr/procedures/libc/strncpy.py +18 -0
- angr/procedures/libc/strnlen.py +13 -0
- angr/procedures/libc/strstr.py +94 -0
- angr/procedures/libc/strtol.py +263 -0
- angr/procedures/libc/strtoul.py +9 -0
- angr/procedures/libc/system.py +12 -0
- angr/procedures/libc/time.py +9 -0
- angr/procedures/libc/tmpnam.py +19 -0
- angr/procedures/libc/tolower.py +7 -0
- angr/procedures/libc/toupper.py +7 -0
- angr/procedures/libc/ungetc.py +19 -0
- angr/procedures/libc/vsnprintf.py +16 -0
- angr/procedures/libc/wchar.py +15 -0
- angr/procedures/libstdcpp/__init__.py +0 -0
- angr/procedures/libstdcpp/_unwind_resume.py +10 -0
- angr/procedures/libstdcpp/std____throw_bad_alloc.py +12 -0
- angr/procedures/libstdcpp/std____throw_bad_cast.py +12 -0
- angr/procedures/libstdcpp/std____throw_length_error.py +12 -0
- angr/procedures/libstdcpp/std____throw_logic_error.py +12 -0
- angr/procedures/libstdcpp/std__terminate.py +12 -0
- angr/procedures/linux_kernel/__init__.py +3 -0
- angr/procedures/linux_kernel/access.py +17 -0
- angr/procedures/linux_kernel/arch_prctl.py +33 -0
- angr/procedures/linux_kernel/arm_user_helpers.py +58 -0
- angr/procedures/linux_kernel/brk.py +17 -0
- angr/procedures/linux_kernel/cwd.py +27 -0
- angr/procedures/linux_kernel/fstat.py +137 -0
- angr/procedures/linux_kernel/fstat64.py +169 -0
- angr/procedures/linux_kernel/futex.py +17 -0
- angr/procedures/linux_kernel/getegid.py +16 -0
- angr/procedures/linux_kernel/geteuid.py +16 -0
- angr/procedures/linux_kernel/getgid.py +16 -0
- angr/procedures/linux_kernel/getpid.py +13 -0
- angr/procedures/linux_kernel/getrlimit.py +24 -0
- angr/procedures/linux_kernel/gettid.py +8 -0
- angr/procedures/linux_kernel/getuid.py +16 -0
- angr/procedures/linux_kernel/iovec.py +43 -0
- angr/procedures/linux_kernel/lseek.py +39 -0
- angr/procedures/linux_kernel/mmap.py +15 -0
- angr/procedures/linux_kernel/mprotect.py +41 -0
- angr/procedures/linux_kernel/munmap.py +7 -0
- angr/procedures/linux_kernel/openat.py +28 -0
- angr/procedures/linux_kernel/set_tid_address.py +7 -0
- angr/procedures/linux_kernel/sigaction.py +16 -0
- angr/procedures/linux_kernel/sigprocmask.py +20 -0
- angr/procedures/linux_kernel/stat.py +22 -0
- angr/procedures/linux_kernel/sysinfo.py +58 -0
- angr/procedures/linux_kernel/tgkill.py +7 -0
- angr/procedures/linux_kernel/time.py +30 -0
- angr/procedures/linux_kernel/uid.py +29 -0
- angr/procedures/linux_kernel/uname.py +28 -0
- angr/procedures/linux_kernel/unlink.py +22 -0
- angr/procedures/linux_kernel/vsyscall.py +15 -0
- angr/procedures/linux_loader/__init__.py +3 -0
- angr/procedures/linux_loader/_dl_initial_error_catch_tsd.py +6 -0
- angr/procedures/linux_loader/_dl_rtld_lock.py +14 -0
- angr/procedures/linux_loader/sim_loader.py +53 -0
- angr/procedures/linux_loader/tls.py +40 -0
- angr/procedures/msvcr/__getmainargs.py +15 -0
- angr/procedures/msvcr/__init__.py +4 -0
- angr/procedures/msvcr/_initterm.py +37 -0
- angr/procedures/msvcr/fmode.py +28 -0
- angr/procedures/ntdll/__init__.py +0 -0
- angr/procedures/ntdll/exceptions.py +57 -0
- angr/procedures/posix/__init__.py +3 -0
- angr/procedures/posix/accept.py +29 -0
- angr/procedures/posix/bind.py +12 -0
- angr/procedures/posix/bzero.py +6 -0
- angr/procedures/posix/chroot.py +26 -0
- angr/procedures/posix/close.py +9 -0
- angr/procedures/posix/closedir.py +6 -0
- angr/procedures/posix/dup.py +55 -0
- angr/procedures/posix/fcntl.py +9 -0
- angr/procedures/posix/fdopen.py +77 -0
- angr/procedures/posix/fileno.py +17 -0
- angr/procedures/posix/fork.py +10 -0
- angr/procedures/posix/getenv.py +34 -0
- angr/procedures/posix/gethostbyname.py +42 -0
- angr/procedures/posix/getpass.py +18 -0
- angr/procedures/posix/getsockopt.py +10 -0
- angr/procedures/posix/htonl.py +11 -0
- angr/procedures/posix/htons.py +11 -0
- angr/procedures/posix/inet_ntoa.py +61 -0
- angr/procedures/posix/listen.py +12 -0
- angr/procedures/posix/mmap.py +140 -0
- angr/procedures/posix/open.py +17 -0
- angr/procedures/posix/opendir.py +9 -0
- angr/procedures/posix/poll.py +54 -0
- angr/procedures/posix/pread64.py +45 -0
- angr/procedures/posix/pthread.py +87 -0
- angr/procedures/posix/pwrite64.py +45 -0
- angr/procedures/posix/read.py +12 -0
- angr/procedures/posix/readdir.py +59 -0
- angr/procedures/posix/recv.py +12 -0
- angr/procedures/posix/recvfrom.py +12 -0
- angr/procedures/posix/select.py +46 -0
- angr/procedures/posix/send.py +22 -0
- angr/procedures/posix/setsockopt.py +8 -0
- angr/procedures/posix/sigaction.py +20 -0
- angr/procedures/posix/sim_time.py +45 -0
- angr/procedures/posix/sleep.py +7 -0
- angr/procedures/posix/socket.py +18 -0
- angr/procedures/posix/strcasecmp.py +23 -0
- angr/procedures/posix/strdup.py +17 -0
- angr/procedures/posix/strtok_r.py +65 -0
- angr/procedures/posix/syslog.py +15 -0
- angr/procedures/posix/tz.py +8 -0
- angr/procedures/posix/unlink.py +10 -0
- angr/procedures/posix/usleep.py +7 -0
- angr/procedures/posix/write.py +12 -0
- angr/procedures/procedure_dict.py +48 -0
- angr/procedures/stubs/CallReturn.py +12 -0
- angr/procedures/stubs/NoReturnUnconstrained.py +12 -0
- angr/procedures/stubs/Nop.py +6 -0
- angr/procedures/stubs/PathTerminator.py +8 -0
- angr/procedures/stubs/Redirect.py +15 -0
- angr/procedures/stubs/ReturnChar.py +10 -0
- angr/procedures/stubs/ReturnUnconstrained.py +24 -0
- angr/procedures/stubs/UnresolvableCallTarget.py +8 -0
- angr/procedures/stubs/UnresolvableJumpTarget.py +8 -0
- angr/procedures/stubs/UserHook.py +15 -0
- angr/procedures/stubs/__init__.py +3 -0
- angr/procedures/stubs/b64_decode.py +12 -0
- angr/procedures/stubs/caller.py +13 -0
- angr/procedures/stubs/crazy_scanf.py +17 -0
- angr/procedures/stubs/format_parser.py +677 -0
- angr/procedures/stubs/syscall_stub.py +26 -0
- angr/procedures/testing/__init__.py +3 -0
- angr/procedures/testing/manyargs.py +8 -0
- angr/procedures/testing/retreg.py +8 -0
- angr/procedures/tracer/__init__.py +4 -0
- angr/procedures/tracer/random.py +8 -0
- angr/procedures/tracer/receive.py +21 -0
- angr/procedures/tracer/transmit.py +24 -0
- angr/procedures/uclibc/__init__.py +3 -0
- angr/procedures/uclibc/__uClibc_main.py +9 -0
- angr/procedures/win32/EncodePointer.py +6 -0
- angr/procedures/win32/ExitProcess.py +8 -0
- angr/procedures/win32/GetCommandLine.py +11 -0
- angr/procedures/win32/GetCurrentProcessId.py +6 -0
- angr/procedures/win32/GetCurrentThreadId.py +6 -0
- angr/procedures/win32/GetLastInputInfo.py +37 -0
- angr/procedures/win32/GetModuleHandle.py +30 -0
- angr/procedures/win32/GetProcessAffinityMask.py +34 -0
- angr/procedures/win32/InterlockedExchange.py +14 -0
- angr/procedures/win32/IsProcessorFeaturePresent.py +6 -0
- angr/procedures/win32/VirtualAlloc.py +113 -0
- angr/procedures/win32/VirtualProtect.py +59 -0
- angr/procedures/win32/__init__.py +3 -0
- angr/procedures/win32/critical_section.py +11 -0
- angr/procedures/win32/dynamic_loading.py +103 -0
- angr/procedures/win32/file_handles.py +47 -0
- angr/procedures/win32/gethostbyname.py +10 -0
- angr/procedures/win32/heap.py +42 -0
- angr/procedures/win32/is_bad_ptr.py +25 -0
- angr/procedures/win32/local_storage.py +85 -0
- angr/procedures/win32/mutex.py +10 -0
- angr/procedures/win32/sim_time.py +135 -0
- angr/procedures/win32/system_paths.py +34 -0
- angr/procedures/win32_kernel/ExAllocatePool.py +12 -0
- angr/procedures/win32_kernel/ExFreePoolWithTag.py +7 -0
- angr/procedures/win32_kernel/__init__.py +3 -0
- angr/procedures/win_user32/__init__.py +0 -0
- angr/procedures/win_user32/chars.py +12 -0
- angr/procedures/win_user32/keyboard.py +13 -0
- angr/procedures/win_user32/messagebox.py +49 -0
- angr/project.py +834 -0
- angr/protos/__init__.py +13 -0
- angr/protos/cfg_pb2.py +31 -0
- angr/protos/function_pb2.py +37 -0
- angr/protos/primitives_pb2.py +124 -0
- angr/protos/variables_pb2.py +126 -0
- angr/protos/xrefs_pb2.py +34 -0
- angr/py.typed +1 -0
- angr/serializable.py +63 -0
- angr/service.py +35 -0
- angr/sim_manager.py +971 -0
- angr/sim_options.py +444 -0
- angr/sim_procedure.py +606 -0
- angr/sim_state.py +1003 -0
- angr/sim_state_options.py +409 -0
- angr/sim_type.py +3372 -0
- angr/sim_variable.py +562 -0
- angr/simos/__init__.py +31 -0
- angr/simos/cgc.py +152 -0
- angr/simos/javavm.py +471 -0
- angr/simos/linux.py +519 -0
- angr/simos/simos.py +450 -0
- angr/simos/snimmuc_nxp.py +152 -0
- angr/simos/userland.py +163 -0
- angr/simos/windows.py +562 -0
- angr/slicer.py +353 -0
- angr/state_hierarchy.py +262 -0
- angr/state_plugins/__init__.py +29 -0
- angr/state_plugins/callstack.py +404 -0
- angr/state_plugins/cgc.py +153 -0
- angr/state_plugins/concrete.py +297 -0
- angr/state_plugins/debug_variables.py +194 -0
- angr/state_plugins/filesystem.py +469 -0
- angr/state_plugins/gdb.py +146 -0
- angr/state_plugins/globals.py +62 -0
- angr/state_plugins/heap/__init__.py +5 -0
- angr/state_plugins/heap/heap_base.py +126 -0
- angr/state_plugins/heap/heap_brk.py +134 -0
- angr/state_plugins/heap/heap_freelist.py +210 -0
- angr/state_plugins/heap/heap_libc.py +45 -0
- angr/state_plugins/heap/heap_ptmalloc.py +646 -0
- angr/state_plugins/heap/utils.py +21 -0
- angr/state_plugins/history.py +548 -0
- angr/state_plugins/inspect.py +376 -0
- angr/state_plugins/javavm_classloader.py +133 -0
- angr/state_plugins/jni_references.py +93 -0
- angr/state_plugins/libc.py +1263 -0
- angr/state_plugins/light_registers.py +170 -0
- angr/state_plugins/log.py +85 -0
- angr/state_plugins/loop_data.py +92 -0
- angr/state_plugins/plugin.py +155 -0
- angr/state_plugins/posix.py +709 -0
- angr/state_plugins/preconstrainer.py +195 -0
- angr/state_plugins/scratch.py +175 -0
- angr/state_plugins/sim_action.py +334 -0
- angr/state_plugins/sim_action_object.py +148 -0
- angr/state_plugins/sim_event.py +58 -0
- angr/state_plugins/solver.py +1129 -0
- angr/state_plugins/symbolizer.py +292 -0
- angr/state_plugins/trace_additions.py +752 -0
- angr/state_plugins/uc_manager.py +85 -0
- angr/state_plugins/unicorn_engine.py +1899 -0
- angr/state_plugins/view.py +341 -0
- angr/storage/__init__.py +9 -0
- angr/storage/file.py +1219 -0
- angr/storage/memory_mixins/__init__.py +393 -0
- angr/storage/memory_mixins/__init__.pyi +49 -0
- angr/storage/memory_mixins/actions_mixin.py +69 -0
- angr/storage/memory_mixins/address_concretization_mixin.py +388 -0
- angr/storage/memory_mixins/bvv_conversion_mixin.py +74 -0
- angr/storage/memory_mixins/clouseau_mixin.py +131 -0
- angr/storage/memory_mixins/conditional_store_mixin.py +24 -0
- angr/storage/memory_mixins/convenient_mappings_mixin.py +257 -0
- angr/storage/memory_mixins/default_filler_mixin.py +146 -0
- angr/storage/memory_mixins/dirty_addrs_mixin.py +9 -0
- angr/storage/memory_mixins/hex_dumper_mixin.py +85 -0
- angr/storage/memory_mixins/javavm_memory/__init__.py +1 -0
- angr/storage/memory_mixins/javavm_memory/javavm_memory_mixin.py +394 -0
- angr/storage/memory_mixins/keyvalue_memory/__init__.py +1 -0
- angr/storage/memory_mixins/keyvalue_memory/keyvalue_memory_mixin.py +36 -0
- angr/storage/memory_mixins/label_merger_mixin.py +31 -0
- angr/storage/memory_mixins/multi_value_merger_mixin.py +68 -0
- angr/storage/memory_mixins/name_resolution_mixin.py +70 -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 +750 -0
- angr/storage/memory_mixins/paged_memory/paged_memory_multivalue_mixin.py +63 -0
- angr/storage/memory_mixins/paged_memory/pages/__init__.py +33 -0
- angr/storage/memory_mixins/paged_memory/pages/cooperation.py +330 -0
- angr/storage/memory_mixins/paged_memory/pages/history_tracking_mixin.py +87 -0
- angr/storage/memory_mixins/paged_memory/pages/ispo_mixin.py +53 -0
- angr/storage/memory_mixins/paged_memory/pages/list_page.py +346 -0
- angr/storage/memory_mixins/paged_memory/pages/multi_values.py +290 -0
- angr/storage/memory_mixins/paged_memory/pages/mv_list_page.py +434 -0
- angr/storage/memory_mixins/paged_memory/pages/permissions_mixin.py +33 -0
- angr/storage/memory_mixins/paged_memory/pages/refcount_mixin.py +51 -0
- angr/storage/memory_mixins/paged_memory/pages/ultra_page.py +468 -0
- angr/storage/memory_mixins/paged_memory/privileged_mixin.py +36 -0
- angr/storage/memory_mixins/paged_memory/stack_allocation_mixin.py +73 -0
- angr/storage/memory_mixins/regioned_memory/__init__.py +6 -0
- angr/storage/memory_mixins/regioned_memory/abstract_address_descriptor.py +35 -0
- angr/storage/memory_mixins/regioned_memory/abstract_merger_mixin.py +43 -0
- angr/storage/memory_mixins/regioned_memory/region_category_mixin.py +7 -0
- angr/storage/memory_mixins/regioned_memory/region_data.py +245 -0
- angr/storage/memory_mixins/regioned_memory/region_meta_mixin.py +125 -0
- angr/storage/memory_mixins/regioned_memory/regioned_address_concretization_mixin.py +118 -0
- angr/storage/memory_mixins/regioned_memory/regioned_memory_mixin.py +462 -0
- angr/storage/memory_mixins/regioned_memory/static_find_mixin.py +70 -0
- angr/storage/memory_mixins/simple_interface_mixin.py +73 -0
- angr/storage/memory_mixins/simplification_mixin.py +13 -0
- angr/storage/memory_mixins/size_resolution_mixin.py +140 -0
- angr/storage/memory_mixins/slotted_memory.py +140 -0
- angr/storage/memory_mixins/smart_find_mixin.py +159 -0
- angr/storage/memory_mixins/symbolic_merger_mixin.py +12 -0
- angr/storage/memory_mixins/top_merger_mixin.py +24 -0
- angr/storage/memory_mixins/underconstrained_mixin.py +67 -0
- angr/storage/memory_mixins/unwrapper_mixin.py +26 -0
- angr/storage/memory_object.py +194 -0
- angr/storage/pcap.py +65 -0
- angr/tablespecs.py +90 -0
- angr/utils/__init__.py +33 -0
- angr/utils/algo.py +33 -0
- angr/utils/constants.py +7 -0
- angr/utils/cowdict.py +64 -0
- angr/utils/dynamic_dictlist.py +92 -0
- angr/utils/enums_conv.py +80 -0
- angr/utils/env.py +11 -0
- angr/utils/formatting.py +124 -0
- angr/utils/funcid.py +133 -0
- angr/utils/graph.py +822 -0
- angr/utils/lazy_import.py +12 -0
- angr/utils/library.py +214 -0
- angr/utils/loader.py +55 -0
- angr/utils/mp.py +64 -0
- angr/utils/segment_list.py +558 -0
- angr/utils/timing.py +45 -0
- angr/utils/typing.py +17 -0
- angr/vaults.py +370 -0
- angr-9.2.103.dist-info/LICENSE +24 -0
- angr-9.2.103.dist-info/METADATA +119 -0
- angr-9.2.103.dist-info/RECORD +1300 -0
- angr-9.2.103.dist-info/WHEEL +5 -0
- angr-9.2.103.dist-info/entry_points.txt +2 -0
- angr-9.2.103.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2166 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import copy
|
|
3
|
+
from collections import defaultdict, namedtuple
|
|
4
|
+
import logging
|
|
5
|
+
import enum
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Any, NamedTuple, TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from collections.abc import Iterable
|
|
10
|
+
|
|
11
|
+
import networkx
|
|
12
|
+
import capstone
|
|
13
|
+
|
|
14
|
+
import ailment
|
|
15
|
+
|
|
16
|
+
from ...knowledge_base import KnowledgeBase
|
|
17
|
+
from ...knowledge_plugins.functions import Function
|
|
18
|
+
from ...knowledge_plugins.cfg.memory_data import MemoryDataSort
|
|
19
|
+
from ...codenode import BlockNode
|
|
20
|
+
from ...utils import timethis
|
|
21
|
+
from ...calling_conventions import SimRegArg, SimStackArg, SimStructArg, SimFunctionArgument
|
|
22
|
+
from ...sim_type import (
|
|
23
|
+
SimTypeChar,
|
|
24
|
+
SimTypeInt,
|
|
25
|
+
SimTypeLongLong,
|
|
26
|
+
SimTypeShort,
|
|
27
|
+
SimTypeFunction,
|
|
28
|
+
SimTypeBottom,
|
|
29
|
+
SimTypeFloat,
|
|
30
|
+
SimTypePointer,
|
|
31
|
+
)
|
|
32
|
+
from ..stack_pointer_tracker import Register, OffsetVal
|
|
33
|
+
from ...sim_variable import SimVariable, SimStackVariable, SimRegisterVariable, SimMemoryVariable
|
|
34
|
+
from ...knowledge_plugins.key_definitions.constants import OP_BEFORE
|
|
35
|
+
from ...procedures.stubs.UnresolvableCallTarget import UnresolvableCallTarget
|
|
36
|
+
from ...procedures.stubs.UnresolvableJumpTarget import UnresolvableJumpTarget
|
|
37
|
+
from .. import Analysis, register_analysis
|
|
38
|
+
from ..cfg.cfg_base import CFGBase
|
|
39
|
+
from ..reaching_definitions import ReachingDefinitionsAnalysis
|
|
40
|
+
from .return_maker import ReturnMaker
|
|
41
|
+
from .ailgraph_walker import AILGraphWalker, RemoveNodeNotice
|
|
42
|
+
from .optimization_passes import (
|
|
43
|
+
get_default_optimization_passes,
|
|
44
|
+
OptimizationPassStage,
|
|
45
|
+
RegisterSaveAreaSimplifier,
|
|
46
|
+
StackCanarySimplifier,
|
|
47
|
+
SpilledRegisterFinder,
|
|
48
|
+
DUPLICATING_OPTS,
|
|
49
|
+
CONDENSING_OPTS,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if TYPE_CHECKING:
|
|
53
|
+
from angr.knowledge_plugins.cfg import CFGModel
|
|
54
|
+
from .decompilation_cache import DecompilationCache
|
|
55
|
+
from .peephole_optimizations import PeepholeOptimizationStmtBase, PeepholeOptimizationExprBase
|
|
56
|
+
|
|
57
|
+
l = logging.getLogger(name=__name__)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
BlockCache = namedtuple("BlockCache", ("rd", "prop"))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ClinicMode(enum.Enum):
|
|
64
|
+
"""
|
|
65
|
+
Analysis mode for Clinic.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
DECOMPILE = 1
|
|
69
|
+
COLLECT_DATA_REFS = 2
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class DataRefDesc:
|
|
74
|
+
"""
|
|
75
|
+
The fields of this class is compatible with items inside IRSB.data_refs.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
data_addr: int
|
|
79
|
+
data_size: int
|
|
80
|
+
block_addr: int
|
|
81
|
+
stmt_idx: int
|
|
82
|
+
ins_addr: int
|
|
83
|
+
data_type_str: str
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Clinic(Analysis):
|
|
87
|
+
"""
|
|
88
|
+
A Clinic deals with AILments.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(
|
|
92
|
+
self,
|
|
93
|
+
func,
|
|
94
|
+
remove_dead_memdefs=False,
|
|
95
|
+
exception_edges=False,
|
|
96
|
+
sp_tracker_track_memory=True,
|
|
97
|
+
fold_callexprs_into_conditions=False,
|
|
98
|
+
insert_labels=True,
|
|
99
|
+
optimization_passes=None,
|
|
100
|
+
cfg=None,
|
|
101
|
+
peephole_optimizations: None | (
|
|
102
|
+
Iterable[type[PeepholeOptimizationStmtBase] | type[PeepholeOptimizationExprBase]]
|
|
103
|
+
) = None, # pylint:disable=line-too-long
|
|
104
|
+
must_struct: set[str] | None = None,
|
|
105
|
+
variable_kb=None,
|
|
106
|
+
reset_variable_names=False,
|
|
107
|
+
rewrite_ites_to_diamonds=True,
|
|
108
|
+
cache: DecompilationCache | None = None,
|
|
109
|
+
mode: ClinicMode = ClinicMode.DECOMPILE,
|
|
110
|
+
sp_shift: int = 0,
|
|
111
|
+
inline_functions: set[Function] | None = frozenset(),
|
|
112
|
+
inlined_counts: dict[int, int] | None = None,
|
|
113
|
+
inlining_parents: set[int] | None = None,
|
|
114
|
+
):
|
|
115
|
+
if not func.normalized and mode == ClinicMode.DECOMPILE:
|
|
116
|
+
raise ValueError("Decompilation must work on normalized function graphs.")
|
|
117
|
+
|
|
118
|
+
self.function = func
|
|
119
|
+
|
|
120
|
+
self.graph = None
|
|
121
|
+
self.cc_graph: networkx.DiGraph | None = None
|
|
122
|
+
self.unoptimized_graph: networkx.DiGraph | None = None
|
|
123
|
+
self.arg_list = None
|
|
124
|
+
self.variable_kb = variable_kb
|
|
125
|
+
self.externs: set[SimMemoryVariable] = set()
|
|
126
|
+
self.data_refs: dict[int, int] = {} # data address to instruction address
|
|
127
|
+
|
|
128
|
+
self._func_graph: networkx.DiGraph | None = None
|
|
129
|
+
self._ail_manager = None
|
|
130
|
+
self._blocks_by_addr_and_size = {}
|
|
131
|
+
|
|
132
|
+
self._fold_callexprs_into_conditions = fold_callexprs_into_conditions
|
|
133
|
+
self._insert_labels = insert_labels
|
|
134
|
+
self._remove_dead_memdefs = remove_dead_memdefs
|
|
135
|
+
self._exception_edges = exception_edges
|
|
136
|
+
self._sp_tracker_track_memory = sp_tracker_track_memory
|
|
137
|
+
self._cfg: CFGModel | None = cfg
|
|
138
|
+
self.peephole_optimizations = peephole_optimizations
|
|
139
|
+
self._must_struct = must_struct
|
|
140
|
+
self._reset_variable_names = reset_variable_names
|
|
141
|
+
self._rewrite_ites_to_diamonds = rewrite_ites_to_diamonds
|
|
142
|
+
self.reaching_definitions: ReachingDefinitionsAnalysis | None = None
|
|
143
|
+
self._cache = cache
|
|
144
|
+
self._mode = mode
|
|
145
|
+
|
|
146
|
+
# inlining help
|
|
147
|
+
self._sp_shift = sp_shift
|
|
148
|
+
self._max_stack_depth = 0
|
|
149
|
+
self._inline_functions = inline_functions
|
|
150
|
+
self._inlined_counts = {} if inlined_counts is None else inlined_counts
|
|
151
|
+
self._inlining_parents = inlining_parents or ()
|
|
152
|
+
|
|
153
|
+
self._register_save_areas_removed: bool = False
|
|
154
|
+
|
|
155
|
+
self._new_block_addrs = set()
|
|
156
|
+
|
|
157
|
+
# sanity checks
|
|
158
|
+
if not self.kb.functions:
|
|
159
|
+
l.warning("No function is available in kb.functions. It will lead to a suboptimal conversion result.")
|
|
160
|
+
|
|
161
|
+
if optimization_passes is not None:
|
|
162
|
+
self._optimization_passes = optimization_passes
|
|
163
|
+
else:
|
|
164
|
+
self._optimization_passes = get_default_optimization_passes(self.project.arch, self.project.simos.name)
|
|
165
|
+
l.debug("Get %d optimization passes for the current binary.", len(self._optimization_passes))
|
|
166
|
+
|
|
167
|
+
if self._mode == ClinicMode.DECOMPILE:
|
|
168
|
+
self._analyze_for_decompiling()
|
|
169
|
+
elif self._mode == ClinicMode.COLLECT_DATA_REFS:
|
|
170
|
+
self._analyze_for_data_refs()
|
|
171
|
+
else:
|
|
172
|
+
raise TypeError(f"Unsupported analysis mode {self._mode}")
|
|
173
|
+
|
|
174
|
+
#
|
|
175
|
+
# Public methods
|
|
176
|
+
#
|
|
177
|
+
|
|
178
|
+
def block(self, addr, size):
|
|
179
|
+
"""
|
|
180
|
+
Get the converted block at the given specific address with the given size.
|
|
181
|
+
|
|
182
|
+
:param int addr:
|
|
183
|
+
:param int size:
|
|
184
|
+
:return:
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
return self._blocks_by_addr_and_size[(addr, size)]
|
|
189
|
+
except KeyError:
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
def dbg_repr(self):
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
:return:
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
s = ""
|
|
199
|
+
|
|
200
|
+
for block in sorted(self.graph.nodes(), key=lambda x: x.addr):
|
|
201
|
+
s += str(block) + "\n\n"
|
|
202
|
+
|
|
203
|
+
return s
|
|
204
|
+
|
|
205
|
+
#
|
|
206
|
+
# Private methods
|
|
207
|
+
#
|
|
208
|
+
|
|
209
|
+
def _analyze_for_decompiling(self):
|
|
210
|
+
if not (ail_graph := self._decompilation_graph_recovery()):
|
|
211
|
+
return
|
|
212
|
+
ail_graph = self._decompilation_fixups(ail_graph)
|
|
213
|
+
|
|
214
|
+
if self._inline_functions:
|
|
215
|
+
self._max_stack_depth += self.calculate_stack_depth()
|
|
216
|
+
ail_graph = self._inline_child_functions(ail_graph)
|
|
217
|
+
|
|
218
|
+
ail_graph = self._decompilation_simplifications(ail_graph)
|
|
219
|
+
self.graph = ail_graph
|
|
220
|
+
|
|
221
|
+
def _decompilation_graph_recovery(self):
|
|
222
|
+
is_pcode_arch = ":" in self.project.arch.name
|
|
223
|
+
|
|
224
|
+
# Set up the function graph according to configurations
|
|
225
|
+
self._update_progress(0.0, text="Setting up function graph")
|
|
226
|
+
self._set_function_graph()
|
|
227
|
+
|
|
228
|
+
# Remove alignment blocks
|
|
229
|
+
self._update_progress(5.0, text="Removing alignment blocks")
|
|
230
|
+
self._remove_alignment_blocks()
|
|
231
|
+
|
|
232
|
+
# if the graph is empty, don't continue
|
|
233
|
+
if not self._func_graph:
|
|
234
|
+
return None
|
|
235
|
+
|
|
236
|
+
# Make sure calling conventions of all functions that the current function calls have been recovered
|
|
237
|
+
if not is_pcode_arch:
|
|
238
|
+
self._update_progress(10.0, text="Recovering calling conventions")
|
|
239
|
+
self._recover_calling_conventions()
|
|
240
|
+
|
|
241
|
+
# initialize the AIL conversion manager
|
|
242
|
+
self._ail_manager = ailment.Manager(arch=self.project.arch)
|
|
243
|
+
|
|
244
|
+
# Convert VEX blocks to AIL blocks and then simplify them
|
|
245
|
+
|
|
246
|
+
self._update_progress(20.0, text="Converting VEX to AIL")
|
|
247
|
+
self._convert_all()
|
|
248
|
+
|
|
249
|
+
return self._make_ailgraph()
|
|
250
|
+
|
|
251
|
+
def _decompilation_fixups(self, ail_graph):
|
|
252
|
+
is_pcode_arch = ":" in self.project.arch.name
|
|
253
|
+
|
|
254
|
+
if self._rewrite_ites_to_diamonds:
|
|
255
|
+
self._rewrite_ite_expressions(ail_graph)
|
|
256
|
+
self._remove_redundant_jump_blocks(ail_graph)
|
|
257
|
+
if self._insert_labels:
|
|
258
|
+
self._insert_block_labels(ail_graph)
|
|
259
|
+
|
|
260
|
+
# Run simplification passes
|
|
261
|
+
self._update_progress(22.0, text="Optimizing fresh ailment graph")
|
|
262
|
+
ail_graph = self._run_simplification_passes(ail_graph, OptimizationPassStage.AFTER_AIL_GRAPH_CREATION)
|
|
263
|
+
|
|
264
|
+
# Fix "fake" indirect jumps and calls
|
|
265
|
+
self._update_progress(25.0, text="Analyzing simple indirect jumps")
|
|
266
|
+
ail_graph = self._replace_single_target_indirect_transitions(ail_graph)
|
|
267
|
+
|
|
268
|
+
# Fix tail calls
|
|
269
|
+
self._update_progress(28.0, text="Analyzing tail calls")
|
|
270
|
+
ail_graph = self._replace_tail_jumps_with_calls(ail_graph)
|
|
271
|
+
|
|
272
|
+
if is_pcode_arch:
|
|
273
|
+
self._update_progress(29.0, text="Recovering calling conventions (AIL mode)")
|
|
274
|
+
self._recover_calling_conventions(func_graph=ail_graph)
|
|
275
|
+
|
|
276
|
+
return ail_graph
|
|
277
|
+
|
|
278
|
+
def _inline_child_functions(self, ail_graph):
|
|
279
|
+
for blk in ail_graph.nodes():
|
|
280
|
+
for idx, stmt in enumerate(blk.statements):
|
|
281
|
+
if isinstance(stmt, ailment.Stmt.Call) and isinstance(stmt.target, ailment.Expr.Const):
|
|
282
|
+
callee = self.function._function_manager.function(stmt.target.value)
|
|
283
|
+
if (
|
|
284
|
+
callee.addr == self.function.addr
|
|
285
|
+
or callee.addr in self._inlining_parents
|
|
286
|
+
or callee not in self._inline_functions
|
|
287
|
+
or callee.is_plt
|
|
288
|
+
or callee.is_simprocedure
|
|
289
|
+
):
|
|
290
|
+
continue
|
|
291
|
+
|
|
292
|
+
ail_graph = self._inline_call(ail_graph, blk, idx, callee)
|
|
293
|
+
return ail_graph
|
|
294
|
+
|
|
295
|
+
def _inline_call(self, ail_graph, caller_block, call_idx, callee):
|
|
296
|
+
callee_clinic = self.project.analyses.Clinic(
|
|
297
|
+
callee,
|
|
298
|
+
mode=ClinicMode.DECOMPILE,
|
|
299
|
+
inline_functions=self._inline_functions,
|
|
300
|
+
inlining_parents=self._inlining_parents + (self.function.addr,),
|
|
301
|
+
inlined_counts=self._inlined_counts,
|
|
302
|
+
optimization_passes=[StackCanarySimplifier, SpilledRegisterFinder],
|
|
303
|
+
sp_shift=self._max_stack_depth,
|
|
304
|
+
)
|
|
305
|
+
self._max_stack_depth = callee_clinic._max_stack_depth
|
|
306
|
+
callee_graph = callee_clinic.copy_graph()
|
|
307
|
+
|
|
308
|
+
# uniquely mark all the blocks in case of duplicates (e.g., foo(); foo();)
|
|
309
|
+
self._inlined_counts.setdefault(callee.addr, 0)
|
|
310
|
+
for blk in callee_graph.nodes():
|
|
311
|
+
blk.idx = self._inlined_counts[callee.addr]
|
|
312
|
+
self._inlined_counts[callee.addr] += 1
|
|
313
|
+
|
|
314
|
+
# figure out where the callee should start at and return to
|
|
315
|
+
callee_start = next(n for n in callee_graph if n.addr == callee.addr)
|
|
316
|
+
caller_successors = list(ail_graph.out_edges(caller_block, data=True))
|
|
317
|
+
assert len(caller_successors) == 1
|
|
318
|
+
caller_successor = caller_successors[0][1]
|
|
319
|
+
ail_graph.remove_edge(caller_block, caller_successor)
|
|
320
|
+
|
|
321
|
+
# update all callee return nodes with caller successor
|
|
322
|
+
# and rewrite pseudoreg-tagged spills to actually use pseudoregs
|
|
323
|
+
ail_graph = networkx.union(ail_graph, callee_graph)
|
|
324
|
+
for blk in callee_graph.nodes():
|
|
325
|
+
for idx, stmt in enumerate(list(blk.statements)):
|
|
326
|
+
if isinstance(stmt, ailment.Stmt.Return):
|
|
327
|
+
blk.statements[idx] = ailment.Stmt.Jump(
|
|
328
|
+
None,
|
|
329
|
+
ailment.Expr.Const(None, None, caller_successor.addr, self.project.arch.bits),
|
|
330
|
+
caller_successor.idx,
|
|
331
|
+
**blk.statements[idx].tags,
|
|
332
|
+
)
|
|
333
|
+
blk.statements.pop(idx)
|
|
334
|
+
ail_graph.add_edge(blk, caller_successor)
|
|
335
|
+
break
|
|
336
|
+
if "pseudoreg" in stmt.tags and isinstance(stmt, ailment.Stmt.Store):
|
|
337
|
+
new_stmt = ailment.Stmt.Assignment(
|
|
338
|
+
stmt.idx, ailment.Expr.Register(None, None, stmt.pseudoreg, stmt.size * 8), stmt.data
|
|
339
|
+
)
|
|
340
|
+
new_stmt.tags.update(stmt.tags)
|
|
341
|
+
new_stmt.tags.pop("pseudoreg")
|
|
342
|
+
blk.statements[idx] = new_stmt
|
|
343
|
+
if "pseudoreg" in stmt.tags and isinstance(stmt, ailment.Stmt.Assignment):
|
|
344
|
+
new_stmt = ailment.Stmt.Assignment(
|
|
345
|
+
stmt.idx, stmt.dst, ailment.Expr.Register(None, None, stmt.pseudoreg, stmt.src.size * 8)
|
|
346
|
+
)
|
|
347
|
+
new_stmt.tags.update(stmt.tags)
|
|
348
|
+
new_stmt.tags.pop("pseudoreg")
|
|
349
|
+
blk.statements[idx] = new_stmt
|
|
350
|
+
|
|
351
|
+
# update the call edge
|
|
352
|
+
caller_block.statements[call_idx] = ailment.Stmt.Jump(
|
|
353
|
+
None,
|
|
354
|
+
ailment.Expr.Const(None, None, callee.addr, self.project.arch.bits),
|
|
355
|
+
callee_start.idx,
|
|
356
|
+
**caller_block.statements[call_idx].tags,
|
|
357
|
+
)
|
|
358
|
+
if (
|
|
359
|
+
isinstance(caller_block.statements[call_idx - 2], ailment.Stmt.Store)
|
|
360
|
+
and caller_block.statements[call_idx - 2].data.value == caller_successor.addr
|
|
361
|
+
):
|
|
362
|
+
# don't push the return address
|
|
363
|
+
caller_block.statements.pop(call_idx - 5) # t6 = rsp<8>
|
|
364
|
+
caller_block.statements.pop(call_idx - 5) # t5 = (t6 - 0x8<64>)
|
|
365
|
+
caller_block.statements.pop(call_idx - 5) # rsp<8> = t5
|
|
366
|
+
caller_block.statements.pop(
|
|
367
|
+
call_idx - 5
|
|
368
|
+
) # STORE(addr=t5, data=0x40121b<64>, size=8, endness=Iend_LE, guard=None)
|
|
369
|
+
caller_block.statements.pop(call_idx - 5) # t7 = (t5 - 0x80<64>) <- wtf is this??
|
|
370
|
+
elif (
|
|
371
|
+
isinstance(caller_block.statements[call_idx - 1], ailment.Stmt.Store)
|
|
372
|
+
and caller_block.statements[call_idx - 1].addr.base == "stack_base"
|
|
373
|
+
and caller_block.statements[call_idx - 1].data.value == caller_successor.addr
|
|
374
|
+
):
|
|
375
|
+
caller_block.statements.pop(call_idx - 1) # s_10 =L 0x401225<64><8>
|
|
376
|
+
ail_graph.add_edge(caller_block, callee_start)
|
|
377
|
+
|
|
378
|
+
return ail_graph
|
|
379
|
+
|
|
380
|
+
def calculate_stack_depth(self):
|
|
381
|
+
# we need to reserve space for our own stack
|
|
382
|
+
spt = self._track_stack_pointers()
|
|
383
|
+
stack_offsets = spt.offsets_for(self.project.arch.sp_offset)
|
|
384
|
+
if max(stack_offsets) > 2 ** (self.project.arch.bits - 1):
|
|
385
|
+
# why is this unsigned...
|
|
386
|
+
depth = min(s for s in stack_offsets if s > 2 ** (self.project.arch.bits - 1)) - 2**self.project.arch.bits
|
|
387
|
+
else:
|
|
388
|
+
depth = min(stack_offsets)
|
|
389
|
+
|
|
390
|
+
if spt.inconsistent_for(self.project.arch.sp_offset):
|
|
391
|
+
l.warning("Inconsistency found during stack pointer tracking. Stack depth may be incorrect.")
|
|
392
|
+
depth -= 0x1000
|
|
393
|
+
|
|
394
|
+
return depth
|
|
395
|
+
|
|
396
|
+
def _decompilation_simplifications(self, ail_graph):
|
|
397
|
+
# Make returns
|
|
398
|
+
self._update_progress(30.0, text="Making return sites")
|
|
399
|
+
if self.function.prototype is None or not isinstance(self.function.prototype.returnty, SimTypeBottom):
|
|
400
|
+
ail_graph = self._make_returns(ail_graph)
|
|
401
|
+
|
|
402
|
+
# full-function constant-only propagation
|
|
403
|
+
self._update_progress(33.0, text="Constant propagation")
|
|
404
|
+
self._simplify_function(
|
|
405
|
+
ail_graph,
|
|
406
|
+
remove_dead_memdefs=False,
|
|
407
|
+
unify_variables=False,
|
|
408
|
+
narrow_expressions=False,
|
|
409
|
+
only_consts=True,
|
|
410
|
+
fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
|
|
411
|
+
max_iterations=1,
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
# cached block-level reaching definition analysis results and propagator results
|
|
415
|
+
block_simplification_cache: dict[ailment.Block, NamedTuple] | None = {}
|
|
416
|
+
|
|
417
|
+
# Track stack pointers
|
|
418
|
+
self._update_progress(15.0, text="Tracking stack pointers")
|
|
419
|
+
spt = self._track_stack_pointers()
|
|
420
|
+
|
|
421
|
+
# Simplify blocks
|
|
422
|
+
# we never remove dead memory definitions before making callsites. otherwise stack arguments may go missing
|
|
423
|
+
# before they are recognized as stack arguments.
|
|
424
|
+
self._update_progress(35.0, text="Simplifying blocks 1")
|
|
425
|
+
ail_graph = self._simplify_blocks(
|
|
426
|
+
ail_graph, stack_pointer_tracker=spt, remove_dead_memdefs=False, cache=block_simplification_cache
|
|
427
|
+
)
|
|
428
|
+
self._rewrite_alloca(ail_graph)
|
|
429
|
+
|
|
430
|
+
# Run simplification passes
|
|
431
|
+
self._update_progress(40.0, text="Running simplifications 1")
|
|
432
|
+
ail_graph = self._run_simplification_passes(
|
|
433
|
+
ail_graph, stage=OptimizationPassStage.AFTER_SINGLE_BLOCK_SIMPLIFICATION
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
# Simplify the entire function for the first time
|
|
437
|
+
self._update_progress(45.0, text="Simplifying function 1")
|
|
438
|
+
self._simplify_function(
|
|
439
|
+
ail_graph,
|
|
440
|
+
remove_dead_memdefs=False,
|
|
441
|
+
unify_variables=False,
|
|
442
|
+
narrow_expressions=True,
|
|
443
|
+
fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Run simplification passes again. there might be more chances for peephole optimizations after function-level
|
|
447
|
+
# simplification
|
|
448
|
+
self._update_progress(48.0, text="Simplifying blocks 2")
|
|
449
|
+
ail_graph = self._simplify_blocks(
|
|
450
|
+
ail_graph, stack_pointer_tracker=spt, remove_dead_memdefs=False, cache=block_simplification_cache
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
# clear _blocks_by_addr_and_size so no one can use it again
|
|
454
|
+
# TODO: Totally remove this dict
|
|
455
|
+
self._blocks_by_addr_and_size = None
|
|
456
|
+
|
|
457
|
+
# Make call-sites
|
|
458
|
+
self._update_progress(50.0, text="Making callsites")
|
|
459
|
+
_, stackarg_offsets = self._make_callsites(ail_graph, stack_pointer_tracker=spt)
|
|
460
|
+
|
|
461
|
+
# Run simplification passes
|
|
462
|
+
self._update_progress(53.0, text="Running simplifications 2")
|
|
463
|
+
ail_graph = self._run_simplification_passes(ail_graph, stage=OptimizationPassStage.AFTER_MAKING_CALLSITES)
|
|
464
|
+
|
|
465
|
+
# Simplify the entire function for the second time
|
|
466
|
+
self._update_progress(55.0, text="Simplifying function 2")
|
|
467
|
+
self._simplify_function(
|
|
468
|
+
ail_graph,
|
|
469
|
+
remove_dead_memdefs=self._remove_dead_memdefs,
|
|
470
|
+
stack_arg_offsets=stackarg_offsets,
|
|
471
|
+
unify_variables=True,
|
|
472
|
+
narrow_expressions=True,
|
|
473
|
+
fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
# After global optimization, there might be more chances for peephole optimizations.
|
|
477
|
+
# Simplify blocks for the second time
|
|
478
|
+
self._update_progress(60.0, text="Simplifying blocks 3")
|
|
479
|
+
ail_graph = self._simplify_blocks(
|
|
480
|
+
ail_graph,
|
|
481
|
+
remove_dead_memdefs=self._remove_dead_memdefs,
|
|
482
|
+
stack_pointer_tracker=spt,
|
|
483
|
+
cache=block_simplification_cache,
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
# Run simplification passes
|
|
487
|
+
self._update_progress(65.0, text="Running simplifications 3 ")
|
|
488
|
+
ail_graph = self._run_simplification_passes(ail_graph, stage=OptimizationPassStage.AFTER_GLOBAL_SIMPLIFICATION)
|
|
489
|
+
|
|
490
|
+
# Simplify the entire function for the third time
|
|
491
|
+
self._update_progress(70.0, text="Simplifying function 3")
|
|
492
|
+
self._simplify_function(
|
|
493
|
+
ail_graph,
|
|
494
|
+
remove_dead_memdefs=self._remove_dead_memdefs,
|
|
495
|
+
stack_arg_offsets=stackarg_offsets,
|
|
496
|
+
unify_variables=True,
|
|
497
|
+
narrow_expressions=True,
|
|
498
|
+
fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
self._update_progress(72.0, text="Simplifying blocks 4")
|
|
502
|
+
ail_graph = self._simplify_blocks(
|
|
503
|
+
ail_graph,
|
|
504
|
+
remove_dead_memdefs=self._remove_dead_memdefs,
|
|
505
|
+
stack_pointer_tracker=spt,
|
|
506
|
+
cache=block_simplification_cache,
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
# Make function arguments
|
|
510
|
+
self._update_progress(75.0, text="Making argument list")
|
|
511
|
+
arg_list = self._make_argument_list()
|
|
512
|
+
|
|
513
|
+
# Recover variables on AIL blocks
|
|
514
|
+
self._update_progress(80.0, text="Recovering variables")
|
|
515
|
+
variable_kb = self._recover_and_link_variables(ail_graph, arg_list)
|
|
516
|
+
|
|
517
|
+
# Make function prototype
|
|
518
|
+
self._update_progress(90.0, text="Making function prototype")
|
|
519
|
+
self._make_function_prototype(arg_list, variable_kb)
|
|
520
|
+
|
|
521
|
+
# Run simplification passes
|
|
522
|
+
self._update_progress(95.0, text="Running simplifications 4")
|
|
523
|
+
ail_graph = self._run_simplification_passes(
|
|
524
|
+
ail_graph, stage=OptimizationPassStage.AFTER_VARIABLE_RECOVERY, variable_kb=variable_kb
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
# remove empty nodes from the graph
|
|
528
|
+
ail_graph = self.remove_empty_nodes(ail_graph)
|
|
529
|
+
|
|
530
|
+
self.arg_list = arg_list
|
|
531
|
+
self.variable_kb = variable_kb
|
|
532
|
+
self.cc_graph = self.copy_graph(ail_graph)
|
|
533
|
+
self.externs = self._collect_externs(ail_graph, variable_kb)
|
|
534
|
+
return ail_graph
|
|
535
|
+
|
|
536
|
+
def _analyze_for_data_refs(self):
|
|
537
|
+
# Set up the function graph according to configurations
|
|
538
|
+
self._update_progress(0.0, text="Setting up function graph")
|
|
539
|
+
self._set_function_graph()
|
|
540
|
+
|
|
541
|
+
# Remove alignment blocks
|
|
542
|
+
self._update_progress(5.0, text="Removing alignment blocks")
|
|
543
|
+
self._remove_alignment_blocks()
|
|
544
|
+
|
|
545
|
+
# if the graph is empty, don't continue
|
|
546
|
+
if not self._func_graph:
|
|
547
|
+
return
|
|
548
|
+
|
|
549
|
+
# initialize the AIL conversion manager
|
|
550
|
+
self._ail_manager = ailment.Manager(arch=self.project.arch)
|
|
551
|
+
|
|
552
|
+
# Track stack pointers
|
|
553
|
+
self._update_progress(15.0, text="Tracking stack pointers")
|
|
554
|
+
spt = self._track_stack_pointers()
|
|
555
|
+
|
|
556
|
+
# Convert VEX blocks to AIL blocks and then simplify them
|
|
557
|
+
|
|
558
|
+
self._update_progress(20.0, text="Converting VEX to AIL")
|
|
559
|
+
self._convert_all()
|
|
560
|
+
|
|
561
|
+
# there must be at least one Load or one Store
|
|
562
|
+
found_load_or_store = False
|
|
563
|
+
for ail_block in self._blocks_by_addr_and_size.values():
|
|
564
|
+
for stmt in ail_block.statements:
|
|
565
|
+
if isinstance(stmt, ailment.Stmt.Store):
|
|
566
|
+
found_load_or_store = True
|
|
567
|
+
break
|
|
568
|
+
if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.Load):
|
|
569
|
+
found_load_or_store = True
|
|
570
|
+
break
|
|
571
|
+
if not found_load_or_store:
|
|
572
|
+
self.data_refs = {}
|
|
573
|
+
return
|
|
574
|
+
|
|
575
|
+
ail_graph = self._make_ailgraph()
|
|
576
|
+
self._remove_redundant_jump_blocks(ail_graph)
|
|
577
|
+
|
|
578
|
+
# full-function constant-only propagation
|
|
579
|
+
self._update_progress(33.0, text="Constant propagation")
|
|
580
|
+
self._simplify_function(
|
|
581
|
+
ail_graph,
|
|
582
|
+
remove_dead_memdefs=False,
|
|
583
|
+
unify_variables=False,
|
|
584
|
+
narrow_expressions=False,
|
|
585
|
+
only_consts=True,
|
|
586
|
+
fold_callexprs_into_conditions=self._fold_callexprs_into_conditions,
|
|
587
|
+
max_iterations=1,
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
# cached block-level reaching definition analysis results and propagator results
|
|
591
|
+
block_simplification_cache: dict[ailment.Block, NamedTuple] | None = {}
|
|
592
|
+
|
|
593
|
+
# Simplify blocks
|
|
594
|
+
# we never remove dead memory definitions before making callsites. otherwise stack arguments may go missing
|
|
595
|
+
# before they are recognized as stack arguments.
|
|
596
|
+
self._update_progress(35.0, text="Simplifying blocks 1")
|
|
597
|
+
ail_graph = self._simplify_blocks(
|
|
598
|
+
ail_graph, stack_pointer_tracker=spt, remove_dead_memdefs=False, cache=block_simplification_cache
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
# Simplify the entire function for the first time
|
|
602
|
+
self._update_progress(45.0, text="Simplifying function 1")
|
|
603
|
+
self._simplify_function(
|
|
604
|
+
ail_graph,
|
|
605
|
+
remove_dead_memdefs=False,
|
|
606
|
+
unify_variables=False,
|
|
607
|
+
narrow_expressions=False,
|
|
608
|
+
fold_callexprs_into_conditions=False,
|
|
609
|
+
rewrite_ccalls=False,
|
|
610
|
+
max_iterations=1,
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
# clear _blocks_by_addr_and_size so no one can use it again
|
|
614
|
+
# TODO: Totally remove this dict
|
|
615
|
+
self._blocks_by_addr_and_size = None
|
|
616
|
+
|
|
617
|
+
self.graph = ail_graph
|
|
618
|
+
self.arg_list = None
|
|
619
|
+
self.variable_kb = None
|
|
620
|
+
self.cc_graph = None
|
|
621
|
+
self.externs = None
|
|
622
|
+
self.data_refs: dict[int, list[DataRefDesc]] = self._collect_data_refs(ail_graph)
|
|
623
|
+
|
|
624
|
+
@staticmethod
|
|
625
|
+
def _copy_graph(graph: networkx.DiGraph) -> networkx.DiGraph:
|
|
626
|
+
"""
|
|
627
|
+
Copy AIL Graph.
|
|
628
|
+
|
|
629
|
+
:return: A copy of the AIl graph.
|
|
630
|
+
"""
|
|
631
|
+
graph_copy = networkx.DiGraph()
|
|
632
|
+
block_mapping = {}
|
|
633
|
+
# copy all blocks
|
|
634
|
+
for block in graph.nodes():
|
|
635
|
+
new_block = copy.copy(block)
|
|
636
|
+
new_stmts = copy.copy(block.statements)
|
|
637
|
+
new_block.statements = new_stmts
|
|
638
|
+
block_mapping[block] = new_block
|
|
639
|
+
graph_copy.add_node(new_block)
|
|
640
|
+
|
|
641
|
+
# copy all edges
|
|
642
|
+
for src, dst, data in graph.edges(data=True):
|
|
643
|
+
new_src = block_mapping[src]
|
|
644
|
+
new_dst = block_mapping[dst]
|
|
645
|
+
graph_copy.add_edge(new_src, new_dst, **data)
|
|
646
|
+
return graph_copy
|
|
647
|
+
|
|
648
|
+
def copy_graph(self, graph=None) -> networkx.DiGraph:
|
|
649
|
+
return self._copy_graph(graph or self.graph)
|
|
650
|
+
|
|
651
|
+
@timethis
|
|
652
|
+
def _set_function_graph(self):
|
|
653
|
+
self._func_graph = self.function.graph_ex(exception_edges=self._exception_edges)
|
|
654
|
+
|
|
655
|
+
@timethis
|
|
656
|
+
def _remove_alignment_blocks(self):
|
|
657
|
+
"""
|
|
658
|
+
Alignment blocks are basic blocks that only consist of nops. They should not be included in the graph.
|
|
659
|
+
"""
|
|
660
|
+
for node in list(self._func_graph.nodes()):
|
|
661
|
+
if self._func_graph.in_degree(node) == 0 and CFGBase._is_noop_block(
|
|
662
|
+
self.project.arch, self.project.factory.block(node.addr, node.size)
|
|
663
|
+
):
|
|
664
|
+
self._func_graph.remove_node(node)
|
|
665
|
+
|
|
666
|
+
@timethis
|
|
667
|
+
def _recover_calling_conventions(self, func_graph=None) -> None:
|
|
668
|
+
"""
|
|
669
|
+
Examine the calling convention and function prototype for each function called. For functions with missing
|
|
670
|
+
calling conventions or function prototypes, analyze each *call site* and recover the calling convention and
|
|
671
|
+
function prototype of the callee function.
|
|
672
|
+
|
|
673
|
+
:return: None
|
|
674
|
+
"""
|
|
675
|
+
|
|
676
|
+
for node in self.function.transition_graph:
|
|
677
|
+
if (
|
|
678
|
+
isinstance(node, BlockNode)
|
|
679
|
+
and node.addr != self.function.addr
|
|
680
|
+
and self.kb.functions.contains_addr(node.addr)
|
|
681
|
+
):
|
|
682
|
+
# tail jumps
|
|
683
|
+
target_func = self.kb.functions.get_by_addr(node.addr)
|
|
684
|
+
elif isinstance(node, Function):
|
|
685
|
+
target_func = node
|
|
686
|
+
else:
|
|
687
|
+
continue
|
|
688
|
+
|
|
689
|
+
# case 0: the calling convention and prototype are available
|
|
690
|
+
if target_func.calling_convention is not None and target_func.prototype is not None:
|
|
691
|
+
continue
|
|
692
|
+
|
|
693
|
+
call_sites = []
|
|
694
|
+
for pred in self.function.transition_graph.predecessors(node):
|
|
695
|
+
call_sites.append(pred)
|
|
696
|
+
# case 1: calling conventions and prototypes are available at every single call site
|
|
697
|
+
if call_sites and all(self.kb.callsite_prototypes.has_prototype(callsite.addr) for callsite in call_sites):
|
|
698
|
+
continue
|
|
699
|
+
|
|
700
|
+
# case 2: the callee is a SimProcedure
|
|
701
|
+
if target_func.is_simprocedure:
|
|
702
|
+
cc = self.project.analyses.CallingConvention(target_func)
|
|
703
|
+
if cc.cc is not None and cc.prototype is not None:
|
|
704
|
+
target_func.calling_convention = cc.cc
|
|
705
|
+
target_func.prototype = cc.prototype
|
|
706
|
+
continue
|
|
707
|
+
|
|
708
|
+
# case 3: the callee is a PLT function
|
|
709
|
+
if target_func.is_plt:
|
|
710
|
+
cc = self.project.analyses.CallingConvention(target_func)
|
|
711
|
+
if cc.cc is not None and cc.prototype is not None:
|
|
712
|
+
target_func.calling_convention = cc.cc
|
|
713
|
+
target_func.prototype = cc.prototype
|
|
714
|
+
continue
|
|
715
|
+
|
|
716
|
+
# case 4: fall back to call site analysis
|
|
717
|
+
for callsite in call_sites:
|
|
718
|
+
if self.kb.callsite_prototypes.has_prototype(callsite.addr):
|
|
719
|
+
continue
|
|
720
|
+
|
|
721
|
+
# parse the call instruction address from the edge
|
|
722
|
+
callsite_ins_addr = None
|
|
723
|
+
edge_data = [
|
|
724
|
+
data
|
|
725
|
+
for src, dst, data in self.function.transition_graph.in_edges(node, data=True)
|
|
726
|
+
if src is callsite
|
|
727
|
+
]
|
|
728
|
+
if len(edge_data) == 1:
|
|
729
|
+
callsite_ins_addr = edge_data[0].get("ins_addr", None)
|
|
730
|
+
if callsite_ins_addr is None:
|
|
731
|
+
# parse the block...
|
|
732
|
+
callsite_block = self.project.factory.block(callsite.addr, size=callsite.size)
|
|
733
|
+
if self.project.arch.branch_delay_slot:
|
|
734
|
+
if callsite_block.instructions < 2:
|
|
735
|
+
continue
|
|
736
|
+
callsite_ins_addr = callsite_block.instruction_addrs[-2]
|
|
737
|
+
else:
|
|
738
|
+
if callsite_block.instructions == 0:
|
|
739
|
+
continue
|
|
740
|
+
callsite_ins_addr = callsite_block.instruction_addrs[-1]
|
|
741
|
+
|
|
742
|
+
cc = self.project.analyses.CallingConvention(
|
|
743
|
+
None,
|
|
744
|
+
analyze_callsites=True,
|
|
745
|
+
caller_func_addr=self.function.addr,
|
|
746
|
+
callsite_block_addr=callsite.addr,
|
|
747
|
+
callsite_insn_addr=callsite_ins_addr,
|
|
748
|
+
func_graph=func_graph,
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
if cc.cc is not None and cc.prototype is not None:
|
|
752
|
+
self.kb.callsite_prototypes.set_prototype(callsite.addr, cc.cc, cc.prototype, manual=False)
|
|
753
|
+
if func_graph is not None and cc.prototype.returnty is not None:
|
|
754
|
+
# patch the AIL call statement if we can find one
|
|
755
|
+
callsite_ail_block: ailment.Block = next(
|
|
756
|
+
iter(bb for bb in func_graph if bb.addr == callsite.addr), None
|
|
757
|
+
)
|
|
758
|
+
if callsite_ail_block is not None and callsite_ail_block.statements:
|
|
759
|
+
last_stmt = callsite_ail_block.statements[-1]
|
|
760
|
+
if isinstance(last_stmt, ailment.Stmt.Call) and last_stmt.ret_expr is None:
|
|
761
|
+
if isinstance(cc.cc.RETURN_VAL, SimRegArg):
|
|
762
|
+
reg_offset, reg_size = self.project.arch.registers[cc.cc.RETURN_VAL.reg_name]
|
|
763
|
+
last_stmt.ret_expr = ailment.Expr.Register(
|
|
764
|
+
None,
|
|
765
|
+
None,
|
|
766
|
+
reg_offset,
|
|
767
|
+
reg_size * 8,
|
|
768
|
+
ins_addr=callsite_ins_addr,
|
|
769
|
+
reg_name=cc.cc.RETURN_VAL.reg_name,
|
|
770
|
+
)
|
|
771
|
+
|
|
772
|
+
# finally, recover the calling convention of the current function
|
|
773
|
+
if self.function.prototype is None or self.function.calling_convention is None:
|
|
774
|
+
self.project.analyses.CompleteCallingConventions(
|
|
775
|
+
recover_variables=True,
|
|
776
|
+
prioritize_func_addrs=[self.function.addr],
|
|
777
|
+
skip_other_funcs=True,
|
|
778
|
+
skip_signature_matched_functions=False,
|
|
779
|
+
func_graphs={self.function.addr: func_graph} if func_graph is not None else None,
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
@timethis
|
|
783
|
+
def _track_stack_pointers(self):
|
|
784
|
+
"""
|
|
785
|
+
For each instruction, track its stack pointer offset and stack base pointer offset.
|
|
786
|
+
|
|
787
|
+
:return: None
|
|
788
|
+
"""
|
|
789
|
+
|
|
790
|
+
regs = {self.project.arch.sp_offset}
|
|
791
|
+
initial_reg_values = {
|
|
792
|
+
self.project.arch.sp_offset: OffsetVal(
|
|
793
|
+
Register(self.project.arch.sp_offset, self.project.arch.bits), self._sp_shift
|
|
794
|
+
)
|
|
795
|
+
}
|
|
796
|
+
if hasattr(self.project.arch, "bp_offset") and self.project.arch.bp_offset is not None:
|
|
797
|
+
regs.add(self.project.arch.bp_offset)
|
|
798
|
+
initial_reg_values[self.project.arch.bp_offset] = OffsetVal(
|
|
799
|
+
Register(self.project.arch.bp_offset, self.project.arch.bits), self._sp_shift
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
regs |= self._find_regs_compared_against_sp(self._func_graph)
|
|
803
|
+
|
|
804
|
+
spt = self.project.analyses.StackPointerTracker(
|
|
805
|
+
self.function,
|
|
806
|
+
regs,
|
|
807
|
+
track_memory=self._sp_tracker_track_memory,
|
|
808
|
+
cross_insn_opt=False,
|
|
809
|
+
initial_reg_values=initial_reg_values,
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
if spt.inconsistent_for(self.project.arch.sp_offset):
|
|
813
|
+
l.warning("Inconsistency found during stack pointer tracking. Decompilation results might be incorrect.")
|
|
814
|
+
return spt
|
|
815
|
+
|
|
816
|
+
@timethis
|
|
817
|
+
def _convert_all(self):
|
|
818
|
+
"""
|
|
819
|
+
Convert all VEX blocks in the function graph to AIL blocks, and fill self._blocks.
|
|
820
|
+
|
|
821
|
+
:return: None
|
|
822
|
+
"""
|
|
823
|
+
|
|
824
|
+
for block_node in self._func_graph.nodes():
|
|
825
|
+
ail_block = self._convert(block_node)
|
|
826
|
+
|
|
827
|
+
if type(ail_block) is ailment.Block:
|
|
828
|
+
# remove constant pc assignments
|
|
829
|
+
ail_block.statements = [
|
|
830
|
+
stmt
|
|
831
|
+
for stmt in ail_block.statements
|
|
832
|
+
if not (
|
|
833
|
+
isinstance(stmt, ailment.Stmt.Assignment)
|
|
834
|
+
and isinstance(stmt.dst, ailment.Expr.Register)
|
|
835
|
+
and stmt.dst.reg_offset == self.project.arch.ip_offset
|
|
836
|
+
and isinstance(stmt.src, ailment.Expr.Const)
|
|
837
|
+
)
|
|
838
|
+
]
|
|
839
|
+
|
|
840
|
+
self._blocks_by_addr_and_size[(block_node.addr, block_node.size)] = ail_block
|
|
841
|
+
|
|
842
|
+
def _convert(self, block_node):
|
|
843
|
+
"""
|
|
844
|
+
Convert a VEX block to an AIL block.
|
|
845
|
+
|
|
846
|
+
:param block_node: A BlockNode instance.
|
|
847
|
+
:return: An converted AIL block.
|
|
848
|
+
:rtype: ailment.Block
|
|
849
|
+
"""
|
|
850
|
+
|
|
851
|
+
if type(block_node) is not BlockNode:
|
|
852
|
+
return block_node
|
|
853
|
+
|
|
854
|
+
block = self.project.factory.block(block_node.addr, block_node.size, cross_insn_opt=False)
|
|
855
|
+
if block.vex.jumpkind not in {"Ijk_Call", "Ijk_Boring", "Ijk_Ret"} and not block.vex.jumpkind.startswith(
|
|
856
|
+
"Ijk_Sys"
|
|
857
|
+
):
|
|
858
|
+
# we don't support lifting this block. use a dummy block instead
|
|
859
|
+
statements = [
|
|
860
|
+
ailment.Stmt.DirtyStatement(
|
|
861
|
+
self._ail_manager.next_atom(),
|
|
862
|
+
f"Unsupported jumpkind {block.vex.jumpkind} at address {block_node.addr}",
|
|
863
|
+
ins_addr=block_node.addr,
|
|
864
|
+
)
|
|
865
|
+
]
|
|
866
|
+
ail_block = ailment.Block(block_node.addr, block_node.size, statements=statements)
|
|
867
|
+
return ail_block
|
|
868
|
+
|
|
869
|
+
ail_block = ailment.IRSBConverter.convert(block.vex, self._ail_manager)
|
|
870
|
+
return ail_block
|
|
871
|
+
|
|
872
|
+
@timethis
|
|
873
|
+
def _replace_single_target_indirect_transitions(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
|
|
874
|
+
"""
|
|
875
|
+
Remove single-target indirect jumps and calls and replace them with direct jumps or calls.
|
|
876
|
+
"""
|
|
877
|
+
if self._cfg is None:
|
|
878
|
+
return ail_graph
|
|
879
|
+
|
|
880
|
+
for block in ail_graph.nodes():
|
|
881
|
+
if not block.statements:
|
|
882
|
+
continue
|
|
883
|
+
last_stmt = block.statements[-1]
|
|
884
|
+
if isinstance(last_stmt, ailment.Stmt.Call) and not isinstance(last_stmt.target, ailment.Expr.Const):
|
|
885
|
+
# indirect call
|
|
886
|
+
# consult CFG to see if this is a call with a single successor
|
|
887
|
+
node = self._cfg.get_any_node(block.addr)
|
|
888
|
+
if node is None:
|
|
889
|
+
continue
|
|
890
|
+
successors = self._cfg.get_successors(node, excluding_fakeret=True, jumpkind="Ijk_Call")
|
|
891
|
+
if len(successors) == 1 and not isinstance(
|
|
892
|
+
self.project.hooked_by(successors[0].addr), UnresolvableCallTarget
|
|
893
|
+
):
|
|
894
|
+
# found a single successor - replace the last statement
|
|
895
|
+
new_last_stmt = last_stmt.copy()
|
|
896
|
+
new_last_stmt.target = ailment.Expr.Const(None, None, successors[0].addr, last_stmt.target.bits)
|
|
897
|
+
block.statements[-1] = new_last_stmt
|
|
898
|
+
|
|
899
|
+
elif isinstance(last_stmt, ailment.Stmt.Jump) and not isinstance(last_stmt.target, ailment.Expr.Const):
|
|
900
|
+
# indirect jump
|
|
901
|
+
# consult CFG to see if there is a jump with a single successor
|
|
902
|
+
node = self._cfg.get_any_node(block.addr)
|
|
903
|
+
if node is None:
|
|
904
|
+
continue
|
|
905
|
+
successors = self._cfg.get_successors(node, excluding_fakeret=True, jumpkind="Ijk_Boring")
|
|
906
|
+
if len(successors) == 1 and not isinstance(
|
|
907
|
+
self.project.hooked_by(successors[0].addr), UnresolvableJumpTarget
|
|
908
|
+
):
|
|
909
|
+
# found a single successor - replace the last statement
|
|
910
|
+
new_last_stmt = last_stmt.copy()
|
|
911
|
+
new_last_stmt.target = ailment.Expr.Const(None, None, successors[0].addr, last_stmt.target.bits)
|
|
912
|
+
block.statements[-1] = new_last_stmt
|
|
913
|
+
|
|
914
|
+
return ail_graph
|
|
915
|
+
|
|
916
|
+
@timethis
|
|
917
|
+
def _replace_tail_jumps_with_calls(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
|
|
918
|
+
"""
|
|
919
|
+
Replace tail jumps them with a return statement and a call expression.
|
|
920
|
+
"""
|
|
921
|
+
for block in list(ail_graph.nodes()):
|
|
922
|
+
out_degree = ail_graph.out_degree[block]
|
|
923
|
+
|
|
924
|
+
if out_degree != 0:
|
|
925
|
+
continue
|
|
926
|
+
|
|
927
|
+
last_stmt = block.statements[-1]
|
|
928
|
+
if isinstance(last_stmt, ailment.Stmt.Jump):
|
|
929
|
+
# jumping to somewhere outside the current function
|
|
930
|
+
# rewrite it as a call *if and only if* the target is identified as a function
|
|
931
|
+
target = last_stmt.target
|
|
932
|
+
if isinstance(target, ailment.Const):
|
|
933
|
+
target_addr = target.value
|
|
934
|
+
if self.kb.functions.contains_addr(target_addr):
|
|
935
|
+
# replace the statement
|
|
936
|
+
target_func = self.kb.functions.get_by_addr(target_addr)
|
|
937
|
+
if target_func.returning:
|
|
938
|
+
ret_reg_offset = self.project.arch.ret_offset
|
|
939
|
+
ret_expr = ailment.Expr.Register(
|
|
940
|
+
None,
|
|
941
|
+
None,
|
|
942
|
+
ret_reg_offset,
|
|
943
|
+
self.project.arch.bits,
|
|
944
|
+
reg_name=self.project.arch.translate_register_name(
|
|
945
|
+
ret_reg_offset, size=self.project.arch.bits
|
|
946
|
+
),
|
|
947
|
+
)
|
|
948
|
+
call_stmt = ailment.Stmt.Call(
|
|
949
|
+
None,
|
|
950
|
+
target,
|
|
951
|
+
calling_convention=None, # target_func.calling_convention,
|
|
952
|
+
prototype=None, # target_func.prototype,
|
|
953
|
+
ret_expr=ret_expr,
|
|
954
|
+
**last_stmt.tags,
|
|
955
|
+
)
|
|
956
|
+
block.statements[-1] = call_stmt
|
|
957
|
+
|
|
958
|
+
ret_stmt = ailment.Stmt.Return(None, [], **last_stmt.tags)
|
|
959
|
+
ret_block = ailment.Block(self.new_block_addr(), 1, statements=[ret_stmt])
|
|
960
|
+
ail_graph.add_edge(block, ret_block, type="fake_return")
|
|
961
|
+
else:
|
|
962
|
+
stmt = ailment.Stmt.Call(None, target, **last_stmt.tags)
|
|
963
|
+
block.statements[-1] = stmt
|
|
964
|
+
|
|
965
|
+
return ail_graph
|
|
966
|
+
|
|
967
|
+
@timethis
|
|
968
|
+
def _make_ailgraph(self) -> networkx.DiGraph:
|
|
969
|
+
graph = self._function_graph_to_ail_graph(self._func_graph)
|
|
970
|
+
return graph
|
|
971
|
+
|
|
972
|
+
@timethis
|
|
973
|
+
def _simplify_blocks(
|
|
974
|
+
self,
|
|
975
|
+
ail_graph: networkx.DiGraph,
|
|
976
|
+
remove_dead_memdefs=False,
|
|
977
|
+
stack_pointer_tracker=None,
|
|
978
|
+
cache: dict[ailment.Block, NamedTuple] | None = None,
|
|
979
|
+
):
|
|
980
|
+
"""
|
|
981
|
+
Simplify all blocks in self._blocks.
|
|
982
|
+
|
|
983
|
+
:param ail_graph: The AIL function graph.
|
|
984
|
+
:param stack_pointer_tracker: The RegisterDeltaTracker analysis instance.
|
|
985
|
+
:param cache: A block-level cache that stores reaching definition analysis results and
|
|
986
|
+
propagation results.
|
|
987
|
+
:return: None
|
|
988
|
+
"""
|
|
989
|
+
|
|
990
|
+
blocks_by_addr_and_idx: dict[tuple[int, int | None], ailment.Block] = {}
|
|
991
|
+
|
|
992
|
+
for ail_block in ail_graph.nodes():
|
|
993
|
+
simplified = self._simplify_block(
|
|
994
|
+
ail_block,
|
|
995
|
+
remove_dead_memdefs=remove_dead_memdefs,
|
|
996
|
+
stack_pointer_tracker=stack_pointer_tracker,
|
|
997
|
+
cache=cache,
|
|
998
|
+
)
|
|
999
|
+
key = ail_block.addr, ail_block.idx
|
|
1000
|
+
blocks_by_addr_and_idx[key] = simplified
|
|
1001
|
+
|
|
1002
|
+
# update blocks_map to allow node_addr to node lookup
|
|
1003
|
+
def _replace_node_handler(node):
|
|
1004
|
+
key = node.addr, node.idx
|
|
1005
|
+
if key in blocks_by_addr_and_idx:
|
|
1006
|
+
return blocks_by_addr_and_idx[key]
|
|
1007
|
+
return None
|
|
1008
|
+
|
|
1009
|
+
AILGraphWalker(ail_graph, _replace_node_handler, replace_nodes=True).walk()
|
|
1010
|
+
|
|
1011
|
+
return ail_graph
|
|
1012
|
+
|
|
1013
|
+
def _simplify_block(self, ail_block, remove_dead_memdefs=False, stack_pointer_tracker=None, cache=None):
|
|
1014
|
+
"""
|
|
1015
|
+
Simplify a single AIL block.
|
|
1016
|
+
|
|
1017
|
+
:param ailment.Block ail_block: The AIL block to simplify.
|
|
1018
|
+
:param stack_pointer_tracker: The RegisterDeltaTracker analysis instance.
|
|
1019
|
+
:return: A simplified AIL block.
|
|
1020
|
+
"""
|
|
1021
|
+
|
|
1022
|
+
cached_rd, cached_prop = None, None
|
|
1023
|
+
cache_item = None
|
|
1024
|
+
if cache:
|
|
1025
|
+
cache_item = cache.get(ail_block, None)
|
|
1026
|
+
if cache_item:
|
|
1027
|
+
# cache hit
|
|
1028
|
+
cached_rd = cache_item.rd
|
|
1029
|
+
cached_prop = cache_item.prop
|
|
1030
|
+
|
|
1031
|
+
simp = self.project.analyses.AILBlockSimplifier(
|
|
1032
|
+
ail_block,
|
|
1033
|
+
self.function.addr,
|
|
1034
|
+
remove_dead_memdefs=remove_dead_memdefs,
|
|
1035
|
+
stack_pointer_tracker=stack_pointer_tracker,
|
|
1036
|
+
peephole_optimizations=self.peephole_optimizations,
|
|
1037
|
+
cached_reaching_definitions=cached_rd,
|
|
1038
|
+
cached_propagator=cached_prop,
|
|
1039
|
+
)
|
|
1040
|
+
# update the cache
|
|
1041
|
+
if cache is not None:
|
|
1042
|
+
if cache_item:
|
|
1043
|
+
del cache[ail_block]
|
|
1044
|
+
cache[simp.result_block] = BlockCache(simp._reaching_definitions, simp._propagator)
|
|
1045
|
+
return simp.result_block
|
|
1046
|
+
|
|
1047
|
+
@timethis
|
|
1048
|
+
def _simplify_function(
|
|
1049
|
+
self,
|
|
1050
|
+
ail_graph,
|
|
1051
|
+
remove_dead_memdefs=False,
|
|
1052
|
+
stack_arg_offsets=None,
|
|
1053
|
+
unify_variables=False,
|
|
1054
|
+
max_iterations: int = 8,
|
|
1055
|
+
narrow_expressions=False,
|
|
1056
|
+
only_consts=False,
|
|
1057
|
+
fold_callexprs_into_conditions=False,
|
|
1058
|
+
rewrite_ccalls=True,
|
|
1059
|
+
) -> None:
|
|
1060
|
+
"""
|
|
1061
|
+
Simplify the entire function until it reaches a fixed point.
|
|
1062
|
+
"""
|
|
1063
|
+
|
|
1064
|
+
for idx in range(max_iterations):
|
|
1065
|
+
simplified = self._simplify_function_once(
|
|
1066
|
+
ail_graph,
|
|
1067
|
+
remove_dead_memdefs=remove_dead_memdefs,
|
|
1068
|
+
unify_variables=unify_variables,
|
|
1069
|
+
stack_arg_offsets=stack_arg_offsets,
|
|
1070
|
+
# only narrow once
|
|
1071
|
+
narrow_expressions=narrow_expressions and idx == 0,
|
|
1072
|
+
only_consts=only_consts,
|
|
1073
|
+
fold_callexprs_into_conditions=fold_callexprs_into_conditions,
|
|
1074
|
+
rewrite_ccalls=rewrite_ccalls,
|
|
1075
|
+
)
|
|
1076
|
+
if not simplified:
|
|
1077
|
+
break
|
|
1078
|
+
|
|
1079
|
+
@timethis
|
|
1080
|
+
def _simplify_function_once(
|
|
1081
|
+
self,
|
|
1082
|
+
ail_graph,
|
|
1083
|
+
remove_dead_memdefs=False,
|
|
1084
|
+
stack_arg_offsets=None,
|
|
1085
|
+
unify_variables=False,
|
|
1086
|
+
narrow_expressions=False,
|
|
1087
|
+
only_consts=False,
|
|
1088
|
+
fold_callexprs_into_conditions=False,
|
|
1089
|
+
rewrite_ccalls=True,
|
|
1090
|
+
):
|
|
1091
|
+
"""
|
|
1092
|
+
Simplify the entire function once.
|
|
1093
|
+
|
|
1094
|
+
:return: None
|
|
1095
|
+
"""
|
|
1096
|
+
|
|
1097
|
+
simp = self.project.analyses.AILSimplifier(
|
|
1098
|
+
self.function,
|
|
1099
|
+
func_graph=ail_graph,
|
|
1100
|
+
remove_dead_memdefs=remove_dead_memdefs,
|
|
1101
|
+
unify_variables=unify_variables,
|
|
1102
|
+
stack_arg_offsets=stack_arg_offsets,
|
|
1103
|
+
ail_manager=self._ail_manager,
|
|
1104
|
+
gp=self.function.info.get("gp", None) if self.project.arch.name in {"MIPS32", "MIPS64"} else None,
|
|
1105
|
+
narrow_expressions=narrow_expressions,
|
|
1106
|
+
only_consts=only_consts,
|
|
1107
|
+
fold_callexprs_into_conditions=fold_callexprs_into_conditions,
|
|
1108
|
+
use_callee_saved_regs_at_return=not self._register_save_areas_removed,
|
|
1109
|
+
rewrite_ccalls=rewrite_ccalls,
|
|
1110
|
+
)
|
|
1111
|
+
# cache the simplifier's RDA analysis
|
|
1112
|
+
self.reaching_definitions = simp._reaching_definitions
|
|
1113
|
+
|
|
1114
|
+
# the function graph has been updated at this point
|
|
1115
|
+
return simp.simplified
|
|
1116
|
+
|
|
1117
|
+
@timethis
|
|
1118
|
+
def _run_simplification_passes(
|
|
1119
|
+
self,
|
|
1120
|
+
ail_graph,
|
|
1121
|
+
stage: OptimizationPassStage = OptimizationPassStage.AFTER_GLOBAL_SIMPLIFICATION,
|
|
1122
|
+
variable_kb=None,
|
|
1123
|
+
**kwargs,
|
|
1124
|
+
):
|
|
1125
|
+
addr_and_idx_to_blocks: dict[tuple[int, int | None], ailment.Block] = {}
|
|
1126
|
+
addr_to_blocks: dict[int, set[ailment.Block]] = defaultdict(set)
|
|
1127
|
+
|
|
1128
|
+
# update blocks_map to allow node_addr to node lookup
|
|
1129
|
+
def _updatedict_handler(node):
|
|
1130
|
+
addr_and_idx_to_blocks[(node.addr, node.idx)] = node
|
|
1131
|
+
addr_to_blocks[node.addr].add(node)
|
|
1132
|
+
|
|
1133
|
+
AILGraphWalker(ail_graph, _updatedict_handler).walk()
|
|
1134
|
+
|
|
1135
|
+
# Run each pass
|
|
1136
|
+
for pass_ in self._optimization_passes:
|
|
1137
|
+
if pass_.STAGE != stage:
|
|
1138
|
+
continue
|
|
1139
|
+
|
|
1140
|
+
if pass_ in DUPLICATING_OPTS + CONDENSING_OPTS and self.unoptimized_graph is None:
|
|
1141
|
+
# we should save a copy at the first time any optimization that could alter the structure
|
|
1142
|
+
# of the graph is applied
|
|
1143
|
+
self.unoptimized_graph = self._copy_graph(ail_graph)
|
|
1144
|
+
|
|
1145
|
+
a = pass_(
|
|
1146
|
+
self.function,
|
|
1147
|
+
blocks_by_addr=addr_to_blocks,
|
|
1148
|
+
blocks_by_addr_and_idx=addr_and_idx_to_blocks,
|
|
1149
|
+
graph=ail_graph,
|
|
1150
|
+
variable_kb=variable_kb,
|
|
1151
|
+
**kwargs,
|
|
1152
|
+
)
|
|
1153
|
+
if a.out_graph:
|
|
1154
|
+
# use the new graph
|
|
1155
|
+
ail_graph = a.out_graph
|
|
1156
|
+
if isinstance(a, RegisterSaveAreaSimplifier):
|
|
1157
|
+
# register save area has been removed - we should no longer use callee-saved registers in RDA
|
|
1158
|
+
self._register_save_areas_removed = True
|
|
1159
|
+
# clear the cached RDA result
|
|
1160
|
+
self.reaching_definitions = None
|
|
1161
|
+
|
|
1162
|
+
return ail_graph
|
|
1163
|
+
|
|
1164
|
+
@timethis
|
|
1165
|
+
def _make_argument_list(self) -> list[SimVariable]:
|
|
1166
|
+
if self.function.calling_convention is not None and self.function.prototype is not None:
|
|
1167
|
+
args: list[SimFunctionArgument] = self.function.calling_convention.arg_locs(self.function.prototype)
|
|
1168
|
+
arg_vars: list[SimVariable] = []
|
|
1169
|
+
if args:
|
|
1170
|
+
arg_names = self.function.prototype.arg_names or [f"a{i}" for i in range(len(args))]
|
|
1171
|
+
for idx, arg in enumerate(args):
|
|
1172
|
+
if isinstance(arg, SimRegArg):
|
|
1173
|
+
argvar = SimRegisterVariable(
|
|
1174
|
+
self.project.arch.registers[arg.reg_name][0],
|
|
1175
|
+
arg.size,
|
|
1176
|
+
ident="arg_%d" % idx,
|
|
1177
|
+
name=arg_names[idx],
|
|
1178
|
+
region=self.function.addr,
|
|
1179
|
+
)
|
|
1180
|
+
elif isinstance(arg, SimStackArg):
|
|
1181
|
+
argvar = SimStackVariable(
|
|
1182
|
+
arg.stack_offset,
|
|
1183
|
+
arg.size,
|
|
1184
|
+
base="bp",
|
|
1185
|
+
ident="arg_%d" % idx,
|
|
1186
|
+
name=arg_names[idx],
|
|
1187
|
+
region=self.function.addr,
|
|
1188
|
+
)
|
|
1189
|
+
elif isinstance(arg, SimStructArg):
|
|
1190
|
+
argvar = SimVariable(
|
|
1191
|
+
ident="arg_%d" % idx,
|
|
1192
|
+
name=arg_names[idx],
|
|
1193
|
+
region=self.function.addr,
|
|
1194
|
+
size=arg.size,
|
|
1195
|
+
)
|
|
1196
|
+
else:
|
|
1197
|
+
raise TypeError("Unsupported function argument type %s." % type(arg))
|
|
1198
|
+
arg_vars.append(argvar)
|
|
1199
|
+
return arg_vars
|
|
1200
|
+
return []
|
|
1201
|
+
|
|
1202
|
+
@timethis
|
|
1203
|
+
def _make_callsites(self, ail_graph, stack_pointer_tracker=None):
|
|
1204
|
+
"""
|
|
1205
|
+
Simplify all function call statements.
|
|
1206
|
+
|
|
1207
|
+
:return: None
|
|
1208
|
+
"""
|
|
1209
|
+
|
|
1210
|
+
# Computing reaching definitions
|
|
1211
|
+
rd = self.project.analyses.ReachingDefinitions(
|
|
1212
|
+
subject=self.function,
|
|
1213
|
+
func_graph=ail_graph,
|
|
1214
|
+
observe_callback=self._make_callsites_rd_observe_callback,
|
|
1215
|
+
use_callee_saved_regs_at_return=not self._register_save_areas_removed,
|
|
1216
|
+
)
|
|
1217
|
+
|
|
1218
|
+
class TempClass: # pylint:disable=missing-class-docstring
|
|
1219
|
+
stack_arg_offsets = set()
|
|
1220
|
+
|
|
1221
|
+
def _handler(block):
|
|
1222
|
+
csm = self.project.analyses.AILCallSiteMaker(
|
|
1223
|
+
block,
|
|
1224
|
+
reaching_definitions=rd,
|
|
1225
|
+
stack_pointer_tracker=stack_pointer_tracker,
|
|
1226
|
+
ail_manager=self._ail_manager,
|
|
1227
|
+
)
|
|
1228
|
+
if csm.stack_arg_offsets is not None:
|
|
1229
|
+
TempClass.stack_arg_offsets |= csm.stack_arg_offsets
|
|
1230
|
+
if csm.result_block:
|
|
1231
|
+
if csm.result_block != block:
|
|
1232
|
+
ail_block = csm.result_block
|
|
1233
|
+
simp = self.project.analyses.AILBlockSimplifier(
|
|
1234
|
+
ail_block,
|
|
1235
|
+
self.function.addr,
|
|
1236
|
+
stack_pointer_tracker=stack_pointer_tracker,
|
|
1237
|
+
peephole_optimizations=self.peephole_optimizations,
|
|
1238
|
+
stack_arg_offsets=csm.stack_arg_offsets,
|
|
1239
|
+
)
|
|
1240
|
+
return simp.result_block
|
|
1241
|
+
return None
|
|
1242
|
+
|
|
1243
|
+
# rewriting call-sites at this point, pre-inlining, causes issues with incorrect call signatures
|
|
1244
|
+
if not self._inlining_parents:
|
|
1245
|
+
AILGraphWalker(ail_graph, _handler, replace_nodes=True).walk()
|
|
1246
|
+
|
|
1247
|
+
return ail_graph, TempClass.stack_arg_offsets
|
|
1248
|
+
|
|
1249
|
+
@timethis
|
|
1250
|
+
def _make_returns(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
|
|
1251
|
+
"""
|
|
1252
|
+
Work on each return statement and fill in its return expressions.
|
|
1253
|
+
"""
|
|
1254
|
+
if self._inlining_parents:
|
|
1255
|
+
# for inlining, we want to keep the return statement separate from the return value, so that
|
|
1256
|
+
# the former can be removed while preserving the latter
|
|
1257
|
+
return ail_graph
|
|
1258
|
+
|
|
1259
|
+
if self.function.calling_convention is None:
|
|
1260
|
+
# unknown calling convention. cannot do much about return expressions.
|
|
1261
|
+
return ail_graph
|
|
1262
|
+
|
|
1263
|
+
ReturnMaker(self._ail_manager, self.project.arch, self.function, ail_graph)
|
|
1264
|
+
|
|
1265
|
+
return ail_graph
|
|
1266
|
+
|
|
1267
|
+
@timethis
|
|
1268
|
+
def _make_function_prototype(self, arg_list: list[SimVariable], variable_kb):
|
|
1269
|
+
if self.function.prototype is not None:
|
|
1270
|
+
if not self.function.is_prototype_guessed:
|
|
1271
|
+
# do not overwrite an existing function prototype
|
|
1272
|
+
# if you want to re-generate the prototype, clear the existing one first
|
|
1273
|
+
return
|
|
1274
|
+
if isinstance(self.function.prototype.returnty, SimTypeFloat) or any(
|
|
1275
|
+
isinstance(arg, SimTypeFloat) for arg in self.function.prototype.args
|
|
1276
|
+
):
|
|
1277
|
+
# Type inference does not yet support floating point variables, but calling convention analysis does
|
|
1278
|
+
# FIXME: remove this branch once type inference supports floating point variables
|
|
1279
|
+
return
|
|
1280
|
+
|
|
1281
|
+
variables = variable_kb.variables[self.function.addr]
|
|
1282
|
+
func_args = []
|
|
1283
|
+
for arg in arg_list:
|
|
1284
|
+
func_arg = None
|
|
1285
|
+
arg_ty = variables.get_variable_type(arg)
|
|
1286
|
+
if arg_ty is None:
|
|
1287
|
+
# determine type based on size
|
|
1288
|
+
if isinstance(arg, (SimRegisterVariable, SimStackVariable)):
|
|
1289
|
+
if arg.size == 1:
|
|
1290
|
+
func_arg = SimTypeChar()
|
|
1291
|
+
elif arg.size == 2:
|
|
1292
|
+
func_arg = SimTypeShort()
|
|
1293
|
+
elif arg.size == 4:
|
|
1294
|
+
func_arg = SimTypeInt()
|
|
1295
|
+
elif arg.size == 8:
|
|
1296
|
+
func_arg = SimTypeLongLong()
|
|
1297
|
+
else:
|
|
1298
|
+
l.warning("Unsupported argument size %d.", arg.size)
|
|
1299
|
+
else:
|
|
1300
|
+
func_arg = arg_ty
|
|
1301
|
+
|
|
1302
|
+
func_args.append(func_arg)
|
|
1303
|
+
|
|
1304
|
+
if self.function.prototype is not None and self.function.prototype.returnty is not None:
|
|
1305
|
+
returnty = self.function.prototype.returnty
|
|
1306
|
+
else:
|
|
1307
|
+
returnty = SimTypeInt()
|
|
1308
|
+
|
|
1309
|
+
self.function.prototype = SimTypeFunction(func_args, returnty).with_arch(self.project.arch)
|
|
1310
|
+
self.function.is_prototype_guessed = False
|
|
1311
|
+
|
|
1312
|
+
@timethis
|
|
1313
|
+
def _recover_and_link_variables(self, ail_graph, arg_list):
|
|
1314
|
+
# variable recovery
|
|
1315
|
+
tmp_kb = KnowledgeBase(self.project) if self.variable_kb is None else self.variable_kb
|
|
1316
|
+
tmp_kb.functions = self.kb.functions
|
|
1317
|
+
vr = self.project.analyses.VariableRecoveryFast(
|
|
1318
|
+
self.function, # pylint:disable=unused-variable
|
|
1319
|
+
func_graph=ail_graph,
|
|
1320
|
+
kb=tmp_kb,
|
|
1321
|
+
track_sp=False,
|
|
1322
|
+
func_args=arg_list,
|
|
1323
|
+
unify_variables=False,
|
|
1324
|
+
)
|
|
1325
|
+
# get ground-truth types
|
|
1326
|
+
var_manager = tmp_kb.variables[self.function.addr]
|
|
1327
|
+
groundtruth = {}
|
|
1328
|
+
for variable in var_manager.variables_with_manual_types:
|
|
1329
|
+
vartype = var_manager.variable_to_types.get(variable, None)
|
|
1330
|
+
if vartype is not None:
|
|
1331
|
+
for tv in vr.var_to_typevars[variable]:
|
|
1332
|
+
groundtruth[tv] = vartype
|
|
1333
|
+
# clean up existing types for this function
|
|
1334
|
+
var_manager.remove_types()
|
|
1335
|
+
# TODO: Type inference for global variables
|
|
1336
|
+
# run type inference
|
|
1337
|
+
if self._must_struct:
|
|
1338
|
+
must_struct = set()
|
|
1339
|
+
for var, typevars in vr.var_to_typevars.items():
|
|
1340
|
+
if var.ident in self._must_struct:
|
|
1341
|
+
must_struct |= typevars
|
|
1342
|
+
else:
|
|
1343
|
+
must_struct = None
|
|
1344
|
+
try:
|
|
1345
|
+
tp = self.project.analyses.Typehoon(
|
|
1346
|
+
vr.type_constraints,
|
|
1347
|
+
vr.func_typevar,
|
|
1348
|
+
kb=tmp_kb,
|
|
1349
|
+
var_mapping=vr.var_to_typevars,
|
|
1350
|
+
must_struct=must_struct,
|
|
1351
|
+
ground_truth=groundtruth,
|
|
1352
|
+
)
|
|
1353
|
+
# tp.pp_constraints()
|
|
1354
|
+
# tp.pp_solution()
|
|
1355
|
+
tp.update_variable_types(
|
|
1356
|
+
self.function.addr,
|
|
1357
|
+
{v: t for v, t in vr.var_to_typevars.items() if isinstance(v, (SimRegisterVariable, SimStackVariable))},
|
|
1358
|
+
)
|
|
1359
|
+
tp.update_variable_types(
|
|
1360
|
+
"global",
|
|
1361
|
+
{
|
|
1362
|
+
v: t
|
|
1363
|
+
for v, t in vr.var_to_typevars.items()
|
|
1364
|
+
if isinstance(v, SimMemoryVariable) and not isinstance(v, SimStackVariable)
|
|
1365
|
+
},
|
|
1366
|
+
)
|
|
1367
|
+
except Exception: # pylint:disable=broad-except
|
|
1368
|
+
l.warning(
|
|
1369
|
+
"Typehoon analysis failed. Variables will not have types. Please report to GitHub.", exc_info=True
|
|
1370
|
+
)
|
|
1371
|
+
|
|
1372
|
+
# for any left-over variables, assign Bottom type (which will get "corrected" into a default type in
|
|
1373
|
+
# VariableManager)
|
|
1374
|
+
bottype = SimTypeBottom().with_arch(self.project.arch)
|
|
1375
|
+
for var in var_manager._variables:
|
|
1376
|
+
if var not in var_manager.variable_to_types:
|
|
1377
|
+
var_manager.set_variable_type(var, bottype)
|
|
1378
|
+
|
|
1379
|
+
# Unify SSA variables
|
|
1380
|
+
tmp_kb.variables.global_manager.assign_variable_names(labels=self.kb.labels, types={SimMemoryVariable})
|
|
1381
|
+
var_manager.unify_variables()
|
|
1382
|
+
var_manager.assign_unified_variable_names(
|
|
1383
|
+
labels=self.kb.labels,
|
|
1384
|
+
arg_names=self.function.prototype.arg_names if self.function.prototype else None,
|
|
1385
|
+
reset=self._reset_variable_names,
|
|
1386
|
+
)
|
|
1387
|
+
|
|
1388
|
+
# Link variables to each statement
|
|
1389
|
+
for block in ail_graph.nodes():
|
|
1390
|
+
self._link_variables_on_block(block, tmp_kb)
|
|
1391
|
+
|
|
1392
|
+
if self._cache is not None:
|
|
1393
|
+
self._cache.type_constraints = vr.type_constraints
|
|
1394
|
+
self._cache.func_typevar = vr.func_typevar
|
|
1395
|
+
self._cache.var_to_typevar = vr.var_to_typevars
|
|
1396
|
+
|
|
1397
|
+
return tmp_kb
|
|
1398
|
+
|
|
1399
|
+
def _link_variables_on_block(self, block, kb):
|
|
1400
|
+
"""
|
|
1401
|
+
Link atoms (AIL expressions) in the given block to corresponding variables identified previously.
|
|
1402
|
+
|
|
1403
|
+
:param ailment.Block block: The AIL block to work on.
|
|
1404
|
+
:return: None
|
|
1405
|
+
"""
|
|
1406
|
+
|
|
1407
|
+
variable_manager = kb.variables[self.function.addr]
|
|
1408
|
+
global_variables = kb.variables["global"]
|
|
1409
|
+
|
|
1410
|
+
for stmt_idx, stmt in enumerate(block.statements):
|
|
1411
|
+
stmt_type = type(stmt)
|
|
1412
|
+
if stmt_type is ailment.Stmt.Store:
|
|
1413
|
+
# find a memory variable
|
|
1414
|
+
mem_vars = variable_manager.find_variables_by_atom(block.addr, stmt_idx, stmt, block_idx=block.idx)
|
|
1415
|
+
if len(mem_vars) == 1:
|
|
1416
|
+
stmt.variable, stmt.offset = next(iter(mem_vars))
|
|
1417
|
+
else:
|
|
1418
|
+
# check if the dest address is a variable
|
|
1419
|
+
stmt: ailment.Stmt.Store
|
|
1420
|
+
# special handling for constant addresses
|
|
1421
|
+
if isinstance(stmt.addr, ailment.Expr.Const):
|
|
1422
|
+
# global variable?
|
|
1423
|
+
variables = global_variables.get_global_variables(stmt.addr.value)
|
|
1424
|
+
if variables:
|
|
1425
|
+
var = next(iter(variables))
|
|
1426
|
+
stmt.variable = var
|
|
1427
|
+
stmt.offset = 0
|
|
1428
|
+
else:
|
|
1429
|
+
self._link_variables_on_expr(
|
|
1430
|
+
variable_manager, global_variables, block, stmt_idx, stmt, stmt.addr
|
|
1431
|
+
)
|
|
1432
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.data)
|
|
1433
|
+
|
|
1434
|
+
elif stmt_type is ailment.Stmt.Assignment:
|
|
1435
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.dst)
|
|
1436
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.src)
|
|
1437
|
+
|
|
1438
|
+
elif stmt_type is ailment.Stmt.ConditionalJump:
|
|
1439
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.condition)
|
|
1440
|
+
|
|
1441
|
+
elif stmt_type is ailment.Stmt.Call:
|
|
1442
|
+
self._link_variables_on_call(variable_manager, global_variables, block, stmt_idx, stmt, is_expr=False)
|
|
1443
|
+
|
|
1444
|
+
elif stmt_type is ailment.Stmt.Return:
|
|
1445
|
+
self._link_variables_on_return(variable_manager, global_variables, block, stmt_idx, stmt)
|
|
1446
|
+
|
|
1447
|
+
def _link_variables_on_return(
|
|
1448
|
+
self, variable_manager, global_variables, block: ailment.Block, stmt_idx: int, stmt: ailment.Stmt.Return
|
|
1449
|
+
):
|
|
1450
|
+
if stmt.ret_exprs:
|
|
1451
|
+
for ret_expr in stmt.ret_exprs:
|
|
1452
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, ret_expr)
|
|
1453
|
+
|
|
1454
|
+
def _link_variables_on_call(self, variable_manager, global_variables, block, stmt_idx, stmt, is_expr=False):
|
|
1455
|
+
if not isinstance(stmt.target, ailment.Expr.Const):
|
|
1456
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.target)
|
|
1457
|
+
if stmt.args:
|
|
1458
|
+
for arg in stmt.args:
|
|
1459
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, arg)
|
|
1460
|
+
if not is_expr and stmt.ret_expr:
|
|
1461
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, stmt.ret_expr)
|
|
1462
|
+
|
|
1463
|
+
def _link_variables_on_expr(self, variable_manager, global_variables, block, stmt_idx, stmt, expr):
|
|
1464
|
+
"""
|
|
1465
|
+
Link atoms (AIL expressions) in the given expression to corresponding variables identified previously.
|
|
1466
|
+
|
|
1467
|
+
:param variable_manager: Variable manager of the function.
|
|
1468
|
+
:param ailment.Block block: AIL block.
|
|
1469
|
+
:param int stmt_idx: ID of the statement.
|
|
1470
|
+
:param stmt: The AIL statement that `expr` belongs to.
|
|
1471
|
+
:param expr: The AIl expression to work on.
|
|
1472
|
+
:return: None
|
|
1473
|
+
"""
|
|
1474
|
+
|
|
1475
|
+
if type(expr) is ailment.Expr.Register:
|
|
1476
|
+
# find a register variable
|
|
1477
|
+
reg_vars = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
|
|
1478
|
+
final_reg_vars = set()
|
|
1479
|
+
if len(reg_vars) > 1:
|
|
1480
|
+
# take phi variables
|
|
1481
|
+
for reg_var in reg_vars:
|
|
1482
|
+
if variable_manager.is_phi_variable(reg_var[0]):
|
|
1483
|
+
final_reg_vars.add(reg_var)
|
|
1484
|
+
else:
|
|
1485
|
+
final_reg_vars = reg_vars
|
|
1486
|
+
if len(final_reg_vars) >= 1:
|
|
1487
|
+
reg_var, offset = next(iter(final_reg_vars))
|
|
1488
|
+
expr.variable = reg_var
|
|
1489
|
+
expr.variable_offset = offset
|
|
1490
|
+
|
|
1491
|
+
elif type(expr) is ailment.Expr.Load:
|
|
1492
|
+
variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
|
|
1493
|
+
if len(variables) == 0:
|
|
1494
|
+
# if it's a constant addr, maybe it's referencing an extern location
|
|
1495
|
+
base_addr, offset = self.parse_variable_addr(expr.addr)
|
|
1496
|
+
if offset is not None and isinstance(offset, ailment.Expr.Expression):
|
|
1497
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, offset)
|
|
1498
|
+
if base_addr is not None:
|
|
1499
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, base_addr)
|
|
1500
|
+
|
|
1501
|
+
# if we are accessing the variable directly (offset == 0), we link the variable onto this expression
|
|
1502
|
+
if offset == 0 or (isinstance(offset, ailment.Expr.Const) and offset.value == 0):
|
|
1503
|
+
if "reference_variable" in base_addr.tags:
|
|
1504
|
+
expr.variable = base_addr.reference_variable
|
|
1505
|
+
expr.variable_offset = base_addr.reference_variable_offset
|
|
1506
|
+
|
|
1507
|
+
if base_addr is None and offset is None:
|
|
1508
|
+
# this is a local variable
|
|
1509
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.addr)
|
|
1510
|
+
if "reference_variable" in expr.addr.tags and expr.addr.reference_variable is not None:
|
|
1511
|
+
# copy over the variable to this expr since the variable on a constant is supposed to be a
|
|
1512
|
+
# reference variable.
|
|
1513
|
+
expr.variable = expr.addr.reference_variable
|
|
1514
|
+
expr.variable_offset = expr.addr.reference_variable_offset
|
|
1515
|
+
else:
|
|
1516
|
+
if len(variables) > 1:
|
|
1517
|
+
l.error(
|
|
1518
|
+
"More than one variable are available for atom %s. Consider fixing it using phi nodes.", expr
|
|
1519
|
+
)
|
|
1520
|
+
var, offset = next(iter(variables))
|
|
1521
|
+
expr.variable = var
|
|
1522
|
+
expr.variable_offset = offset
|
|
1523
|
+
|
|
1524
|
+
elif type(expr) is ailment.Expr.BinaryOp:
|
|
1525
|
+
variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
|
|
1526
|
+
if len(variables) >= 1:
|
|
1527
|
+
var, offset = next(iter(variables))
|
|
1528
|
+
expr.variable = var
|
|
1529
|
+
expr.variable_offset = offset
|
|
1530
|
+
else:
|
|
1531
|
+
self._link_variables_on_expr(
|
|
1532
|
+
variable_manager, global_variables, block, stmt_idx, stmt, expr.operands[0]
|
|
1533
|
+
)
|
|
1534
|
+
self._link_variables_on_expr(
|
|
1535
|
+
variable_manager, global_variables, block, stmt_idx, stmt, expr.operands[1]
|
|
1536
|
+
)
|
|
1537
|
+
|
|
1538
|
+
elif type(expr) is ailment.Expr.UnaryOp:
|
|
1539
|
+
variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
|
|
1540
|
+
if len(variables) >= 1:
|
|
1541
|
+
var, offset = next(iter(variables))
|
|
1542
|
+
expr.variable = var
|
|
1543
|
+
expr.variable_offset = offset
|
|
1544
|
+
else:
|
|
1545
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.operand)
|
|
1546
|
+
|
|
1547
|
+
elif type(expr) is ailment.Expr.Convert:
|
|
1548
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.operand)
|
|
1549
|
+
|
|
1550
|
+
elif type(expr) is ailment.Expr.ITE:
|
|
1551
|
+
variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
|
|
1552
|
+
if len(variables) >= 1:
|
|
1553
|
+
var, offset = next(iter(variables))
|
|
1554
|
+
expr.variable = var
|
|
1555
|
+
expr.variable_offset = offset
|
|
1556
|
+
else:
|
|
1557
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.cond)
|
|
1558
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.iftrue)
|
|
1559
|
+
self._link_variables_on_expr(variable_manager, global_variables, block, stmt_idx, stmt, expr.iffalse)
|
|
1560
|
+
|
|
1561
|
+
elif isinstance(expr, ailment.Expr.BasePointerOffset):
|
|
1562
|
+
variables = variable_manager.find_variables_by_atom(block.addr, stmt_idx, expr, block_idx=block.idx)
|
|
1563
|
+
if len(variables) >= 1:
|
|
1564
|
+
var, offset = next(iter(variables))
|
|
1565
|
+
expr.variable = var
|
|
1566
|
+
expr.variable_offset = offset
|
|
1567
|
+
|
|
1568
|
+
elif isinstance(expr, ailment.Expr.Const):
|
|
1569
|
+
# custom string?
|
|
1570
|
+
if hasattr(expr, "custom_string") and expr.custom_string is True:
|
|
1571
|
+
s = self.kb.custom_strings[expr.value]
|
|
1572
|
+
expr.tags["reference_values"] = {
|
|
1573
|
+
SimTypePointer(SimTypeChar().with_arch(self.project.arch)).with_arch(self.project.arch): s.decode(
|
|
1574
|
+
"ascii"
|
|
1575
|
+
),
|
|
1576
|
+
}
|
|
1577
|
+
else:
|
|
1578
|
+
# global variable?
|
|
1579
|
+
global_vars = global_variables.get_global_variables(expr.value)
|
|
1580
|
+
if not global_vars:
|
|
1581
|
+
# detect if there is a related symbol
|
|
1582
|
+
if self.project.loader.find_object_containing(expr.value):
|
|
1583
|
+
symbol = self.project.loader.find_symbol(expr.value)
|
|
1584
|
+
if symbol is not None:
|
|
1585
|
+
# Create a new global variable if there isn't one already
|
|
1586
|
+
global_vars = global_variables.get_global_variables(symbol.rebased_addr)
|
|
1587
|
+
if not global_vars:
|
|
1588
|
+
global_var = SimMemoryVariable(symbol.rebased_addr, symbol.size, name=symbol.name)
|
|
1589
|
+
global_variables.add_variable("global", global_var.addr, global_var)
|
|
1590
|
+
global_vars = {global_var}
|
|
1591
|
+
if global_vars:
|
|
1592
|
+
global_var = next(iter(global_vars))
|
|
1593
|
+
expr.tags["reference_variable"] = global_var
|
|
1594
|
+
expr.tags["reference_variable_offset"] = 0
|
|
1595
|
+
|
|
1596
|
+
elif isinstance(expr, ailment.Stmt.Call):
|
|
1597
|
+
self._link_variables_on_call(variable_manager, global_variables, block, stmt_idx, expr, is_expr=True)
|
|
1598
|
+
|
|
1599
|
+
def _function_graph_to_ail_graph(self, func_graph, blocks_by_addr_and_size=None):
|
|
1600
|
+
if blocks_by_addr_and_size is None:
|
|
1601
|
+
blocks_by_addr_and_size = self._blocks_by_addr_and_size
|
|
1602
|
+
|
|
1603
|
+
node_to_block_mapping = {}
|
|
1604
|
+
graph = networkx.DiGraph()
|
|
1605
|
+
|
|
1606
|
+
for node in func_graph.nodes():
|
|
1607
|
+
ail_block = blocks_by_addr_and_size.get((node.addr, node.size), node)
|
|
1608
|
+
node_to_block_mapping[node] = ail_block
|
|
1609
|
+
|
|
1610
|
+
if ail_block is not None:
|
|
1611
|
+
graph.add_node(ail_block)
|
|
1612
|
+
|
|
1613
|
+
for src_node, dst_node, data in func_graph.edges(data=True):
|
|
1614
|
+
src = node_to_block_mapping[src_node]
|
|
1615
|
+
dst = node_to_block_mapping[dst_node]
|
|
1616
|
+
|
|
1617
|
+
if dst is not None:
|
|
1618
|
+
graph.add_edge(src, dst, **data)
|
|
1619
|
+
|
|
1620
|
+
return graph
|
|
1621
|
+
|
|
1622
|
+
def _rewrite_ite_expressions(self, ail_graph):
|
|
1623
|
+
cfg = self._cfg
|
|
1624
|
+
for block in list(ail_graph):
|
|
1625
|
+
if cfg is not None and block.addr in cfg.jump_tables:
|
|
1626
|
+
continue
|
|
1627
|
+
|
|
1628
|
+
ite_ins_addrs = []
|
|
1629
|
+
for stmt in block.statements:
|
|
1630
|
+
if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.ITE):
|
|
1631
|
+
if stmt.ins_addr not in ite_ins_addrs:
|
|
1632
|
+
ite_ins_addrs.append(stmt.ins_addr)
|
|
1633
|
+
|
|
1634
|
+
if ite_ins_addrs:
|
|
1635
|
+
block_addr = block.addr
|
|
1636
|
+
for ite_ins_addr in ite_ins_addrs:
|
|
1637
|
+
block_addr = self._create_triangle_for_ite_expression(ail_graph, block_addr, ite_ins_addr)
|
|
1638
|
+
if block_addr is None or block_addr >= block.addr + block.original_size:
|
|
1639
|
+
break
|
|
1640
|
+
|
|
1641
|
+
def _create_triangle_for_ite_expression(self, ail_graph, block_addr: int, ite_ins_addr: int):
|
|
1642
|
+
# lift the ite instruction to get its size
|
|
1643
|
+
ite_insn_size = self.project.factory.block(ite_ins_addr, num_inst=1).size
|
|
1644
|
+
if ite_insn_size <= 2: # we need an address for true_block and another address for false_block
|
|
1645
|
+
return None
|
|
1646
|
+
|
|
1647
|
+
# relift the head and the ITE instruction
|
|
1648
|
+
new_head = self.project.factory.block(
|
|
1649
|
+
block_addr, size=ite_ins_addr - block_addr + ite_insn_size, cross_insn_opt=False
|
|
1650
|
+
)
|
|
1651
|
+
new_head_ail = ailment.IRSBConverter.convert(new_head.vex, self._ail_manager)
|
|
1652
|
+
# remove all statements between the ITE expression and the very end of the block
|
|
1653
|
+
ite_expr_stmt_idx = None
|
|
1654
|
+
ite_expr_stmt = None
|
|
1655
|
+
for idx, stmt in enumerate(new_head_ail.statements):
|
|
1656
|
+
if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.ITE):
|
|
1657
|
+
ite_expr_stmt_idx = idx
|
|
1658
|
+
ite_expr_stmt = stmt
|
|
1659
|
+
break
|
|
1660
|
+
if ite_expr_stmt_idx is None:
|
|
1661
|
+
return None
|
|
1662
|
+
|
|
1663
|
+
ite_expr: ailment.Expr.ITE = ite_expr_stmt.src
|
|
1664
|
+
new_head_ail.statements = new_head_ail.statements[:ite_expr_stmt_idx]
|
|
1665
|
+
# build the conditional jump
|
|
1666
|
+
true_block_addr = ite_ins_addr + 1
|
|
1667
|
+
false_block_addr = ite_ins_addr + 2
|
|
1668
|
+
cond_jump_stmt = ailment.Stmt.ConditionalJump(
|
|
1669
|
+
ite_expr_stmt.idx,
|
|
1670
|
+
ite_expr.cond,
|
|
1671
|
+
ailment.Expr.Const(None, None, true_block_addr, self.project.arch.bits, **ite_expr_stmt.tags),
|
|
1672
|
+
ailment.Expr.Const(None, None, false_block_addr, self.project.arch.bits, **ite_expr_stmt.tags),
|
|
1673
|
+
**ite_expr_stmt.tags,
|
|
1674
|
+
)
|
|
1675
|
+
new_head_ail.statements.append(cond_jump_stmt)
|
|
1676
|
+
|
|
1677
|
+
# build the true block
|
|
1678
|
+
true_block = self.project.factory.block(ite_ins_addr, num_inst=1)
|
|
1679
|
+
true_block_ail = ailment.IRSBConverter.convert(true_block.vex, self._ail_manager)
|
|
1680
|
+
true_block_ail.addr = true_block_addr
|
|
1681
|
+
|
|
1682
|
+
ite_expr_stmt_idx = None
|
|
1683
|
+
ite_expr_stmt = None
|
|
1684
|
+
for idx, stmt in enumerate(true_block_ail.statements):
|
|
1685
|
+
if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.ITE):
|
|
1686
|
+
ite_expr_stmt_idx = idx
|
|
1687
|
+
ite_expr_stmt = stmt
|
|
1688
|
+
break
|
|
1689
|
+
if ite_expr_stmt_idx is None:
|
|
1690
|
+
return None
|
|
1691
|
+
|
|
1692
|
+
true_block_ail.statements[ite_expr_stmt_idx] = ailment.Stmt.Assignment(
|
|
1693
|
+
ite_expr_stmt.idx, ite_expr_stmt.dst, ite_expr_stmt.src.iftrue, **ite_expr_stmt.tags
|
|
1694
|
+
)
|
|
1695
|
+
|
|
1696
|
+
# build the false block
|
|
1697
|
+
false_block = self.project.factory.block(ite_ins_addr, num_inst=1)
|
|
1698
|
+
false_block_ail = ailment.IRSBConverter.convert(false_block.vex, self._ail_manager)
|
|
1699
|
+
false_block_ail.addr = false_block_addr
|
|
1700
|
+
|
|
1701
|
+
ite_expr_stmt_idx = None
|
|
1702
|
+
ite_expr_stmt = None
|
|
1703
|
+
for idx, stmt in enumerate(false_block_ail.statements):
|
|
1704
|
+
if isinstance(stmt, ailment.Stmt.Assignment) and isinstance(stmt.src, ailment.Expr.ITE):
|
|
1705
|
+
ite_expr_stmt_idx = idx
|
|
1706
|
+
ite_expr_stmt = stmt
|
|
1707
|
+
break
|
|
1708
|
+
if ite_expr_stmt_idx is None:
|
|
1709
|
+
return None
|
|
1710
|
+
|
|
1711
|
+
false_block_ail.statements[ite_expr_stmt_idx] = ailment.Stmt.Assignment(
|
|
1712
|
+
ite_expr_stmt.idx, ite_expr_stmt.dst, ite_expr_stmt.src.iffalse, **ite_expr_stmt.tags
|
|
1713
|
+
)
|
|
1714
|
+
|
|
1715
|
+
original_block = next(iter(b for b in ail_graph if b.addr == block_addr))
|
|
1716
|
+
|
|
1717
|
+
original_block_in_edges = list(ail_graph.in_edges(original_block))
|
|
1718
|
+
original_block_out_edges = list(ail_graph.out_edges(original_block))
|
|
1719
|
+
|
|
1720
|
+
# build the target block if the target block does not exist in the current function
|
|
1721
|
+
end_block_addr = ite_ins_addr + ite_insn_size
|
|
1722
|
+
if block_addr < end_block_addr < block_addr + original_block.original_size:
|
|
1723
|
+
end_block = self.project.factory.block(
|
|
1724
|
+
ite_ins_addr + ite_insn_size,
|
|
1725
|
+
size=block_addr + original_block.original_size - (ite_ins_addr + ite_insn_size),
|
|
1726
|
+
cross_insn_opt=False,
|
|
1727
|
+
)
|
|
1728
|
+
end_block_ail = ailment.IRSBConverter.convert(end_block.vex, self._ail_manager)
|
|
1729
|
+
else:
|
|
1730
|
+
try:
|
|
1731
|
+
end_block_ail = next(iter(b for b in ail_graph if b.addr == end_block_addr))
|
|
1732
|
+
except StopIteration:
|
|
1733
|
+
return None
|
|
1734
|
+
|
|
1735
|
+
# last check: if the first instruction of the end block has Sar, then we bail (due to the peephole optimization
|
|
1736
|
+
# SarToSignedDiv)
|
|
1737
|
+
for stmt in end_block_ail.statements:
|
|
1738
|
+
if stmt.ins_addr > end_block_ail.addr:
|
|
1739
|
+
break
|
|
1740
|
+
if (
|
|
1741
|
+
isinstance(stmt, ailment.Stmt.Assignment)
|
|
1742
|
+
and isinstance(stmt.src, ailment.Expr.BinaryOp)
|
|
1743
|
+
and stmt.src.op == "Sar"
|
|
1744
|
+
):
|
|
1745
|
+
return None
|
|
1746
|
+
|
|
1747
|
+
ail_graph.remove_node(original_block)
|
|
1748
|
+
|
|
1749
|
+
if end_block_ail not in ail_graph:
|
|
1750
|
+
# newly created. add it and the necessary edges into the graph
|
|
1751
|
+
for _, dst in original_block_out_edges:
|
|
1752
|
+
if dst is original_block:
|
|
1753
|
+
ail_graph.add_edge(end_block_ail, new_head_ail)
|
|
1754
|
+
else:
|
|
1755
|
+
ail_graph.add_edge(end_block_ail, dst)
|
|
1756
|
+
|
|
1757
|
+
# in edges
|
|
1758
|
+
for src, _ in original_block_in_edges:
|
|
1759
|
+
if src is original_block:
|
|
1760
|
+
# loop
|
|
1761
|
+
ail_graph.add_edge(end_block_ail, new_head_ail)
|
|
1762
|
+
else:
|
|
1763
|
+
ail_graph.add_edge(src, new_head_ail)
|
|
1764
|
+
|
|
1765
|
+
# triangle
|
|
1766
|
+
ail_graph.add_edge(new_head_ail, true_block_ail)
|
|
1767
|
+
ail_graph.add_edge(new_head_ail, false_block_ail)
|
|
1768
|
+
ail_graph.add_edge(true_block_ail, end_block_ail)
|
|
1769
|
+
ail_graph.add_edge(false_block_ail, end_block_ail)
|
|
1770
|
+
|
|
1771
|
+
return end_block_ail.addr
|
|
1772
|
+
|
|
1773
|
+
@staticmethod
|
|
1774
|
+
def _remove_redundant_jump_blocks(ail_graph):
|
|
1775
|
+
def first_conditional_jump(block: ailment.Block) -> ailment.Stmt.ConditionalJump | None:
|
|
1776
|
+
for stmt in block.statements:
|
|
1777
|
+
if isinstance(stmt, ailment.Stmt.ConditionalJump):
|
|
1778
|
+
return stmt
|
|
1779
|
+
return None
|
|
1780
|
+
|
|
1781
|
+
def patch_conditional_jump_target(cond_jump_stmt: ailment.Stmt.ConditionalJump, old_addr: int, new_addr: int):
|
|
1782
|
+
if (
|
|
1783
|
+
isinstance(cond_jump_stmt.true_target, ailment.Expr.Const)
|
|
1784
|
+
and cond_jump_stmt.true_target.value == old_addr
|
|
1785
|
+
):
|
|
1786
|
+
cond_jump_stmt.true_target.value = new_addr
|
|
1787
|
+
if (
|
|
1788
|
+
isinstance(cond_jump_stmt.false_target, ailment.Expr.Const)
|
|
1789
|
+
and cond_jump_stmt.false_target.value == old_addr
|
|
1790
|
+
):
|
|
1791
|
+
cond_jump_stmt.false_target.value = new_addr
|
|
1792
|
+
|
|
1793
|
+
# note that blocks don't have labels inserted at this point
|
|
1794
|
+
for node in list(ail_graph.nodes):
|
|
1795
|
+
if (
|
|
1796
|
+
len(node.statements) == 1
|
|
1797
|
+
and isinstance(node.statements[0], ailment.Stmt.Jump)
|
|
1798
|
+
and isinstance(node.statements[0].target, ailment.Expr.Const)
|
|
1799
|
+
):
|
|
1800
|
+
jump_target = node.statements[0].target.value
|
|
1801
|
+
succs = list(ail_graph.successors(node))
|
|
1802
|
+
if len(succs) == 1 and succs[0].addr == jump_target:
|
|
1803
|
+
preds = list(ail_graph.predecessors(node))
|
|
1804
|
+
if len(preds) == 1 and ail_graph.out_degree[preds[0]] == 2:
|
|
1805
|
+
# remove this node
|
|
1806
|
+
for pred in preds:
|
|
1807
|
+
if pred.statements:
|
|
1808
|
+
last_stmt = pred.statements[-1]
|
|
1809
|
+
if (
|
|
1810
|
+
isinstance(last_stmt, ailment.Stmt.Jump)
|
|
1811
|
+
and isinstance(last_stmt.target, ailment.Expr.Const)
|
|
1812
|
+
and last_stmt.target.value == node.addr
|
|
1813
|
+
):
|
|
1814
|
+
last_stmt.target.value = succs[0].addr
|
|
1815
|
+
elif isinstance(last_stmt, ailment.Stmt.ConditionalJump):
|
|
1816
|
+
patch_conditional_jump_target(last_stmt, node.addr, succs[0].addr)
|
|
1817
|
+
first_cond_jump = first_conditional_jump(pred)
|
|
1818
|
+
if first_cond_jump is not None and first_cond_jump is not last_stmt:
|
|
1819
|
+
patch_conditional_jump_target(first_cond_jump, node.addr, succs[0].addr)
|
|
1820
|
+
ail_graph.add_edge(pred, succs[0])
|
|
1821
|
+
ail_graph.remove_node(node)
|
|
1822
|
+
|
|
1823
|
+
@staticmethod
|
|
1824
|
+
def _insert_block_labels(ail_graph):
|
|
1825
|
+
for node in ail_graph.nodes:
|
|
1826
|
+
node: ailment.Block
|
|
1827
|
+
lbl = ailment.Stmt.Label(None, f"LABEL_{node.addr:x}", node.addr, block_idx=node.idx)
|
|
1828
|
+
node.statements.insert(0, lbl)
|
|
1829
|
+
|
|
1830
|
+
@staticmethod
|
|
1831
|
+
def _collect_externs(ail_graph, variable_kb):
|
|
1832
|
+
global_vars = variable_kb.variables.global_manager.get_variables()
|
|
1833
|
+
walker = ailment.AILBlockWalker()
|
|
1834
|
+
variables = set()
|
|
1835
|
+
|
|
1836
|
+
def handle_expr(
|
|
1837
|
+
expr_idx: int,
|
|
1838
|
+
expr: ailment.expression.Expression,
|
|
1839
|
+
stmt_idx: int,
|
|
1840
|
+
stmt: ailment.statement.Statement,
|
|
1841
|
+
block: ailment.Block | None,
|
|
1842
|
+
):
|
|
1843
|
+
if expr is None:
|
|
1844
|
+
return None
|
|
1845
|
+
for v in [
|
|
1846
|
+
getattr(expr, "variable", None),
|
|
1847
|
+
expr.tags.get("reference_variable", None) if hasattr(expr, "tags") else None,
|
|
1848
|
+
]:
|
|
1849
|
+
if v and v in global_vars:
|
|
1850
|
+
variables.add(v)
|
|
1851
|
+
return ailment.AILBlockWalker._handle_expr(walker, expr_idx, expr, stmt_idx, stmt, block)
|
|
1852
|
+
|
|
1853
|
+
def handle_Store(stmt_idx: int, stmt: ailment.statement.Store, block: ailment.Block | None):
|
|
1854
|
+
if stmt.variable and stmt.variable in global_vars:
|
|
1855
|
+
variables.add(stmt.variable)
|
|
1856
|
+
return ailment.AILBlockWalker._handle_Store(walker, stmt_idx, stmt, block)
|
|
1857
|
+
|
|
1858
|
+
walker.stmt_handlers[ailment.statement.Store] = handle_Store
|
|
1859
|
+
walker._handle_expr = handle_expr
|
|
1860
|
+
AILGraphWalker(ail_graph, walker.walk).walk()
|
|
1861
|
+
return variables
|
|
1862
|
+
|
|
1863
|
+
@staticmethod
|
|
1864
|
+
def _collect_data_refs(ail_graph) -> dict[int, list[DataRefDesc]]:
|
|
1865
|
+
# pylint:disable=unused-argument
|
|
1866
|
+
walker = ailment.AILBlockWalker()
|
|
1867
|
+
data_refs: dict[int, list[DataRefDesc]] = defaultdict(list)
|
|
1868
|
+
|
|
1869
|
+
def handle_Const(
|
|
1870
|
+
expr_idx: int,
|
|
1871
|
+
expr: ailment.expression.Const,
|
|
1872
|
+
stmt_idx: int,
|
|
1873
|
+
stmt: ailment.statement.Statement,
|
|
1874
|
+
block: ailment.Block | None,
|
|
1875
|
+
):
|
|
1876
|
+
if isinstance(expr.value, int) and hasattr(expr, "ins_addr"):
|
|
1877
|
+
data_refs[block.addr].append(
|
|
1878
|
+
DataRefDesc(expr.value, 1, block.addr, stmt_idx, expr.ins_addr, MemoryDataSort.Unknown)
|
|
1879
|
+
)
|
|
1880
|
+
if hasattr(expr, "deref_src_addr"):
|
|
1881
|
+
data_refs[block.addr].append(
|
|
1882
|
+
DataRefDesc(
|
|
1883
|
+
expr.deref_src_addr, expr.size, block.addr, stmt_idx, expr.ins_addr, MemoryDataSort.Unknown
|
|
1884
|
+
)
|
|
1885
|
+
)
|
|
1886
|
+
|
|
1887
|
+
def handle_Load(
|
|
1888
|
+
expr_idx: int,
|
|
1889
|
+
expr: ailment.expression.Load,
|
|
1890
|
+
stmt_idx: int,
|
|
1891
|
+
stmt: ailment.statement.Statement,
|
|
1892
|
+
block: ailment.Block | None,
|
|
1893
|
+
):
|
|
1894
|
+
if isinstance(expr.addr, ailment.expression.Const):
|
|
1895
|
+
addr = expr.addr
|
|
1896
|
+
if isinstance(addr.value, int) and hasattr(addr, "ins_addr"):
|
|
1897
|
+
data_refs[block.addr].append(
|
|
1898
|
+
DataRefDesc(
|
|
1899
|
+
addr.value,
|
|
1900
|
+
expr.size,
|
|
1901
|
+
block.addr,
|
|
1902
|
+
stmt_idx,
|
|
1903
|
+
addr.ins_addr,
|
|
1904
|
+
MemoryDataSort.Integer if expr.size == 4 else MemoryDataSort.Unknown,
|
|
1905
|
+
)
|
|
1906
|
+
)
|
|
1907
|
+
if hasattr(addr, "deref_src_addr"):
|
|
1908
|
+
data_refs[block.addr].append(
|
|
1909
|
+
DataRefDesc(
|
|
1910
|
+
addr.deref_src_addr,
|
|
1911
|
+
expr.size,
|
|
1912
|
+
block.addr,
|
|
1913
|
+
stmt_idx,
|
|
1914
|
+
addr.ins_addr,
|
|
1915
|
+
MemoryDataSort.Integer if expr.size == 4 else MemoryDataSort.Unknown,
|
|
1916
|
+
)
|
|
1917
|
+
)
|
|
1918
|
+
return None
|
|
1919
|
+
|
|
1920
|
+
return ailment.AILBlockWalker._handle_Load(walker, expr_idx, expr, stmt_idx, stmt, block)
|
|
1921
|
+
|
|
1922
|
+
def handle_Store(stmt_idx: int, stmt: ailment.statement.Store, block: ailment.Block | None):
|
|
1923
|
+
if isinstance(stmt.addr, ailment.expression.Const):
|
|
1924
|
+
addr = stmt.addr
|
|
1925
|
+
if isinstance(addr.value, int) and hasattr(addr, "ins_addr"):
|
|
1926
|
+
data_refs[block.addr].append(
|
|
1927
|
+
DataRefDesc(
|
|
1928
|
+
addr.value,
|
|
1929
|
+
stmt.size,
|
|
1930
|
+
block.addr,
|
|
1931
|
+
stmt_idx,
|
|
1932
|
+
addr.ins_addr,
|
|
1933
|
+
MemoryDataSort.Integer if stmt.size == 4 else MemoryDataSort.Unknown,
|
|
1934
|
+
)
|
|
1935
|
+
)
|
|
1936
|
+
if hasattr(addr, "deref_src_addr"):
|
|
1937
|
+
data_refs[block.addr].append(
|
|
1938
|
+
DataRefDesc(
|
|
1939
|
+
addr.deref_src_addr,
|
|
1940
|
+
stmt.size,
|
|
1941
|
+
block.addr,
|
|
1942
|
+
stmt_idx,
|
|
1943
|
+
addr.ins_addr,
|
|
1944
|
+
MemoryDataSort.Integer if stmt.size == 4 else MemoryDataSort.Unknown,
|
|
1945
|
+
)
|
|
1946
|
+
)
|
|
1947
|
+
return None
|
|
1948
|
+
|
|
1949
|
+
return ailment.AILBlockWalker._handle_Store(walker, stmt_idx, stmt, block)
|
|
1950
|
+
|
|
1951
|
+
walker.stmt_handlers[ailment.statement.Store] = handle_Store
|
|
1952
|
+
walker.expr_handlers[ailment.expression.Load] = handle_Load
|
|
1953
|
+
walker.expr_handlers[ailment.expression.Const] = handle_Const
|
|
1954
|
+
AILGraphWalker(ail_graph, walker.walk).walk()
|
|
1955
|
+
return data_refs
|
|
1956
|
+
|
|
1957
|
+
def _next_atom(self) -> int:
|
|
1958
|
+
return self._ail_manager.next_atom()
|
|
1959
|
+
|
|
1960
|
+
@staticmethod
|
|
1961
|
+
def _make_callsites_rd_observe_callback(ob_type, **kwargs):
|
|
1962
|
+
if ob_type != "insn":
|
|
1963
|
+
return False
|
|
1964
|
+
stmt = kwargs.pop("stmt")
|
|
1965
|
+
op_type = kwargs.pop("op_type")
|
|
1966
|
+
return isinstance(stmt, ailment.Stmt.Call) and op_type == OP_BEFORE
|
|
1967
|
+
|
|
1968
|
+
def parse_variable_addr(self, addr: ailment.Expr.Expression) -> tuple[Any, Any] | None:
|
|
1969
|
+
if isinstance(addr, ailment.Expr.Const):
|
|
1970
|
+
return addr, 0
|
|
1971
|
+
if isinstance(addr, ailment.Expr.BinaryOp):
|
|
1972
|
+
if addr.op == "Add":
|
|
1973
|
+
op0, op1 = addr.operands
|
|
1974
|
+
if (
|
|
1975
|
+
isinstance(op0, ailment.Expr.Const)
|
|
1976
|
+
and self.project.loader.find_object_containing(op0.value) is not None
|
|
1977
|
+
):
|
|
1978
|
+
return op0, op1
|
|
1979
|
+
elif (
|
|
1980
|
+
isinstance(op1, ailment.Expr.Const)
|
|
1981
|
+
and self.project.loader.find_object_containing(op1.value) is not None
|
|
1982
|
+
):
|
|
1983
|
+
return op1, op0
|
|
1984
|
+
return op0, op1 # best-effort guess
|
|
1985
|
+
return None, None
|
|
1986
|
+
|
|
1987
|
+
def new_block_addr(self) -> int:
|
|
1988
|
+
"""
|
|
1989
|
+
Return a block address that does not conflict with any existing blocks.
|
|
1990
|
+
|
|
1991
|
+
:return: The block address.
|
|
1992
|
+
"""
|
|
1993
|
+
if self._new_block_addrs:
|
|
1994
|
+
new_addr = max(self._new_block_addrs) + 1
|
|
1995
|
+
else:
|
|
1996
|
+
new_addr = max(self.function.block_addrs_set) + 2048
|
|
1997
|
+
self._new_block_addrs.add(new_addr)
|
|
1998
|
+
return new_addr
|
|
1999
|
+
|
|
2000
|
+
@staticmethod
|
|
2001
|
+
@timethis
|
|
2002
|
+
def remove_empty_nodes(graph: networkx.DiGraph) -> networkx.DiGraph:
|
|
2003
|
+
def handle_node(node: ailment.Block):
|
|
2004
|
+
if not node.statements:
|
|
2005
|
+
preds = list(pred for pred in graph.predecessors(node) if pred is not node)
|
|
2006
|
+
succs = list(succ for succ in graph.successors(node) if succ is not node)
|
|
2007
|
+
if len(preds) == 1 and len(succs) == 1:
|
|
2008
|
+
pred = preds[0]
|
|
2009
|
+
succ = succs[0]
|
|
2010
|
+
value_updated = False
|
|
2011
|
+
# update the last statement of pred
|
|
2012
|
+
if pred.statements and isinstance(pred.statements[-1], ailment.Stmt.ConditionalJump):
|
|
2013
|
+
last_stmt = pred.statements[-1]
|
|
2014
|
+
if (
|
|
2015
|
+
isinstance(last_stmt.true_target, ailment.Expr.Const)
|
|
2016
|
+
and last_stmt.true_target.value == node.addr
|
|
2017
|
+
):
|
|
2018
|
+
last_stmt.true_target.value = succ.addr
|
|
2019
|
+
value_updated = True
|
|
2020
|
+
if (
|
|
2021
|
+
isinstance(last_stmt.false_target, ailment.Expr.Const)
|
|
2022
|
+
and last_stmt.false_target.value == node.addr
|
|
2023
|
+
):
|
|
2024
|
+
last_stmt.false_target.value = succ.addr
|
|
2025
|
+
value_updated = True
|
|
2026
|
+
|
|
2027
|
+
if value_updated:
|
|
2028
|
+
graph.add_edge(pred, succ)
|
|
2029
|
+
raise RemoveNodeNotice()
|
|
2030
|
+
elif len(preds) >= 1 and len(succs) == 1:
|
|
2031
|
+
succ = succs[0]
|
|
2032
|
+
branch_updates = 0
|
|
2033
|
+
for pred in preds:
|
|
2034
|
+
# test how many last statements of pred can potentially be updated
|
|
2035
|
+
if pred.statements and isinstance(pred.statements[-1], ailment.Stmt.ConditionalJump):
|
|
2036
|
+
last_stmt = pred.statements[-1]
|
|
2037
|
+
if (
|
|
2038
|
+
isinstance(last_stmt.true_target, ailment.Expr.Const)
|
|
2039
|
+
and last_stmt.true_target.value == node.addr
|
|
2040
|
+
):
|
|
2041
|
+
branch_updates += 1
|
|
2042
|
+
if (
|
|
2043
|
+
isinstance(last_stmt.false_target, ailment.Expr.Const)
|
|
2044
|
+
and last_stmt.false_target.value == node.addr
|
|
2045
|
+
):
|
|
2046
|
+
branch_updates += 1
|
|
2047
|
+
|
|
2048
|
+
if branch_updates == len(preds):
|
|
2049
|
+
# actually do the update
|
|
2050
|
+
for pred in preds:
|
|
2051
|
+
graph.add_edge(pred, succ)
|
|
2052
|
+
if pred.statements and isinstance(pred.statements[-1], ailment.Stmt.ConditionalJump):
|
|
2053
|
+
last_stmt = pred.statements[-1]
|
|
2054
|
+
if (
|
|
2055
|
+
isinstance(last_stmt.true_target, ailment.Expr.Const)
|
|
2056
|
+
and last_stmt.true_target.value == node.addr
|
|
2057
|
+
):
|
|
2058
|
+
last_stmt.true_target.value = succ.addr
|
|
2059
|
+
if (
|
|
2060
|
+
isinstance(last_stmt.false_target, ailment.Expr.Const)
|
|
2061
|
+
and last_stmt.false_target.value == node.addr
|
|
2062
|
+
):
|
|
2063
|
+
last_stmt.false_target.value = succ.addr
|
|
2064
|
+
raise RemoveNodeNotice()
|
|
2065
|
+
elif not preds or not succs:
|
|
2066
|
+
raise RemoveNodeNotice()
|
|
2067
|
+
|
|
2068
|
+
AILGraphWalker(graph, handle_node, replace_nodes=True).walk()
|
|
2069
|
+
return graph
|
|
2070
|
+
|
|
2071
|
+
def _find_regs_compared_against_sp(self, func_graph):
|
|
2072
|
+
# TODO: Implement this function for architectures beyond amd64
|
|
2073
|
+
extra_regs = set()
|
|
2074
|
+
if self.project.arch.name == "AMD64":
|
|
2075
|
+
for node in func_graph.nodes:
|
|
2076
|
+
block = self.project.factory.block(node.addr, size=node.size).capstone
|
|
2077
|
+
for insn in block.insns:
|
|
2078
|
+
if insn.mnemonic == "cmp":
|
|
2079
|
+
capstone_reg_offset = None
|
|
2080
|
+
if (
|
|
2081
|
+
insn.operands[0].type == capstone.x86.X86_OP_REG
|
|
2082
|
+
and insn.operands[0].reg == capstone.x86.X86_REG_RSP
|
|
2083
|
+
and insn.operands[1].type == capstone.x86.X86_OP_REG
|
|
2084
|
+
):
|
|
2085
|
+
capstone_reg_offset = insn.operands[1].reg
|
|
2086
|
+
elif (
|
|
2087
|
+
insn.operands[1].type == capstone.x86.X86_OP_REG
|
|
2088
|
+
and insn.operands[1].reg == capstone.x86.X86_REG_RSP
|
|
2089
|
+
and insn.operands[0].type == capstone.x86.X86_OP_REG
|
|
2090
|
+
):
|
|
2091
|
+
capstone_reg_offset = insn.operands[0].reg
|
|
2092
|
+
|
|
2093
|
+
if capstone_reg_offset is not None:
|
|
2094
|
+
reg_name = insn.reg_name(capstone_reg_offset)
|
|
2095
|
+
extra_regs.add(self.project.arch.registers[reg_name][0])
|
|
2096
|
+
|
|
2097
|
+
return extra_regs
|
|
2098
|
+
|
|
2099
|
+
def _rewrite_alloca(self, ail_graph):
|
|
2100
|
+
# pylint:disable=too-many-boolean-expressions
|
|
2101
|
+
alloca_node = None
|
|
2102
|
+
sp_equal_to = None
|
|
2103
|
+
|
|
2104
|
+
for node in ail_graph:
|
|
2105
|
+
if ail_graph.in_degree[node] == 2 and ail_graph.out_degree[node] == 2:
|
|
2106
|
+
succs = ail_graph.successors(node)
|
|
2107
|
+
if node in succs:
|
|
2108
|
+
# self loop!
|
|
2109
|
+
if len(node.statements) >= 6:
|
|
2110
|
+
stmt0 = node.statements[1] # skip the LABEL statement
|
|
2111
|
+
stmt1 = node.statements[2]
|
|
2112
|
+
last_stmt = node.statements[-1]
|
|
2113
|
+
if (
|
|
2114
|
+
isinstance(stmt0, ailment.Stmt.Assignment)
|
|
2115
|
+
and isinstance(stmt0.dst, ailment.Expr.Register)
|
|
2116
|
+
and isinstance(stmt0.src, ailment.Expr.StackBaseOffset)
|
|
2117
|
+
and stmt0.src.offset == -0x1000
|
|
2118
|
+
):
|
|
2119
|
+
if (
|
|
2120
|
+
isinstance(stmt1, ailment.Stmt.Store)
|
|
2121
|
+
and isinstance(stmt1.addr, ailment.Expr.StackBaseOffset)
|
|
2122
|
+
and stmt1.addr.offset == -0x1000
|
|
2123
|
+
and isinstance(stmt1.data, ailment.Expr.Load)
|
|
2124
|
+
and isinstance(stmt1.data.addr, ailment.Expr.StackBaseOffset)
|
|
2125
|
+
and stmt1.data.addr.offset == -0x1000
|
|
2126
|
+
):
|
|
2127
|
+
if (
|
|
2128
|
+
isinstance(last_stmt, ailment.Stmt.ConditionalJump)
|
|
2129
|
+
and isinstance(last_stmt.condition, ailment.Expr.BinaryOp)
|
|
2130
|
+
and last_stmt.condition.op == "CmpEQ"
|
|
2131
|
+
and isinstance(last_stmt.condition.operands[0], ailment.Expr.StackBaseOffset)
|
|
2132
|
+
and last_stmt.condition.operands[0].offset == -0x1000
|
|
2133
|
+
and isinstance(last_stmt.condition.operands[1], ailment.Expr.Register)
|
|
2134
|
+
and isinstance(last_stmt.false_target, ailment.Expr.Const)
|
|
2135
|
+
and last_stmt.false_target.value == node.addr
|
|
2136
|
+
):
|
|
2137
|
+
# found it!
|
|
2138
|
+
alloca_node = node
|
|
2139
|
+
sp_equal_to = ailment.Expr.BinaryOp(
|
|
2140
|
+
None,
|
|
2141
|
+
"Sub",
|
|
2142
|
+
[
|
|
2143
|
+
ailment.Expr.Register(
|
|
2144
|
+
None, None, self.project.arch.sp_offset, self.project.arch.bits
|
|
2145
|
+
),
|
|
2146
|
+
last_stmt.condition.operands[1],
|
|
2147
|
+
],
|
|
2148
|
+
False,
|
|
2149
|
+
)
|
|
2150
|
+
break
|
|
2151
|
+
|
|
2152
|
+
if alloca_node is not None:
|
|
2153
|
+
stmt0 = alloca_node.statements[1]
|
|
2154
|
+
statements = [ailment.Stmt.Call(stmt0.idx, "alloca", args=[sp_equal_to], **stmt0.tags)]
|
|
2155
|
+
new_node = ailment.Block(alloca_node.addr, alloca_node.original_size, statements=statements)
|
|
2156
|
+
# replace the node
|
|
2157
|
+
preds = [pred for pred in ail_graph.predecessors(alloca_node) if pred is not alloca_node]
|
|
2158
|
+
succs = [succ for succ in ail_graph.successors(alloca_node) if succ is not alloca_node]
|
|
2159
|
+
ail_graph.remove_node(alloca_node)
|
|
2160
|
+
for pred in preds:
|
|
2161
|
+
ail_graph.add_edge(pred, new_node)
|
|
2162
|
+
for succ in succs:
|
|
2163
|
+
ail_graph.add_edge(new_node, succ)
|
|
2164
|
+
|
|
2165
|
+
|
|
2166
|
+
register_analysis(Clinic, "Clinic")
|