From 05748c67bec777672a69462178625dffc7d5eb56 Mon Sep 17 00:00:00 2001 From: John Doe Date: Wed, 1 Dec 2021 00:50:44 -0800 Subject: [PATCH] the coupe does 190 but it feels like 60 mph --- include/vmctx.hpp | 77 +++++++++++++++++++++++---------------------- include/vmutils.hpp | 18 +++++++++++ src/vmctx.cpp | 50 +++++++++++++++-------------- src/vmutils.cpp | 24 +++++--------- 4 files changed, 91 insertions(+), 78 deletions(-) diff --git a/include/vmctx.hpp b/include/vmctx.hpp index ea7c174..cb42ff7 100644 --- a/include/vmctx.hpp +++ b/include/vmctx.hpp @@ -3,45 +3,46 @@ #include #include -namespace vm -{ - /// - /// vm::ctx_t class is used to auto generate vm_entry, calc_jmp, and other per-vm entry information... - /// creating a vm::ctx_t object can make it easier to pass around information pertaining to a given vm entry... - /// - class ctx_t - { - public: - /// - /// default constructor for vm::ctx_t... all information for a given vm entry must be provided... - /// - /// the linear virtual address of the module base... - /// image base from optional nt header... IMAGE_OPTIONAL_HEADER64... - /// image size from optional nt header... IMAGE_OPTIONAL_HEADER64... - /// relative virtual address from the module base address to the first push prior to - /// a vm entry... - explicit ctx_t( std::uintptr_t module_base, std::uintptr_t image_base, std::uintptr_t image_size, - std::uintptr_t vm_entry_rva ); +namespace vm { +/// +/// vm::ctx_t class is used to auto generate vm_entry, calc_jmp, and other +/// per-vm entry information... creating a vm::ctx_t object can make it easier +/// to pass around information pertaining to a given vm entry... +/// +class ctx_t { + public: + /// + /// default constructor for vm::ctx_t... all information for a given vm entry + /// must be provided... + /// + /// the linear virtual address of the module + /// base... image base from optional nt + /// header... IMAGE_OPTIONAL_HEADER64... + /// image size from optional nt header... IMAGE_OPTIONAL_HEADER64... + /// relative virtual address from the module base + /// address to the first push prior to a vm entry... + explicit ctx_t(std::uintptr_t module_base, std::uintptr_t image_base, + std::uintptr_t image_size, std::uintptr_t vm_entry_rva); - /// - /// init all per-vm entry data such as vm_entry, calc_jmp, and vm handlers... - /// - /// returns true if no errors... - bool init(); + /// + /// init all per-vm entry data such as vm_entry, calc_jmp, and vm handlers... + /// + /// returns true if no errors... + bool init(); - const std::uintptr_t module_base, image_base, vm_entry_rva, image_size; + const std::uintptr_t module_base, image_base, vm_entry_rva, image_size; - /// - /// the order in which VIP advances... - /// - vmp2::exec_type_t exec_type; - zydis_routine_t vm_entry, calc_jmp; + /// + /// the order in which VIP advances... + /// + vmp2::exec_type_t exec_type; + zydis_routine_t vm_entry, calc_jmp; - /// - /// all the vm handlers for the given vm entry... - /// - std::vector< vm::handler::handler_t > vm_handlers; - }; -} // namespace vm \ No newline at end of file + /// + /// all the vm handlers for the given vm entry... + /// + std::vector vm_handlers; +}; +} // namespace vm \ No newline at end of file diff --git a/include/vmutils.hpp b/include/vmutils.hpp index d3b783f..163d755 100644 --- a/include/vmutils.hpp +++ b/include/vmutils.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -76,6 +77,23 @@ using zydis_routine_t = std::vector; /// utils used by the other cpp files... misc things that get used a lot... /// namespace vm::util { + +inline std::shared_ptr g_decoder = nullptr; +inline std::shared_ptr g_formatter = nullptr; + +inline void init() { + if (!vm::util::g_decoder && !vm::util::g_formatter) { + vm::util::g_decoder = std::make_shared(); + vm::util::g_formatter = std::make_shared(); + + ZydisDecoderInit(vm::util::g_decoder.get(), ZYDIS_MACHINE_MODE_LONG_64, + ZYDIS_ADDRESS_WIDTH_64); + + ZydisFormatterInit(vm::util::g_formatter.get(), + ZYDIS_FORMATTER_STYLE_INTEL); + } +} + /// /// utils pertaining to native registers... /// diff --git a/src/vmctx.cpp b/src/vmctx.cpp index e3742cc..7cd2dbb 100644 --- a/src/vmctx.cpp +++ b/src/vmctx.cpp @@ -1,31 +1,33 @@ +#include + #include -namespace vm -{ - ctx_t::ctx_t( std::uintptr_t module_base, std::uintptr_t image_base, std::uintptr_t image_size, - std::uintptr_t vm_entry_rva ) - : module_base( module_base ), image_base( image_base ), image_size( image_size ), vm_entry_rva( vm_entry_rva ) - { - } +namespace vm { +ctx_t::ctx_t(std::uintptr_t module_base, std::uintptr_t image_base, + std::uintptr_t image_size, std::uintptr_t vm_entry_rva) + : module_base(module_base), + image_base(image_base), + image_size(image_size), + vm_entry_rva(vm_entry_rva) {} - bool ctx_t::init() - { - if ( !vm::util::flatten( vm_entry, vm_entry_rva + module_base ) ) - return false; +bool ctx_t::init() { + vm::util::init(); + if (!vm::util::flatten(vm_entry, vm_entry_rva + module_base)) return false; - vm::util::deobfuscate( vm_entry ); - if ( !vm::calc_jmp::get( vm_entry, calc_jmp ) ) - return false; + vm::util::deobfuscate(vm_entry); + if (!vm::calc_jmp::get(vm_entry, calc_jmp)) return false; - if ( auto vm_handler_table = vm::handler::table::get( vm_entry ); - !vm::handler::get_all( module_base, image_base, vm_entry, vm_handler_table, vm_handlers ) ) - return false; + if (auto vm_handler_table = vm::handler::table::get(vm_entry); + !vm::handler::get_all(module_base, image_base, vm_entry, vm_handler_table, + vm_handlers)) + return false; - if ( auto advancement = vm::calc_jmp::get_advancement( calc_jmp ); advancement.has_value() ) - exec_type = advancement.value(); - else - return false; + if (auto advancement = vm::calc_jmp::get_advancement(calc_jmp); + advancement.has_value()) + exec_type = advancement.value(); + else + return false; - return true; - } -} // namespace vm \ No newline at end of file + return true; +} +} // namespace vm \ No newline at end of file diff --git a/src/vmutils.cpp b/src/vmutils.cpp index 533ea0b..8670a0d 100644 --- a/src/vmutils.cpp +++ b/src/vmutils.cpp @@ -60,21 +60,16 @@ std::optional get_fetch_operand( void print(const zydis_decoded_instr_t &instr) { char buffer[256]; - ZydisFormatter formatter; - ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); - ZydisFormatterFormatInstruction(&formatter, &instr, buffer, sizeof(buffer), - 0u); + ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer, + sizeof(buffer), 0u); std::puts(buffer); } void print(zydis_routine_t &routine) { char buffer[256]; - ZydisFormatter formatter; - ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); - for (auto [instr, raw, addr] : routine) { - ZydisFormatterFormatInstruction(&formatter, &instr, buffer, sizeof(buffer), - addr); + ZydisFormatterFormatInstruction(vm::util::g_formatter.get(), &instr, buffer, + sizeof(buffer), addr); std::printf("> %p %s\n", addr, buffer); } } @@ -87,15 +82,12 @@ bool is_jmp(const zydis_decoded_instr_t &instr) { bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps, std::uint32_t max_instrs, std::uintptr_t module_base) { - ZydisDecoder decoder; zydis_decoded_instr_t instr; - - ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, - ZYDIS_ADDRESS_WIDTH_64); - std::uint32_t instr_cnt = 0u; + while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer( - &decoder, reinterpret_cast(routine_addr), 0x1000, &instr))) { + vm::util::g_decoder.get(), reinterpret_cast(routine_addr), 0x1000, + &instr))) { if (++instr_cnt > max_instrs) return false; // detect if we have already been at this instruction... if so that means // there is a loop and we are going to just return... @@ -116,9 +108,9 @@ bool flatten(zydis_routine_t &routine, std::uintptr_t routine_addr, } if (keep_jmps) routine.push_back({instr, raw_instr, routine_addr}); - ZydisCalcAbsoluteAddress(&instr, &instr.operands[0], routine_addr, &routine_addr); + } else if (instr.mnemonic == ZYDIS_MNEMONIC_RET) { routine.push_back({instr, raw_instr, routine_addr}); return true;