From 31f934cfb7cf57ae2c98db2eefe5aa0160b3b34b Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 9 Jun 2021 23:24:50 -0700 Subject: [PATCH 01/20] cleaned the code a bunch, preparing for doxygen... --- include/calc_jmp.hpp | 12 + include/transform.hpp | 2 +- include/vmctx.hpp | 20 ++ include/vmhandlers.hpp | 38 ++++ include/vminstrs.hpp | 69 ++++++ include/vmp2.hpp | 87 +++++++- include/vmprofiler.hpp | 343 +---------------------------- include/vmprofiles.hpp | 138 ++++++++++++ include/{vmutils.h => vmutils.hpp} | 8 + src/calc_jmp.cpp | 41 ++-- src/vmhandler.cpp | 66 ++---- src/vminstrs.cpp | 30 +-- src/vmprofiles/add.cpp | 2 +- src/vmprofiles/call.cpp | 2 +- src/vmprofiles/div.cpp | 2 +- src/vmprofiles/jmp.cpp | 2 +- src/vmprofiles/lconst.cpp | 2 +- src/vmprofiles/lflags.cpp | 2 +- src/vmprofiles/lreg.cpp | 2 +- src/vmprofiles/mul.cpp | 2 +- src/vmprofiles/nand.cpp | 2 +- src/vmprofiles/pushvsp.cpp | 2 +- src/vmprofiles/read.cpp | 2 +- src/vmprofiles/shl.cpp | 2 +- src/vmprofiles/shr.cpp | 2 +- src/vmprofiles/sreg.cpp | 2 +- src/vmprofiles/vmexit.cpp | 2 +- src/vmprofiles/write.cpp | 2 +- src/vmutils.cpp | 69 ++++-- vmprofiler.vcxproj | 7 +- vmprofiler.vcxproj.filters | 17 +- 31 files changed, 517 insertions(+), 462 deletions(-) create mode 100644 include/calc_jmp.hpp create mode 100644 include/vmctx.hpp create mode 100644 include/vmhandlers.hpp create mode 100644 include/vminstrs.hpp create mode 100644 include/vmprofiles.hpp rename include/{vmutils.h => vmutils.hpp} (81%) diff --git a/include/calc_jmp.hpp b/include/calc_jmp.hpp new file mode 100644 index 0000000..973efdf --- /dev/null +++ b/include/calc_jmp.hpp @@ -0,0 +1,12 @@ +#pragma once +#include +#include + +namespace vm +{ + namespace calc_jmp + { + bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ); + std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp ); + } // namespace calc_jmp +} // namespace vm \ No newline at end of file diff --git a/include/transform.hpp b/include/transform.hpp index 7ce3075..2bfe3c0 100644 --- a/include/transform.hpp +++ b/include/transform.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include namespace vm { diff --git a/include/vmctx.hpp b/include/vmctx.hpp new file mode 100644 index 0000000..e47403f --- /dev/null +++ b/include/vmctx.hpp @@ -0,0 +1,20 @@ +#pragma once +#include +#include +#include + +namespace vm +{ + class ctx_t + { + public: + explicit ctx_t( std::uintptr_t module_base, std::uintptr_t image_base, std::uintptr_t image_size, + std::uintptr_t vm_entry_rva ); + + bool init(); + const std::uintptr_t module_base, image_base, vm_entry_rva, image_size; + vmp2::exec_type_t exec_type; + zydis_routine_t vm_entry, calc_jmp; + std::vector< vm::handler::handler_t > vm_handlers; + }; +} // namespace vm \ No newline at end of file diff --git a/include/vmhandlers.hpp b/include/vmhandlers.hpp new file mode 100644 index 0000000..a2927bf --- /dev/null +++ b/include/vmhandlers.hpp @@ -0,0 +1,38 @@ +#pragma once +#include +#include + +namespace vm +{ + namespace handler + { + struct handler_t + { + u8 imm_size; // size in bits... + vm::transform::map_t transforms; + vm::handler::profile_t *profile; + zydis_routine_t instrs; + std::uintptr_t address; + }; + + bool has_imm( const zydis_routine_t &vm_handler ); + std::optional< std::uint8_t > imm_size( const zydis_routine_t &vm_handler ); + bool get( zydis_routine_t &vm_entry, zydis_routine_t &vm_handler, std::uintptr_t handler_addr ); + + bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry, + std::uintptr_t *vm_handler_table, std::vector< handler_t > &vm_handlers ); + + bool get_operand_transforms( zydis_routine_t &vm_handler, transform::map_t &transforms ); + vm::handler::profile_t *get_profile( handler_t &vm_handler ); + vm::handler::profile_t *get_profile( vm::handler::mnemonic_t mnemonic ); + + namespace table + { + std::uintptr_t *get( const zydis_routine_t &vm_entry ); + bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ); + + std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); + std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); + } // namespace table + } // namespace handler +} // namespace vm \ No newline at end of file diff --git a/include/vminstrs.hpp b/include/vminstrs.hpp new file mode 100644 index 0000000..8e98a28 --- /dev/null +++ b/include/vminstrs.hpp @@ -0,0 +1,69 @@ +#pragma once +#include +#include +#include +#include + +namespace vm +{ + namespace instrs + { + // decrypt transformations for encrypted virtual instruction rva... + bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs ); + + std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand, + std::uint64_t rolling_key ); + + std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand, + std::uint64_t rolling_key ); + + /// + /// get virt_instr_t filled in with data given a vmp2 trace entry and vm context... + /// + /// current vm context + /// vmp2 trace entry containing all of the native/virtual register/stack values... + /// returns a filled in virt_instr_t on success... + std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry ); + + /// + /// gets the second operand (imm) given vip and vm::ctx_t... + /// + /// vm context + /// immediate value size in bits... + /// virtual instruction pointer, linear virtual address... + /// returns immediate value if imm_size is not 0... + std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip ); + + /// + /// get jcc data out of a code block... this function will loop over the code block + /// and look for the last LCONSTDW in the virtual instructions. + /// + /// it will then loop and look for all PUSHVSP's, checking each to see if the stack + /// contains two encrypted rva's to each branch.. if there is not two encrypted rva's + /// then the virtual jmp instruction only has one dest... + /// + /// vm context + /// code block that does not have its jcc_data yet + /// if last lconstdw is found, return filled in jcc_data structure... + std::optional< jcc_data > get_jcc_data( vm::ctx_t &ctx, code_block_t &code_block ); + + /// + /// the top of the stack will contain the lower 32bits of the RVA to the virtual instructions + /// that will be jumping too... the RVA is image based (not module based, but optional header image + /// based)... this means the value ontop of the stack could be "40007fd8" with image base being + /// 0x140000000... as you can see the 0x100000000 is missing... the below statement deals with this... + /// + /// vm context + /// current trace entry for virtual JMP instruction + /// returns linear virtual address of the next code block... + std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry ); + + /// + /// same routine as above except lower_32bits is passed directly and not extracted from the stack... + /// + /// vm context + /// lower 32bits of the relative virtual address... + /// returns full linear virtual address of code block... + std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits ); + } // namespace instrs +} // namespace vm \ No newline at end of file diff --git a/include/vmp2.hpp b/include/vmp2.hpp index decdb85..02520d2 100644 --- a/include/vmp2.hpp +++ b/include/vmp2.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #define VMP_MAGIC '2PMV' namespace vmp2 @@ -139,4 +140,88 @@ namespace vmp2 } vsp; }; } // namespace v2 -} +} // namespace vmp2 + +namespace vm +{ + namespace instrs + { + struct virt_instr_t + { + vm::handler::mnemonic_t mnemonic_t; + std::uint8_t opcode; // aka vm handler idx... + + // can be used to look at values on the stack... + vmp2::v2::entry_t trace_data; + + struct + { + bool has_imm; + struct + { + std::uint8_t imm_size; // size in bits... + union + { + std::int64_t s; + std::uint64_t u; + }; + } imm; + } operand; + }; + + enum class jcc_type + { + none, + branching, + absolute + }; + + struct jcc_data + { + bool has_jcc; + jcc_type type; + std::uintptr_t block_addr[ 2 ]; + }; + + struct code_block_t + { + std::uintptr_t vip_begin; + jcc_data jcc; + std::vector< virt_instr_t > vinstrs; + }; + } // namespace instrs +} // namespace vm + +namespace vmp2 +{ + namespace v3 + { + struct file_header + { + u32 magic; // VMP2 + u64 epoch_time; + version_t version; + + u64 module_base; + u64 image_base; + u64 vm_entry_rva; + + u32 module_offset; + u32 module_size; + + u32 code_block_offset; + u32 code_block_count; + }; + + struct code_block_t + { + std::uintptr_t vip_begin; + std::uintptr_t next_block_offset; + vm::instrs::jcc_data jcc; + + // serialized from std::vector... + std::uint32_t vinstr_count; + vm::instrs::virt_instr_t vinstr[]; + }; + } // namespace v3 +} // namespace vmp2 diff --git a/include/vmprofiler.hpp b/include/vmprofiler.hpp index b1a5d9a..976d76f 100644 --- a/include/vmprofiler.hpp +++ b/include/vmprofiler.hpp @@ -1,340 +1,9 @@ #pragma once -#include #include +#include #include - -namespace vm -{ - namespace handler - { - using instr_callback_t = bool ( * )( const zydis_decoded_instr_t &instr ); - - enum mnemonic_t - { - INVALID, - LRFLAGS, - PUSHVSP, - MULQ, - DIVQ, - CALL, - JMP, - VMEXIT, - - SREGQ, - SREGDW, - SREGW, - - LREGQ, - LREGDW, - - LCONSTQ, - LCONSTBZXW, - LCONSTBSXQ, - LCONSTBSXDW, - LCONSTDWSXQ, - LCONSTWSXQ, - LCONSTWSXDW, - LCONSTDW, - LCONSTW, - - READQ, - READDW, - READW, - - WRITEQ, - WRITEDW, - WRITEW, - WRITEB, - - ADDQ, - ADDDW, - ADDW, - - SHLQ, - SHLDW, - - SHRQ, - SHRW, - - NANDQ, - NANDDW, - NANDW - }; - - enum extention_t - { - none, - sign_extend, - zero_extend - }; - - struct profile_t - { - const char *name; - mnemonic_t mnemonic; - u8 imm_size; - std::vector< instr_callback_t > signature; - extention_t extention; - }; - - struct handler_t - { - u8 imm_size; // size in bits... - vm::transform::map_t transforms; - vm::handler::profile_t *profile; - zydis_routine_t instrs; - std::uintptr_t address; - }; - - bool has_imm( const zydis_routine_t &vm_handler ); - std::uint8_t imm_size( const zydis_routine_t &vm_handler ); - bool get( zydis_routine_t &vm_entry, zydis_routine_t &vm_handler, std::uintptr_t handler_addr ); - - // may throw an exception... - bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry, - std::uintptr_t *vm_handler_table, std::vector< handler_t > &vm_handlers ); - - // can be used on calc_jmp... - bool get_operand_transforms( const zydis_routine_t &vm_handler, transform::map_t &transforms ); - vm::handler::profile_t *get_profile( handler_t &vm_handler ); - vm::handler::profile_t *get_profile( vm::handler::mnemonic_t mnemonic ); - - namespace table - { - std::uintptr_t *get( const zydis_routine_t &vm_entry ); - bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ); - - std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); - std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); - } // namespace table - - namespace profile - { - extern vm::handler::profile_t sregq; - extern vm::handler::profile_t sregdw; - extern vm::handler::profile_t sregw; - - extern vm::handler::profile_t lregq; - extern vm::handler::profile_t lregdw; - - extern vm::handler::profile_t lconstq; - extern vm::handler::profile_t lconstdw; - extern vm::handler::profile_t lconstw; - - extern vm::handler::profile_t lconstbzxw; - extern vm::handler::profile_t lconstbsxdw; - extern vm::handler::profile_t lconstbsxq; - extern vm::handler::profile_t lconstdwsxq; - extern vm::handler::profile_t lconstwsxq; - extern vm::handler::profile_t lconstwsxdw; - - extern vm::handler::profile_t addq; - extern vm::handler::profile_t adddw; - extern vm::handler::profile_t addw; - - extern vm::handler::profile_t shlq; - extern vm::handler::profile_t shldw; - - extern vm::handler::profile_t nandq; - extern vm::handler::profile_t nanddw; - extern vm::handler::profile_t nandw; - - extern vm::handler::profile_t writeq; - extern vm::handler::profile_t writedw; - extern vm::handler::profile_t writeb; - - extern vm::handler::profile_t readq; - extern vm::handler::profile_t readdw; - - extern vm::handler::profile_t shrq; - extern vm::handler::profile_t shrw; - - extern vm::handler::profile_t lrflags; - extern vm::handler::profile_t call; - extern vm::handler::profile_t pushvsp; - extern vm::handler::profile_t mulq; - extern vm::handler::profile_t divq; - extern vm::handler::profile_t jmp; - extern vm::handler::profile_t vmexit; - - inline std::vector< vm::handler::profile_t * > all = { - &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, &lconstbsxdw, - &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, &addq, &adddw, - &addw, - - &shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, &nandw, - - &shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq, &jmp, - &lrflags, &vmexit, &call }; - } // namespace profile - } // namespace handler - - class ctx_t - { - public: - explicit ctx_t( std::uintptr_t module_base, std::uintptr_t image_base, std::uintptr_t image_size, - std::uintptr_t vm_entry_rva ); - - bool init(); - const std::uintptr_t module_base, image_base, vm_entry_rva, image_size; - vmp2::exec_type_t exec_type; - zydis_routine_t vm_entry, calc_jmp; - std::vector< vm::handler::handler_t > vm_handlers; - }; -} // namespace vm - -namespace vm -{ - namespace instrs - { - struct virt_instr_t - { - vm::handler::mnemonic_t mnemonic_t; - std::uint8_t opcode; // aka vm handler idx... - - // can be used to look at values on the stack... - vmp2::v2::entry_t trace_data; - - struct - { - bool has_imm; - struct - { - std::uint8_t imm_size; // size in bits... - union - { - std::int64_t s; - std::uint64_t u; - }; - } imm; - } operand; - }; - - enum class jcc_type - { - none, - branching, - absolute - }; - - struct jcc_data - { - bool has_jcc; - jcc_type type; - std::uintptr_t block_addr[ 2 ]; - }; - - struct code_block_t - { - std::uintptr_t vip_begin; - jcc_data jcc; - std::vector< virt_instr_t > vinstrs; - }; - } // namespace instrs -} // namespace vm - -namespace vmp2 -{ - namespace v3 - { - struct file_header - { - u32 magic; // VMP2 - u64 epoch_time; - version_t version; - - u64 module_base; - u64 image_base; - u64 vm_entry_rva; - - u32 module_offset; - u32 module_size; - - u32 code_block_offset; - u32 code_block_count; - }; - - struct code_block_t - { - std::uintptr_t vip_begin; - std::uintptr_t next_block_offset; - vm::instrs::jcc_data jcc; - - // serialized from std::vector... - std::uint32_t vinstr_count; - vm::instrs::virt_instr_t vinstr[]; - }; - } // namespace v3 -} // namespace vmp2 - -namespace vm -{ - namespace instrs - { - // decrypt transformations for encrypted virtual instruction rva... - bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs ); - - std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand, - std::uint64_t rolling_key ); - - std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand, - std::uint64_t rolling_key ); - - /// - /// get virt_instr_t filled in with data given a vmp2 trace entry and vm context... - /// - /// current vm context - /// vmp2 trace entry containing all of the native/virtual register/stack values... - /// returns a filled in virt_instr_t on success... - std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry ); - - /// - /// gets the second operand (imm) given vip and vm::ctx_t... - /// - /// vm context - /// immediate value size in bits... - /// virtual instruction pointer, linear virtual address... - /// returns immediate value if imm_size is not 0... - std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip ); - - /// - /// get jcc data out of a code block... this function will loop over the code block - /// and look for the last two NANDW in the virtual instructions, then it will look - /// for the last LCONSTW which is the xor key... - /// - /// it will then loop and look for all PUSHVSP's, checking each to see if the stack - /// contains two encrypted rva's to each branch.. if there is not two encrypted rva's - /// then the virtual jmp instruction only has one dest... - /// - /// vm context - /// code block that does not have its jcc_data yet - /// if last lconstdw is found, return filled in jcc_data structure... - std::optional< jcc_data > get_jcc_data( vm::ctx_t &ctx, code_block_t &code_block ); - - /// - /// the top of the stack will contain the lower 32bits of the RVA to the virtual instructions - /// that will be jumping too... the RVA is image based (not module based, but optional header image - /// based)... this means the value ontop of the stack could be "40007fd8" with image base being - /// 0x140000000... as you can see the 0x100000000 is missing... the below statement deals with this... - /// - /// vm context - /// current trace entry for virtual JMP instruction - /// returns linear virtual address of the next code block... - std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry ); - - /// - /// same routine as above except lower_32bits is passed directly and not extracted from the stack... - /// - /// vm context - /// lower 32bits of the relative virtual address... - /// returns full linear virtual address of code block... - std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits ); - } // namespace instrs - - namespace calc_jmp - { - bool get( const zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ); - - std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp ); - } // namespace calc_jmp -} // namespace vm \ No newline at end of file +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/include/vmprofiles.hpp b/include/vmprofiles.hpp new file mode 100644 index 0000000..34d3d32 --- /dev/null +++ b/include/vmprofiles.hpp @@ -0,0 +1,138 @@ +#pragma once +#include + +namespace vm +{ + namespace handler + { + enum mnemonic_t + { + INVALID, + LRFLAGS, + PUSHVSP, + MULQ, + DIVQ, + CALL, + JMP, + VMEXIT, + + SREGQ, + SREGDW, + SREGW, + + LREGQ, + LREGDW, + + LCONSTQ, + LCONSTBZXW, + LCONSTBSXQ, + LCONSTBSXDW, + LCONSTDWSXQ, + LCONSTWSXQ, + LCONSTWSXDW, + LCONSTDW, + LCONSTW, + + READQ, + READDW, + READW, + + WRITEQ, + WRITEDW, + WRITEW, + WRITEB, + + ADDQ, + ADDDW, + ADDW, + + SHLQ, + SHLDW, + + SHRQ, + SHRW, + + NANDQ, + NANDDW, + NANDW + }; + + using zydis_callback_t = std::function; + + enum extention_t + { + none, + sign_extend, + zero_extend + }; + + struct profile_t + { + const char *name; + mnemonic_t mnemonic; + u8 imm_size; + std::vector< zydis_callback_t > signature; + extention_t extention; + }; + + namespace profile + { + extern vm::handler::profile_t sregq; + extern vm::handler::profile_t sregdw; + extern vm::handler::profile_t sregw; + + extern vm::handler::profile_t lregq; + extern vm::handler::profile_t lregdw; + + extern vm::handler::profile_t lconstq; + extern vm::handler::profile_t lconstdw; + extern vm::handler::profile_t lconstw; + + extern vm::handler::profile_t lconstbzxw; + extern vm::handler::profile_t lconstbsxdw; + extern vm::handler::profile_t lconstbsxq; + extern vm::handler::profile_t lconstdwsxq; + extern vm::handler::profile_t lconstwsxq; + extern vm::handler::profile_t lconstwsxdw; + + extern vm::handler::profile_t addq; + extern vm::handler::profile_t adddw; + extern vm::handler::profile_t addw; + + extern vm::handler::profile_t shlq; + extern vm::handler::profile_t shldw; + + extern vm::handler::profile_t nandq; + extern vm::handler::profile_t nanddw; + extern vm::handler::profile_t nandw; + + extern vm::handler::profile_t writeq; + extern vm::handler::profile_t writedw; + extern vm::handler::profile_t writeb; + + extern vm::handler::profile_t readq; + extern vm::handler::profile_t readdw; + + extern vm::handler::profile_t shrq; + extern vm::handler::profile_t shrw; + + extern vm::handler::profile_t lrflags; + extern vm::handler::profile_t call; + extern vm::handler::profile_t pushvsp; + extern vm::handler::profile_t mulq; + extern vm::handler::profile_t divq; + extern vm::handler::profile_t jmp; + extern vm::handler::profile_t vmexit; + + inline std::vector< vm::handler::profile_t * > all = { + &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, &lconstbsxdw, + &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, &addq, &adddw, + &addw, + + &shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, &nandw, + + &shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq, &jmp, + &lrflags, &vmexit, &call }; + } // namespace profile + } // namespace handler +} // namespace vm \ No newline at end of file diff --git a/include/vmutils.h b/include/vmutils.hpp similarity index 81% rename from include/vmutils.h rename to include/vmutils.hpp index 9a9bac0..a118b16 100644 --- a/include/vmutils.h +++ b/include/vmutils.hpp @@ -1,9 +1,14 @@ #pragma once #include #include + +#include #include #include +#define NOMINMAX +#include + using u8 = unsigned char; using u16 = unsigned short; using u32 = unsigned int; @@ -34,6 +39,9 @@ namespace vm bool compare( zydis_register_t a, zydis_register_t b ); } // namespace reg + bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ); + std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ); + void print( zydis_routine_t &routine ); void print( const zydis_decoded_instr_t &instr ); bool is_jmp( const zydis_decoded_instr_t &instr ); diff --git a/src/calc_jmp.cpp b/src/calc_jmp.cpp index e612da1..adbb115 100644 --- a/src/calc_jmp.cpp +++ b/src/calc_jmp.cpp @@ -4,25 +4,14 @@ namespace vm { namespace calc_jmp { - bool get( const zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ) + bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ) { - auto result = - std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { - // mov/movsx/movzx rax/eax/ax/al, [rsi] - return ( instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI ); - } ); + auto result = vm::util::get_fetch_operand( vm_entry ); - if ( result == vm_entry.end() ) + if ( !result.has_value() ) return false; - calc_jmp.insert( calc_jmp.end(), result, vm_entry.end() ); + calc_jmp.insert( calc_jmp.end(), result.value(), vm_entry.end() ); return true; } @@ -39,26 +28,26 @@ namespace vm if ( result == calc_jmp.end() ) return {}; - const auto instr = &result->instr; + const auto &instr = result->instr; - switch ( instr->mnemonic ) + switch ( instr.mnemonic ) { case ZYDIS_MNEMONIC_LEA: // if operand type is memory, then return advancement type // based off of the disposition value... (neg == backward, pos == forward) - if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY ) - return instr->operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward - : vmp2::exec_type_t::backward; + if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY ) + return instr.operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward + : vmp2::exec_type_t::backward; break; case ZYDIS_MNEMONIC_ADD: - if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) - return instr->operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward - : vmp2::exec_type_t::backward; + if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) + return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward + : vmp2::exec_type_t::backward; break; case ZYDIS_MNEMONIC_SUB: - if ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) - return instr->operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward - : vmp2::exec_type_t::forward; + if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) + return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward + : vmp2::exec_type_t::forward; break; case ZYDIS_MNEMONIC_INC: return vmp2::exec_type_t::forward; diff --git a/src/vmhandler.cpp b/src/vmhandler.cpp index 546785a..b745ef9 100644 --- a/src/vmhandler.cpp +++ b/src/vmhandler.cpp @@ -86,12 +86,13 @@ namespace vm const auto has_imm = vm::handler::has_imm( vm_handler_instrs ); const auto imm_size = vm::handler::imm_size( vm_handler_instrs ); - if ( has_imm && !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) ) + if ( has_imm && ( !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) || + !imm_size.has_value() ) ) return false; vm_handler.address = ( decrypt_val - image_base ) + module_base; vm_handler.instrs = vm_handler_instrs; - vm_handler.imm_size = imm_size; + vm_handler.imm_size = imm_size.value(); vm_handler.transforms = transforms; vm_handler.profile = vm::handler::get_profile( vm_handler ); vm_handlers.push_back( vm_handler ); @@ -102,65 +103,30 @@ namespace vm bool has_imm( const zydis_routine_t &vm_handler ) { - const auto result = - std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { - // mov/movsx/movzx rax/eax/ax/al, [rsi] - return instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; - } ); - - return result != vm_handler.end(); + zydis_instr_t instr_data; + return vm::util::get_fetch_operand( vm_handler, instr_data ); } - std::uint8_t imm_size( const zydis_routine_t &vm_handler ) + std::optional< std::uint8_t > imm_size( const zydis_routine_t &vm_handler ) { - const auto result = - std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { - // mov/movsx/movzx rax/eax/ax/al, [rsi] - return instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; - } ); + zydis_instr_t instr_data; + if ( !vm::util::get_fetch_operand( vm_handler, instr_data ) ) + return {}; - if ( result == vm_handler.end() ) - return 0u; - - return result->instr.operands[ 1 ].size; + return instr_data.instr.operands[ 1 ].size; } - bool get_operand_transforms( const zydis_routine_t &vm_handler, transform::map_t &transforms ) + bool get_operand_transforms( zydis_routine_t &vm_handler, transform::map_t &transforms ) { - auto imm_fetch = - std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { - // mov/movsx/movzx rax/eax/ax/al, [rsi] - return instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; - } ); + auto imm_fetch = vm::util::get_fetch_operand( vm_handler ); - if ( imm_fetch == vm_handler.end() ) + if ( !imm_fetch.has_value() ) return false; // this finds the first transformation which looks like: // transform rax, rbx <--- note these registers can be smaller so we to64 them... auto transform_instr = - std::find_if( imm_fetch, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { + std::find_if( imm_fetch.value(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { return vm::transform::valid( instr_data.instr.mnemonic ) && instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && @@ -171,7 +137,7 @@ namespace vm return false; // look for a primer/instruction that alters RAX prior to the 5 transformations... - auto generic0 = std::find_if( imm_fetch, transform_instr, []( const zydis_instr_t &instr_data ) -> bool { + auto generic0 = std::find_if( imm_fetch.value(), transform_instr, []( const zydis_instr_t &instr_data ) -> bool { return vm::transform::valid( instr_data.instr.mnemonic ) && instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && @@ -264,7 +230,7 @@ namespace vm if ( result == vm_entry.end() ) return nullptr; - std::uintptr_t ptr = 0u; + auto ptr = 0ull; ZydisCalcAbsoluteAddress( &result->instr, &result->instr.operands[ 1 ], result->addr, &ptr ); return reinterpret_cast< std::uintptr_t * >( ptr ); diff --git a/src/vminstrs.cpp b/src/vminstrs.cpp index 3301df3..fb241a5 100644 --- a/src/vminstrs.cpp +++ b/src/vminstrs.cpp @@ -50,10 +50,10 @@ namespace vm switch ( update_key.operands[ 0 ].size ) { case 8: - rolling_key = ( rolling_key & ~0xFFull ) + result; + rolling_key = ( rolling_key & ~std::numeric_limits< u8 >::max() ) + result; break; case 16: - rolling_key = ( rolling_key & ~0xFFFFull ) + result; + rolling_key = ( rolling_key & ~std::numeric_limits< u16 >::max() ) + result; break; default: rolling_key = result; @@ -79,14 +79,16 @@ namespace vm auto result = transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand ); - // make sure we update the rolling decryption key correctly... + // mov rax, al does not clear the top bits... + // mov rax, ax does not clear the top bits... + // mov rax, eax does clear the top bits... switch ( update_key.operands[ 0 ].size ) { case 8: - rolling_key = ( rolling_key & ~0xFFull ) + result; + rolling_key = ( rolling_key & ~std::numeric_limits< u8 >::max() ) + result; break; case 16: - rolling_key = ( rolling_key & ~0xFFFFull ) + result; + rolling_key = ( rolling_key & ~std::numeric_limits< u16 >::max() ) + result; break; default: rolling_key = result; @@ -163,11 +165,10 @@ namespace vm if ( !imm_size ) return {}; - std::uint64_t result = 0u; - if ( ctx.exec_type == vmp2::exec_type_t::forward ) - std::memcpy( &result, reinterpret_cast< void * >( vip ), imm_size / 8 ); - else // else the second operand is below vip... - std::memcpy( &result, reinterpret_cast< void * >( vip - ( imm_size / 8 ) ), imm_size / 8 ); + auto result = 0ull; + ctx.exec_type == vmp2::exec_type_t::forward + ? std::memcpy( &result, reinterpret_cast< void * >( vip ), imm_size / 8 ) + : std::memcpy( &result, reinterpret_cast< void * >( vip - ( imm_size / 8 ) ), imm_size / 8 ); return result; } @@ -181,6 +182,7 @@ namespace vm result.mnemonic_t = profile ? profile->mnemonic : vm::handler::INVALID; result.opcode = entry.handler_idx; result.trace_data = entry; + result.operand.has_imm = false; if ( vm_handler.imm_size ) { @@ -194,8 +196,6 @@ namespace vm result.operand.imm.u = vm::instrs::decrypt_operand( vm_handler.transforms, imm_val.value(), entry.decrypt_key ).first; } - else - result.operand.has_imm = false; return result; } @@ -266,12 +266,14 @@ namespace vm std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry ) { - return ( ( entry.vsp.qword[ 0 ] & 0xFFFFFFFFull ) - ( ctx.image_base & 0xFFFFFFFFull ) ) + ctx.module_base; + return ( ( entry.vsp.qword[ 0 ] & std::numeric_limits< u32 >::max() ) - + ( ctx.image_base & std::numeric_limits< u32 >::max() ) ) + + ctx.module_base; } std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits ) { - return ( lower_32bits - ( ctx.image_base & 0xFFFFFFFFull ) ) + ctx.module_base; + return ( lower_32bits - ( ctx.image_base & std::numeric_limits< u32 >::max() ) ) + ctx.module_base; } } // namespace instrs } // namespace vm \ No newline at end of file diff --git a/src/vmprofiles/add.cpp b/src/vmprofiles/add.cpp index 4d92c58..0700c81 100644 --- a/src/vmprofiles/add.cpp +++ b/src/vmprofiles/add.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/call.cpp b/src/vmprofiles/call.cpp index bb3af63..861c6d8 100644 --- a/src/vmprofiles/call.cpp +++ b/src/vmprofiles/call.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/div.cpp b/src/vmprofiles/div.cpp index e69c211..e459897 100644 --- a/src/vmprofiles/div.cpp +++ b/src/vmprofiles/div.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/jmp.cpp b/src/vmprofiles/jmp.cpp index dc2a94e..00d4298 100644 --- a/src/vmprofiles/jmp.cpp +++ b/src/vmprofiles/jmp.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/lconst.cpp b/src/vmprofiles/lconst.cpp index 9b7bbca..cd93080 100644 --- a/src/vmprofiles/lconst.cpp +++ b/src/vmprofiles/lconst.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/lflags.cpp b/src/vmprofiles/lflags.cpp index 5b84ef6..0317bea 100644 --- a/src/vmprofiles/lflags.cpp +++ b/src/vmprofiles/lflags.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/lreg.cpp b/src/vmprofiles/lreg.cpp index 265311d..93ccb9e 100644 --- a/src/vmprofiles/lreg.cpp +++ b/src/vmprofiles/lreg.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/mul.cpp b/src/vmprofiles/mul.cpp index d1a0cf9..29c22b3 100644 --- a/src/vmprofiles/mul.cpp +++ b/src/vmprofiles/mul.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/nand.cpp b/src/vmprofiles/nand.cpp index 0fbcec0..b92a051 100644 --- a/src/vmprofiles/nand.cpp +++ b/src/vmprofiles/nand.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/pushvsp.cpp b/src/vmprofiles/pushvsp.cpp index 2995c7f..5206bd4 100644 --- a/src/vmprofiles/pushvsp.cpp +++ b/src/vmprofiles/pushvsp.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/read.cpp b/src/vmprofiles/read.cpp index 31fc822..632cbd7 100644 --- a/src/vmprofiles/read.cpp +++ b/src/vmprofiles/read.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/shl.cpp b/src/vmprofiles/shl.cpp index 939507f..57bb435 100644 --- a/src/vmprofiles/shl.cpp +++ b/src/vmprofiles/shl.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/shr.cpp b/src/vmprofiles/shr.cpp index 610e2f7..41f1f78 100644 --- a/src/vmprofiles/shr.cpp +++ b/src/vmprofiles/shr.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/sreg.cpp b/src/vmprofiles/sreg.cpp index 294f736..8380479 100644 --- a/src/vmprofiles/sreg.cpp +++ b/src/vmprofiles/sreg.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/vmexit.cpp b/src/vmprofiles/vmexit.cpp index 1183fc0..76e1791 100644 --- a/src/vmprofiles/vmexit.cpp +++ b/src/vmprofiles/vmexit.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmprofiles/write.cpp b/src/vmprofiles/write.cpp index bf0b7ff..5041a29 100644 --- a/src/vmprofiles/write.cpp +++ b/src/vmprofiles/write.cpp @@ -1,4 +1,4 @@ -#include "../../include/vmprofiler.hpp" +#include namespace vm { diff --git a/src/vmutils.cpp b/src/vmutils.cpp index 432bbbc..85cb779 100644 --- a/src/vmutils.cpp +++ b/src/vmutils.cpp @@ -1,5 +1,4 @@ -#include "vmutils.h" -#include +#include namespace vm { @@ -18,13 +17,55 @@ namespace vm } } // namespace reg + bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ) + { + const auto result = + std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool { + // mov/movsx/movzx rax/eax/ax/al, [rsi] + return instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && + instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; + } ); + + if ( result == routine.end() ) + return false; + + fetch_instr = *result; + return true; + } + + std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ) + { + auto result = std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool { + // mov/movsx/movzx rax/eax/ax/al, [rsi] + return instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && + instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; + } ); + + if ( result == routine.end() ) + return {}; + + return result; + } + 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 ); - puts( buffer ); + std::puts( buffer ); } void print( zydis_routine_t &routine ) @@ -35,9 +76,8 @@ namespace vm for ( auto [ instr, raw, addr ] : routine ) { - std::printf( "> 0x%p ", addr ); ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); - puts( buffer ); + std::printf( "> 0x%p %s", addr, buffer ); } } @@ -83,10 +123,10 @@ namespace vm while ( ZYAN_SUCCESS( ZydisDecoderDecodeBuffer( &decoder, reinterpret_cast< void * >( routine_addr ), 0x1000, &instr ) ) ) { - // detect if we have already been at this instruction... if so that means there is a loop and we are going - // to just return... - if (std::find_if( routine.begin(), routine.end(), [ & ]( const zydis_instr_t &zydis_instr ) -> bool { - return zydis_instr.addr == routine_addr; + // detect if we have already been at this instruction... if so that means there is a loop and we are + // going to just return... + if ( std::find_if( routine.begin(), routine.end(), [ & ]( const zydis_instr_t &zydis_instr ) -> bool { + return zydis_instr.addr == routine_addr; } ) != routine.end() ) return true; @@ -133,8 +173,9 @@ namespace vm { return reg::compare( op.reg.value, reg ); } + default: + break; } - return false; }; @@ -151,7 +192,7 @@ namespace vm for ( ; itr >= routine.begin(); --itr ) { const auto instruction = &itr->instr; - bool stop = false; + auto stop = false; if ( instruction->mnemonic == ZYDIS_MNEMONIC_JMP ) continue; @@ -172,10 +213,8 @@ namespace vm if ( opcode_size < 32 && op->size > opcode_size ) continue; - if ( op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE ) - op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE; - else - stop = true; + op->actions &ZYDIS_OPERAND_ACTION_MASK_WRITE ? op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE + : stop = true; } if ( !_writes( *instruction ) ) diff --git a/vmprofiler.vcxproj b/vmprofiler.vcxproj index e357f76..e3f447f 100644 --- a/vmprofiler.vcxproj +++ b/vmprofiler.vcxproj @@ -146,10 +146,15 @@ + + + + - + + diff --git a/vmprofiler.vcxproj.filters b/vmprofiler.vcxproj.filters index 7c02f19..f07da1c 100644 --- a/vmprofiler.vcxproj.filters +++ b/vmprofiler.vcxproj.filters @@ -164,7 +164,22 @@ Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files From 099a7e9c58f0ea5be364b3bc41045f3af921a564 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 9 Jun 2021 19:45:12 -0700 Subject: [PATCH 02/20] added vtil to the project --- .gitmodules | 3 +++ dependencies/vtil | 1 + 2 files changed, 4 insertions(+) create mode 160000 dependencies/vtil diff --git a/.gitmodules b/.gitmodules index 88e35ec..a7910d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "dependencies/zydis"] path = dependencies/zydis url = https://github.com/zyantific/zydis.git +[submodule "dependencies/vtil"] + path = dependencies/vtil + url = https://githacks.org/_xeroxz/vtil.git diff --git a/dependencies/vtil b/dependencies/vtil new file mode 160000 index 0000000..e9dc43b --- /dev/null +++ b/dependencies/vtil @@ -0,0 +1 @@ +Subproject commit e9dc43bd7da388c5f8304407fd076f802bd97a7f From 08635457a776d4bd142367eabe9b486d47649f24 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 9 Jun 2021 22:39:38 -0700 Subject: [PATCH 03/20] still adding doxygen comments... --- include/calc_jmp.hpp | 25 ++- include/transform.hpp | 457 ++++++++++++++++++++++----------------- include/vmctx.hpp | 29 ++- include/vmhandlers.hpp | 161 +++++++++++--- include/vminstrs.hpp | 131 ++++++----- include/vmprofiles.hpp | 303 ++++++++++++++------------ include/vmutils.hpp | 37 ++-- src/vminstrs.cpp | 477 ++++++++++++++++++++--------------------- 8 files changed, 936 insertions(+), 684 deletions(-) diff --git a/include/calc_jmp.hpp b/include/calc_jmp.hpp index 973efdf..5df23f6 100644 --- a/include/calc_jmp.hpp +++ b/include/calc_jmp.hpp @@ -2,11 +2,22 @@ #include #include -namespace vm +namespace vm::calc_jmp { - namespace calc_jmp - { - bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ); - std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp ); - } // namespace calc_jmp -} // namespace vm \ No newline at end of file + /// + /// extracts calc_jmp out of vm_entry... you can learn about calc_jmp here. + /// + /// pass by reference vm entry... + /// zydis_routine_t filled up with native instructions by this routine... + /// returns truee if no errors happen... + bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ); + + /// + /// gets the advancement of the virtual instruction pointer... iterates over calc_jmp for LEA, MOV, INC, DEC, SUB, + /// ADD, ETC instructions and then decides which way VIP advances based upon this information... + /// + /// + /// + std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp ); +} // namespace vm::calc_jmp \ No newline at end of file diff --git a/include/transform.hpp b/include/transform.hpp index 2bfe3c0..e754c63 100644 --- a/include/transform.hpp +++ b/include/transform.hpp @@ -5,215 +5,282 @@ #include #include -namespace vm +namespace vm::transform { - namespace transform + /// + /// rotate left template function take from IDA SDK... + /// + /// type of data to rotate left... + /// value to rotate left + /// number of bits to rotate left... + /// returns the rotated value... + template < class T > inline T __ROL__( T value, int count ) { - // taken from ida... - template < class T > inline T __ROL__( T value, int count ) - { - const unsigned int nbits = sizeof( T ) * 8; - - if ( count > 0 ) - { - count %= nbits; - T high = value >> ( nbits - count ); - if ( T( -1 ) < 0 ) // signed value - high &= ~( ( T( -1 ) << count ) ); - value <<= count; - value |= high; - } - else - { - count = -count % nbits; - T low = value << ( nbits - count ); - value >>= count; - value |= low; - } - return value; - } + const unsigned int nbits = sizeof( T ) * 8; - // taken from ida... - inline u8 __ROL1__( u8 value, int count ) - { - return __ROL__( ( u8 )value, count ); - } - inline u16 __ROL2__( u16 value, int count ) - { - return __ROL__( ( u16 )value, count ); - } - inline u32 __ROL4__( u32 value, int count ) + if ( count > 0 ) { - return __ROL__( ( u32 )value, count ); + count %= nbits; + T high = value >> ( nbits - count ); + if ( T( -1 ) < 0 ) // signed value + high &= ~( ( T( -1 ) << count ) ); + value <<= count; + value |= high; } - inline u64 __ROL8__( u64 value, int count ) + else { - return __ROL__( ( u64 )value, count ); + count = -count % nbits; + T low = value << ( nbits - count ); + value >>= count; + value |= low; } - inline u8 __ROR1__( u8 value, int count ) - { - return __ROL__( ( u8 )value, -count ); - } - inline u16 __ROR2__( u16 value, int count ) - { - return __ROL__( ( u16 )value, -count ); - } - inline u32 __ROR4__( u32 value, int count ) - { - return __ROL__( ( u32 )value, -count ); - } - inline u64 __ROR8__( u64 value, int count ) - { - return __ROL__( ( u64 )value, -count ); - } - - template < typename T > using transform_t = std::function< T( T, T ) >; - - enum class type - { - generic0, - rolling_key, - generic1, - generic2, - generic3, - update_key - }; - - using map_t = std::map< transform::type, zydis_decoded_instr_t >; - - template < class T > - inline const auto _bswap = []( T a, T b ) -> T { - if constexpr ( std::is_same_v< T, std::uint64_t > ) - return _byteswap_uint64( a ); - if constexpr ( std::is_same_v< T, std::uint32_t > ) - return _byteswap_ulong( a ); - if constexpr ( std::is_same_v< T, std::uint16_t > ) - return _byteswap_ushort( a ); - - throw std::invalid_argument( "invalid type size..." ); - }; - - template < class T > inline const auto _add = []( T a, T b ) -> T { return a + b; }; - - template < class T > inline const auto _xor = []( T a, T b ) -> T { return a ^ b; }; - - template < class T > inline const auto _sub = []( T a, T b ) -> T { return a - b; }; - - template < class T > inline const auto _neg = []( T a, T b ) -> T { return a * -1; }; - - template < class T > inline const auto _not = []( T a, T b ) -> T { return ~a; }; - - template < class T > - inline const auto _ror = []( T a, T b ) -> T { - if constexpr ( std::is_same_v< T, std::uint64_t > ) - return __ROR8__( a, b ); - if constexpr ( std::is_same_v< T, std::uint32_t > ) - return __ROR4__( a, b ); - if constexpr ( std::is_same_v< T, std::uint16_t > ) - return __ROR2__( a, b ); - if constexpr ( std::is_same_v< T, std::uint8_t > ) - return __ROR1__( a, b ); - - throw std::invalid_argument( "invalid type size..." ); - }; - - template < class T > - inline const auto _rol = []( T a, T b ) -> T { - if constexpr ( std::is_same_v< T, std::uint64_t > ) - return __ROL8__( a, b ); - if constexpr ( std::is_same_v< T, std::uint32_t > ) - return __ROL4__( a, b ); - if constexpr ( std::is_same_v< T, std::uint16_t > ) - return __ROL2__( a, b ); - if constexpr ( std::is_same_v< T, std::uint8_t > ) - return __ROL1__( a, b ); - - throw std::invalid_argument( "invalid type size..." ); - }; - - template < class T > inline const auto _inc = []( T a, T b ) -> T { return a + 1; }; - - template < class T > inline const auto _dec = []( T a, T b ) -> T { return a - 1; }; - - template < class T > - inline std::map< zydis_mnemonic_t, transform_t< T > > transforms = { - { ZYDIS_MNEMONIC_ADD, _add< T > }, { ZYDIS_MNEMONIC_XOR, _xor< T > }, { ZYDIS_MNEMONIC_BSWAP, _bswap< T > }, - { ZYDIS_MNEMONIC_SUB, _sub< T > }, { ZYDIS_MNEMONIC_NEG, _neg< T > }, { ZYDIS_MNEMONIC_NOT, _not< T > }, - { ZYDIS_MNEMONIC_ROR, _ror< T > }, { ZYDIS_MNEMONIC_ROL, _rol< T > }, { ZYDIS_MNEMONIC_INC, _inc< T > }, - { ZYDIS_MNEMONIC_DEC, _dec< T > } }; - - inline std::map< zydis_mnemonic_t, zydis_mnemonic_t > inverse = { - { ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_SUB }, { ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR }, - { ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP }, { ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD }, - { ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NEG }, { ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT }, - { ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR }, - { ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC }, { ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC } }; - - inline bool valid( zydis_mnemonic_t op ) - { - return transforms< std::uint64_t >.find( op ) != transforms< std::uint64_t >.end(); - } - - inline void inverse_transforms( transform::map_t &transforms, transform::map_t &inverse ) - { - inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ]; - inverse[ transform::type::generic0 ].mnemonic = - transform::inverse[ transforms[ transform::type::generic0 ].mnemonic ]; - - inverse[ transform::type::rolling_key ] = transforms[ transform::type::rolling_key ]; - inverse[ transform::type::rolling_key ].mnemonic = - transform::inverse[ transforms[ transform::type::rolling_key ].mnemonic ]; + return value; + } + + /// + /// rotate left a one byte value... + /// + /// byte value + /// number of bits to rotate + /// return rotated value... + inline u8 __ROL1__( u8 value, int count ) + { + return __ROL__( ( u8 )value, count ); + } + + /// + /// rotate left a two byte value... + /// + /// two byte value to rotate... + /// number of bits to rotate... + /// return rotated value... + inline u16 __ROL2__( u16 value, int count ) + { + return __ROL__( ( u16 )value, count ); + } + + /// + /// rotate left a four byte value... + /// + /// four byte value to rotate... + /// number of bits to shift... + /// return rotated value... + inline u32 __ROL4__( u32 value, int count ) + { + return __ROL__( ( u32 )value, count ); + } + + /// + /// rotate left an eight byte value... + /// + /// eight byte value... + /// number of bits to shift... + /// return rotated value... + inline u64 __ROL8__( u64 value, int count ) + { + return __ROL__( ( u64 )value, count ); + } + + /// + /// rotate right a one byte value... + /// + /// one byte value... + /// number of bits to shift... + /// return rotated value... + inline u8 __ROR1__( u8 value, int count ) + { + return __ROL__( ( u8 )value, -count ); + } + + /// + /// rotate right a two byte value... + /// + /// two byte value to rotate... + /// number of bits to shift... + /// + inline u16 __ROR2__( u16 value, int count ) + { + return __ROL__( ( u16 )value, -count ); + } + + /// + /// rotate right a four byte value... + /// + /// four byte value to rotate... + /// number of bits to rotate... + /// return rotated value... + inline u32 __ROR4__( u32 value, int count ) + { + return __ROL__( ( u32 )value, -count ); + } + + /// + /// rotate right an eight byte value... + /// + /// eight byte value + /// number of bits to rotate... + /// return rotated value... + inline u64 __ROR8__( u64 value, int count ) + { + return __ROL__( ( u64 )value, -count ); + } + + /// + /// transform function, such as ADD, SUB, BSWAP... etc... + /// + /// returns the transform result... + template < typename T > using transform_t = std::function< T( T, T ) >; + + /// + /// type of transformation... + /// + enum class type + { + generic0, + rolling_key, + generic1, + generic2, + generic3, + update_key + }; + + /// + /// map of transform type to zydis decoded instruction of the transform... + /// + using map_t = std::map< transform::type, zydis_decoded_instr_t >; + + template < class T > + inline const auto _bswap = []( T a, T b ) -> T { + if constexpr ( std::is_same_v< T, std::uint64_t > ) + return _byteswap_uint64( a ); + if constexpr ( std::is_same_v< T, std::uint32_t > ) + return _byteswap_ulong( a ); + if constexpr ( std::is_same_v< T, std::uint16_t > ) + return _byteswap_ushort( a ); + + throw std::invalid_argument( "invalid type size..." ); + }; + + template < class T > inline const auto _add = []( T a, T b ) -> T { return a + b; }; + + template < class T > inline const auto _xor = []( T a, T b ) -> T { return a ^ b; }; + + template < class T > inline const auto _sub = []( T a, T b ) -> T { return a - b; }; + + template < class T > inline const auto _neg = []( T a, T b ) -> T { return a * -1; }; + + template < class T > inline const auto _not = []( T a, T b ) -> T { return ~a; }; + + template < class T > + inline const auto _ror = []( T a, T b ) -> T { + if constexpr ( std::is_same_v< T, std::uint64_t > ) + return __ROR8__( a, b ); + if constexpr ( std::is_same_v< T, std::uint32_t > ) + return __ROR4__( a, b ); + if constexpr ( std::is_same_v< T, std::uint16_t > ) + return __ROR2__( a, b ); + if constexpr ( std::is_same_v< T, std::uint8_t > ) + return __ROR1__( a, b ); + + throw std::invalid_argument( "invalid type size..." ); + }; + + template < class T > + inline const auto _rol = []( T a, T b ) -> T { + if constexpr ( std::is_same_v< T, std::uint64_t > ) + return __ROL8__( a, b ); + if constexpr ( std::is_same_v< T, std::uint32_t > ) + return __ROL4__( a, b ); + if constexpr ( std::is_same_v< T, std::uint16_t > ) + return __ROL2__( a, b ); + if constexpr ( std::is_same_v< T, std::uint8_t > ) + return __ROL1__( a, b ); + + throw std::invalid_argument( "invalid type size..." ); + }; + + template < class T > inline const auto _inc = []( T a, T b ) -> T { return a + 1; }; + + template < class T > inline const auto _dec = []( T a, T b ) -> T { return a - 1; }; + + template < class T > + inline std::map< zydis_mnemonic_t, transform_t< T > > transforms = { + { ZYDIS_MNEMONIC_ADD, _add< T > }, { ZYDIS_MNEMONIC_XOR, _xor< T > }, { ZYDIS_MNEMONIC_BSWAP, _bswap< T > }, + { ZYDIS_MNEMONIC_SUB, _sub< T > }, { ZYDIS_MNEMONIC_NEG, _neg< T > }, { ZYDIS_MNEMONIC_NOT, _not< T > }, + { ZYDIS_MNEMONIC_ROR, _ror< T > }, { ZYDIS_MNEMONIC_ROL, _rol< T > }, { ZYDIS_MNEMONIC_INC, _inc< T > }, + { ZYDIS_MNEMONIC_DEC, _dec< T > } }; + + inline std::map< zydis_mnemonic_t, zydis_mnemonic_t > inverse = { + { ZYDIS_MNEMONIC_ADD, ZYDIS_MNEMONIC_SUB }, { ZYDIS_MNEMONIC_XOR, ZYDIS_MNEMONIC_XOR }, + { ZYDIS_MNEMONIC_BSWAP, ZYDIS_MNEMONIC_BSWAP }, { ZYDIS_MNEMONIC_SUB, ZYDIS_MNEMONIC_ADD }, + { ZYDIS_MNEMONIC_NEG, ZYDIS_MNEMONIC_NEG }, { ZYDIS_MNEMONIC_NOT, ZYDIS_MNEMONIC_NOT }, + { ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR }, + { ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC }, { ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC } }; + + inline bool valid( zydis_mnemonic_t op ) + { + return transforms< std::uint64_t >.find( op ) != transforms< std::uint64_t >.end(); + } - inverse[ transform::type::generic1 ] = transforms[ transform::type::generic1 ]; - inverse[ transform::type::generic1 ].mnemonic = - transform::inverse[ transforms[ transform::type::generic1 ].mnemonic ]; + inline void inverse_transforms( transform::map_t &transforms, transform::map_t &inverse ) + { + inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ]; + inverse[ transform::type::generic0 ].mnemonic = + transform::inverse[ transforms[ transform::type::generic0 ].mnemonic ]; - inverse[ transform::type::generic2 ] = transforms[ transform::type::generic2 ]; - inverse[ transform::type::generic2 ].mnemonic = - transform::inverse[ transforms[ transform::type::generic2 ].mnemonic ]; + inverse[ transform::type::rolling_key ] = transforms[ transform::type::rolling_key ]; + inverse[ transform::type::rolling_key ].mnemonic = + transform::inverse[ transforms[ transform::type::rolling_key ].mnemonic ]; - inverse[ transform::type::generic3 ] = transforms[ transform::type::generic3 ]; - inverse[ transform::type::generic3 ].mnemonic = - transform::inverse[ transforms[ transform::type::generic3 ].mnemonic ]; + inverse[ transform::type::generic1 ] = transforms[ transform::type::generic1 ]; + inverse[ transform::type::generic1 ].mnemonic = + transform::inverse[ transforms[ transform::type::generic1 ].mnemonic ]; - inverse[ transform::type::update_key ] = transforms[ transform::type::update_key ]; - inverse[ transform::type::update_key ].mnemonic = - transform::inverse[ transforms[ transform::type::update_key ].mnemonic ]; - } + inverse[ transform::type::generic2 ] = transforms[ transform::type::generic2 ]; + inverse[ transform::type::generic2 ].mnemonic = + transform::inverse[ transforms[ transform::type::generic2 ].mnemonic ]; - inline auto inverse_transforms( std::vector< zydis_decoded_instr_t > &instrs ) -> bool - { - for ( auto idx = 0u; idx < instrs.size(); idx++ ) - if ( !( instrs[ idx ].mnemonic = inverse[ instrs[ idx ].mnemonic ] ) ) - return false; + inverse[ transform::type::generic3 ] = transforms[ transform::type::generic3 ]; + inverse[ transform::type::generic3 ].mnemonic = + transform::inverse[ transforms[ transform::type::generic3 ].mnemonic ]; - std::reverse( instrs.begin(), instrs.end() ); - return true; - } + inverse[ transform::type::update_key ] = transforms[ transform::type::update_key ]; + inverse[ transform::type::update_key ].mnemonic = + transform::inverse[ transforms[ transform::type::update_key ].mnemonic ]; + } - // max size of a and b is 64 bits, a and b is then converted to - // the number of bits in bitsize, the transformation is applied, - // finally the result is converted back to 64bits... zero extended... - inline auto apply( std::uint8_t bitsize, ZydisMnemonic op, std::uint64_t a, std::uint64_t b ) -> std::uint64_t + inline auto inverse_transforms( std::vector< zydis_decoded_instr_t > &instrs ) -> bool + { + for ( auto idx = 0u; idx < instrs.size(); idx++ ) + if ( !( instrs[ idx ].mnemonic = inverse[ instrs[ idx ].mnemonic ] ) ) + return false; + + std::reverse( instrs.begin(), instrs.end() ); + return true; + } + + // max size of a and b is 64 bits, a and b is then converted to + // the number of bits in bitsize, the transformation is applied, + // finally the result is converted back to 64bits... zero extended... + inline auto apply( std::uint8_t bitsize, ZydisMnemonic op, std::uint64_t a, std::uint64_t b ) -> std::uint64_t + { + switch ( bitsize ) { - switch ( bitsize ) - { - case 8: - return transforms< std::uint8_t >[ op ]( a, b ); - case 16: - return transforms< std::uint16_t >[ op ]( a, b ); - case 32: - return transforms< std::uint32_t >[ op ]( a, b ); - case 64: - return transforms< std::uint64_t >[ op ]( a, b ); - default: - throw std::invalid_argument( "invalid bit size..." ); - } + case 8: + return transforms< std::uint8_t >[ op ]( a, b ); + case 16: + return transforms< std::uint16_t >[ op ]( a, b ); + case 32: + return transforms< std::uint32_t >[ op ]( a, b ); + case 64: + return transforms< std::uint64_t >[ op ]( a, b ); + default: + throw std::invalid_argument( "invalid bit size..." ); } + } - inline bool has_imm( const zydis_decoded_instr_t *instr ) - { - return instr->operand_count > 1 && ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ); - } - } // namespace transform -} // namespace vm \ No newline at end of file + inline bool has_imm( const zydis_decoded_instr_t *instr ) + { + return instr->operand_count > 1 && ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ); + } +} // namespace vm::transform \ No newline at end of file diff --git a/include/vmctx.hpp b/include/vmctx.hpp index e47403f..ea7c174 100644 --- a/include/vmctx.hpp +++ b/include/vmctx.hpp @@ -1,20 +1,47 @@ #pragma once #include -#include #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 ); + /// + /// 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; + + /// + /// 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 diff --git a/include/vmhandlers.hpp b/include/vmhandlers.hpp index a2927bf..ae59ebe 100644 --- a/include/vmhandlers.hpp +++ b/include/vmhandlers.hpp @@ -2,37 +2,134 @@ #include #include -namespace vm +namespace vm::handler { - namespace handler + /// + /// handler_t contains all the information for a vm handler such as its immidate value size (zero if there is no + /// imm), the transformations applied to the imm to decrypt it (if any), a pointer to the profile (nullptr if + /// there is none), and other meta data... + /// + struct handler_t { - struct handler_t - { - u8 imm_size; // size in bits... - vm::transform::map_t transforms; - vm::handler::profile_t *profile; - zydis_routine_t instrs; - std::uintptr_t address; - }; - - bool has_imm( const zydis_routine_t &vm_handler ); - std::optional< std::uint8_t > imm_size( const zydis_routine_t &vm_handler ); - bool get( zydis_routine_t &vm_entry, zydis_routine_t &vm_handler, std::uintptr_t handler_addr ); - - bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry, - std::uintptr_t *vm_handler_table, std::vector< handler_t > &vm_handlers ); - - bool get_operand_transforms( zydis_routine_t &vm_handler, transform::map_t &transforms ); - vm::handler::profile_t *get_profile( handler_t &vm_handler ); - vm::handler::profile_t *get_profile( vm::handler::mnemonic_t mnemonic ); - - namespace table - { - std::uintptr_t *get( const zydis_routine_t &vm_entry ); - bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ); - - std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); - std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); - } // namespace table - } // namespace handler -} // namespace vm \ No newline at end of file + /// + /// imm size in bits, zero if no imm... + /// + u8 imm_size; + + /// + /// transformations to decrypt imm... + /// + vm::transform::map_t transforms; + + /// + /// pointer to the profile, nullptr if none... + /// + vm::handler::profile_t *profile; + + /// + /// native instructions of the vm handler... (calc_jmp/check_vsp is removed from this)... + /// + zydis_routine_t instrs; + + /// + /// linear virtual address to the vm handler... + /// + std::uintptr_t address; + }; + + /// + /// given a vm handler returns true if the vm handler decrypts an operand... + /// + /// const reference to a vm handler... + /// returns true if the vm handler decrypts an operand, else false... + bool has_imm( const zydis_routine_t &vm_handler ); + + /// + /// gets the imm size of a vm handler... + /// + /// const reference to a vm handler... + /// returns the imm size, otherwise returns an empty optional value... + std::optional< std::uint8_t > imm_size( const zydis_routine_t &vm_handler ); + + /// + /// gets a vm handler, puts all of the native instructions inside of the vm_handler param... + /// + /// reference to a zydis_routine_t containing the native instructions of a vm + /// entry... reference to a zydis_routine_t that will get filled with the + /// native instructions of the vm handler... linear virtual address to the + /// first instruction of the vm handler... returns true if the native instructions of the vm + /// handler was extracted... + bool get( zydis_routine_t &vm_entry, zydis_routine_t &vm_handler, std::uintptr_t handler_addr ); + + /// + /// get all 256 vm handlers... + /// + /// linear virtual address of the module base... + /// image base from optional nt header... IMAGE_OPTIONAL_HEADER64... + /// zydis_routine_t containing the deobfuscated and flattened vm entry native + /// instructions... linear virtual address to the vm handler + /// table... vector of handler_t's that will be filled with the vm + /// handlers... returns true if all vm handlers were extracted, else false... + bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry, + std::uintptr_t *vm_handler_table, std::vector< handler_t > &vm_handlers ); + + /// + /// get operand decryption instructions given a vm handler... + /// + /// reference to a zydis_routine_t containing the deobfuscated and flattened vm handler + /// native instructions... reference to a transform::map_t that will get filled + /// up with the transforms needed to decrypt operands... returns true if the transformations + /// were extracted successfully + bool get_operand_transforms( zydis_routine_t &vm_handler, transform::map_t &transforms ); + + /// + /// get a vm handler profile given a handler_t... + /// + /// reference to a handler_t structure that contains all the information of a given vm + /// handler... returns a pointer to the vm profile, else a nullptr... + vm::handler::profile_t *get_profile( handler_t &vm_handler ); + + /// + /// get a vm handler profile given the mnemonic of the vm handler... + /// + /// mnemonic of the vm handler... + /// returns a pointer to the profile if the given menmonic is implimented, else a nullptr... + vm::handler::profile_t *get_profile( vm::handler::mnemonic_t mnemonic ); + + namespace table + { + /// + /// get the linear virtual address of the vm handler table give a deobfuscated, flattened, vm entry... + /// + /// deobfuscated, flattened, vm entry... + /// returns the linear virtual address of the vm handler table... + std::uintptr_t *get( const zydis_routine_t &vm_entry ); + + /// + /// get the single native instruction used to decrypt vm handler entries... + /// + /// reference to the deobfuscated, flattened, vm entry... + /// + /// + bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ); + + /// + /// encrypt a linear virtual address given the transformation that is used to decrypt the vm handler table + /// entry... this function will apply the inverse of the transformation so you dont need to get the inverse + /// yourself... + /// + /// reference to the transformation native instruction... + /// value to be encrypted (linear virtual address) + /// returns the encrypted value... + std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); + + /// + /// decrypts a vm handler table entry... + /// + /// transformation extracted from vm_entry that decrypts vm handler table + /// entries... encrypted value to be decrypted... returns the + /// decrypted value... + std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ); + } // namespace table +} // namespace vm::handler \ No newline at end of file diff --git a/include/vminstrs.hpp b/include/vminstrs.hpp index 8e98a28..aa51aa8 100644 --- a/include/vminstrs.hpp +++ b/include/vminstrs.hpp @@ -4,66 +4,87 @@ #include #include -namespace vm +namespace vm::instrs { - namespace instrs - { - // decrypt transformations for encrypted virtual instruction rva... - bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs ); + /// + /// gets the native instructions that are used to decrypt the relative virtual address to virtual instructions + /// located on the stack at RSP+0xA0... you can learn about this @link https://back.engineering/17/05/2021/#vm_entry + /// + /// pass by reference of the specific vm entry you want to get the decryption instructions + /// from... pass by reference vector that will be filled with the decryption + /// instructions... returns true if the decryption instructions are extracted... + bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs ); - std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand, - std::uint64_t rolling_key ); + /// + /// decrypt virtual instruction operand given the decryption transformations... you can read about these + /// transformations + /// @link https://back.engineering/17/05/2021/#operand-decryption + /// + /// decryption transformations... + /// encrypted virtual instruction operand... + /// the decryption key (RBX)... + /// + std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand, + std::uint64_t rolling_key ); - std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand, - std::uint64_t rolling_key ); + /// + /// encrypt a virtual instructions operand given the transformations to decrypt the operand... the transformations + /// are inversed by this functions so you dont need to worry about doing that. + /// + /// you can learn about transformations @link https://back.engineering/17/05/2021/#operand-decryption + /// + /// transformations to decrypt operand, these transformations are inversed by the + /// function... operand to be encrypted... encryption key... (RBX)... + std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand, + std::uint64_t rolling_key ); - /// - /// get virt_instr_t filled in with data given a vmp2 trace entry and vm context... - /// - /// current vm context - /// vmp2 trace entry containing all of the native/virtual register/stack values... - /// returns a filled in virt_instr_t on success... - std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry ); + /// + /// get virt_instr_t filled in with data given a vmp2 trace entry and vm context... + /// + /// current vm context + /// vmp2 trace entry containing all of the native/virtual register/stack values... + /// returns a filled in virt_instr_t on success... + std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry ); - /// - /// gets the second operand (imm) given vip and vm::ctx_t... - /// - /// vm context - /// immediate value size in bits... - /// virtual instruction pointer, linear virtual address... - /// returns immediate value if imm_size is not 0... - std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip ); + /// + /// gets the second operand (imm) given vip and vm::ctx_t... + /// + /// vm context + /// immediate value size in bits... + /// virtual instruction pointer, linear virtual address... + /// returns immediate value if imm_size is not 0... + std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip ); - /// - /// get jcc data out of a code block... this function will loop over the code block - /// and look for the last LCONSTDW in the virtual instructions. - /// - /// it will then loop and look for all PUSHVSP's, checking each to see if the stack - /// contains two encrypted rva's to each branch.. if there is not two encrypted rva's - /// then the virtual jmp instruction only has one dest... - /// - /// vm context - /// code block that does not have its jcc_data yet - /// if last lconstdw is found, return filled in jcc_data structure... - std::optional< jcc_data > get_jcc_data( vm::ctx_t &ctx, code_block_t &code_block ); + /// + /// get jcc data out of a code block... this function will loop over the code block + /// and look for the last LCONSTDW in the virtual instructions. + /// + /// it will then loop and look for all PUSHVSP's, checking each to see if the stack + /// contains two encrypted rva's to each branch.. if there is not two encrypted rva's + /// then the virtual jmp instruction only has one dest... + /// + /// vm context + /// code block that does not have its jcc_data yet + /// if last lconstdw is found, return filled in jcc_data structure... + std::optional< jcc_data > get_jcc_data( vm::ctx_t &ctx, code_block_t &code_block ); - /// - /// the top of the stack will contain the lower 32bits of the RVA to the virtual instructions - /// that will be jumping too... the RVA is image based (not module based, but optional header image - /// based)... this means the value ontop of the stack could be "40007fd8" with image base being - /// 0x140000000... as you can see the 0x100000000 is missing... the below statement deals with this... - /// - /// vm context - /// current trace entry for virtual JMP instruction - /// returns linear virtual address of the next code block... - std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry ); + /// + /// the top of the stack will contain the lower 32bits of the RVA to the virtual instructions + /// that will be jumping too... the RVA is image based (not module based, but optional header image + /// based)... this means the value ontop of the stack could be "40007fd8" with image base being + /// 0x140000000... as you can see the 0x100000000 is missing... the below statement deals with this... + /// + /// vm context + /// current trace entry for virtual JMP instruction + /// returns linear virtual address of the next code block... + std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry ); - /// - /// same routine as above except lower_32bits is passed directly and not extracted from the stack... - /// - /// vm context - /// lower 32bits of the relative virtual address... - /// returns full linear virtual address of code block... - std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits ); - } // namespace instrs -} // namespace vm \ No newline at end of file + /// + /// same routine as above except lower_32bits is passed directly and not extracted from the stack... + /// + /// vm context + /// lower 32bits of the relative virtual address... + /// returns full linear virtual address of code block... + std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits ); +} // namespace vm::instrs \ No newline at end of file diff --git a/include/vmprofiles.hpp b/include/vmprofiles.hpp index 34d3d32..25f6f58 100644 --- a/include/vmprofiles.hpp +++ b/include/vmprofiles.hpp @@ -1,138 +1,175 @@ #pragma once #include -namespace vm +/// +/// contains all information pertaining to vm handler identification... +/// +namespace vm::handler { - namespace handler + /// + /// vm handler mnemonic... so you dont need to compare strings! + /// + enum mnemonic_t { - enum mnemonic_t - { - INVALID, - LRFLAGS, - PUSHVSP, - MULQ, - DIVQ, - CALL, - JMP, - VMEXIT, - - SREGQ, - SREGDW, - SREGW, - - LREGQ, - LREGDW, - - LCONSTQ, - LCONSTBZXW, - LCONSTBSXQ, - LCONSTBSXDW, - LCONSTDWSXQ, - LCONSTWSXQ, - LCONSTWSXDW, - LCONSTDW, - LCONSTW, - - READQ, - READDW, - READW, - - WRITEQ, - WRITEDW, - WRITEW, - WRITEB, - - ADDQ, - ADDDW, - ADDW, - - SHLQ, - SHLDW, - - SHRQ, - SHRW, - - NANDQ, - NANDDW, - NANDW - }; - - using zydis_callback_t = std::function; - - enum extention_t - { - none, - sign_extend, - zero_extend - }; - - struct profile_t - { - const char *name; - mnemonic_t mnemonic; - u8 imm_size; - std::vector< zydis_callback_t > signature; - extention_t extention; - }; - - namespace profile - { - extern vm::handler::profile_t sregq; - extern vm::handler::profile_t sregdw; - extern vm::handler::profile_t sregw; - - extern vm::handler::profile_t lregq; - extern vm::handler::profile_t lregdw; - - extern vm::handler::profile_t lconstq; - extern vm::handler::profile_t lconstdw; - extern vm::handler::profile_t lconstw; - - extern vm::handler::profile_t lconstbzxw; - extern vm::handler::profile_t lconstbsxdw; - extern vm::handler::profile_t lconstbsxq; - extern vm::handler::profile_t lconstdwsxq; - extern vm::handler::profile_t lconstwsxq; - extern vm::handler::profile_t lconstwsxdw; - - extern vm::handler::profile_t addq; - extern vm::handler::profile_t adddw; - extern vm::handler::profile_t addw; - - extern vm::handler::profile_t shlq; - extern vm::handler::profile_t shldw; - - extern vm::handler::profile_t nandq; - extern vm::handler::profile_t nanddw; - extern vm::handler::profile_t nandw; - - extern vm::handler::profile_t writeq; - extern vm::handler::profile_t writedw; - extern vm::handler::profile_t writeb; - - extern vm::handler::profile_t readq; - extern vm::handler::profile_t readdw; - - extern vm::handler::profile_t shrq; - extern vm::handler::profile_t shrw; - - extern vm::handler::profile_t lrflags; - extern vm::handler::profile_t call; - extern vm::handler::profile_t pushvsp; - extern vm::handler::profile_t mulq; - extern vm::handler::profile_t divq; - extern vm::handler::profile_t jmp; - extern vm::handler::profile_t vmexit; - - inline std::vector< vm::handler::profile_t * > all = { - &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, &lconstbsxdw, - &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, &addq, &adddw, - &addw, - - &shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, &nandw, - - &shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq, &jmp, - &lrflags, &vmexit, &call }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + INVALID, + LRFLAGS, + PUSHVSP, + MULQ, + DIVQ, + CALL, + JMP, + VMEXIT, + + SREGQ, + SREGDW, + SREGW, + + LREGQ, + LREGDW, + + LCONSTQ, + LCONSTBZXW, + LCONSTBSXQ, + LCONSTBSXDW, + LCONSTDWSXQ, + LCONSTWSXQ, + LCONSTWSXDW, + LCONSTDW, + LCONSTW, + + READQ, + READDW, + READW, + + WRITEQ, + WRITEDW, + WRITEW, + WRITEB, + + ADDQ, + ADDDW, + ADDW, + + SHLQ, + SHLDW, + + SHRQ, + SHRW, + + NANDQ, + NANDDW, + NANDW + }; + + /// + /// zydis callback lambda used to pattern match native instructions... + /// + using zydis_callback_t = std::function< bool( const zydis_decoded_instr_t &instr ) >; + + /// + /// how sign extention is handled... + /// + enum extention_t + { + none, + sign_extend, + zero_extend + }; + + /// + /// pre defined vm handler profile containing all compiled time known information about a vm handler... + /// + struct profile_t + { + /// + /// name of the vm handler, such as JMP or LCONST... + /// + const char *name; + + /// + /// the mnemonic of the vm handler... so you dont need to compare strings... + /// + mnemonic_t mnemonic; + + /// + /// size, in bits, of the operand (imm)... if there is none then this will be zero... + /// + u8 imm_size; + + /// + /// a vector of signatures used to compare native instructions against zydis aided signatures... + /// + std::vector< zydis_callback_t > signature; + + /// + /// how sign extention of operands are handled... + /// + extention_t extention; + }; + + /// + /// contains all profiles defined, as well as a vector of all of the defined profiles... + /// + namespace profile + { + extern vm::handler::profile_t sregq; + extern vm::handler::profile_t sregdw; + extern vm::handler::profile_t sregw; + + extern vm::handler::profile_t lregq; + extern vm::handler::profile_t lregdw; + + extern vm::handler::profile_t lconstq; + extern vm::handler::profile_t lconstdw; + extern vm::handler::profile_t lconstw; + + extern vm::handler::profile_t lconstbzxw; + extern vm::handler::profile_t lconstbsxdw; + extern vm::handler::profile_t lconstbsxq; + extern vm::handler::profile_t lconstdwsxq; + extern vm::handler::profile_t lconstwsxq; + extern vm::handler::profile_t lconstwsxdw; + + extern vm::handler::profile_t addq; + extern vm::handler::profile_t adddw; + extern vm::handler::profile_t addw; + + extern vm::handler::profile_t shlq; + extern vm::handler::profile_t shldw; + + extern vm::handler::profile_t nandq; + extern vm::handler::profile_t nanddw; + extern vm::handler::profile_t nandw; + + extern vm::handler::profile_t writeq; + extern vm::handler::profile_t writedw; + extern vm::handler::profile_t writeb; + + extern vm::handler::profile_t readq; + extern vm::handler::profile_t readdw; + + extern vm::handler::profile_t shrq; + extern vm::handler::profile_t shrw; + + extern vm::handler::profile_t lrflags; + extern vm::handler::profile_t call; + extern vm::handler::profile_t pushvsp; + extern vm::handler::profile_t mulq; + extern vm::handler::profile_t divq; + extern vm::handler::profile_t jmp; + extern vm::handler::profile_t vmexit; + + /// + /// a vector of pointers to all defined vm handler profiles... + /// + inline std::vector< vm::handler::profile_t * > all = { + &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, &lconstbsxdw, + &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, &addq, &adddw, + &addw, + + &shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, &nandw, + + &shrq, &shrw, &readq, &readdw, &mulq, &pushvsp, &divq, &jmp, + &lrflags, &vmexit, &call }; + } // namespace profile +} // namespace vm::handler \ No newline at end of file diff --git a/include/vmutils.hpp b/include/vmutils.hpp index a118b16..afc877c 100644 --- a/include/vmutils.hpp +++ b/include/vmutils.hpp @@ -28,25 +28,22 @@ struct zydis_instr_t using zydis_routine_t = std::vector< zydis_instr_t >; -namespace vm +namespace vm::util { - namespace util + namespace reg { - namespace reg - { - // converts say... AL to RAX... - zydis_register_t to64( zydis_register_t reg ); - bool compare( zydis_register_t a, zydis_register_t b ); - } // namespace reg - - bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ); - std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ); - - void print( zydis_routine_t &routine ); - void print( const zydis_decoded_instr_t &instr ); - bool is_jmp( const zydis_decoded_instr_t &instr ); - - bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps = false ); - void deobfuscate( zydis_routine_t &routine ); - } // namespace util -} // namespace vm \ No newline at end of file + // converts say... AL to RAX... + zydis_register_t to64( zydis_register_t reg ); + bool compare( zydis_register_t a, zydis_register_t b ); + } // namespace reg + + bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ); + std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ); + + void print( zydis_routine_t &routine ); + void print( const zydis_decoded_instr_t &instr ); + bool is_jmp( const zydis_decoded_instr_t &instr ); + + bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps = false ); + void deobfuscate( zydis_routine_t &routine ); +} // namespace vm::util \ No newline at end of file diff --git a/src/vminstrs.cpp b/src/vminstrs.cpp index fb241a5..f6cef09 100644 --- a/src/vminstrs.cpp +++ b/src/vminstrs.cpp @@ -1,279 +1,274 @@ #include -namespace vm +namespace vm::instrs { - namespace instrs + std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand, + std::uint64_t rolling_key ) { - std::pair< std::uint64_t, std::uint64_t > decrypt_operand( transform::map_t &transforms, std::uint64_t operand, - std::uint64_t rolling_key ) + const auto &generic_decrypt_0 = transforms[ transform::type::generic0 ]; + const auto &key_decrypt = transforms[ transform::type::rolling_key ]; + const auto &generic_decrypt_1 = transforms[ transform::type::generic1 ]; + const auto &generic_decrypt_2 = transforms[ transform::type::generic2 ]; + const auto &generic_decrypt_3 = transforms[ transform::type::generic3 ]; + const auto &update_key = transforms[ transform::type::update_key ]; + + if ( generic_decrypt_0.mnemonic != ZYDIS_MNEMONIC_INVALID ) { - const auto &generic_decrypt_0 = transforms[ transform::type::generic0 ]; - const auto &key_decrypt = transforms[ transform::type::rolling_key ]; - const auto &generic_decrypt_1 = transforms[ transform::type::generic1 ]; - const auto &generic_decrypt_2 = transforms[ transform::type::generic2 ]; - const auto &generic_decrypt_3 = transforms[ transform::type::generic3 ]; - const auto &update_key = transforms[ transform::type::update_key ]; - - if ( generic_decrypt_0.mnemonic != ZYDIS_MNEMONIC_INVALID ) - { - operand = transform::apply( - generic_decrypt_0.operands[ 0 ].size, generic_decrypt_0.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_0 ) ? generic_decrypt_0.operands[ 1 ].imm.value.u : 0 ); - } - - // apply transformation with rolling decrypt key... - operand = transform::apply( key_decrypt.operands[ 0 ].size, key_decrypt.mnemonic, operand, rolling_key ); - - // apply three generic transformations... - { - operand = transform::apply( - generic_decrypt_1.operands[ 0 ].size, generic_decrypt_1.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_1 ) ? generic_decrypt_1.operands[ 1 ].imm.value.u : 0 ); - - operand = transform::apply( - generic_decrypt_2.operands[ 0 ].size, generic_decrypt_2.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_2 ) ? generic_decrypt_2.operands[ 1 ].imm.value.u : 0 ); - - operand = transform::apply( - generic_decrypt_3.operands[ 0 ].size, generic_decrypt_3.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_3 ) ? generic_decrypt_3.operands[ 1 ].imm.value.u : 0 ); - } - - // update rolling key... - auto result = transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand ); - - // update decryption key correctly... - switch ( update_key.operands[ 0 ].size ) - { - case 8: - rolling_key = ( rolling_key & ~std::numeric_limits< u8 >::max() ) + result; - break; - case 16: - rolling_key = ( rolling_key & ~std::numeric_limits< u16 >::max() ) + result; - break; - default: - rolling_key = result; - break; - } - - return { operand, rolling_key }; + operand = transform::apply( + generic_decrypt_0.operands[ 0 ].size, generic_decrypt_0.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_0 ) ? generic_decrypt_0.operands[ 1 ].imm.value.u : 0 ); } - std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand, - std::uint64_t rolling_key ) + // apply transformation with rolling decrypt key... + operand = transform::apply( key_decrypt.operands[ 0 ].size, key_decrypt.mnemonic, operand, rolling_key ); + + // apply three generic transformations... { - transform::map_t inverse; - inverse_transforms( transforms, inverse ); - const auto apply_key = rolling_key; - - const auto &generic_decrypt_0 = inverse[ transform::type::generic0 ]; - const auto &key_decrypt = inverse[ transform::type::rolling_key ]; - const auto &generic_decrypt_1 = inverse[ transform::type::generic1 ]; - const auto &generic_decrypt_2 = inverse[ transform::type::generic2 ]; - const auto &generic_decrypt_3 = inverse[ transform::type::generic3 ]; - const auto &update_key = transforms[ transform::type::update_key ]; - - auto result = transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand ); - - // mov rax, al does not clear the top bits... - // mov rax, ax does not clear the top bits... - // mov rax, eax does clear the top bits... - switch ( update_key.operands[ 0 ].size ) - { - case 8: - rolling_key = ( rolling_key & ~std::numeric_limits< u8 >::max() ) + result; - break; - case 16: - rolling_key = ( rolling_key & ~std::numeric_limits< u16 >::max() ) + result; - break; - default: - rolling_key = result; - break; - } - - { - operand = transform::apply( - generic_decrypt_3.operands[ 0 ].size, generic_decrypt_3.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_3 ) ? generic_decrypt_3.operands[ 1 ].imm.value.u : 0 ); - - operand = transform::apply( - generic_decrypt_2.operands[ 0 ].size, generic_decrypt_2.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_2 ) ? generic_decrypt_2.operands[ 1 ].imm.value.u : 0 ); - - operand = transform::apply( - generic_decrypt_1.operands[ 0 ].size, generic_decrypt_1.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_1 ) ? generic_decrypt_1.operands[ 1 ].imm.value.u : 0 ); - } - - operand = transform::apply( key_decrypt.operands[ 0 ].size, key_decrypt.mnemonic, operand, apply_key ); - - if ( generic_decrypt_0.mnemonic != ZYDIS_MNEMONIC_INVALID ) - { - operand = transform::apply( - generic_decrypt_0.operands[ 0 ].size, generic_decrypt_0.mnemonic, operand, - // check to see if this instruction has an IMM... - transform::has_imm( &generic_decrypt_0 ) ? generic_decrypt_0.operands[ 1 ].imm.value.u : 0 ); - } - - return { operand, rolling_key }; + operand = transform::apply( + generic_decrypt_1.operands[ 0 ].size, generic_decrypt_1.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_1 ) ? generic_decrypt_1.operands[ 1 ].imm.value.u : 0 ); + + operand = transform::apply( + generic_decrypt_2.operands[ 0 ].size, generic_decrypt_2.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_2 ) ? generic_decrypt_2.operands[ 1 ].imm.value.u : 0 ); + + operand = transform::apply( + generic_decrypt_3.operands[ 0 ].size, generic_decrypt_3.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_3 ) ? generic_decrypt_3.operands[ 1 ].imm.value.u : 0 ); } - bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs ) + // update rolling key... + auto result = transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand ); + + // update decryption key correctly... + switch ( update_key.operands[ 0 ].size ) { - // find mov esi, [rsp+0xA0] - auto result = - std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { - return instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSP && - instr_data.instr.operands[ 1 ].mem.disp.value == 0xA0; - } ); + case 8: + rolling_key = ( rolling_key & ~std::numeric_limits< u8 >::max() ) + result; + break; + case 16: + rolling_key = ( rolling_key & ~std::numeric_limits< u16 >::max() ) + result; + break; + default: + rolling_key = result; + break; + } - if ( result == vm_entry.end() ) - return false; + return { operand, rolling_key }; + } - // find the next three instructions with ESI as - // the first operand... and make sure actions & writes... - for ( auto idx = 0u; idx < 3; ++idx ) - { - result = std::find_if( ++result, vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { - return vm::transform::valid( instr_data.instr.mnemonic ) && - instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && - instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI; - } ); + std::pair< std::uint64_t, std::uint64_t > encrypt_operand( transform::map_t &transforms, std::uint64_t operand, + std::uint64_t rolling_key ) + { + transform::map_t inverse; + inverse_transforms( transforms, inverse ); + const auto apply_key = rolling_key; + + const auto &generic_decrypt_0 = inverse[ transform::type::generic0 ]; + const auto &key_decrypt = inverse[ transform::type::rolling_key ]; + const auto &generic_decrypt_1 = inverse[ transform::type::generic1 ]; + const auto &generic_decrypt_2 = inverse[ transform::type::generic2 ]; + const auto &generic_decrypt_3 = inverse[ transform::type::generic3 ]; + const auto &update_key = transforms[ transform::type::update_key ]; + + auto result = transform::apply( update_key.operands[ 0 ].size, update_key.mnemonic, rolling_key, operand ); + + // mov rax, al does not clear the top bits... + // mov rax, ax does not clear the top bits... + // mov rax, eax does clear the top bits... + switch ( update_key.operands[ 0 ].size ) + { + case 8: + rolling_key = ( rolling_key & ~std::numeric_limits< u8 >::max() ) + result; + break; + case 16: + rolling_key = ( rolling_key & ~std::numeric_limits< u16 >::max() ) + result; + break; + default: + rolling_key = result; + break; + } - if ( result == vm_entry.end() ) - return false; + { + operand = transform::apply( + generic_decrypt_3.operands[ 0 ].size, generic_decrypt_3.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_3 ) ? generic_decrypt_3.operands[ 1 ].imm.value.u : 0 ); + + operand = transform::apply( + generic_decrypt_2.operands[ 0 ].size, generic_decrypt_2.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_2 ) ? generic_decrypt_2.operands[ 1 ].imm.value.u : 0 ); + + operand = transform::apply( + generic_decrypt_1.operands[ 0 ].size, generic_decrypt_1.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_1 ) ? generic_decrypt_1.operands[ 1 ].imm.value.u : 0 ); + } - transform_instrs.push_back( result->instr ); - } + operand = transform::apply( key_decrypt.operands[ 0 ].size, key_decrypt.mnemonic, operand, apply_key ); - return true; + if ( generic_decrypt_0.mnemonic != ZYDIS_MNEMONIC_INVALID ) + { + operand = transform::apply( + generic_decrypt_0.operands[ 0 ].size, generic_decrypt_0.mnemonic, operand, + // check to see if this instruction has an IMM... + transform::has_imm( &generic_decrypt_0 ) ? generic_decrypt_0.operands[ 1 ].imm.value.u : 0 ); } - std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip ) + return { operand, rolling_key }; + } + + bool get_rva_decrypt( const zydis_routine_t &vm_entry, std::vector< zydis_decoded_instr_t > &transform_instrs ) + { + // find mov esi, [rsp+0xA0] + auto result = std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { + return instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI && + instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSP && + instr_data.instr.operands[ 1 ].mem.disp.value == 0xA0; + } ); + + if ( result == vm_entry.end() ) + return false; + + // find the next three instructions with ESI as + // the first operand... and make sure actions & writes... + for ( auto idx = 0u; idx < 3; ++idx ) { - if ( !imm_size ) - return {}; + result = std::find_if( ++result, vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && + instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI; + } ); - auto result = 0ull; - ctx.exec_type == vmp2::exec_type_t::forward - ? std::memcpy( &result, reinterpret_cast< void * >( vip ), imm_size / 8 ) - : std::memcpy( &result, reinterpret_cast< void * >( vip - ( imm_size / 8 ) ), imm_size / 8 ); + if ( result == vm_entry.end() ) + return false; - return result; + transform_instrs.push_back( result->instr ); } - std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry ) - { - virt_instr_t result; - auto &vm_handler = ctx.vm_handlers[ entry.handler_idx ]; - const auto profile = vm_handler.profile; + return true; + } - result.mnemonic_t = profile ? profile->mnemonic : vm::handler::INVALID; - result.opcode = entry.handler_idx; - result.trace_data = entry; - result.operand.has_imm = false; + std::optional< std::uint64_t > get_imm( vm::ctx_t &ctx, std::uint8_t imm_size, std::uintptr_t vip ) + { + if ( !imm_size ) + return {}; - if ( vm_handler.imm_size ) - { - result.operand.has_imm = true; - result.operand.imm.imm_size = vm_handler.imm_size; - const auto imm_val = get_imm( ctx, vm_handler.imm_size, entry.vip ); + auto result = 0ull; + ctx.exec_type == vmp2::exec_type_t::forward + ? std::memcpy( &result, reinterpret_cast< void * >( vip ), imm_size / 8 ) + : std::memcpy( &result, reinterpret_cast< void * >( vip - ( imm_size / 8 ) ), imm_size / 8 ); - if ( !imm_val.has_value() ) - return {}; + return result; + } - result.operand.imm.u = - vm::instrs::decrypt_operand( vm_handler.transforms, imm_val.value(), entry.decrypt_key ).first; - } + std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry ) + { + virt_instr_t result; + auto &vm_handler = ctx.vm_handlers[ entry.handler_idx ]; + const auto profile = vm_handler.profile; - return result; - } + result.mnemonic_t = profile ? profile->mnemonic : vm::handler::INVALID; + result.opcode = entry.handler_idx; + result.trace_data = entry; + result.operand.has_imm = false; - std::optional< jcc_data > get_jcc_data( vm::ctx_t &vmctx, code_block_t &code_block ) + if ( vm_handler.imm_size ) { - // there is no branch for this as this is a vmexit... - if ( code_block.vinstrs.back().mnemonic_t == vm::handler::VMEXIT ) + result.operand.has_imm = true; + result.operand.imm.imm_size = vm_handler.imm_size; + const auto imm_val = get_imm( ctx, vm_handler.imm_size, entry.vip ); + + if ( !imm_val.has_value() ) return {}; - // find the last LCONSTDW... the imm value is the JMP xor decrypt key... - // we loop backwards here (using rbegin and rend)... - auto result = std::find_if( code_block.vinstrs.rbegin(), code_block.vinstrs.rend(), - []( const vm::instrs::virt_instr_t &vinstr ) -> bool { - auto profile = vm::handler::get_profile( vinstr.mnemonic_t ); - return profile && profile->mnemonic == vm::handler::LCONSTDW; - } ); - - jcc_data jcc; - const auto xor_key = static_cast< std::uint32_t >( result->operand.imm.u ); - const auto &last_trace = code_block.vinstrs.back().trace_data; - - // since result is already a variable and is a reverse itr - // im going to be using rbegin and rend here again... - // - // look for PUSHVSP virtual instructions with two encrypted virtual - // instruction rva's ontop of the virtual stack... - result = std::find_if( code_block.vinstrs.rbegin(), code_block.vinstrs.rend(), - [ & ]( const vm::instrs::virt_instr_t &vinstr ) -> bool { - if ( auto profile = vm::handler::get_profile( vinstr.mnemonic_t ); - profile && profile->mnemonic == vm::handler::PUSHVSP ) - { - const auto possible_block_1 = code_block_addr( - vmctx, vinstr.trace_data.vsp.qword[ 0 ] ^ xor_key ), - possible_block_2 = code_block_addr( - vmctx, vinstr.trace_data.vsp.qword[ 1 ] ^ xor_key ); - - // if this returns too many false positives we might have to get - // our hands dirty and look into trying to emulate each branch - // to see if the first instruction is an SREGQ... - return possible_block_1 > vmctx.module_base && - possible_block_1 < vmctx.module_base + vmctx.image_size && - possible_block_2 > vmctx.module_base && - possible_block_2 < vmctx.module_base + vmctx.image_size; - } - return false; - } ); - - // if there is not two branches... - if ( result == code_block.vinstrs.rend() ) - { - jcc.block_addr[ 0 ] = code_block_addr( vmctx, last_trace ); - jcc.has_jcc = false; - jcc.type = jcc_type::absolute; - } - // else there are two branches... - else - { - jcc.block_addr[ 0 ] = code_block_addr( vmctx, result->trace_data.vsp.qword[ 0 ] ^ xor_key ); - jcc.block_addr[ 1 ] = code_block_addr( vmctx, result->trace_data.vsp.qword[ 1 ] ^ xor_key ); - - jcc.has_jcc = true; - jcc.type = jcc_type::branching; - } - - return jcc; + result.operand.imm.u = + vm::instrs::decrypt_operand( vm_handler.transforms, imm_val.value(), entry.decrypt_key ).first; } - std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry ) + return result; + } + + std::optional< jcc_data > get_jcc_data( vm::ctx_t &vmctx, code_block_t &code_block ) + { + // there is no branch for this as this is a vmexit... + if ( code_block.vinstrs.back().mnemonic_t == vm::handler::VMEXIT ) + return {}; + + // find the last LCONSTDW... the imm value is the JMP xor decrypt key... + // we loop backwards here (using rbegin and rend)... + auto result = std::find_if( code_block.vinstrs.rbegin(), code_block.vinstrs.rend(), + []( const vm::instrs::virt_instr_t &vinstr ) -> bool { + auto profile = vm::handler::get_profile( vinstr.mnemonic_t ); + return profile && profile->mnemonic == vm::handler::LCONSTDW; + } ); + + jcc_data jcc; + const auto xor_key = static_cast< std::uint32_t >( result->operand.imm.u ); + const auto &last_trace = code_block.vinstrs.back().trace_data; + + // since result is already a variable and is a reverse itr + // im going to be using rbegin and rend here again... + // + // look for PUSHVSP virtual instructions with two encrypted virtual + // instruction rva's ontop of the virtual stack... + result = std::find_if( + code_block.vinstrs.rbegin(), code_block.vinstrs.rend(), + [ & ]( const vm::instrs::virt_instr_t &vinstr ) -> bool { + if ( auto profile = vm::handler::get_profile( vinstr.mnemonic_t ); + profile && profile->mnemonic == vm::handler::PUSHVSP ) + { + const auto possible_block_1 = code_block_addr( vmctx, vinstr.trace_data.vsp.qword[ 0 ] ^ xor_key ), + possible_block_2 = code_block_addr( vmctx, vinstr.trace_data.vsp.qword[ 1 ] ^ xor_key ); + + // if this returns too many false positives we might have to get + // our hands dirty and look into trying to emulate each branch + // to see if the first instruction is an SREGQ... + return possible_block_1 > vmctx.module_base && + possible_block_1 < vmctx.module_base + vmctx.image_size && + possible_block_2 > vmctx.module_base && + possible_block_2 < vmctx.module_base + vmctx.image_size; + } + return false; + } ); + + // if there is not two branches... + if ( result == code_block.vinstrs.rend() ) { - return ( ( entry.vsp.qword[ 0 ] & std::numeric_limits< u32 >::max() ) - - ( ctx.image_base & std::numeric_limits< u32 >::max() ) ) + - ctx.module_base; + jcc.block_addr[ 0 ] = code_block_addr( vmctx, last_trace ); + jcc.has_jcc = false; + jcc.type = jcc_type::absolute; } - - std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits ) + // else there are two branches... + else { - return ( lower_32bits - ( ctx.image_base & std::numeric_limits< u32 >::max() ) ) + ctx.module_base; + jcc.block_addr[ 0 ] = code_block_addr( vmctx, result->trace_data.vsp.qword[ 0 ] ^ xor_key ); + jcc.block_addr[ 1 ] = code_block_addr( vmctx, result->trace_data.vsp.qword[ 1 ] ^ xor_key ); + + jcc.has_jcc = true; + jcc.type = jcc_type::branching; } - } // namespace instrs -} // namespace vm \ No newline at end of file + + return jcc; + } + + std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const vmp2::v2::entry_t &entry ) + { + return ( ( entry.vsp.qword[ 0 ] & std::numeric_limits< u32 >::max() ) - + ( ctx.image_base & std::numeric_limits< u32 >::max() ) ) + + ctx.module_base; + } + + std::uintptr_t code_block_addr( const vm::ctx_t &ctx, const std::uint32_t lower_32bits ) + { + return ( lower_32bits - ( ctx.image_base & std::numeric_limits< u32 >::max() ) ) + ctx.module_base; + } +} // namespace vm::instrs \ No newline at end of file From 3276cc96d0e52f77fc3a6a7ddbe61252ddf41e1a Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 9 Jun 2021 23:11:07 -0700 Subject: [PATCH 04/20] added more doxygen comments... --- include/vminstrs.hpp | 5 +++- include/vmutils.hpp | 58 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/include/vminstrs.hpp b/include/vminstrs.hpp index aa51aa8..ad5465b 100644 --- a/include/vminstrs.hpp +++ b/include/vminstrs.hpp @@ -4,6 +4,9 @@ #include #include +/// +/// contains all functions related to virtual instructions... +/// namespace vm::instrs { /// @@ -48,7 +51,7 @@ namespace vm::instrs std::optional< virt_instr_t > get( vm::ctx_t &ctx, vmp2::v2::entry_t &entry ); /// - /// gets the second operand (imm) given vip and vm::ctx_t... + /// gets the encrypted second operand (imm) given vip and vm::ctx_t... /// /// vm context /// immediate value size in bits... diff --git a/include/vmutils.hpp b/include/vmutils.hpp index afc877c..009be67 100644 --- a/include/vmutils.hpp +++ b/include/vmutils.hpp @@ -28,22 +28,78 @@ struct zydis_instr_t using zydis_routine_t = std::vector< zydis_instr_t >; +/// +/// utils used by the other cpp files... misc things that get used a lot... +/// namespace vm::util { + /// + /// utils pertaining to native registers... + /// namespace reg { - // converts say... AL to RAX... + /// + /// converts say... AL to RAX... + /// + /// a zydis decoded register value... + /// returns the largest width register of the given register... AL gives RAX... zydis_register_t to64( zydis_register_t reg ); + + /// + /// compares to registers with each other... calls to64 and compares... + /// + /// register a... + /// register b... + /// returns true if register to64(a) == to64(b)... bool compare( zydis_register_t a, zydis_register_t b ); } // namespace reg + /// + /// get the instruction that fetches an operand out of VIP... + /// + /// this is a deobfuscated, flattened, view of any set of native instructions that read an operand out of VIP... can be calc_jmp, vm_entry, or vm handlers... + /// + /// returns true of the fetch operand native instruction is found... bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ); + + /// + /// gets the instruction that fetches an operand out of VIP and returns an iterator to it... + /// + /// this is a deobfuscated, flattened, view of any set of native instructions that read an operand out of VIP... can be calc_jmp, vm_entry, or vm handlers... + /// returns the iterator of the native instruction, else an empty std::optional... std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ); + /// + /// prints a disassembly view of a routine... + /// + /// reference to a zydis_routine_t to be printed... void print( zydis_routine_t &routine ); + + /// + /// prints a single disassembly view of an instruction... + /// + /// instruction to print... void print( const zydis_decoded_instr_t &instr ); + + /// + /// determines if a given decoded native instruction is a JCC... + /// + /// + /// bool is_jmp( const zydis_decoded_instr_t &instr ); + /// + /// flatten native instruction stream, takes every JCC (follows the branch)... + /// + /// filled with decoded instructions... + /// linear virtual address to start flattening from... + /// keep JCC's in the flattened instruction stream... + /// returns true if flattened was successful... bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps = false ); + + /// + /// deadstore deobfuscation of a flattened routine... + /// + /// reference to a flattened instruction vector... void deobfuscate( zydis_routine_t &routine ); } // namespace vm::util \ No newline at end of file From ae9f255180d62720aff5caed1a1ed7a1169dd30a Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Wed, 9 Jun 2021 23:18:07 -0700 Subject: [PATCH 05/20] added some more doxygen comments... --- include/transform.hpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/transform.hpp b/include/transform.hpp index e754c63..562961b 100644 --- a/include/transform.hpp +++ b/include/transform.hpp @@ -217,11 +217,21 @@ namespace vm::transform { ZYDIS_MNEMONIC_ROR, ZYDIS_MNEMONIC_ROL }, { ZYDIS_MNEMONIC_ROL, ZYDIS_MNEMONIC_ROR }, { ZYDIS_MNEMONIC_INC, ZYDIS_MNEMONIC_DEC }, { ZYDIS_MNEMONIC_DEC, ZYDIS_MNEMONIC_INC } }; + /// + /// determines if the given mnemonic is a valid transformation... + /// + /// mnemonic of the native instruction... + /// returns true if the mnemonic is a transformation... inline bool valid( zydis_mnemonic_t op ) { return transforms< std::uint64_t >.find( op ) != transforms< std::uint64_t >.end(); } + /// + /// inverse operand decryption transformations... + /// + /// reference to the transformations to be inversed... + /// reference to the resulting inversed transformations... inline void inverse_transforms( transform::map_t &transforms, transform::map_t &inverse ) { inverse[ transform::type::generic0 ] = transforms[ transform::type::generic0 ]; @@ -249,6 +259,11 @@ namespace vm::transform transform::inverse[ transforms[ transform::type::update_key ].mnemonic ]; } + /// + /// inverse transformations given a vector of them... + /// + /// reference to a vector of transformations... + /// returns true if all transformations were inversed... inline auto inverse_transforms( std::vector< zydis_decoded_instr_t > &instrs ) -> bool { for ( auto idx = 0u; idx < instrs.size(); idx++ ) @@ -279,6 +294,11 @@ namespace vm::transform } } + /// + /// determines if a given decoded instruction has a second operand that is an immediate value... + /// + /// pointer to a decoded instruction... + /// returns true if the second operand is of type immediate... inline bool has_imm( const zydis_decoded_instr_t *instr ) { return instr->operand_count > 1 && ( instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ); From 13fef335fead8d5e0e68501c6b3efa474d397ec8 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 00:40:57 -0700 Subject: [PATCH 06/20] cleaned the code a bunch more... --- include/vmprofiles.hpp | 66 +++++ src/calc_jmp.cpp | 96 ++++---- src/vmhandler.cpp | 486 ++++++++++++++++++------------------- src/vmprofiles/add.cpp | 154 ++++++------ src/vmprofiles/call.cpp | 68 +++--- src/vmprofiles/div.cpp | 126 +++++----- src/vmprofiles/jmp.cpp | 90 ++++--- src/vmprofiles/lconst.cpp | 439 ++++++++++++++++----------------- src/vmprofiles/lflags.cpp | 57 ++--- src/vmprofiles/lreg.cpp | 146 ++++++----- src/vmprofiles/mul.cpp | 128 +++++----- src/vmprofiles/nand.cpp | 334 ++++++++++++------------- src/vmprofiles/pushvsp.cpp | 69 +++--- src/vmprofiles/read.cpp | 115 ++++----- src/vmprofiles/shl.cpp | 252 +++++++++---------- src/vmprofiles/shr.cpp | 254 +++++++++---------- src/vmprofiles/sreg.cpp | 210 ++++++++-------- src/vmprofiles/vmexit.cpp | 44 ++-- src/vmprofiles/write.cpp | 250 +++++++++---------- src/vmutils.cpp | 391 +++++++++++++++-------------- 20 files changed, 1818 insertions(+), 1957 deletions(-) diff --git a/include/vmprofiles.hpp b/include/vmprofiles.hpp index 25f6f58..19b6aa2 100644 --- a/include/vmprofiles.hpp +++ b/include/vmprofiles.hpp @@ -119,7 +119,33 @@ namespace vm::handler extern vm::handler::profile_t lregq; extern vm::handler::profile_t lregdw; + /// + /// mov rax, [rsi] + /// xor rax, rbx ; transformation + /// bswap rax ; transformation + /// lea rsi, [rsi+8] ; advance VIP… + /// rol rax, 0Ch ; transformation + /// inc rax ; transformation + /// xor rbx, rax ; transformation (update rolling decrypt key) + /// sub rbp, 8 + /// mov [rbp+0], rax + /// extern vm::handler::profile_t lconstq; + + /// + /// mov eax, [rsi-0x04] + /// bswap eax + /// add eax, ebx + /// dec eax + /// neg eax + /// xor eax, 0x2FFD187C + /// push rbx + /// add [rsp], eax + /// pop rbx + /// sub rbp, 0x04 + /// mov [rbp], eax + /// add rsi, 0xFFFFFFFFFFFFFFFC + /// extern vm::handler::profile_t lconstdw; extern vm::handler::profile_t lconstw; @@ -130,7 +156,21 @@ namespace vm::handler extern vm::handler::profile_t lconstwsxq; extern vm::handler::profile_t lconstwsxdw; + /// + /// mov rax, [rbp+0] + /// add [rbp+8], rax + /// pushfq + /// pop qword ptr [rbp+0] + /// extern vm::handler::profile_t addq; + + /// + /// mov ax, [rbp] + /// sub rbp, 0x06 + /// add [rbp+0x08], ax + /// pushfq + /// pop [rbp] + /// extern vm::handler::profile_t adddw; extern vm::handler::profile_t addw; @@ -152,10 +192,36 @@ namespace vm::handler extern vm::handler::profile_t shrw; extern vm::handler::profile_t lrflags; + + /// + /// mov rdx, [rbp] + /// add rbp, 0x08 + /// call rdx + /// extern vm::handler::profile_t call; extern vm::handler::profile_t pushvsp; extern vm::handler::profile_t mulq; + + /// + /// mov rdx, [rbp] + /// mov rax, [rbp+0x08] + /// div [rbp+0x10] + /// mov [rbp+0x08], rdx + /// mov [rbp+0x10], rax + /// pushfq + /// pop [rbp] + /// extern vm::handler::profile_t divq; + + /// + /// mov esi, [rbp] + /// add rbp, 0x08 + /// lea r12, [0x0000000000048F29] + /// mov rax, 0x00 ; image base bytes above 32bits... + /// add rsi, rax + /// mov rbx, rsi ; update decrypt key + /// add rsi, [rbp] ; add module base address + /// extern vm::handler::profile_t jmp; extern vm::handler::profile_t vmexit; diff --git a/src/calc_jmp.cpp b/src/calc_jmp.cpp index adbb115..4d47bf0 100644 --- a/src/calc_jmp.cpp +++ b/src/calc_jmp.cpp @@ -1,62 +1,56 @@ #include -namespace vm +namespace vm::calc_jmp { - namespace calc_jmp + bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ) { - bool get( zydis_routine_t &vm_entry, zydis_routine_t &calc_jmp ) - { - auto result = vm::util::get_fetch_operand( vm_entry ); + auto result = vm::util::get_fetch_operand( vm_entry ); - if ( !result.has_value() ) - return false; + if ( !result.has_value() ) + return false; - calc_jmp.insert( calc_jmp.end(), result.value(), vm_entry.end() ); - return true; - } + calc_jmp.insert( calc_jmp.end(), result.value(), vm_entry.end() ); + return true; + } - std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp ) - { - auto result = - std::find_if( calc_jmp.begin(), calc_jmp.end(), []( const zydis_instr_t &instr_data ) -> bool { - // look for any instruction with RSI being the first operand and its being written too.. - return instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI; - } ); + std::optional< vmp2::exec_type_t > get_advancement( const zydis_routine_t &calc_jmp ) + { + auto result = std::find_if( calc_jmp.begin(), calc_jmp.end(), []( const zydis_instr_t &instr_data ) -> bool { + // look for any instruction with RSI being the first operand and its being written too.. + return instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr_data.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI; + } ); - if ( result == calc_jmp.end() ) - return {}; + if ( result == calc_jmp.end() ) + return {}; - const auto &instr = result->instr; + const auto &instr = result->instr; - switch ( instr.mnemonic ) - { - case ZYDIS_MNEMONIC_LEA: - // if operand type is memory, then return advancement type - // based off of the disposition value... (neg == backward, pos == forward) - if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY ) - return instr.operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward - : vmp2::exec_type_t::backward; - break; - case ZYDIS_MNEMONIC_ADD: - if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) - return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward - : vmp2::exec_type_t::backward; - break; - case ZYDIS_MNEMONIC_SUB: - if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) - return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward - : vmp2::exec_type_t::forward; - break; - case ZYDIS_MNEMONIC_INC: - return vmp2::exec_type_t::forward; - case ZYDIS_MNEMONIC_DEC: - return vmp2::exec_type_t::backward; - default: - break; - } - return {}; + switch ( instr.mnemonic ) + { + case ZYDIS_MNEMONIC_LEA: + // if operand type is memory, then return advancement type + // based off of the disposition value... (neg == backward, pos == forward) + if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY ) + return instr.operands[ 1 ].mem.disp.value > 0 ? vmp2::exec_type_t::forward + : vmp2::exec_type_t::backward; + break; + case ZYDIS_MNEMONIC_ADD: + if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) + return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::forward : vmp2::exec_type_t::backward; + break; + case ZYDIS_MNEMONIC_SUB: + if ( instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE ) + return instr.operands[ 1 ].imm.value.s > 0 ? vmp2::exec_type_t::backward : vmp2::exec_type_t::forward; + break; + case ZYDIS_MNEMONIC_INC: + return vmp2::exec_type_t::forward; + case ZYDIS_MNEMONIC_DEC: + return vmp2::exec_type_t::backward; + default: + break; } - } // namespace calc_jmp -} // namespace vm \ No newline at end of file + return {}; + } +} // namespace vm::calc_jmp \ No newline at end of file diff --git a/src/vmhandler.cpp b/src/vmhandler.cpp index b745ef9..f0987d5 100644 --- a/src/vmhandler.cpp +++ b/src/vmhandler.cpp @@ -1,306 +1,302 @@ #include -namespace vm +namespace vm::handler { - namespace handler + bool get( zydis_routine_t &calc_jmp, zydis_routine_t &vm_handler, std::uintptr_t handler_addr ) { - bool get( zydis_routine_t &calc_jmp, zydis_routine_t &vm_handler, std::uintptr_t handler_addr ) + if ( !vm::util::flatten( vm_handler, handler_addr ) ) + return false; + + vm::util::deobfuscate( vm_handler ); + + static const auto calc_jmp_check = [ & ]( std::uintptr_t addr ) -> bool { + for ( const auto &[ instr, instr_raw, instr_addr ] : calc_jmp ) + if ( instr_addr == addr ) + return true; + + return false; + }; + + // find LEA RAX, [RDI+0xE0], else determine if the instruction is inside of calc_jmp... + auto result = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr ) -> bool { + return instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA && + instr.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI && + instr.instr.operands[ 1 ].mem.disp.value == 0xE0 + ? true + : calc_jmp_check( instr.addr ); + } ); + + // remove calc_jmp from the vm handler vector... + if ( result != vm_handler.end() ) + vm_handler.erase( result, vm_handler.end() ); + else // locate the last mov al, [rsi], + // then remove all instructions after that... { - if ( !vm::util::flatten( vm_handler, handler_addr ) ) - return false; - - vm::util::deobfuscate( vm_handler ); - - static const auto calc_jmp_check = [ & ]( std::uintptr_t addr ) -> bool { - for ( const auto &[ instr, instr_raw, instr_addr ] : calc_jmp ) - if ( instr_addr == addr ) - return true; - - return false; - }; - - // find LEA RAX, [RDI+0xE0], else determine if the instruction is inside of calc_jmp... - auto result = std::find_if( vm_handler.begin(), vm_handler.end(), []( const zydis_instr_t &instr ) -> bool { - return instr.instr.mnemonic == ZYDIS_MNEMONIC_LEA && - instr.instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI && - instr.instr.operands[ 1 ].mem.disp.value == 0xE0 - ? true - : calc_jmp_check( instr.addr ); - } ); + zydis_routine_t::iterator last = vm_handler.end(); + result = vm_handler.begin(); - // remove calc_jmp from the vm handler vector... - if ( result != vm_handler.end() ) - vm_handler.erase( result, vm_handler.end() ); - else // locate the last mov al, [rsi], - // then remove all instructions after that... + while ( result != vm_handler.end() ) { - zydis_routine_t::iterator last = vm_handler.end(); - result = vm_handler.begin(); - - while ( result != vm_handler.end() ) - { - result = std::find_if( ++result, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { - // mov/movsx/movzx rax/eax/ax/al, [rsi] - return instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; - } ); - - if ( result != vm_handler.end() ) - last = result; - } - - if ( last != vm_handler.end() ) - vm_handler.erase( last, vm_handler.end() ); + result = std::find_if( ++result, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { + // mov/movsx/movzx rax/eax/ax/al, [rsi] + return instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && + instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; + } ); + + if ( result != vm_handler.end() ) + last = result; } - return true; + + if ( last != vm_handler.end() ) + vm_handler.erase( last, vm_handler.end() ); } + return true; + } + + bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry, + std::uintptr_t *vm_handler_table, std::vector< vm::handler::handler_t > &vm_handlers ) + { + zydis_decoded_instr_t instr; + if ( !vm::handler::table::get_transform( vm_entry, &instr ) ) + return false; + + zydis_routine_t calc_jmp; + if ( !vm::calc_jmp::get( vm_entry, calc_jmp ) ) + return false; - bool get_all( std::uintptr_t module_base, std::uintptr_t image_base, zydis_routine_t &vm_entry, - std::uintptr_t *vm_handler_table, std::vector< vm::handler::handler_t > &vm_handlers ) + for ( auto idx = 0u; idx < 256; ++idx ) { - zydis_decoded_instr_t instr; - if ( !vm::handler::table::get_transform( vm_entry, &instr ) ) + handler_t vm_handler; + vm::transform::map_t transforms; + zydis_routine_t vm_handler_instrs; + + const auto decrypt_val = vm::handler::table::decrypt( instr, vm_handler_table[ idx ] ); + if ( !vm::handler::get( calc_jmp, vm_handler_instrs, ( decrypt_val - image_base ) + module_base ) ) return false; - zydis_routine_t calc_jmp; - if ( !vm::calc_jmp::get( vm_entry, calc_jmp ) ) + const auto has_imm = vm::handler::has_imm( vm_handler_instrs ); + const auto imm_size = vm::handler::imm_size( vm_handler_instrs ); + + if ( has_imm && + ( !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) || !imm_size.has_value() ) ) return false; - for ( auto idx = 0u; idx < 256; ++idx ) - { - handler_t vm_handler; - vm::transform::map_t transforms; - zydis_routine_t vm_handler_instrs; + vm_handler.address = ( decrypt_val - image_base ) + module_base; + vm_handler.instrs = vm_handler_instrs; + vm_handler.imm_size = imm_size.value(); + vm_handler.transforms = transforms; + vm_handler.profile = vm::handler::get_profile( vm_handler ); + vm_handlers.push_back( vm_handler ); + } - const auto decrypt_val = vm::handler::table::decrypt( instr, vm_handler_table[ idx ] ); - if ( !vm::handler::get( calc_jmp, vm_handler_instrs, ( decrypt_val - image_base ) + module_base ) ) - return false; + return true; + } - const auto has_imm = vm::handler::has_imm( vm_handler_instrs ); - const auto imm_size = vm::handler::imm_size( vm_handler_instrs ); + bool has_imm( const zydis_routine_t &vm_handler ) + { + zydis_instr_t instr_data; + return vm::util::get_fetch_operand( vm_handler, instr_data ); + } - if ( has_imm && ( !vm::handler::get_operand_transforms( vm_handler_instrs, transforms ) || - !imm_size.has_value() ) ) - return false; + std::optional< std::uint8_t > imm_size( const zydis_routine_t &vm_handler ) + { + zydis_instr_t instr_data; + if ( !vm::util::get_fetch_operand( vm_handler, instr_data ) ) + return {}; - vm_handler.address = ( decrypt_val - image_base ) + module_base; - vm_handler.instrs = vm_handler_instrs; - vm_handler.imm_size = imm_size.value(); - vm_handler.transforms = transforms; - vm_handler.profile = vm::handler::get_profile( vm_handler ); - vm_handlers.push_back( vm_handler ); - } + return instr_data.instr.operands[ 1 ].size; + } - return true; - } + bool get_operand_transforms( zydis_routine_t &vm_handler, transform::map_t &transforms ) + { + auto imm_fetch = vm::util::get_fetch_operand( vm_handler ); - bool has_imm( const zydis_routine_t &vm_handler ) - { - zydis_instr_t instr_data; - return vm::util::get_fetch_operand( vm_handler, instr_data ); - } + if ( !imm_fetch.has_value() ) + return false; - std::optional< std::uint8_t > imm_size( const zydis_routine_t &vm_handler ) - { - zydis_instr_t instr_data; - if ( !vm::util::get_fetch_operand( vm_handler, instr_data ) ) - return {}; + // this finds the first transformation which looks like: + // transform rax, rbx <--- note these registers can be smaller so we to64 them... + auto transform_instr = + std::find_if( imm_fetch.value(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && + util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && + util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ); + } ); - return instr_data.instr.operands[ 1 ].size; - } + if ( transform_instr == vm_handler.end() ) + return false; - bool get_operand_transforms( zydis_routine_t &vm_handler, transform::map_t &transforms ) - { - auto imm_fetch = vm::util::get_fetch_operand( vm_handler ); + // look for a primer/instruction that alters RAX prior to the 5 transformations... + auto generic0 = + std::find_if( imm_fetch.value(), transform_instr, []( const zydis_instr_t &instr_data ) -> bool { + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && + util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && + !util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ); + } ); - if ( !imm_fetch.has_value() ) - return false; + zydis_decoded_instr_t nogeneric0; + nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID; + transforms[ transform::type::generic0 ] = generic0 != transform_instr ? generic0->instr : nogeneric0; + + // last transformation is the same as the first except src and dest are swwapped... + transforms[ transform::type::rolling_key ] = transform_instr->instr; + auto instr_copy = transform_instr->instr; + instr_copy.operands[ 0 ].reg.value = transform_instr->instr.operands[ 1 ].reg.value; + instr_copy.operands[ 1 ].reg.value = transform_instr->instr.operands[ 0 ].reg.value; + transforms[ transform::type::update_key ] = instr_copy; - // this finds the first transformation which looks like: - // transform rax, rbx <--- note these registers can be smaller so we to64 them... - auto transform_instr = - std::find_if( imm_fetch.value(), vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { + // three generic transformations... + for ( auto idx = static_cast< unsigned >( vm::transform::type::generic1 ); + idx < static_cast< unsigned >( vm::transform::type::update_key ); ++idx ) + { + transform_instr = + std::find_if( ++transform_instr, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { return vm::transform::valid( instr_data.instr.mnemonic ) && instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && - util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && - util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ); + util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ); } ); if ( transform_instr == vm_handler.end() ) return false; - // look for a primer/instruction that alters RAX prior to the 5 transformations... - auto generic0 = std::find_if( imm_fetch.value(), transform_instr, []( const zydis_instr_t &instr_data ) -> bool { - return vm::transform::valid( instr_data.instr.mnemonic ) && - instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && - util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ) && - !util::reg::compare( instr_data.instr.operands[ 1 ].reg.value, ZYDIS_REGISTER_RBX ); - } ); + transforms[ static_cast< vm::transform::type >( idx ) ] = transform_instr->instr; + } - zydis_decoded_instr_t nogeneric0; - nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID; - transforms[ transform::type::generic0 ] = generic0 != transform_instr ? generic0->instr : nogeneric0; + return true; + } - // last transformation is the same as the first except src and dest are swwapped... - transforms[ transform::type::rolling_key ] = transform_instr->instr; - auto instr_copy = transform_instr->instr; - instr_copy.operands[ 0 ].reg.value = transform_instr->instr.operands[ 1 ].reg.value; - instr_copy.operands[ 1 ].reg.value = transform_instr->instr.operands[ 0 ].reg.value; - transforms[ transform::type::update_key ] = instr_copy; + vm::handler::profile_t *get_profile( handler_t &vm_handler ) + { + static const auto vcontains = []( vm::handler::profile_t *vprofile, handler_t *vm_handler ) -> bool { + if ( vprofile->imm_size != vm_handler->imm_size ) + return false; + + zydis_routine_t::iterator contains = vm_handler->instrs.begin(); - // three generic transformations... - for ( auto idx = static_cast< unsigned >( vm::transform::type::generic1 ); - idx < static_cast< unsigned >( vm::transform::type::update_key ); ++idx ) + for ( auto &instr : vprofile->signature ) { - transform_instr = - std::find_if( ++transform_instr, vm_handler.end(), []( const zydis_instr_t &instr_data ) -> bool { - return vm::transform::valid( instr_data.instr.mnemonic ) && - instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE && - util::reg::compare( instr_data.instr.operands[ 0 ].reg.value, ZYDIS_REGISTER_RAX ); - } ); - - if ( transform_instr == vm_handler.end() ) - return false; + contains = + std::find_if( contains, vm_handler->instrs.end(), + [ & ]( zydis_instr_t &instr_data ) -> bool { return instr( instr_data.instr ); } ); - transforms[ static_cast< vm::transform::type >( idx ) ] = transform_instr->instr; + if ( contains == vm_handler->instrs.end() ) + return false; } return true; - } + }; - vm::handler::profile_t *get_profile( handler_t &vm_handler ) - { - static const auto vcontains = []( vm::handler::profile_t *vprofile, handler_t *vm_handler ) -> bool { - if ( vprofile->imm_size != vm_handler->imm_size ) - return false; - - zydis_routine_t::iterator contains = vm_handler->instrs.begin(); + for ( auto profile : vm::handler::profile::all ) + if ( vcontains( profile, &vm_handler ) ) + return profile; - for ( auto &instr : vprofile->signature ) - { - contains = - std::find_if( contains, vm_handler->instrs.end(), [ & ]( zydis_instr_t &instr_data ) -> bool { - return instr( instr_data.instr ); - } ); + return nullptr; + } - if ( contains == vm_handler->instrs.end() ) - return false; - } + vm::handler::profile_t *get_profile( vm::handler::mnemonic_t mnemonic ) + { + auto result = + std::find_if( vm::handler::profile::all.begin(), vm::handler::profile::all.end(), + [ & ]( vm::handler::profile_t *profile ) -> bool { return profile->mnemonic == mnemonic; } ); - return true; - }; + return result != vm::handler::profile::all.end() ? *result : nullptr; + } - for ( auto profile : vm::handler::profile::all ) - if ( vcontains( profile, &vm_handler ) ) - return profile; + namespace table + { + std::uintptr_t *get( const zydis_routine_t &vm_entry ) + { + const auto result = + std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { + const auto instr = &instr_data.instr; + // lea r12, vm_handlers... (always r12)... + return instr->mnemonic == ZYDIS_MNEMONIC_LEA && + instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_R12 && + !instr->raw.sib.base; // no register used for the sib base... + } ); - return nullptr; - } + if ( result == vm_entry.end() ) + return nullptr; - vm::handler::profile_t *get_profile( vm::handler::mnemonic_t mnemonic ) - { - auto result = std::find_if( - vm::handler::profile::all.begin(), vm::handler::profile::all.end(), - [ & ]( vm::handler::profile_t *profile ) -> bool { return profile->mnemonic == mnemonic; } ); + auto ptr = 0ull; + ZydisCalcAbsoluteAddress( &result->instr, &result->instr.operands[ 1 ], result->addr, &ptr ); - return result != vm::handler::profile::all.end() ? *result : nullptr; + return reinterpret_cast< std::uintptr_t * >( ptr ); } - namespace table + bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ) { - std::uintptr_t *get( const zydis_routine_t &vm_entry ) - { - const auto result = - std::find_if( vm_entry.begin(), vm_entry.end(), []( const zydis_instr_t &instr_data ) -> bool { - const auto instr = &instr_data.instr; - // lea r12, vm_handlers... (always r12)... - return instr->mnemonic == ZYDIS_MNEMONIC_LEA && - instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_R12 && - !instr->raw.sib.base; // no register used for the sib base... - } ); - - if ( result == vm_entry.end() ) - return nullptr; - - auto ptr = 0ull; - ZydisCalcAbsoluteAddress( &result->instr, &result->instr.operands[ 1 ], result->addr, &ptr ); - - return reinterpret_cast< std::uintptr_t * >( ptr ); - } + auto handler_fetch = + std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool { + const auto instr = &instr_data.instr; + return instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 && + instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr->operands[ 1 ].mem.base == ZYDIS_REGISTER_R12 && + instr->operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX && + instr->operands[ 1 ].mem.scale == 8 && + instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + ( instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX || + instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RCX ); + } ); - bool get_transform( const zydis_routine_t &vm_entry, zydis_decoded_instr_t *transform_instr ) - { - auto handler_fetch = - std::find_if( vm_entry.begin(), vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool { - const auto instr = &instr_data.instr; - return instr->mnemonic == ZYDIS_MNEMONIC_MOV && instr->operand_count == 2 && - instr->operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr->operands[ 1 ].mem.base == ZYDIS_REGISTER_R12 && - instr->operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX && - instr->operands[ 1 ].mem.scale == 8 && - instr->operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - ( instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX || - instr->operands[ 0 ].reg.value == ZYDIS_REGISTER_RCX ); - } ); - - // check to see if we found the fetch instruction and if the next instruction - // is not the end of the vector... - if ( handler_fetch == vm_entry.end() || - // must be RCX or RDX... else something went wrong... - ( handler_fetch->instr.operands[ 0 ].reg.value != ZYDIS_REGISTER_RCX && - handler_fetch->instr.operands[ 0 ].reg.value != ZYDIS_REGISTER_RDX ) ) - return false; + // check to see if we found the fetch instruction and if the next instruction + // is not the end of the vector... + if ( handler_fetch == vm_entry.end() || + // must be RCX or RDX... else something went wrong... + ( handler_fetch->instr.operands[ 0 ].reg.value != ZYDIS_REGISTER_RCX && + handler_fetch->instr.operands[ 0 ].reg.value != ZYDIS_REGISTER_RDX ) ) + return false; - // find the next instruction that writes to RCX or RDX... - // the register is determined by the vm handler fetch above... - auto handler_transform = - std::find_if( handler_fetch, vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool { - return vm::transform::valid( instr_data.instr.mnemonic ) && - instr_data.instr.operands[ 0 ].reg.value == - handler_fetch->instr.operands[ 0 ].reg.value && - instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE; - } ); - - if ( handler_transform == vm_entry.end() ) - return false; + // find the next instruction that writes to RCX or RDX... + // the register is determined by the vm handler fetch above... + auto handler_transform = + std::find_if( handler_fetch, vm_entry.end(), [ & ]( const zydis_instr_t &instr_data ) -> bool { + return vm::transform::valid( instr_data.instr.mnemonic ) && + instr_data.instr.operands[ 0 ].reg.value == handler_fetch->instr.operands[ 0 ].reg.value && + instr_data.instr.operands[ 0 ].actions & ZYDIS_OPERAND_ACTION_WRITE; + } ); - *transform_instr = handler_transform->instr; - return true; - } + if ( handler_transform == vm_entry.end() ) + return false; - std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ) - { - assert( transform_instr.operands[ 0 ].size == 64, - "invalid transformation for vm handler table entries..." ); + *transform_instr = handler_transform->instr; + return true; + } - const auto operation = vm::transform::inverse[ transform_instr.mnemonic ]; - const auto bitsize = transform_instr.operands[ 0 ].size; - const auto imm = - vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u; + std::uint64_t encrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ) + { + assert( transform_instr.operands[ 0 ].size == 64, + "invalid transformation for vm handler table entries..." ); - return vm::transform::apply( bitsize, operation, val, imm ); - } + const auto operation = vm::transform::inverse[ transform_instr.mnemonic ]; + const auto bitsize = transform_instr.operands[ 0 ].size; + const auto imm = + vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u; - std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ) - { - assert( transform_instr.operands[ 0 ].size == 64, - "invalid transformation for vm handler table entries..." ); + return vm::transform::apply( bitsize, operation, val, imm ); + } - const auto operation = transform_instr.mnemonic; - const auto bitsize = transform_instr.operands[ 0 ].size; - const auto imm = - vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u; + std::uint64_t decrypt( zydis_decoded_instr_t &transform_instr, std::uint64_t val ) + { + assert( transform_instr.operands[ 0 ].size == 64, + "invalid transformation for vm handler table entries..." ); - return vm::transform::apply( bitsize, operation, val, imm ); - } - } // namespace table - } // namespace handler -} // namespace vm \ No newline at end of file + const auto operation = transform_instr.mnemonic; + const auto bitsize = transform_instr.operands[ 0 ].size; + const auto imm = + vm::transform::has_imm( &transform_instr ) ? transform_instr.operands[ 1 ].imm.value.u : 0u; + + return vm::transform::apply( bitsize, operation, val, imm ); + } + } // namespace table +} // namespace vm::handler \ No newline at end of file diff --git a/src/vmprofiles/add.cpp b/src/vmprofiles/add.cpp index 0700c81..883f69f 100644 --- a/src/vmprofiles/add.cpp +++ b/src/vmprofiles/add.cpp @@ -1,91 +1,73 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t addq = { - // ADD [RBP+8], RAX - // PUSHFQ - // POP [RBP] - "ADDQ", - ADDQ, - NULL, - { { // ADD [RBP+8], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; + vm::handler::profile_t addq = { + // ADD [RBP+8], RAX + // PUSHFQ + // POP [RBP] + "ADDQ", + ADDQ, + NULL, + { { // ADD [RBP+8], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; - vm::handler::profile_t adddw = { - // ADD [RBP+8], EAX - // PUSHFQ - // POP [RBP] - "ADDDW", - ADDDW, - NULL, - { { // ADD [RBP+8], EAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; + vm::handler::profile_t adddw = { + // ADD [RBP+8], EAX + // PUSHFQ + // POP [RBP] + "ADDDW", + ADDDW, + NULL, + { { // ADD [RBP+8], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; - vm::handler::profile_t addw = { - // ADD [RBP+8], AX - // PUSHFQ - // POP [RBP] - "ADDW", - ADDW, - NULL, - { { // ADD [RBP+8], AX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t addw = { + // ADD [RBP+8], AX + // PUSHFQ + // POP [RBP] + "ADDW", + ADDW, + NULL, + { { // ADD [RBP+8], AX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/call.cpp b/src/vmprofiles/call.cpp index 861c6d8..732ab80 100644 --- a/src/vmprofiles/call.cpp +++ b/src/vmprofiles/call.cpp @@ -1,40 +1,34 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t call = { - // MOV RDX, [RBP] - // ADD RBP, 0x8 - // CALL RDX - "CALL", - CALL, - NULL, - { { // MOV RDX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // ADD RBP, 0x8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // CALL RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_CALL && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t call = { + // MOV RDX, [RBP] + // ADD RBP, 0x8 + // CALL RDX + "CALL", + CALL, + NULL, + { { // MOV RDX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // ADD RBP, 0x8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // CALL RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_CALL && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/div.cpp b/src/vmprofiles/div.cpp index e459897..e23f25f 100644 --- a/src/vmprofiles/div.cpp +++ b/src/vmprofiles/div.cpp @@ -1,74 +1,58 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t divq = { - // MOV RDX, [RBP] - // MOV RAX, [RBP+0x8] - // DIV [RBP+0x10] - // MOV [RBP+0x8], RDX - // MOV [RBP+0x10], RAX - // PUSHFQ - // POP [RBP] - "DIVQ", - DIVQ, - NULL, - { { // MOV RDX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV RAX, [RBP+0x8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.index == 0x8; - }, - // DIV [RBP+0x10] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_DIV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.index == 0x10; - }, - // MOV [RBP+0x8], RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.index == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; - }, - // MOV [RBP+0x10], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.index == 0x10 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t divq = { + // MOV RDX, [RBP] + // MOV RAX, [RBP+0x8] + // DIV [RBP+0x10] + // MOV [RBP+0x8], RDX + // MOV [RBP+0x10], RAX + // PUSHFQ + // POP [RBP] + "DIVQ", + DIVQ, + NULL, + { { // MOV RDX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV RAX, [RBP+0x8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.index == 0x8; + }, + // DIV [RBP+0x10] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_DIV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 0 ].mem.index == 0x10; + }, + // MOV [RBP+0x8], RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 0 ].mem.index == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; + }, + // MOV [RBP+0x10], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 0 ].mem.index == 0x10 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/jmp.cpp b/src/vmprofiles/jmp.cpp index 00d4298..08cb66d 100644 --- a/src/vmprofiles/jmp.cpp +++ b/src/vmprofiles/jmp.cpp @@ -1,51 +1,45 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t jmp = { - // MOV ESI, [RBP] - // ADD RSI, RAX - // MOV RBX, RSI - // ADD RSI, [RBP] - "JMP", - JMP, - NULL, - { { // MOV ESI, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // ADD RSI, RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // MOV RBX, RSI - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RSI; - }, - // ADD RSI, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t jmp = { + // MOV ESI, [RBP] + // ADD RSI, RAX + // MOV RBX, RSI + // ADD RSI, [RBP] + "JMP", + JMP, + NULL, + { { // MOV ESI, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_ESI && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // ADD RSI, RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // MOV RBX, RSI + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RSI; + }, + // ADD RSI, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSI && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/lconst.cpp b/src/vmprofiles/lconst.cpp index cd93080..d63e6a2 100644 --- a/src/vmprofiles/lconst.cpp +++ b/src/vmprofiles/lconst.cpp @@ -1,239 +1,222 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t lconstq = { - // MOV RAX, [RSI] - // SUB RBP, 8 - // MOV [RBP], RAX - "LCONSTQ", - LCONSTQ, - 64, - { { // SUB RBP, 8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // MOV [RBP], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - } } } }; + vm::handler::profile_t lconstq = { + // MOV RAX, [RSI] + // SUB RBP, 8 + // MOV [RBP], RAX + "LCONSTQ", + LCONSTQ, + 64, + { { // SUB RBP, 8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // MOV [RBP], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + } } } }; - vm::handler::profile_t lconstdw = { - // SUB RBP, 4 - // MOV [RBP], EAX - "LCONSTDW", - LCONSTDW, - 32, - { { // SUB RBP, 4 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x4; - }, - // MOV [RBP], EAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; - } } } }; + vm::handler::profile_t lconstdw = { + // SUB RBP, 4 + // MOV [RBP], EAX + "LCONSTDW", + LCONSTDW, + 32, + { { // SUB RBP, 4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // MOV [RBP], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + } } } }; - vm::handler::profile_t lconstw = { - // SUB RBP, 2 - // MOV [RBP], AX - "LCONSTW", - LCONSTW, - 16, - { { // SUB RBP, 2 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x2; - }, - // MOV [RBP], AX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; - } } } }; + vm::handler::profile_t lconstw = { + // SUB RBP, 2 + // MOV [RBP], AX + "LCONSTW", + LCONSTW, + 16, + { { // SUB RBP, 2 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x2; + }, + // MOV [RBP], AX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; + } } } }; - vm::handler::profile_t lconstbzxw = { - // MOV AL, [RSI] - // SUB RBP, 2 - // MOV [RBP], AX - "LCONSTBZXW", - LCONSTBZXW, - 8, - { { // SUB RBP, 2 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x2; - }, - // MOV [RBP], AX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; - } } } }; + vm::handler::profile_t lconstbzxw = { + // MOV AL, [RSI] + // SUB RBP, 2 + // MOV [RBP], AX + "LCONSTBZXW", + LCONSTBZXW, + 8, + { { // SUB RBP, 2 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x2; + }, + // MOV [RBP], AX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; + } } } }; - vm::handler::profile_t lconstbsxdw = { - // CWDE - // SUB RBP, 4 - // MOV [RBP], EAX - "LCONSTBSXDW", - LCONSTBSXDW, - 8, - { { // CWDE - []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CWDE; }, - // SUB RBP, 4 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x4; - }, - // MOV [RBP], EAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; - } } }, - vm::handler::extention_t::sign_extend }; + vm::handler::profile_t lconstbsxdw = { + // CWDE + // SUB RBP, 4 + // MOV [RBP], EAX + "LCONSTBSXDW", + LCONSTBSXDW, + 8, + { { // CWDE + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CWDE; }, + // SUB RBP, 4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // MOV [RBP], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + } } }, + vm::handler::extention_t::sign_extend }; - vm::handler::profile_t lconstbsxq = { - // CDQE - // SUB RBP, 0x8 - // MOV [RBP], RAX - "LCONSTBSXQ", - LCONSTBSXQ, - 8, - { { // CDQE - []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; }, - // SUB RBP, 0x8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // MOV [RBP], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - } } }, - vm::handler::extention_t::sign_extend }; + vm::handler::profile_t lconstbsxq = { + // CDQE + // SUB RBP, 0x8 + // MOV [RBP], RAX + "LCONSTBSXQ", + LCONSTBSXQ, + 8, + { { // CDQE + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; }, + // SUB RBP, 0x8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // MOV [RBP], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + } } }, + vm::handler::extention_t::sign_extend }; - vm::handler::profile_t lconstdwsxq = { - // CDQE - // SUB RBP, 8 - // MOV [RBP], RAX - "LCONSTDWSXQ", - LCONSTDWSXQ, - 32, - { // CDQE - []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; }, - // SUB RBP, 8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // MOV [RBP], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - } }, - vm::handler::extention_t::sign_extend }; + vm::handler::profile_t lconstdwsxq = { + // CDQE + // SUB RBP, 8 + // MOV [RBP], RAX + "LCONSTDWSXQ", + LCONSTDWSXQ, + 32, + { // CDQE + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; }, + // SUB RBP, 8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.operands[ 1 ].imm.value.u == 0x8; + }, + // MOV [RBP], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + } }, + vm::handler::extention_t::sign_extend }; - vm::handler::profile_t lconstwsxq = { - // CDQE - // SUB RBP, 8 - // MOV [RBP], RAX - "LCONSTWSXQ", - LCONSTWSXQ, - 16, - { { // CDQE - []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; }, - // SUB RBP, 8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // MOV [RBP], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - } } }, - vm::handler::extention_t::sign_extend }; + vm::handler::profile_t lconstwsxq = { + // CDQE + // SUB RBP, 8 + // MOV [RBP], RAX + "LCONSTWSXQ", + LCONSTWSXQ, + 16, + { { // CDQE + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CDQE; }, + // SUB RBP, 8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // MOV [RBP], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + } } }, + vm::handler::extention_t::sign_extend }; - vm::handler::profile_t lconstwsxdw = { - // CWDE - // SUB RBP, 4 - // MOV [RBP], EAX - "LCONSTWSXDW", - LCONSTWSXDW, - 16, - { { // CWDE - []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CWDE; }, - // SUB RBP, 4 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x4; - }, - // MOV [RBP], EAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; - } } }, - vm::handler::extention_t::sign_extend }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t lconstwsxdw = { + // CWDE + // SUB RBP, 4 + // MOV [RBP], EAX + "LCONSTWSXDW", + LCONSTWSXDW, + 16, + { { // CWDE + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_CWDE; }, + // SUB RBP, 4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // MOV [RBP], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + } } }, + vm::handler::extention_t::sign_extend }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/lflags.cpp b/src/vmprofiles/lflags.cpp index 0317bea..0c8a523 100644 --- a/src/vmprofiles/lflags.cpp +++ b/src/vmprofiles/lflags.cpp @@ -1,36 +1,27 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t lrflags = { - // PUSH [RBP] - // ADD RBP, 0x8 - // POPFQ - "LRFLAGS", - LRFLAGS, - NULL, - { { // PUSH [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // ADD RBP, 0x8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // POPFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t lrflags = { + // PUSH [RBP] + // ADD RBP, 0x8 + // POPFQ + "LRFLAGS", + LRFLAGS, + NULL, + { { // PUSH [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_PUSH && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // ADD RBP, 0x8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // POPFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ; } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/lreg.cpp b/src/vmprofiles/lreg.cpp index 93ccb9e..eb9ed7c 100644 --- a/src/vmprofiles/lreg.cpp +++ b/src/vmprofiles/lreg.cpp @@ -1,81 +1,73 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t lregq = { - // MOV RDX, [RAX+RDI] - // SUB RBP, 8 - // MOV [RBP], RDX - "LREGQ", - LREGQ, - 8, - { { // MOV RDX, [RAX+RDI] or MOV RDX, [RDI+RAX] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - ( instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX || - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI ) && - ( instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RDI || - instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX ); - }, - // SUB RBP, 8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // MOV [RBP], RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; - } } } }; + vm::handler::profile_t lregq = { + // MOV RDX, [RAX+RDI] + // SUB RBP, 8 + // MOV [RBP], RDX + "LREGQ", + LREGQ, + 8, + { { // MOV RDX, [RAX+RDI] or MOV RDX, [RDI+RAX] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + ( instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX || + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI ) && + ( instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RDI || + instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX ); + }, + // SUB RBP, 8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // MOV [RBP], RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; + } } } }; - vm::handler::profile_t lregdw = { - // MOVZX AL, [RSI] - // MOV RDX, [RAX + RDI] - // SUB RBP, 0x4 - // MOV [RBP], EDX - "LREGDW", - LREGDW, - 8, - { { // MOV RDX, [RAX + RDI] or MOV RDX, [RDI + RAX] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - ( instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX || - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI ) && - ( instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX || - instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RDI ); - }, - // SUB RBP, 0x4 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x4; - }, - // MOV [RBP], EDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX; - } } } }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t lregdw = { + // MOVZX AL, [RSI] + // MOV RDX, [RAX + RDI] + // SUB RBP, 0x4 + // MOV [RBP], EDX + "LREGDW", + LREGDW, + 8, + { { // MOV RDX, [RAX + RDI] or MOV RDX, [RDI + RAX] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + ( instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX || + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RDI ) && + ( instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RAX || + instr.operands[ 1 ].mem.index == ZYDIS_REGISTER_RDI ); + }, + // SUB RBP, 0x4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // MOV [RBP], EDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/mul.cpp b/src/vmprofiles/mul.cpp index 29c22b3..f5ebaa1 100644 --- a/src/vmprofiles/mul.cpp +++ b/src/vmprofiles/mul.cpp @@ -1,73 +1,61 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t mulq = { - // MOV RAX, [RBP+0x8] - // SUB RBP, 0x8 - // MUL RDX - // MOV [RBP+0x8], RDX - // MOV [RBP+0x10], RAX - // PUSHFQ - // POP [RBP] - "MULQ", - MULQ, - NULL, - { { // MOV RAX, [RBP+0x8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x8; - }, - // SUB RBP, 0x8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // MUL RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MUL && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX; - }, - // MOV [RBP+0x8], RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; - }, - // MOV [RBP+0x10], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x10 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t mulq = { + // MOV RAX, [RBP+0x8] + // SUB RBP, 0x8 + // MUL RDX + // MOV [RBP+0x8], RDX + // MOV [RBP+0x10], RAX + // PUSHFQ + // POP [RBP] + "MULQ", + MULQ, + NULL, + { { // MOV RAX, [RBP+0x8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8; + }, + // SUB RBP, 0x8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // MUL RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MUL && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX; + }, + // MOV [RBP+0x8], RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; + }, + // MOV [RBP+0x10], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x10 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/nand.cpp b/src/vmprofiles/nand.cpp index b92a051..4e23dc0 100644 --- a/src/vmprofiles/nand.cpp +++ b/src/vmprofiles/nand.cpp @@ -1,183 +1,161 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t nandq = { - // MOV RAX, [RBP] - // MOV RDX, [RBP+8] - // NOT RAX - // NOT RDX - // AND RAX, RDX - // MOV [RBP], RAX - // PUSHFQ - // POP [RBP] - "NANDQ", - NANDQ, - NULL, - { { // MOV RAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV RDX, [RBP+8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x8; - }, - // NOT RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_NOT && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // NOT RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_NOT && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX; - }, - // AND RAX, RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_AND && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; - }, - // MOV [RBP], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; + vm::handler::profile_t nandq = { + // MOV RAX, [RBP] + // MOV RDX, [RBP+8] + // NOT RAX + // NOT RDX + // AND RAX, RDX + // MOV [RBP], RAX + // PUSHFQ + // POP [RBP] + "NANDQ", + NANDQ, + NULL, + { { // MOV RAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV RDX, [RBP+8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8; + }, + // NOT RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_NOT && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // NOT RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_NOT && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX; + }, + // AND RAX, RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_AND && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; + }, + // MOV [RBP], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; - vm::handler::profile_t nanddw = { - // NOT QWORD PTR [RBP] - // MOV EAX, [RBP] - // SUB RBP, 0x4 - // AND [RBP+0x8], EAX - // PUSHFQ - // POP [RBP] - "NANDDW", - NANDDW, - NULL, - { { // NOT QWORD PTR [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_NOT && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].size == 64 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV EAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // SUB RBP, 0x4 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x4; - }, - // AND [RBP+0x8], EAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_AND && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; + vm::handler::profile_t nanddw = { + // NOT QWORD PTR [RBP] + // MOV EAX, [RBP] + // SUB RBP, 0x4 + // AND [RBP+0x8], EAX + // PUSHFQ + // POP [RBP] + "NANDDW", + NANDDW, + NULL, + { { // NOT QWORD PTR [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_NOT && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].size == 64 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV EAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // SUB RBP, 0x4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // AND [RBP+0x8], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_AND && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; - vm::handler::profile_t nandw = { - // NOT DWORD PTR [RBP] - // MOV AX, [RBP] - // SUB RBP, 0x6 - // AND [RBP+0x8], AX - // PUSHFQ - // POP [RBP] - "NANDW", - NANDW, - NULL, - { { // NOT DWORD PTR [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_NOT && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].size == 32 && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV AX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // SUB RBP, 0x6 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x6; - }, - // AND [RBP+0x8], AX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_AND && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t nandw = { + // NOT DWORD PTR [RBP] + // MOV AX, [RBP] + // SUB RBP, 0x6 + // AND [RBP+0x8], AX + // PUSHFQ + // POP [RBP] + "NANDW", + NANDW, + NULL, + { { // NOT DWORD PTR [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_NOT && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].size == 32 && instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV AX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // SUB RBP, 0x6 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x6; + }, + // AND [RBP+0x8], AX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_AND && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/pushvsp.cpp b/src/vmprofiles/pushvsp.cpp index 5206bd4..426b99e 100644 --- a/src/vmprofiles/pushvsp.cpp +++ b/src/vmprofiles/pushvsp.cpp @@ -1,41 +1,34 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t pushvsp = { - // MOV RAX, RBP - // SUB RBP, 8 - "PUSHVSP", - PUSHVSP, - NULL, - { { // MOV RAX, RBP - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP; - }, - // SUB RBP, 8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x8; - }, - // MOV [RBP], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t pushvsp = { + // MOV RAX, RBP + // SUB RBP, 8 + "PUSHVSP", + PUSHVSP, + NULL, + { { // MOV RAX, RBP + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP; + }, + // SUB RBP, 8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x8; + }, + // MOV [RBP], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/read.cpp b/src/vmprofiles/read.cpp index 632cbd7..048855b 100644 --- a/src/vmprofiles/read.cpp +++ b/src/vmprofiles/read.cpp @@ -1,66 +1,57 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t readq = { - // MOV RAX, [RAX] - // MOV [RBP], RAX - "READQ", - READQ, - NULL, - { { - // MOV RAX, [RAX] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX; - }, - // MOV [RBP], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - } } } }; + vm::handler::profile_t readq = { + // MOV RAX, [RAX] + // MOV [RBP], RAX + "READQ", + READQ, + NULL, + { { // MOV RAX, [RAX] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX; + }, + // MOV [RBP], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + } } } }; - vm::handler::profile_t readdw = { - // ADD RBP, 0x4 - // MOV EAX, [RAX] - // MOV [RBP], EAX - "READDW", - READDW, - NULL, - { { // ADD RBP, 0x4 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x4; - }, - // MOV EAX, [RAX] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX; - }, - // MOV [RBP], EAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t readdw = { + // ADD RBP, 0x4 + // MOV EAX, [RAX] + // MOV [RBP], EAX + "READDW", + READDW, + NULL, + { { // ADD RBP, 0x4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // MOV EAX, [RAX] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RAX; + }, + // MOV [RBP], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/shl.cpp b/src/vmprofiles/shl.cpp index 57bb435..fd8ad94 100644 --- a/src/vmprofiles/shl.cpp +++ b/src/vmprofiles/shl.cpp @@ -1,138 +1,122 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t shlq = { - // MOV RAX, [RBP] - // MOV CL, [RBP+0x8] - // SUB RBP, 0x6 - // SHL RAX, CL - // MOV [RBP+0x8], RAX - // PUSHFQ - // POP [RBP] - "SHLQ", - SHLQ, - NULL, - { { // MOV RAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV CL, [RBP+0x8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x8; - }, - // SUB RBP, 0x6 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x6; - }, - // SHL RAX, CL - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SHL && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; - }, - // MOV [RBP+0x8], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; + vm::handler::profile_t shlq = { + // MOV RAX, [RBP] + // MOV CL, [RBP+0x8] + // SUB RBP, 0x6 + // SHL RAX, CL + // MOV [RBP+0x8], RAX + // PUSHFQ + // POP [RBP] + "SHLQ", + SHLQ, + NULL, + { { // MOV RAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV CL, [RBP+0x8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8; + }, + // SUB RBP, 0x6 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x6; + }, + // SHL RAX, CL + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SHL && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; + }, + // MOV [RBP+0x8], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; - vm::handler::profile_t shldw = { - // MOV EAX, [RBP] - // MOV CL, [RBP+0x4] - // SUB RBP, 0x6 - // SHL EAX, CL - // MOV [RBP+0x8], EAX - // PUSHFQ - // POP [RBP] - "SHLQ", - SHLQ, - NULL, - { { // MOV EAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV CL, [RBP+0x4] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x4; - }, - // SUB RBP, 0x6 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x6; - }, - // SHL EAX, CL - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SHL && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; - }, - // MOV [RBP+0x8], EAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t shldw = { + // MOV EAX, [RBP] + // MOV CL, [RBP+0x4] + // SUB RBP, 0x6 + // SHL EAX, CL + // MOV [RBP+0x8], EAX + // PUSHFQ + // POP [RBP] + "SHLQ", + SHLQ, + NULL, + { { // MOV EAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV CL, [RBP+0x4] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x4; + }, + // SUB RBP, 0x6 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x6; + }, + // SHL EAX, CL + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SHL && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; + }, + // MOV [RBP+0x8], EAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/shr.cpp b/src/vmprofiles/shr.cpp index 41f1f78..f728fe4 100644 --- a/src/vmprofiles/shr.cpp +++ b/src/vmprofiles/shr.cpp @@ -1,138 +1,122 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t shrq = { - // MOV RAX, [RBP] - // MOV CL, [RBP+0x8] - // SUB RBP, 0x6 - // SHR RAX, CL - // MOV [RBP+0x8], RAX - // PUSHFQ - // POP [RBP] - "SHRQ", - SHRQ, - NULL, - { { // MOV RAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV CL, [RBP+0x8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x8; - }, - // SUB RBP, 0x6 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x6; - }, - // SHR RAX, CL - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SHR && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; - }, - // MOV [RBP+0x8], RAX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - - vm::handler::profile_t shrw = { - // MOV AX, [RBP] - // MOV CL, [RBP+0x2] - // SUB RBP, 0x6 - // SHR AX, CL - // MOV [RBP+0x8], AX - // PUSHFQ - // POP [RBP] - "SHRW", - SHRW, - NULL, - { { // MOV AX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV CL, [RBP+0x2] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x2; - }, - // SUB RBP, 0x6 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SUB && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x6; - }, - // SHR AX, CL - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_SHR && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; - }, - // MOV [RBP+0x8], AX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 0 ].mem.disp.value == 0x8 && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; - }, - // PUSHFQ - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; - }, - // POP [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_POP && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t shrq = { + // MOV RAX, [RBP] + // MOV CL, [RBP+0x8] + // SUB RBP, 0x6 + // SHR RAX, CL + // MOV [RBP+0x8], RAX + // PUSHFQ + // POP [RBP] + "SHRQ", + SHRQ, + NULL, + { { // MOV RAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV CL, [RBP+0x8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8; + }, + // SUB RBP, 0x6 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x6; + }, + // SHR RAX, CL + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SHR && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; + }, + // MOV [RBP+0x8], RAX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RAX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; + + vm::handler::profile_t shrw = { + // MOV AX, [RBP] + // MOV CL, [RBP+0x2] + // SUB RBP, 0x6 + // SHR AX, CL + // MOV [RBP+0x8], AX + // PUSHFQ + // POP [RBP] + "SHRW", + SHRW, + NULL, + { { // MOV AX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV CL, [RBP+0x2] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_CL && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x2; + }, + // SUB RBP, 0x6 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SUB && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x6; + }, + // SHR AX, CL + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_SHR && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_AX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_CL; + }, + // MOV [RBP+0x8], AX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP && + instr.operands[ 0 ].mem.disp.value == 0x8 && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_AX; + }, + // PUSHFQ + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ; }, + // POP [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/sreg.cpp b/src/vmprofiles/sreg.cpp index 8380479..8883226 100644 --- a/src/vmprofiles/sreg.cpp +++ b/src/vmprofiles/sreg.cpp @@ -1,115 +1,105 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t sregq = { - // MOV RDX, [RBP] - // ADD RBP, 8 - // MOV [RAX+RDI], RDX - "SREGQ", - SREGQ, - 8, - { { // MOV RDX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // ADD RBP, 8 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 8; - }, - // MOV [RAX+RDI], RDX or MOV [RDI+RAX], RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX || - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) && - ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI || - instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX ) && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; - } } } }; + vm::handler::profile_t sregq = { + // MOV RDX, [RBP] + // ADD RBP, 8 + // MOV [RAX+RDI], RDX + "SREGQ", + SREGQ, + 8, + { { // MOV RDX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // ADD RBP, 8 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && instr.operands[ 1 ].imm.value.u == 8; + }, + // MOV [RAX+RDI], RDX or MOV [RDI+RAX], RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX || + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) && + ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI || + instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX ) && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; + } } } }; - vm::handler::profile_t sregdw = { - // MOV EDX, [RBP] - // ADD RBP, 0x4 - // MOV [RAX+RDI], EDX - "SREGDW", - SREGDW, - 8, - { { // MOV EDX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // ADD RBP, 0x4 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x4; - }, - // MOV [RAX+RDI], EDX or MOV [RDI+RAX], EDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX || - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) && - ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX || - instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI ) && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX; - } } } }; + vm::handler::profile_t sregdw = { + // MOV EDX, [RBP] + // ADD RBP, 0x4 + // MOV [RAX+RDI], EDX + "SREGDW", + SREGDW, + 8, + { { // MOV EDX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // ADD RBP, 0x4 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x4; + }, + // MOV [RAX+RDI], EDX or MOV [RDI+RAX], EDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX || + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) && + ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX || + instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI ) && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX; + } } } }; - vm::handler::profile_t sregw = { - // MOV DX, [RBP] - // ADD RBP, 0x2 - // MOV [RAX+RDI], DX - "SREGW", - SREGW, - 8, - { { // MOV DX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_DX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // ADD RBP, 0x2 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x2; - }, - // MOV [RAX+RDI], DX or MOV [RDI+RAX], DX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX || - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) && - ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI || - instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX ) && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_DX; - } } } }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t sregw = { + // MOV DX, [RBP] + // ADD RBP, 0x2 + // MOV [RAX+RDI], DX + "SREGW", + SREGW, + 8, + { { // MOV DX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_DX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // ADD RBP, 0x2 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x2; + }, + // MOV [RAX+RDI], DX or MOV [RDI+RAX], DX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + ( instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX || + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RDI ) && + ( instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RDI || + instr.operands[ 0 ].mem.index == ZYDIS_REGISTER_RAX ) && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_DX; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/vmexit.cpp b/src/vmprofiles/vmexit.cpp index 76e1791..72b6828 100644 --- a/src/vmprofiles/vmexit.cpp +++ b/src/vmprofiles/vmexit.cpp @@ -1,29 +1,21 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t vmexit = { - // MOV RSP, RBP - // RET - "VMEXIT", - VMEXIT, - NULL, - { { // MOV RSP, RBP - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP; - }, - // RET - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_RET; - } } } }; - } - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t vmexit = { + // MOV RSP, RBP + // RET + "VMEXIT", + VMEXIT, + NULL, + { { // MOV RSP, RBP + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RSP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RBP; + }, + // RET + []( const zydis_decoded_instr_t &instr ) -> bool { return instr.mnemonic == ZYDIS_MNEMONIC_RET; } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmprofiles/write.cpp b/src/vmprofiles/write.cpp index 5041a29..c37ef76 100644 --- a/src/vmprofiles/write.cpp +++ b/src/vmprofiles/write.cpp @@ -1,136 +1,124 @@ #include -namespace vm +namespace vm::handler::profile { - namespace handler - { - namespace profile - { - vm::handler::profile_t writeq = { - // MOV RAX, [RBP] - // MOV RDX, [RBP+0x8] - // ADD RBP, 0x10 - // MOV [RAX], RDX - "WRITEQ", - WRITEQ, - NULL, - { { // MOV RAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV RDX, [RBP+0x8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x8; - }, - // ADD RBP, 0x10 - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0x10; - }, - // MOV [RAX], RDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; - } } } }; + vm::handler::profile_t writeq = { + // MOV RAX, [RBP] + // MOV RDX, [RBP+0x8] + // ADD RBP, 0x10 + // MOV [RAX], RDX + "WRITEQ", + WRITEQ, + NULL, + { { // MOV RAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV RDX, [RBP+0x8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8; + }, + // ADD RBP, 0x10 + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0x10; + }, + // MOV [RAX], RDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_RDX; + } } } }; - vm::handler::profile_t writedw = { - // MOV RAX, [RBP] - // MOV EDX, [RBP+0x8] - // ADD RBP, 0xC - // MOV [RAX], EDX - "WRITEDW", - WRITEDW, - NULL, - { { // MOV RAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV EDX, [RBP+0x8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x8; - }, - // ADD RBP, 0xC - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0xC; - }, - // MOV [RAX], EDX - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX; - } } } }; + vm::handler::profile_t writedw = { + // MOV RAX, [RBP] + // MOV EDX, [RBP+0x8] + // ADD RBP, 0xC + // MOV [RAX], EDX + "WRITEDW", + WRITEDW, + NULL, + { { // MOV RAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV EDX, [RBP+0x8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_EDX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8; + }, + // ADD RBP, 0xC + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0xC; + }, + // MOV [RAX], EDX + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_EDX; + } } } }; - vm::handler::profile_t writeb = { - // MOV RAX, [RBP] - // MOV DL, [RBP+0x8] - // ADD RBP, 0xA - // MOV [RAX], DL - "WRITEB", - WRITEB, - NULL, - { { // MOV RAX, [RBP] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; - }, - // MOV DL, [RBP+0x8] - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_DL && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].mem.disp.value == 0x8; - }, - // ADD RBP, 0xA - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_ADD && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - instr.operands[ 1 ].imm.value.u == 0xA; - }, - // MOV [RAX], DL - []( const zydis_decoded_instr_t &instr ) -> bool { - return instr.mnemonic == ZYDIS_MNEMONIC_MOV && - instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && - instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_DL; - } } } }; - } // namespace profile - } // namespace handler -} // namespace vm \ No newline at end of file + vm::handler::profile_t writeb = { + // MOV RAX, [RBP] + // MOV DL, [RBP+0x8] + // ADD RBP, 0xA + // MOV [RAX], DL + "WRITEB", + WRITEB, + NULL, + { { // MOV RAX, [RBP] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + }, + // MOV DL, [RBP+0x8] + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_DL && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP && instr.operands[ 1 ].mem.disp.value == 0x8; + }, + // ADD RBP, 0xA + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_ADD && + instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + instr.operands[ 1 ].imm.value.u == 0xA; + }, + // MOV [RAX], DL + []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 0 ].mem.base == ZYDIS_REGISTER_RAX && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 1 ].reg.value == ZYDIS_REGISTER_DL; + } } } }; +} // namespace vm::handler::profile \ No newline at end of file diff --git a/src/vmutils.cpp b/src/vmutils.cpp index 85cb779..35b3fdf 100644 --- a/src/vmutils.cpp +++ b/src/vmutils.cpp @@ -1,47 +1,24 @@ #include -namespace vm +namespace vm::util { - namespace util + namespace reg { - namespace reg + zydis_register_t to64( zydis_register_t reg ) { - zydis_register_t to64( zydis_register_t reg ) - { - return ZydisRegisterGetLargestEnclosing( ZYDIS_MACHINE_MODE_LONG_64, reg ); - } - - bool compare( zydis_register_t a, zydis_register_t b ) - { - return to64( a ) == to64( b ); - } - } // namespace reg + return ZydisRegisterGetLargestEnclosing( ZYDIS_MACHINE_MODE_LONG_64, reg ); + } - bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ) + bool compare( zydis_register_t a, zydis_register_t b ) { - const auto result = - std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool { - // mov/movsx/movzx rax/eax/ax/al, [rsi] - return instr_data.instr.operand_count > 1 && - ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || - instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && - instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && - util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && - instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && - instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; - } ); - - if ( result == routine.end() ) - return false; - - fetch_instr = *result; - return true; + return to64( a ) == to64( b ); } + } // namespace reg - std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ) - { - auto result = std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool { + bool get_fetch_operand( const zydis_routine_t &routine, zydis_instr_t &fetch_instr ) + { + const auto result = + std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool { // mov/movsx/movzx rax/eax/ax/al, [rsi] return instr_data.instr.operand_count > 1 && ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || @@ -53,209 +30,229 @@ namespace vm instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; } ); - if ( result == routine.end() ) - return {}; + if ( result == routine.end() ) + return false; - return result; - } + fetch_instr = *result; + return true; + } - void print( const zydis_decoded_instr_t &instr ) + std::optional< zydis_routine_t::iterator > get_fetch_operand( zydis_routine_t &routine ) + { + auto result = std::find_if( routine.begin(), routine.end(), []( const zydis_instr_t &instr_data ) -> bool { + // mov/movsx/movzx rax/eax/ax/al, [rsi] + return instr_data.instr.operand_count > 1 && + ( instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVSX || + instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOVZX ) && + instr_data.instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + util::reg::to64( instr_data.instr.operands[ 0 ].reg.value ) == ZYDIS_REGISTER_RAX && + instr_data.instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr_data.instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RSI; + } ); + + if ( result == routine.end() ) + return {}; + + return result; + } + + 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 ); + 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 ) { - char buffer[ 256 ]; - ZydisFormatter formatter; - ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); - ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), 0u ); - std::puts( buffer ); + ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); + std::printf( "> 0x%p %s", addr, buffer ); } + } - void print( zydis_routine_t &routine ) + bool is_jmp( const zydis_decoded_instr_t &instr ) + { + switch ( instr.mnemonic ) { - char buffer[ 256 ]; - ZydisFormatter formatter; - ZydisFormatterInit( &formatter, ZYDIS_FORMATTER_STYLE_INTEL ); - - for ( auto [ instr, raw, addr ] : routine ) - { - ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); - std::printf( "> 0x%p %s", addr, buffer ); - } + case ZYDIS_MNEMONIC_JB: + case ZYDIS_MNEMONIC_JBE: + case ZYDIS_MNEMONIC_JCXZ: + case ZYDIS_MNEMONIC_JECXZ: + case ZYDIS_MNEMONIC_JKNZD: + case ZYDIS_MNEMONIC_JKZD: + case ZYDIS_MNEMONIC_JL: + case ZYDIS_MNEMONIC_JLE: + case ZYDIS_MNEMONIC_JMP: + case ZYDIS_MNEMONIC_JNB: + case ZYDIS_MNEMONIC_JNBE: + case ZYDIS_MNEMONIC_JNL: + case ZYDIS_MNEMONIC_JNLE: + case ZYDIS_MNEMONIC_JNO: + case ZYDIS_MNEMONIC_JNP: + case ZYDIS_MNEMONIC_JNS: + case ZYDIS_MNEMONIC_JNZ: + case ZYDIS_MNEMONIC_JO: + case ZYDIS_MNEMONIC_JP: + case ZYDIS_MNEMONIC_JRCXZ: + case ZYDIS_MNEMONIC_JS: + case ZYDIS_MNEMONIC_JZ: + return true; + default: + break; } + return false; + } - bool is_jmp( const zydis_decoded_instr_t &instr ) + bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps ) + { + ZydisDecoder decoder; + zydis_decoded_instr_t instr; + ZydisDecoderInit( &decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64 ); + + while ( ZYAN_SUCCESS( + ZydisDecoderDecodeBuffer( &decoder, reinterpret_cast< void * >( routine_addr ), 0x1000, &instr ) ) ) { - switch ( instr.mnemonic ) - { - case ZYDIS_MNEMONIC_JB: - case ZYDIS_MNEMONIC_JBE: - case ZYDIS_MNEMONIC_JCXZ: - case ZYDIS_MNEMONIC_JECXZ: - case ZYDIS_MNEMONIC_JKNZD: - case ZYDIS_MNEMONIC_JKZD: - case ZYDIS_MNEMONIC_JL: - case ZYDIS_MNEMONIC_JLE: - case ZYDIS_MNEMONIC_JMP: - case ZYDIS_MNEMONIC_JNB: - case ZYDIS_MNEMONIC_JNBE: - case ZYDIS_MNEMONIC_JNL: - case ZYDIS_MNEMONIC_JNLE: - case ZYDIS_MNEMONIC_JNO: - case ZYDIS_MNEMONIC_JNP: - case ZYDIS_MNEMONIC_JNS: - case ZYDIS_MNEMONIC_JNZ: - case ZYDIS_MNEMONIC_JO: - case ZYDIS_MNEMONIC_JP: - case ZYDIS_MNEMONIC_JRCXZ: - case ZYDIS_MNEMONIC_JS: - case ZYDIS_MNEMONIC_JZ: + // detect if we have already been at this instruction... if so that means there is a loop and we are + // going to just return... + if ( std::find_if( routine.begin(), routine.end(), [ & ]( const zydis_instr_t &zydis_instr ) -> bool { + return zydis_instr.addr == routine_addr; + } ) != routine.end() ) return true; - default: - break; - } - return false; - } - bool flatten( zydis_routine_t &routine, std::uintptr_t routine_addr, bool keep_jmps ) - { - ZydisDecoder decoder; - zydis_decoded_instr_t instr; - ZydisDecoderInit( &decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64 ); + std::vector< u8 > raw_instr; + raw_instr.insert( raw_instr.begin(), ( u8 * )routine_addr, ( u8 * )routine_addr + instr.length ); - while ( ZYAN_SUCCESS( - ZydisDecoderDecodeBuffer( &decoder, reinterpret_cast< void * >( routine_addr ), 0x1000, &instr ) ) ) + if ( is_jmp( instr ) ) { - // detect if we have already been at this instruction... if so that means there is a loop and we are - // going to just return... - if ( std::find_if( routine.begin(), routine.end(), [ & ]( const zydis_instr_t &zydis_instr ) -> bool { - return zydis_instr.addr == routine_addr; - } ) != routine.end() ) - return true; - - std::vector< u8 > raw_instr; - raw_instr.insert( raw_instr.begin(), ( u8 * )routine_addr, ( u8 * )routine_addr + instr.length ); - - if ( is_jmp( instr ) ) - { - if ( instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER ) - { - routine.push_back( { instr, raw_instr, routine_addr } ); - return true; - } - - 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 ) + if ( instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER ) { routine.push_back( { instr, raw_instr, routine_addr } ); return true; } - else - { + + if ( keep_jmps ) routine.push_back( { instr, raw_instr, routine_addr } ); - routine_addr += instr.length; - } + + 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; + } + else + { + routine.push_back( { instr, raw_instr, routine_addr } ); + routine_addr += instr.length; } - return false; } + return false; + } - void deobfuscate( zydis_routine_t &routine ) - { - static const auto _uses = []( ZydisDecodedOperand &op, zydis_register_t reg ) -> bool { - switch ( op.type ) - { - case ZYDIS_OPERAND_TYPE_MEMORY: - { - return reg::compare( op.mem.base, reg ) || reg::compare( op.mem.index, reg ); - } - case ZYDIS_OPERAND_TYPE_REGISTER: - { - return reg::compare( op.reg.value, reg ); - } - default: - break; - } - return false; - }; + void deobfuscate( zydis_routine_t &routine ) + { + static const auto _uses = []( ZydisDecodedOperand &op, zydis_register_t reg ) -> bool { + switch ( op.type ) + { + case ZYDIS_OPERAND_TYPE_MEMORY: + { + return reg::compare( op.mem.base, reg ) || reg::compare( op.mem.index, reg ); + } + case ZYDIS_OPERAND_TYPE_REGISTER: + { + return reg::compare( op.reg.value, reg ); + } + default: + break; + } + return false; + }; - static const auto _writes = []( zydis_decoded_instr_t &inst ) -> bool { - for ( auto idx = 0; idx < inst.operand_count; ++idx ) - if ( inst.operands[ idx ].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE ) - return true; + static const auto _writes = []( zydis_decoded_instr_t &inst ) -> bool { + for ( auto idx = 0; idx < inst.operand_count; ++idx ) + if ( inst.operands[ idx ].actions & ZYDIS_OPERAND_ACTION_MASK_WRITE ) + return true; - return false; - }; + return false; + }; - static const auto _remove = []( zydis_routine_t &routine, zydis_routine_t::iterator itr, - zydis_register_t reg, u32 opcode_size ) -> void { - for ( ; itr >= routine.begin(); --itr ) + static const auto _remove = []( zydis_routine_t &routine, zydis_routine_t::iterator itr, zydis_register_t reg, + u32 opcode_size ) -> void { + for ( ; itr >= routine.begin(); --itr ) + { + const auto instruction = &itr->instr; + auto stop = false; + + if ( instruction->mnemonic == ZYDIS_MNEMONIC_JMP ) + continue; + + for ( auto op_idx = 0u; op_idx < instruction->operand_count; ++op_idx ) { - const auto instruction = &itr->instr; - auto stop = false; + const auto op = &instruction->operands[ op_idx ]; - if ( instruction->mnemonic == ZYDIS_MNEMONIC_JMP ) + if ( !_uses( *op, reg ) ) continue; - for ( auto op_idx = 0u; op_idx < instruction->operand_count; ++op_idx ) + if ( op->type == ZYDIS_OPERAND_TYPE_MEMORY ) { - const auto op = &instruction->operands[ op_idx ]; - - if ( !_uses( *op, reg ) ) - continue; + stop = true; + continue; + } - if ( op->type == ZYDIS_OPERAND_TYPE_MEMORY ) - { - stop = true; - continue; - } + if ( opcode_size < 32 && op->size > opcode_size ) + continue; - if ( opcode_size < 32 && op->size > opcode_size ) - continue; + op->actions &ZYDIS_OPERAND_ACTION_MASK_WRITE ? op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE + : stop = true; + } - op->actions &ZYDIS_OPERAND_ACTION_MASK_WRITE ? op->actions &= ~ZYDIS_OPERAND_ACTION_MASK_WRITE - : stop = true; - } + if ( !_writes( *instruction ) ) + routine.erase( itr ); - if ( !_writes( *instruction ) ) - routine.erase( itr ); + else if ( stop ) + break; + } + }; - else if ( stop ) - break; - } - }; + for ( const auto &instr_data : routine ) + { + if ( routine.empty() || routine.size() == 1 || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP ) + continue; - for ( const auto &instr_data : routine ) + for ( auto itr = routine.begin() + 1; itr != routine.end(); itr++ ) { - if ( routine.empty() || routine.size() == 1 || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP ) - continue; + if ( itr->instr.mnemonic == ZYDIS_MNEMONIC_JMP || itr->instr.mnemonic == ZYDIS_MNEMONIC_RET ) + break; - for ( auto itr = routine.begin() + 1; itr != routine.end(); itr++ ) + // find the write operations that happen... + for ( auto idx = 0u; idx < itr->instr.operand_count; ++idx ) { - if ( itr->instr.mnemonic == ZYDIS_MNEMONIC_JMP || itr->instr.mnemonic == ZYDIS_MNEMONIC_RET ) - break; - - // find the write operations that happen... - for ( auto idx = 0u; idx < itr->instr.operand_count; ++idx ) - { - const auto op = &itr->instr.operands[ idx ]; - // if its a read, continue to next opcode... - if ( op->actions & ZYDIS_OPERAND_ACTION_MASK_READ ) - continue; + const auto op = &itr->instr.operands[ idx ]; + // if its a read, continue to next opcode... + if ( op->actions & ZYDIS_OPERAND_ACTION_MASK_READ ) + continue; - // if its not a write then continue to next opcode... - if ( !( op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE ) ) - continue; + // if its not a write then continue to next opcode... + if ( !( op->actions & ZYDIS_OPERAND_ACTION_MASK_WRITE ) ) + continue; - // if this operand is not a register then we continue... - if ( op->type != ZYDIS_OPERAND_TYPE_REGISTER ) - continue; + // if this operand is not a register then we continue... + if ( op->type != ZYDIS_OPERAND_TYPE_REGISTER ) + continue; - // else we see if we can remove dead writes to this register... - _remove( routine, itr - 1, op->reg.value, op->size ); - } + // else we see if we can remove dead writes to this register... + _remove( routine, itr - 1, op->reg.value, op->size ); } } } - } // namespace util -} // namespace vm \ No newline at end of file + } +} // namespace vm::util \ No newline at end of file From 9e26605601f03af41cef95aba8c6603c2c213e63 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 13:36:33 -0700 Subject: [PATCH 07/20] fixed some bugs... --- src/vmhandler.cpp | 2 +- src/vmutils.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmhandler.cpp b/src/vmhandler.cpp index f0987d5..426b161 100644 --- a/src/vmhandler.cpp +++ b/src/vmhandler.cpp @@ -90,7 +90,7 @@ namespace vm::handler vm_handler.address = ( decrypt_val - image_base ) + module_base; vm_handler.instrs = vm_handler_instrs; - vm_handler.imm_size = imm_size.value(); + vm_handler.imm_size = imm_size.has_value() ? imm_size.value() : 0u; vm_handler.transforms = transforms; vm_handler.profile = vm::handler::get_profile( vm_handler ); vm_handlers.push_back( vm_handler ); diff --git a/src/vmutils.cpp b/src/vmutils.cpp index 35b3fdf..69d519c 100644 --- a/src/vmutils.cpp +++ b/src/vmutils.cpp @@ -75,7 +75,7 @@ namespace vm::util for ( auto [ instr, raw, addr ] : routine ) { ZydisFormatterFormatInstruction( &formatter, &instr, buffer, sizeof( buffer ), addr ); - std::printf( "> 0x%p %s", addr, buffer ); + std::printf( "> 0x%p %s\n", addr, buffer ); } } From 1840945596ed7dbb511863fb7a1a10e04a35ba92 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 16:46:26 -0700 Subject: [PATCH 08/20] starting to define lifters for vmp2 IL... --- include/vmlifters.hpp | 25 +++++++++++++++++++++++++ src/vmlifters/add.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/vmlifters/lregq.cpp | 10 ++++++++++ vmprofiler.vcxproj | 7 +++++-- vmprofiler.vcxproj.filters | 12 ++++++++++++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 include/vmlifters.hpp create mode 100644 src/vmlifters/add.cpp create mode 100644 src/vmlifters/lregq.cpp diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp new file mode 100644 index 0000000..0c764a5 --- /dev/null +++ b/include/vmlifters.hpp @@ -0,0 +1,25 @@ +#include +#include +#include + +namespace vm::lifters +{ + using lifter_callback_t = std::function< void( vtil::basic_block *, vm::instrs::virt_instr_t * ) >; + using lifter_t = std::pair< vm::handler::mnemonic_t, lifter_callback_t >; + + // taken from + // https://github.com/can1357/NoVmp/blob/6c23c9a335f70e8d5ed6299668fd802f2314c896/NoVmp/vmprotect/il2vtil.cpp#L66 + inline constexpr vtil::register_desc make_virtual_register( uint8_t context_offset, uint8_t size ) + { + fassert( ( ( context_offset & 7 ) + size ) <= 8 && size ); + + return { vtil::register_virtual, ( size_t )context_offset / 8, size * 8, ( context_offset % 8 ) * 8 }; + } + + extern lifter_t lregq; + extern lifter_t addq, adddw, addw; + + inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { + lregq, addq, adddw, addw + }; +} // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/add.cpp b/src/vmlifters/add.cpp new file mode 100644 index 0000000..4afc9d0 --- /dev/null +++ b/src/vmlifters/add.cpp @@ -0,0 +1,37 @@ +#include + +namespace vm::lifters +{ + lifter_t addq = { + // vsp[0] = vsp[1] + vsp[0]; + vm::handler::ADDQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t0, t1 ] = blk->tmp( 64, 64 ); + blk->pop( t0 ); + blk->pop( t1 ); + blk->add( t1, t0 ); + blk->push( t1 ); + blk->pushf(); + } }; + + lifter_t adddw = { + // vsp[0] = vsp[1] + vsp[0]; + vm::handler::ADDDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t0, t1 ] = blk->tmp( 32, 32 ); + blk->pop( t0 ); + blk->pop( t1 ); + blk->add( t1, t0 ); + blk->push( t1 ); + blk->pushf(); + } }; + + lifter_t addw = { + // vsp[0] = vsp[1] + vsp[0]; + vm::handler::ADDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t0, t1 ] = blk->tmp( 16, 16 ); + blk->pop( t0 ); + blk->pop( t1 ); + blk->add( t1, t0 ); + blk->push( t1 ); + blk->pushf(); + } }; +} // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/lregq.cpp b/src/vmlifters/lregq.cpp new file mode 100644 index 0000000..8eecf0a --- /dev/null +++ b/src/vmlifters/lregq.cpp @@ -0,0 +1,10 @@ +#include + +namespace vm::lifters +{ + lifter_t lregq = { + // push vregX + vm::handler::LREGQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( make_virtual_register( vinstr->operand.imm.u, 8 ) ); + } }; +} \ No newline at end of file diff --git a/vmprofiler.vcxproj b/vmprofiler.vcxproj index e3f447f..3b08b53 100644 --- a/vmprofiler.vcxproj +++ b/vmprofiler.vcxproj @@ -47,11 +47,11 @@ false - $(ProjectDir)dependencies\zydis\msvc;$(ProjectDir)dependencies\zydis\dependencies\zycore\include;$(ProjectDir)include;$(ProjectDir)dependencies\zydis\include;$(IncludePath) + $(ProjectDir)dependencies\zydis\msvc;$(ProjectDir)dependencies\zydis\dependencies\zycore\include;$(ProjectDir)include;$(ProjectDir)dependencies\zydis\include;$(ProjectDir)dependencies\vtil\VTIL\includes\;$(ProjectDir)dependencies\vtil\VTIL-Architecture\includes\;$(ProjectDir)dependencies\vtil\VTIL-Common\includes\;$(ProjectDir)dependencies\vtil\VTIL-Compiler\includes;$(ProjectDir)dependencies\vtil\VTIL-SymEx\includes\;$(ProjectDir)dependencies\vtil\dependencies\keystone\include;$(ProjectDir)dependencies\vtil\dependencies\capstone\include;$(IncludePath) false - $(ProjectDir)dependencies\zydis\msvc;$(ProjectDir)dependencies\zydis\dependencies\zycore\include;$(ProjectDir)include;$(ProjectDir)dependencies\zydis\include;$(IncludePath) + $(ProjectDir)dependencies\zydis\msvc;$(ProjectDir)dependencies\zydis\dependencies\zycore\include;$(ProjectDir)include;$(ProjectDir)dependencies\zydis\include;$(ProjectDir)dependencies\vtil\VTIL\includes\;$(ProjectDir)dependencies\vtil\VTIL-Architecture\includes\;$(ProjectDir)dependencies\vtil\VTIL-Common\includes\;$(ProjectDir)dependencies\vtil\VTIL-Compiler\includes;$(ProjectDir)dependencies\vtil\VTIL-SymEx\includes\;$(ProjectDir)dependencies\vtil\dependencies\keystone\include;$(ProjectDir)dependencies\vtil\dependencies\capstone\include;$(IncludePath) @@ -151,6 +151,7 @@ + @@ -164,6 +165,8 @@ + + diff --git a/vmprofiler.vcxproj.filters b/vmprofiler.vcxproj.filters index f07da1c..23968ce 100644 --- a/vmprofiler.vcxproj.filters +++ b/vmprofiler.vcxproj.filters @@ -30,6 +30,9 @@ {b4d15e7c-77b4-497f-89ea-cb7366955816} + + {2e1e240b-494d-4668-9f6d-2d4405f04a74} + @@ -182,6 +185,9 @@ Header Files + + Header Files + @@ -252,5 +258,11 @@ Source Files + + Source Files\vmlifters + + + Source Files\vmlifters + \ No newline at end of file From 0699518ae99dde9716302c84588bcced13bf648f Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 17:16:19 -0700 Subject: [PATCH 09/20] added more lifters... --- include/vmlifters.hpp | 15 +++++++++++---- src/vmlifters/{lregq.cpp => lreg.cpp} | 8 +++++++- src/vmlifters/sreg.cpp | 22 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 5 deletions(-) rename src/vmlifters/{lregq.cpp => lreg.cpp} (51%) create mode 100644 src/vmlifters/sreg.cpp diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp index 0c764a5..d1da347 100644 --- a/include/vmlifters.hpp +++ b/include/vmlifters.hpp @@ -16,10 +16,17 @@ namespace vm::lifters return { vtil::register_virtual, ( size_t )context_offset / 8, size * 8, ( context_offset % 8 ) * 8 }; } - extern lifter_t lregq; + extern lifter_t lregq, lregdw; extern lifter_t addq, adddw, addw; + extern lifter_t sregq, sregdw, sregw; - inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { - lregq, addq, adddw, addw - }; + inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { + // lreg lifters... + lregq, lregdw, + + // add lifters... + addq, adddw, addw, + + // sreg lifters... + sregq, sregdw, sregw }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/lregq.cpp b/src/vmlifters/lreg.cpp similarity index 51% rename from src/vmlifters/lregq.cpp rename to src/vmlifters/lreg.cpp index 8eecf0a..7db2ad8 100644 --- a/src/vmlifters/lregq.cpp +++ b/src/vmlifters/lreg.cpp @@ -7,4 +7,10 @@ namespace vm::lifters vm::handler::LREGQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( make_virtual_register( vinstr->operand.imm.u, 8 ) ); } }; -} \ No newline at end of file + + lifter_t lregdw = { + // push vregX + vm::handler::LREGDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( make_virtual_register( vinstr->operand.imm.u, 4 ) ); + } }; +} // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/sreg.cpp b/src/vmlifters/sreg.cpp new file mode 100644 index 0000000..59022e4 --- /dev/null +++ b/src/vmlifters/sreg.cpp @@ -0,0 +1,22 @@ +#include + +namespace vm::lifters +{ + lifter_t sregq = { + // pop vregX + vm::handler::SREGQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->pop( make_virtual_register( vinstr->operand.imm.u, 8 ) ); + } }; + + lifter_t sregdw = { + // pop vregX + vm::handler::SREGDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->pop( make_virtual_register( vinstr->operand.imm.u, 4 ) ); + } }; + + lifter_t sregw = { + // pop vregX + vm::handler::SREGW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->pop( make_virtual_register( vinstr->operand.imm.u, 2 ) ); + } }; +} // namespace vm::lifters \ No newline at end of file From 2d3b22a7acf5edba40cff6ef6432ee523ce599fb Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 17:31:59 -0700 Subject: [PATCH 10/20] fixed compiling issues... --- include/vmlifters.hpp | 6 +++--- src/vmlifters/add.cpp | 6 +++--- src/vmlifters/lreg.cpp | 4 ++-- src/vmlifters/sreg.cpp | 6 +++--- vmprofiler.vcxproj | 5 ++++- vmprofiler.vcxproj.filters | 5 ++++- 6 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp index d1da347..e6f7179 100644 --- a/include/vmlifters.hpp +++ b/include/vmlifters.hpp @@ -16,9 +16,9 @@ namespace vm::lifters return { vtil::register_virtual, ( size_t )context_offset / 8, size * 8, ( context_offset % 8 ) * 8 }; } - extern lifter_t lregq, lregdw; - extern lifter_t addq, adddw, addw; - extern lifter_t sregq, sregdw, sregw; + extern vm::lifters::lifter_t lregq, lregdw; + extern vm::lifters::lifter_t addq, adddw, addw; + extern vm::lifters::lifter_t sregq, sregdw, sregw; inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { // lreg lifters... diff --git a/src/vmlifters/add.cpp b/src/vmlifters/add.cpp index 4afc9d0..f52bdc9 100644 --- a/src/vmlifters/add.cpp +++ b/src/vmlifters/add.cpp @@ -2,7 +2,7 @@ namespace vm::lifters { - lifter_t addq = { + vm::lifters::lifter_t addq = { // vsp[0] = vsp[1] + vsp[0]; vm::handler::ADDQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { auto [ t0, t1 ] = blk->tmp( 64, 64 ); @@ -13,7 +13,7 @@ namespace vm::lifters blk->pushf(); } }; - lifter_t adddw = { + vm::lifters::lifter_t adddw = { // vsp[0] = vsp[1] + vsp[0]; vm::handler::ADDDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { auto [ t0, t1 ] = blk->tmp( 32, 32 ); @@ -24,7 +24,7 @@ namespace vm::lifters blk->pushf(); } }; - lifter_t addw = { + vm::lifters::lifter_t addw = { // vsp[0] = vsp[1] + vsp[0]; vm::handler::ADDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { auto [ t0, t1 ] = blk->tmp( 16, 16 ); diff --git a/src/vmlifters/lreg.cpp b/src/vmlifters/lreg.cpp index 7db2ad8..324b876 100644 --- a/src/vmlifters/lreg.cpp +++ b/src/vmlifters/lreg.cpp @@ -2,13 +2,13 @@ namespace vm::lifters { - lifter_t lregq = { + vm::lifters::lifter_t lregq = { // push vregX vm::handler::LREGQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( make_virtual_register( vinstr->operand.imm.u, 8 ) ); } }; - lifter_t lregdw = { + vm::lifters::lifter_t lregdw = { // push vregX vm::handler::LREGDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( make_virtual_register( vinstr->operand.imm.u, 4 ) ); diff --git a/src/vmlifters/sreg.cpp b/src/vmlifters/sreg.cpp index 59022e4..c6d6698 100644 --- a/src/vmlifters/sreg.cpp +++ b/src/vmlifters/sreg.cpp @@ -2,19 +2,19 @@ namespace vm::lifters { - lifter_t sregq = { + vm::lifters::lifter_t sregq = { // pop vregX vm::handler::SREGQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->pop( make_virtual_register( vinstr->operand.imm.u, 8 ) ); } }; - lifter_t sregdw = { + vm::lifters::lifter_t sregdw = { // pop vregX vm::handler::SREGDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->pop( make_virtual_register( vinstr->operand.imm.u, 4 ) ); } }; - lifter_t sregw = { + vm::lifters::lifter_t sregw = { // pop vregX vm::handler::SREGW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->pop( make_virtual_register( vinstr->operand.imm.u, 2 ) ); diff --git a/vmprofiler.vcxproj b/vmprofiler.vcxproj index 3b08b53..0b0bbd6 100644 --- a/vmprofiler.vcxproj +++ b/vmprofiler.vcxproj @@ -64,6 +64,7 @@ stdcpplatest Disabled MultiThreadedDLL + $(IntDir)%(RelativeDir) Console @@ -87,6 +88,7 @@ stdcpplatest Disabled MultiThreadedDebugDLL + $(IntDir)%(RelativeDir) Console @@ -166,7 +168,8 @@ - + + diff --git a/vmprofiler.vcxproj.filters b/vmprofiler.vcxproj.filters index 23968ce..b6c647e 100644 --- a/vmprofiler.vcxproj.filters +++ b/vmprofiler.vcxproj.filters @@ -261,7 +261,10 @@ Source Files\vmlifters - + + Source Files\vmlifters + + Source Files\vmlifters From bc0a1d7b5b7918e98f405ba653155965467810fe Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 19:07:46 -0700 Subject: [PATCH 11/20] added more lifters... --- include/vmlifters.hpp | 10 +++++++++- src/vmlifters/lconst.cpp | 22 ++++++++++++++++++++++ src/vmlifters/vmexit.cpp | 8 ++++++++ vmprofiler.vcxproj | 2 ++ vmprofiler.vcxproj.filters | 6 ++++++ 5 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/vmlifters/lconst.cpp create mode 100644 src/vmlifters/vmexit.cpp diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp index e6f7179..feedcdf 100644 --- a/include/vmlifters.hpp +++ b/include/vmlifters.hpp @@ -19,6 +19,8 @@ namespace vm::lifters extern vm::lifters::lifter_t lregq, lregdw; extern vm::lifters::lifter_t addq, adddw, addw; extern vm::lifters::lifter_t sregq, sregdw, sregw; + extern vm::lifters::lifter_t lconstq, lconstdw, lconstw; + extern vm::lifters::lifter_t vmexit; inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { // lreg lifters... @@ -28,5 +30,11 @@ namespace vm::lifters addq, adddw, addw, // sreg lifters... - sregq, sregdw, sregw }; + sregq, sregdw, sregw, + + // lconst lifters... + lconstq, lconstdw, lconstw, + + // vmexit lifter... + vmexit }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/lconst.cpp b/src/vmlifters/lconst.cpp new file mode 100644 index 0000000..a9e54c8 --- /dev/null +++ b/src/vmlifters/lconst.cpp @@ -0,0 +1,22 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t lconstq = { + // push imm + vm::handler::LCONSTQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); + } }; + + vm::lifters::lifter_t lconstdw = { + // push imm + vm::handler::LCONSTDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 32 ) ); + } }; + + vm::lifters::lifter_t lconstw = { + // push imm + vm::handler::LCONSTW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 16 ) ); + } }; +} // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/vmexit.cpp b/src/vmlifters/vmexit.cpp new file mode 100644 index 0000000..254e17b --- /dev/null +++ b/src/vmlifters/vmexit.cpp @@ -0,0 +1,8 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t vmexit = { + // ret + vm::handler::VMEXIT, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->vexit(); } }; +} \ No newline at end of file diff --git a/vmprofiler.vcxproj b/vmprofiler.vcxproj index 0b0bbd6..510b98a 100644 --- a/vmprofiler.vcxproj +++ b/vmprofiler.vcxproj @@ -168,8 +168,10 @@ + + diff --git a/vmprofiler.vcxproj.filters b/vmprofiler.vcxproj.filters index b6c647e..7c4ef1d 100644 --- a/vmprofiler.vcxproj.filters +++ b/vmprofiler.vcxproj.filters @@ -267,5 +267,11 @@ Source Files\vmlifters + + Source Files\vmlifters + + + Source Files\vmlifters + \ No newline at end of file From 89af2c2654d1a9ab60359645a74df6bb02934a8c Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 19:25:02 -0700 Subject: [PATCH 12/20] added more profiles... --- include/vmlifters.hpp | 9 +++-- src/vmlifters/lconst.cpp | 36 ++++++++++++++++++++ src/vmlifters/nand.cpp | 67 ++++++++++++++++++++++++++++++++++++++ vmprofiler.vcxproj | 1 + vmprofiler.vcxproj.filters | 3 ++ 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/vmlifters/nand.cpp diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp index feedcdf..6da70cc 100644 --- a/include/vmlifters.hpp +++ b/include/vmlifters.hpp @@ -19,7 +19,9 @@ namespace vm::lifters extern vm::lifters::lifter_t lregq, lregdw; extern vm::lifters::lifter_t addq, adddw, addw; extern vm::lifters::lifter_t sregq, sregdw, sregw; - extern vm::lifters::lifter_t lconstq, lconstdw, lconstw; + extern vm::lifters::lifter_t lconstq, lconstdw, lconstw, lconstbzxw, lconstbsxdw, lconstbsxq, lconstdwsxq, + lconstwsxq, lconstwsxdw; + extern vm::lifters::lifter_t nandq, nanddw, nandw; extern vm::lifters::lifter_t vmexit; inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { @@ -33,7 +35,10 @@ namespace vm::lifters sregq, sregdw, sregw, // lconst lifters... - lconstq, lconstdw, lconstw, + lconstq, lconstdw, lconstw, lconstbzxw, lconstbsxdw, lconstbsxq, lconstdwsxq, lconstwsxq, lconstwsxdw, + + // nand lifters... + nandq, nanddw, nandw, // vmexit lifter... vmexit }; diff --git a/src/vmlifters/lconst.cpp b/src/vmlifters/lconst.cpp index a9e54c8..2b246e3 100644 --- a/src/vmlifters/lconst.cpp +++ b/src/vmlifters/lconst.cpp @@ -19,4 +19,40 @@ namespace vm::lifters vm::handler::LCONSTW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( vtil::operand( vinstr->operand.imm.u, 16 ) ); } }; + + vm::lifters::lifter_t lconstbzxw = { + // push imm + vm::handler::LCONSTBZXW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 16 ) ); + } }; + + vm::lifters::lifter_t lconstbsxdw = { + // push imm + vm::handler::LCONSTBSXDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 32 ) ); + } }; + + vm::lifters::lifter_t lconstbsxq = { + // push imm + vm::handler::LCONSTBSXQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); + } }; + + vm::lifters::lifter_t lconstdwsxq = { + // push imm + vm::handler::LCONSTDWSXQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); + } }; + + vm::lifters::lifter_t lconstwsxq = { + // push imm + vm::handler::LCONSTWSXQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); + } }; + + vm::lifters::lifter_t lconstwsxdw = { + // push imm + vm::handler::LCONSTWSXDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->push( vtil::operand( vinstr->operand.imm.u, 32 ) ); + } }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/nand.cpp b/src/vmlifters/nand.cpp new file mode 100644 index 0000000..141c8f4 --- /dev/null +++ b/src/vmlifters/nand.cpp @@ -0,0 +1,67 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t nandq = { + // pop vregX + // pop vregY + // not vregX + // not vregY + // and vregX, vregY + // push vregX + // pushf + vm::handler::NANDQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t1, t2 ] = blk->tmp( 64, 64 ); + blk->pop( t1 ); + blk->pop( t2 ); + + blk->bnot( t1 ); + blk->bnot( t2 ); + + blk->band( t1, t2 ); + blk->push( t1 ); + blk->pushf(); + } }; + + vm::lifters::lifter_t nanddw = { + // pop vregX + // pop vregY + // not vregX + // not vregY + // and vregX, vregY + // push vregX + // pushf + vm::handler::NANDDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t1, t2 ] = blk->tmp( 32, 32 ); + blk->pop( t1 ); + blk->pop( t2 ); + + blk->bnot( t1 ); + blk->bnot( t2 ); + + blk->band( t1, t2 ); + blk->push( t1 ); + blk->pushf(); + } }; + + vm::lifters::lifter_t nandw = { + // pop vregX + // pop vregY + // not vregX + // not vregY + // and vregX, vregY + // push vregX + // pushf + vm::handler::NANDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t1, t2 ] = blk->tmp( 16, 16 ); + blk->pop( t1 ); + blk->pop( t2 ); + + blk->bnot( t1 ); + blk->bnot( t2 ); + + blk->band( t1, t2 ); + blk->push( t1 ); + blk->pushf(); + } }; +} // namespace vm::lifters \ No newline at end of file diff --git a/vmprofiler.vcxproj b/vmprofiler.vcxproj index 510b98a..9cacdad 100644 --- a/vmprofiler.vcxproj +++ b/vmprofiler.vcxproj @@ -170,6 +170,7 @@ + diff --git a/vmprofiler.vcxproj.filters b/vmprofiler.vcxproj.filters index 7c4ef1d..49e7c3a 100644 --- a/vmprofiler.vcxproj.filters +++ b/vmprofiler.vcxproj.filters @@ -273,5 +273,8 @@ Source Files\vmlifters + + Source Files\vmlifters + \ No newline at end of file From eb13c85f4865077b20b08c0464bd354c3a84a9f4 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 19:50:45 -0700 Subject: [PATCH 13/20] added more lifters... --- include/vmlifters.hpp | 12 ++++++++++++ src/vmlifters/pushvsp.cpp | 9 +++++++++ src/vmlifters/read.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/vmlifters/shr.cpp | 34 ++++++++++++++++++++++++++++++++++ vmprofiler.vcxproj | 3 +++ vmprofiler.vcxproj.filters | 9 +++++++++ 6 files changed, 104 insertions(+) create mode 100644 src/vmlifters/pushvsp.cpp create mode 100644 src/vmlifters/read.cpp create mode 100644 src/vmlifters/shr.cpp diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp index 6da70cc..029f4f5 100644 --- a/include/vmlifters.hpp +++ b/include/vmlifters.hpp @@ -22,7 +22,10 @@ namespace vm::lifters extern vm::lifters::lifter_t lconstq, lconstdw, lconstw, lconstbzxw, lconstbsxdw, lconstbsxq, lconstdwsxq, lconstwsxq, lconstwsxdw; extern vm::lifters::lifter_t nandq, nanddw, nandw; + extern vm::lifters::lifter_t readq, readdw, readw; + extern vm::lifters::lifter_t shrq, shrw; extern vm::lifters::lifter_t vmexit; + extern vm::lifters::lifter_t pushvsp; inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { // lreg lifters... @@ -40,6 +43,15 @@ namespace vm::lifters // nand lifters... nandq, nanddw, nandw, + // read lifters.... + readq, readdw, readw, + + // shr lifters... + shrq, shrw, + + // pushvsp lifter... + pushvsp, + // vmexit lifter... vmexit }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/pushvsp.cpp b/src/vmlifters/pushvsp.cpp new file mode 100644 index 0000000..566a430 --- /dev/null +++ b/src/vmlifters/pushvsp.cpp @@ -0,0 +1,9 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t pushvsp = { + // push vsp + vm::handler::PUSHVSP, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( vtil::REG_SP ); } }; +} \ No newline at end of file diff --git a/src/vmlifters/read.cpp b/src/vmlifters/read.cpp new file mode 100644 index 0000000..db3420e --- /dev/null +++ b/src/vmlifters/read.cpp @@ -0,0 +1,37 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t readq = { + // pop vregX + // ldd vregX, vregX, 0 + // push vregX + vm::handler::READQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto t0 = blk->tmp( 64 ); + blk->pop( t0 ); + blk->ldd( t0, t0, 0 ); + blk->push( t0 ); + } }; + + vm::lifters::lifter_t readdw = { + // pop vregX + // ldd vregX, vregX, 0 + // push vregX + vm::handler::READDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto t0 = blk->tmp( 32 ); + blk->pop( t0 ); + blk->ldd( t0, t0, 0 ); + blk->push( t0 ); + } }; + + vm::lifters::lifter_t readw = { + // pop vregX + // ldd vregX, vregX, 0 + // push vregX + vm::handler::READW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto t0 = blk->tmp( 16 ); + blk->pop( t0 ); + blk->ldd( t0, t0, 0 ); + blk->push( t0 ); + } }; +} // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/shr.cpp b/src/vmlifters/shr.cpp new file mode 100644 index 0000000..8e88e17 --- /dev/null +++ b/src/vmlifters/shr.cpp @@ -0,0 +1,34 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t shrq = { + // pop vregX + // pop vregY + // shr vregX, vregY + // push vregX + // pushf + vm::handler::SHRQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t0, t1 ] = blk->tmp( 64, 8 ); + blk->pop( t0 ); + blk->pop( t1 ); + blk->bshr( t0, t1 ); + blk->push( t0 ); + blk->pushf(); + } }; + + vm::lifters::lifter_t shrw = { + // pop vregX + // pop vregY + // shr vregX, vregY + // push vregX + // pushf + vm::handler::SHRW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + auto [ t0, t1 ] = blk->tmp( 16, 8 ); + blk->pop( t0 ); + blk->pop( t1 ); + blk->bshr( t0, t1 ); + blk->push( t0 ); + blk->pushf(); + } }; +} // namespace vm::lifters \ No newline at end of file diff --git a/vmprofiler.vcxproj b/vmprofiler.vcxproj index 9cacdad..dd0c3c4 100644 --- a/vmprofiler.vcxproj +++ b/vmprofiler.vcxproj @@ -171,6 +171,9 @@ + + + diff --git a/vmprofiler.vcxproj.filters b/vmprofiler.vcxproj.filters index 49e7c3a..242966a 100644 --- a/vmprofiler.vcxproj.filters +++ b/vmprofiler.vcxproj.filters @@ -276,5 +276,14 @@ Source Files\vmlifters + + Source Files\vmlifters + + + Source Files\vmlifters + + + Source Files\vmlifters + \ No newline at end of file From 28e50e7b0c425f078d9b4ced850435616852ec4e Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 10 Jun 2021 23:36:34 -0700 Subject: [PATCH 14/20] added more lifters and profiles... updated deps... --- dependencies/vtil | 2 +- include/vmlifters.hpp | 33 +++++++++++++++++++++++---------- include/vmprofiler.hpp | 3 ++- include/vmprofiles.hpp | 8 +++++++- src/vmlifters/jmp.cpp | 10 ++++++++++ src/vmlifters/lflags.cpp | 9 +++++++++ src/vmlifters/lvsp.cpp | 9 +++++++++ src/vmlifters/read.cpp | 18 +++++++++--------- src/vmlifters/vmexit.cpp | 4 +++- src/vmprofiles/lvsp.cpp | 16 ++++++++++++++++ vmprofiler.vcxproj | 4 ++++ vmprofiler.vcxproj.filters | 12 ++++++++++++ 12 files changed, 105 insertions(+), 23 deletions(-) create mode 100644 src/vmlifters/jmp.cpp create mode 100644 src/vmlifters/lflags.cpp create mode 100644 src/vmlifters/lvsp.cpp create mode 100644 src/vmprofiles/lvsp.cpp diff --git a/dependencies/vtil b/dependencies/vtil index e9dc43b..46220b2 160000 --- a/dependencies/vtil +++ b/dependencies/vtil @@ -1 +1 @@ -Subproject commit e9dc43bd7da388c5f8304407fd076f802bd97a7f +Subproject commit 46220b2d054f7c250d9eef27879a2f05b7c9d9fa diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp index 029f4f5..e0ec8b1 100644 --- a/include/vmlifters.hpp +++ b/include/vmlifters.hpp @@ -24,34 +24,47 @@ namespace vm::lifters extern vm::lifters::lifter_t nandq, nanddw, nandw; extern vm::lifters::lifter_t readq, readdw, readw; extern vm::lifters::lifter_t shrq, shrw; + + extern vm::lifters::lifter_t jmp; extern vm::lifters::lifter_t vmexit; extern vm::lifters::lifter_t pushvsp; + extern vm::lifters::lifter_t lrflags; + extern vm::lifters::lifter_t lvsp; - inline std::map< vm::handler::mnemonic_t, lifter_callback_t > all = { + inline std::vector< vm::lifters::lifter_t * > all = { // lreg lifters... - lregq, lregdw, + &lregq, &lregdw, // add lifters... - addq, adddw, addw, + &addq, &adddw, &addw, // sreg lifters... - sregq, sregdw, sregw, + &sregq, &sregdw, &sregw, // lconst lifters... - lconstq, lconstdw, lconstw, lconstbzxw, lconstbsxdw, lconstbsxq, lconstdwsxq, lconstwsxq, lconstwsxdw, + &lconstq, &lconstdw, &lconstw, &lconstbzxw, &lconstbsxdw, &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, // nand lifters... - nandq, nanddw, nandw, + &nandq, &nanddw, &nandw, // read lifters.... - readq, readdw, readw, + &readq, &readdw, &readw, // shr lifters... - shrq, shrw, + &shrq, &shrw, // pushvsp lifter... - pushvsp, + &pushvsp, + + // jmp lifter... + &jmp, + + // lflags lifter... + &lrflags, + + // lvsp lifter... + &lvsp, // vmexit lifter... - vmexit }; + &vmexit }; } // namespace vm::lifters \ No newline at end of file diff --git a/include/vmprofiler.hpp b/include/vmprofiler.hpp index 976d76f..8b40e7c 100644 --- a/include/vmprofiler.hpp +++ b/include/vmprofiler.hpp @@ -6,4 +6,5 @@ #include #include #include -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/include/vmprofiles.hpp b/include/vmprofiles.hpp index 19b6aa2..f338fda 100644 --- a/include/vmprofiles.hpp +++ b/include/vmprofiles.hpp @@ -19,6 +19,7 @@ namespace vm::handler CALL, JMP, VMEXIT, + LVSP, SREGQ, SREGDW, @@ -223,6 +224,11 @@ namespace vm::handler /// add rsi, [rbp] ; add module base address /// extern vm::handler::profile_t jmp; + + /// + /// mov rbp [rbp+0] + /// + extern vm::handler::profile_t lvsp; extern vm::handler::profile_t vmexit; /// @@ -231,7 +237,7 @@ namespace vm::handler inline std::vector< vm::handler::profile_t * > all = { &sregq, &sregdw, &sregw, &lregq, &lregdw, &lconstq, &lconstbzxw, &lconstbsxdw, &lconstbsxq, &lconstdwsxq, &lconstwsxq, &lconstwsxdw, &lconstdw, &lconstw, &addq, &adddw, - &addw, + &addw, &lvsp, &shlq, &shldw, &writeq, &writedw, &writeb, &nandq, &nanddw, &nandw, diff --git a/src/vmlifters/jmp.cpp b/src/vmlifters/jmp.cpp new file mode 100644 index 0000000..538346c --- /dev/null +++ b/src/vmlifters/jmp.cpp @@ -0,0 +1,10 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t jmp = { + // jmp + vm::handler::JMP, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->jmp( vinstr->trace_data.vsp.qword[ 0 ] ); + } }; +} \ No newline at end of file diff --git a/src/vmlifters/lflags.cpp b/src/vmlifters/lflags.cpp new file mode 100644 index 0000000..30b6c51 --- /dev/null +++ b/src/vmlifters/lflags.cpp @@ -0,0 +1,9 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t lrflags = { + // push flags + vm::handler::LRFLAGS, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( vtil::REG_FLAGS ); } }; +} \ No newline at end of file diff --git a/src/vmlifters/lvsp.cpp b/src/vmlifters/lvsp.cpp new file mode 100644 index 0000000..3bc49b7 --- /dev/null +++ b/src/vmlifters/lvsp.cpp @@ -0,0 +1,9 @@ +#include + +namespace vm::lifters +{ + vm::lifters::lifter_t lvsp = { + // vsp = vsp[0] + vm::handler::LVSP, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->pop( vtil::REG_SP ); } }; +} \ No newline at end of file diff --git a/src/vmlifters/read.cpp b/src/vmlifters/read.cpp index db3420e..171d1d8 100644 --- a/src/vmlifters/read.cpp +++ b/src/vmlifters/read.cpp @@ -7,10 +7,10 @@ namespace vm::lifters // ldd vregX, vregX, 0 // push vregX vm::handler::READQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { - auto t0 = blk->tmp( 64 ); + auto [ t0, t1 ] = blk->tmp( 64, 64 ); blk->pop( t0 ); - blk->ldd( t0, t0, 0 ); - blk->push( t0 ); + blk->ldd( t1, t0, vtil::make_imm( 0ull ) ); + blk->push( t1 ); } }; vm::lifters::lifter_t readdw = { @@ -18,10 +18,10 @@ namespace vm::lifters // ldd vregX, vregX, 0 // push vregX vm::handler::READDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { - auto t0 = blk->tmp( 32 ); + auto [ t0, t1 ] = blk->tmp( 64, 32 ); blk->pop( t0 ); - blk->ldd( t0, t0, 0 ); - blk->push( t0 ); + blk->ldd( t1, t0, vtil::make_imm( 0ull ) ); + blk->push( t1 ); } }; vm::lifters::lifter_t readw = { @@ -29,9 +29,9 @@ namespace vm::lifters // ldd vregX, vregX, 0 // push vregX vm::handler::READW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { - auto t0 = blk->tmp( 16 ); + auto [ t0, t1 ] = blk->tmp( 64, 16 ); blk->pop( t0 ); - blk->ldd( t0, t0, 0 ); - blk->push( t0 ); + blk->ldd( t1, t0, vtil::make_imm( 0ull ) ); + blk->push( t1 ); } }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/vmexit.cpp b/src/vmlifters/vmexit.cpp index 254e17b..b3eb4a3 100644 --- a/src/vmlifters/vmexit.cpp +++ b/src/vmlifters/vmexit.cpp @@ -4,5 +4,7 @@ namespace vm::lifters { vm::lifters::lifter_t vmexit = { // ret - vm::handler::VMEXIT, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->vexit(); } }; + vm::handler::VMEXIT, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + blk->vexit( vinstr->trace_data.vsp.qword[ 12 ] ); + } }; } \ No newline at end of file diff --git a/src/vmprofiles/lvsp.cpp b/src/vmprofiles/lvsp.cpp new file mode 100644 index 0000000..5bed39e --- /dev/null +++ b/src/vmprofiles/lvsp.cpp @@ -0,0 +1,16 @@ +#include + +namespace vm::handler::profile +{ + vm::handler::profile_t lvsp = { + // MOV RBP [RBP] + "LVSP", + LVSP, + NULL, + { { []( const zydis_decoded_instr_t &instr ) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_MOV && instr.operands[ 0 ].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[ 0 ].reg.value == ZYDIS_REGISTER_RBP && + instr.operands[ 1 ].type == ZYDIS_OPERAND_TYPE_MEMORY && + instr.operands[ 1 ].mem.base == ZYDIS_REGISTER_RBP; + } } } }; +} \ No newline at end of file diff --git a/vmprofiler.vcxproj b/vmprofiler.vcxproj index dd0c3c4..62d20e5 100644 --- a/vmprofiler.vcxproj +++ b/vmprofiler.vcxproj @@ -168,8 +168,11 @@ + + + @@ -183,6 +186,7 @@ + diff --git a/vmprofiler.vcxproj.filters b/vmprofiler.vcxproj.filters index 242966a..d72e456 100644 --- a/vmprofiler.vcxproj.filters +++ b/vmprofiler.vcxproj.filters @@ -285,5 +285,17 @@ Source Files\vmlifters + + Source Files\vmlifters + + + Source Files\vmlifters + + + Source Files\vmlifters + + + Source Files\vmprofiles + \ No newline at end of file From accba38deef3aae73af62dff8744a232bd490804 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Fri, 11 Jun 2021 00:48:29 -0700 Subject: [PATCH 15/20] vmexit lifter now puts the return address... --- src/vmlifters/vmexit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vmlifters/vmexit.cpp b/src/vmlifters/vmexit.cpp index b3eb4a3..55f7a9b 100644 --- a/src/vmlifters/vmexit.cpp +++ b/src/vmlifters/vmexit.cpp @@ -5,6 +5,6 @@ namespace vm::lifters vm::lifters::lifter_t vmexit = { // ret vm::handler::VMEXIT, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { - blk->vexit( vinstr->trace_data.vsp.qword[ 12 ] ); + blk->vexit( vtil::make_imm( vinstr->trace_data.vsp.qword[ 0x13 ] - vinstr->trace_data.regs.r13 ) ); } }; } \ No newline at end of file From 87acc2837b696d37a85663277be3a0ff726d4c31 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Fri, 11 Jun 2021 01:10:58 -0700 Subject: [PATCH 16/20] updated vtil dep... --- dependencies/vtil | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies/vtil b/dependencies/vtil index 46220b2..04eaba7 160000 --- a/dependencies/vtil +++ b/dependencies/vtil @@ -1 +1 @@ -Subproject commit 46220b2d054f7c250d9eef27879a2f05b7c9d9fa +Subproject commit 04eaba7cf2b30200ec894bc0b45d28e889ad1c1c From 44e412cffb14c98806b1eb5a91bbccf5180b9dbb Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Fri, 11 Jun 2021 14:29:33 -0700 Subject: [PATCH 17/20] added a param to the lifter_callback_t... --- include/vmlifters.hpp | 2 +- src/vmlifters/add.cpp | 6 +++--- src/vmlifters/jmp.cpp | 12 ++++++++++-- src/vmlifters/lconst.cpp | 27 ++++++++++++++++++--------- src/vmlifters/lflags.cpp | 4 ++-- src/vmlifters/lreg.cpp | 6 ++++-- src/vmlifters/lvsp.cpp | 4 ++-- src/vmlifters/nand.cpp | 9 ++++++--- src/vmlifters/pushvsp.cpp | 4 ++-- src/vmlifters/read.cpp | 9 ++++++--- src/vmlifters/shr.cpp | 6 ++++-- src/vmlifters/sreg.cpp | 9 ++++++--- src/vmlifters/vmexit.cpp | 3 ++- 13 files changed, 66 insertions(+), 35 deletions(-) diff --git a/include/vmlifters.hpp b/include/vmlifters.hpp index e0ec8b1..955f840 100644 --- a/include/vmlifters.hpp +++ b/include/vmlifters.hpp @@ -4,7 +4,7 @@ namespace vm::lifters { - using lifter_callback_t = std::function< void( vtil::basic_block *, vm::instrs::virt_instr_t * ) >; + using lifter_callback_t = std::function< void( vtil::basic_block *, vm::instrs::virt_instr_t *, vmp2::v3::code_block_t* ) >; using lifter_t = std::pair< vm::handler::mnemonic_t, lifter_callback_t >; // taken from diff --git a/src/vmlifters/add.cpp b/src/vmlifters/add.cpp index f52bdc9..65fe6d7 100644 --- a/src/vmlifters/add.cpp +++ b/src/vmlifters/add.cpp @@ -4,7 +4,7 @@ namespace vm::lifters { vm::lifters::lifter_t addq = { // vsp[0] = vsp[1] + vsp[0]; - vm::handler::ADDQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::ADDQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t* code_blk ) { auto [ t0, t1 ] = blk->tmp( 64, 64 ); blk->pop( t0 ); blk->pop( t1 ); @@ -15,7 +15,7 @@ namespace vm::lifters vm::lifters::lifter_t adddw = { // vsp[0] = vsp[1] + vsp[0]; - vm::handler::ADDDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::ADDDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t* code_blk ) { auto [ t0, t1 ] = blk->tmp( 32, 32 ); blk->pop( t0 ); blk->pop( t1 ); @@ -26,7 +26,7 @@ namespace vm::lifters vm::lifters::lifter_t addw = { // vsp[0] = vsp[1] + vsp[0]; - vm::handler::ADDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::ADDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t* code_blk ) { auto [ t0, t1 ] = blk->tmp( 16, 16 ); blk->pop( t0 ); blk->pop( t1 ); diff --git a/src/vmlifters/jmp.cpp b/src/vmlifters/jmp.cpp index 538346c..4f07da6 100644 --- a/src/vmlifters/jmp.cpp +++ b/src/vmlifters/jmp.cpp @@ -4,7 +4,15 @@ namespace vm::lifters { vm::lifters::lifter_t jmp = { // jmp - vm::handler::JMP, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { - blk->jmp( vinstr->trace_data.vsp.qword[ 0 ] ); + vm::handler::JMP, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { + if ( code_blk->jcc.has_jcc ) + { + // TODO: figure out what bit the JCC is determined on... + blk->js( vtil::REG_FLAGS.select( 1, 11 ), code_blk->jcc.block_addr[ 0 ], + code_blk->jcc.block_addr[ 1 ] ); + } + else + blk->jmp( vinstr->trace_data.vsp.qword[ 0 ] ); } }; } \ No newline at end of file diff --git a/src/vmlifters/lconst.cpp b/src/vmlifters/lconst.cpp index 2b246e3..964e3a2 100644 --- a/src/vmlifters/lconst.cpp +++ b/src/vmlifters/lconst.cpp @@ -4,55 +4,64 @@ namespace vm::lifters { vm::lifters::lifter_t lconstq = { // push imm - vm::handler::LCONSTQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); } }; vm::lifters::lifter_t lconstdw = { // push imm - vm::handler::LCONSTDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 32 ) ); } }; vm::lifters::lifter_t lconstw = { // push imm - vm::handler::LCONSTW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 16 ) ); } }; vm::lifters::lifter_t lconstbzxw = { // push imm - vm::handler::LCONSTBZXW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTBZXW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 16 ) ); } }; vm::lifters::lifter_t lconstbsxdw = { // push imm - vm::handler::LCONSTBSXDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTBSXDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 32 ) ); } }; vm::lifters::lifter_t lconstbsxq = { // push imm - vm::handler::LCONSTBSXQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTBSXQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); } }; vm::lifters::lifter_t lconstdwsxq = { // push imm - vm::handler::LCONSTDWSXQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTDWSXQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); } }; vm::lifters::lifter_t lconstwsxq = { // push imm - vm::handler::LCONSTWSXQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTWSXQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 64 ) ); } }; vm::lifters::lifter_t lconstwsxdw = { // push imm - vm::handler::LCONSTWSXDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LCONSTWSXDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::operand( vinstr->operand.imm.u, 32 ) ); } }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/lflags.cpp b/src/vmlifters/lflags.cpp index 30b6c51..8ba753a 100644 --- a/src/vmlifters/lflags.cpp +++ b/src/vmlifters/lflags.cpp @@ -4,6 +4,6 @@ namespace vm::lifters { vm::lifters::lifter_t lrflags = { // push flags - vm::handler::LRFLAGS, - []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( vtil::REG_FLAGS ); } }; + vm::handler::LRFLAGS, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, + vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::REG_FLAGS ); } }; } \ No newline at end of file diff --git a/src/vmlifters/lreg.cpp b/src/vmlifters/lreg.cpp index 324b876..2f0fb23 100644 --- a/src/vmlifters/lreg.cpp +++ b/src/vmlifters/lreg.cpp @@ -4,13 +4,15 @@ namespace vm::lifters { vm::lifters::lifter_t lregq = { // push vregX - vm::handler::LREGQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LREGQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( make_virtual_register( vinstr->operand.imm.u, 8 ) ); } }; vm::lifters::lifter_t lregdw = { // push vregX - vm::handler::LREGDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::LREGDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->push( make_virtual_register( vinstr->operand.imm.u, 4 ) ); } }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/lvsp.cpp b/src/vmlifters/lvsp.cpp index 3bc49b7..7943aa9 100644 --- a/src/vmlifters/lvsp.cpp +++ b/src/vmlifters/lvsp.cpp @@ -4,6 +4,6 @@ namespace vm::lifters { vm::lifters::lifter_t lvsp = { // vsp = vsp[0] - vm::handler::LVSP, - []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->pop( vtil::REG_SP ); } }; + vm::handler::LVSP, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, + vmp2::v3::code_block_t *code_blk ) { blk->pop( vtil::REG_SP ); } }; } \ No newline at end of file diff --git a/src/vmlifters/nand.cpp b/src/vmlifters/nand.cpp index 141c8f4..bdf4bb8 100644 --- a/src/vmlifters/nand.cpp +++ b/src/vmlifters/nand.cpp @@ -10,7 +10,8 @@ namespace vm::lifters // and vregX, vregY // push vregX // pushf - vm::handler::NANDQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::NANDQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t1, t2 ] = blk->tmp( 64, 64 ); blk->pop( t1 ); blk->pop( t2 ); @@ -31,7 +32,8 @@ namespace vm::lifters // and vregX, vregY // push vregX // pushf - vm::handler::NANDDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::NANDDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t1, t2 ] = blk->tmp( 32, 32 ); blk->pop( t1 ); blk->pop( t2 ); @@ -52,7 +54,8 @@ namespace vm::lifters // and vregX, vregY // push vregX // pushf - vm::handler::NANDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::NANDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t1, t2 ] = blk->tmp( 16, 16 ); blk->pop( t1 ); blk->pop( t2 ); diff --git a/src/vmlifters/pushvsp.cpp b/src/vmlifters/pushvsp.cpp index 566a430..1de8465 100644 --- a/src/vmlifters/pushvsp.cpp +++ b/src/vmlifters/pushvsp.cpp @@ -4,6 +4,6 @@ namespace vm::lifters { vm::lifters::lifter_t pushvsp = { // push vsp - vm::handler::PUSHVSP, - []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { blk->push( vtil::REG_SP ); } }; + vm::handler::PUSHVSP, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, + vmp2::v3::code_block_t *code_blk ) { blk->push( vtil::REG_SP ); } }; } \ No newline at end of file diff --git a/src/vmlifters/read.cpp b/src/vmlifters/read.cpp index 171d1d8..6299524 100644 --- a/src/vmlifters/read.cpp +++ b/src/vmlifters/read.cpp @@ -6,7 +6,8 @@ namespace vm::lifters // pop vregX // ldd vregX, vregX, 0 // push vregX - vm::handler::READQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::READQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t0, t1 ] = blk->tmp( 64, 64 ); blk->pop( t0 ); blk->ldd( t1, t0, vtil::make_imm( 0ull ) ); @@ -17,7 +18,8 @@ namespace vm::lifters // pop vregX // ldd vregX, vregX, 0 // push vregX - vm::handler::READDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::READDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t0, t1 ] = blk->tmp( 64, 32 ); blk->pop( t0 ); blk->ldd( t1, t0, vtil::make_imm( 0ull ) ); @@ -28,7 +30,8 @@ namespace vm::lifters // pop vregX // ldd vregX, vregX, 0 // push vregX - vm::handler::READW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::READW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t0, t1 ] = blk->tmp( 64, 16 ); blk->pop( t0 ); blk->ldd( t1, t0, vtil::make_imm( 0ull ) ); diff --git a/src/vmlifters/shr.cpp b/src/vmlifters/shr.cpp index 8e88e17..f8610ac 100644 --- a/src/vmlifters/shr.cpp +++ b/src/vmlifters/shr.cpp @@ -8,7 +8,8 @@ namespace vm::lifters // shr vregX, vregY // push vregX // pushf - vm::handler::SHRQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::SHRQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t0, t1 ] = blk->tmp( 64, 8 ); blk->pop( t0 ); blk->pop( t1 ); @@ -23,7 +24,8 @@ namespace vm::lifters // shr vregX, vregY // push vregX // pushf - vm::handler::SHRW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::SHRW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { auto [ t0, t1 ] = blk->tmp( 16, 8 ); blk->pop( t0 ); blk->pop( t1 ); diff --git a/src/vmlifters/sreg.cpp b/src/vmlifters/sreg.cpp index c6d6698..253322f 100644 --- a/src/vmlifters/sreg.cpp +++ b/src/vmlifters/sreg.cpp @@ -4,19 +4,22 @@ namespace vm::lifters { vm::lifters::lifter_t sregq = { // pop vregX - vm::handler::SREGQ, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::SREGQ, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->pop( make_virtual_register( vinstr->operand.imm.u, 8 ) ); } }; vm::lifters::lifter_t sregdw = { // pop vregX - vm::handler::SREGDW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::SREGDW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->pop( make_virtual_register( vinstr->operand.imm.u, 4 ) ); } }; vm::lifters::lifter_t sregw = { // pop vregX - vm::handler::SREGW, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::SREGW, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->pop( make_virtual_register( vinstr->operand.imm.u, 2 ) ); } }; } // namespace vm::lifters \ No newline at end of file diff --git a/src/vmlifters/vmexit.cpp b/src/vmlifters/vmexit.cpp index 55f7a9b..1fa8a9b 100644 --- a/src/vmlifters/vmexit.cpp +++ b/src/vmlifters/vmexit.cpp @@ -4,7 +4,8 @@ namespace vm::lifters { vm::lifters::lifter_t vmexit = { // ret - vm::handler::VMEXIT, []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr ) { + vm::handler::VMEXIT, + []( vtil::basic_block *blk, vm::instrs::virt_instr_t *vinstr, vmp2::v3::code_block_t *code_blk ) { blk->vexit( vtil::make_imm( vinstr->trace_data.vsp.qword[ 0x13 ] - vinstr->trace_data.regs.r13 ) ); } }; } \ No newline at end of file From a99d7a9f0a9924abc24d5fdef35a181e14bb294e Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sat, 12 Jun 2021 21:25:21 -0700 Subject: [PATCH 18/20] updated jmp lifter... --- src/vmlifters/jmp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vmlifters/jmp.cpp b/src/vmlifters/jmp.cpp index 4f07da6..6769e43 100644 --- a/src/vmlifters/jmp.cpp +++ b/src/vmlifters/jmp.cpp @@ -9,10 +9,10 @@ namespace vm::lifters if ( code_blk->jcc.has_jcc ) { // TODO: figure out what bit the JCC is determined on... - blk->js( vtil::REG_FLAGS.select( 1, 11 ), code_blk->jcc.block_addr[ 0 ], - code_blk->jcc.block_addr[ 1 ] ); + blk->js( vtil::REG_FLAGS.select( 1, 11 ), code_blk->jcc.block_addr[ 0 ] - vinstr->trace_data.regs.r13, + code_blk->jcc.block_addr[ 1 ] - vinstr->trace_data.regs.r13 ); } else - blk->jmp( vinstr->trace_data.vsp.qword[ 0 ] ); + blk->jmp( vinstr->trace_data.vsp.qword[ 0 ] - vinstr->trace_data.regs.r13 ); } }; } \ No newline at end of file From 64a139ffca1a7b678b89effa7ebf2fa9f8af9515 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sat, 12 Jun 2021 18:52:30 -0700 Subject: [PATCH 19/20] added doxygen to the project --- doxygen/Doxyfile | 2660 +++++++++++++++++ doxygen/html/_r_e_a_d_m_e_8md.html | 77 + doxygen/html/annotated.html | 101 + doxygen/html/bc_s.png | Bin 0 -> 676 bytes doxygen/html/bdwn.png | Bin 0 -> 147 bytes doxygen/html/calc__jmp_8cpp.html | 102 + doxygen/html/calc__jmp_8hpp.html | 105 + doxygen/html/calc__jmp_8hpp_source.html | 97 + doxygen/html/call_8cpp.html | 96 + doxygen/html/classes.html | 104 + doxygen/html/classvm_1_1ctx__t-members.html | 94 + doxygen/html/classvm_1_1ctx__t.html | 325 ++ doxygen/html/closed.png | Bin 0 -> 132 bytes .../dir_34caf5031dac7df8f41881fc650fad9e.html | 109 + .../dir_41b4d5d37872f2c0144673a67fd94b20.html | 119 + .../dir_68267d1309a1af8e8297ef4c3efbcdba.html | 102 + .../dir_d44c64559bbebec7f509842c48db8b23.html | 105 + doxygen/html/div_8cpp.html | 96 + doxygen/html/doc.png | Bin 0 -> 746 bytes doxygen/html/doxygen.css | 1793 +++++++++++ doxygen/html/doxygen.svg | 26 + doxygen/html/dynsections.js | 121 + doxygen/html/files.html | 129 + doxygen/html/folderclosed.png | Bin 0 -> 616 bytes doxygen/html/folderopen.png | Bin 0 -> 597 bytes doxygen/html/functions.html | 408 +++ doxygen/html/functions_func.html | 81 + doxygen/html/functions_vars.html | 402 +++ doxygen/html/globals.html | 108 + doxygen/html/globals_defs.html | 81 + doxygen/html/globals_type.html | 102 + doxygen/html/icon.png | Bin 0 -> 6949 bytes doxygen/html/index.html | 81 + doxygen/html/jquery.js | 35 + doxygen/html/md__r_e_a_d_m_e.html | 81 + doxygen/html/menu.js | 51 + doxygen/html/menudata.js | 146 + doxygen/html/mul_8cpp.html | 96 + doxygen/html/namespacemembers.html | 628 ++++ doxygen/html/namespacemembers_enum.html | 93 + doxygen/html/namespacemembers_eval.html | 258 ++ doxygen/html/namespacemembers_func.html | 237 ++ doxygen/html/namespacemembers_type.html | 90 + doxygen/html/namespacemembers_vars.html | 316 ++ doxygen/html/namespaces.html | 107 + doxygen/html/namespacevm.html | 105 + doxygen/html/namespacevm_1_1calc__jmp.html | 159 + doxygen/html/namespacevm_1_1handler.html | 599 ++++ .../namespacevm_1_1handler_1_1profile.html | 1236 ++++++++ .../html/namespacevm_1_1handler_1_1table.html | 241 ++ doxygen/html/namespacevm_1_1instrs.html | 490 +++ doxygen/html/namespacevm_1_1lifters.html | 976 ++++++ doxygen/html/namespacevm_1_1transform.html | 1232 ++++++++ doxygen/html/namespacevm_1_1util.html | 336 +++ doxygen/html/namespacevm_1_1util_1_1reg.html | 164 + doxygen/html/namespacevmp2.html | 158 + doxygen/html/namespacevmp2_1_1v1.html | 91 + doxygen/html/namespacevmp2_1_1v2.html | 91 + doxygen/html/namespacevmp2_1_1v3.html | 91 + doxygen/html/nav_f.png | Bin 0 -> 153 bytes doxygen/html/nav_g.png | Bin 0 -> 95 bytes doxygen/html/nav_h.png | Bin 0 -> 98 bytes doxygen/html/open.png | Bin 0 -> 123 bytes doxygen/html/pages.html | 82 + doxygen/html/search/all_0.html | 37 + doxygen/html/search/all_0.js | 22 + doxygen/html/search/all_1.html | 37 + doxygen/html/search/all_1.js | 16 + doxygen/html/search/all_10.html | 37 + doxygen/html/search/all_10.js | 4 + doxygen/html/search/all_11.html | 37 + doxygen/html/search/all_11.js | 30 + doxygen/html/search/all_12.html | 37 + doxygen/html/search/all_12.js | 23 + doxygen/html/search/all_13.html | 37 + doxygen/html/search/all_13.js | 9 + doxygen/html/search/all_14.html | 37 + doxygen/html/search/all_14.js | 10 + doxygen/html/search/all_15.html | 37 + doxygen/html/search/all_15.js | 47 + doxygen/html/search/all_16.html | 37 + doxygen/html/search/all_16.js | 11 + doxygen/html/search/all_17.html | 37 + doxygen/html/search/all_17.js | 10 + doxygen/html/search/all_2.html | 37 + doxygen/html/search/all_2.js | 6 + doxygen/html/search/all_3.html | 37 + doxygen/html/search/all_3.js | 15 + doxygen/html/search/all_4.html | 37 + doxygen/html/search/all_4.js | 10 + doxygen/html/search/all_5.html | 37 + doxygen/html/search/all_5.js | 13 + doxygen/html/search/all_6.html | 37 + doxygen/html/search/all_6.js | 6 + doxygen/html/search/all_7.html | 37 + doxygen/html/search/all_7.js | 17 + doxygen/html/search/all_8.html | 37 + doxygen/html/search/all_8.js | 7 + doxygen/html/search/all_9.html | 37 + doxygen/html/search/all_9.js | 15 + doxygen/html/search/all_a.html | 37 + doxygen/html/search/all_a.js | 9 + doxygen/html/search/all_b.html | 37 + doxygen/html/search/all_b.js | 35 + doxygen/html/search/all_c.html | 37 + doxygen/html/search/all_c.js | 14 + doxygen/html/search/all_d.html | 37 + doxygen/html/search/all_d.js | 14 + doxygen/html/search/all_e.html | 37 + doxygen/html/search/all_e.js | 5 + doxygen/html/search/all_f.html | 37 + doxygen/html/search/all_f.js | 9 + doxygen/html/search/classes_0.html | 37 + doxygen/html/search/classes_0.js | 5 + doxygen/html/search/classes_1.html | 37 + doxygen/html/search/classes_1.js | 4 + doxygen/html/search/classes_2.html | 37 + doxygen/html/search/classes_2.js | 4 + doxygen/html/search/classes_3.html | 37 + doxygen/html/search/classes_3.js | 4 + doxygen/html/search/classes_4.html | 37 + doxygen/html/search/classes_4.js | 4 + doxygen/html/search/classes_5.html | 37 + doxygen/html/search/classes_5.js | 4 + doxygen/html/search/classes_6.html | 37 + doxygen/html/search/classes_6.js | 4 + doxygen/html/search/classes_7.html | 37 + doxygen/html/search/classes_7.js | 4 + doxygen/html/search/close.svg | 31 + doxygen/html/search/defines_0.html | 37 + doxygen/html/search/defines_0.js | 4 + doxygen/html/search/defines_1.html | 37 + doxygen/html/search/defines_1.js | 4 + doxygen/html/search/enums_0.html | 37 + doxygen/html/search/enums_0.js | 5 + doxygen/html/search/enums_1.html | 37 + doxygen/html/search/enums_1.js | 4 + doxygen/html/search/enums_2.html | 37 + doxygen/html/search/enums_2.js | 4 + doxygen/html/search/enums_3.html | 37 + doxygen/html/search/enums_3.js | 4 + doxygen/html/search/enums_4.html | 37 + doxygen/html/search/enums_4.js | 4 + doxygen/html/search/enumvalues_0.html | 37 + doxygen/html/search/enumvalues_0.js | 7 + doxygen/html/search/enumvalues_1.html | 37 + doxygen/html/search/enumvalues_1.js | 5 + doxygen/html/search/enumvalues_10.html | 37 + doxygen/html/search/enumvalues_10.js | 7 + doxygen/html/search/enumvalues_11.html | 37 + doxygen/html/search/enumvalues_11.js | 4 + doxygen/html/search/enumvalues_2.html | 37 + doxygen/html/search/enumvalues_2.js | 4 + doxygen/html/search/enumvalues_3.html | 37 + doxygen/html/search/enumvalues_3.js | 4 + doxygen/html/search/enumvalues_4.html | 37 + doxygen/html/search/enumvalues_4.js | 4 + doxygen/html/search/enumvalues_5.html | 37 + doxygen/html/search/enumvalues_5.js | 7 + doxygen/html/search/enumvalues_6.html | 37 + doxygen/html/search/enumvalues_6.js | 5 + doxygen/html/search/enumvalues_7.html | 37 + doxygen/html/search/enumvalues_7.js | 4 + doxygen/html/search/enumvalues_8.html | 37 + doxygen/html/search/enumvalues_8.js | 16 + doxygen/html/search/enumvalues_9.html | 37 + doxygen/html/search/enumvalues_9.js | 4 + doxygen/html/search/enumvalues_a.html | 37 + doxygen/html/search/enumvalues_a.js | 7 + doxygen/html/search/enumvalues_b.html | 37 + doxygen/html/search/enumvalues_b.js | 4 + doxygen/html/search/enumvalues_c.html | 37 + doxygen/html/search/enumvalues_c.js | 7 + doxygen/html/search/enumvalues_d.html | 37 + doxygen/html/search/enumvalues_d.js | 11 + doxygen/html/search/enumvalues_e.html | 37 + doxygen/html/search/enumvalues_e.js | 4 + doxygen/html/search/enumvalues_f.html | 37 + doxygen/html/search/enumvalues_f.js | 7 + doxygen/html/search/files_0.html | 37 + doxygen/html/search/files_0.js | 4 + doxygen/html/search/files_1.html | 37 + doxygen/html/search/files_1.js | 6 + doxygen/html/search/files_2.html | 37 + doxygen/html/search/files_2.js | 4 + doxygen/html/search/files_3.html | 37 + doxygen/html/search/files_3.js | 4 + doxygen/html/search/files_4.html | 37 + doxygen/html/search/files_4.js | 7 + doxygen/html/search/files_5.html | 37 + doxygen/html/search/files_5.js | 4 + doxygen/html/search/files_6.html | 37 + doxygen/html/search/files_6.js | 4 + doxygen/html/search/files_7.html | 37 + doxygen/html/search/files_7.js | 4 + doxygen/html/search/files_8.html | 37 + doxygen/html/search/files_8.js | 5 + doxygen/html/search/files_9.html | 37 + doxygen/html/search/files_9.js | 6 + doxygen/html/search/files_a.html | 37 + doxygen/html/search/files_a.js | 4 + doxygen/html/search/files_b.html | 37 + doxygen/html/search/files_b.js | 16 + doxygen/html/search/files_c.html | 37 + doxygen/html/search/files_c.js | 4 + doxygen/html/search/functions_0.html | 37 + doxygen/html/search/functions_0.js | 12 + doxygen/html/search/functions_1.html | 37 + doxygen/html/search/functions_1.js | 4 + doxygen/html/search/functions_2.html | 37 + doxygen/html/search/functions_2.js | 6 + doxygen/html/search/functions_3.html | 37 + doxygen/html/search/functions_3.js | 6 + doxygen/html/search/functions_4.html | 37 + doxygen/html/search/functions_4.js | 5 + doxygen/html/search/functions_5.html | 37 + doxygen/html/search/functions_5.js | 4 + doxygen/html/search/functions_6.html | 37 + doxygen/html/search/functions_6.js | 13 + doxygen/html/search/functions_7.html | 37 + doxygen/html/search/functions_7.js | 4 + doxygen/html/search/functions_8.html | 37 + doxygen/html/search/functions_8.js | 7 + doxygen/html/search/functions_9.html | 37 + doxygen/html/search/functions_9.js | 4 + doxygen/html/search/functions_a.html | 37 + doxygen/html/search/functions_a.js | 4 + doxygen/html/search/functions_b.html | 37 + doxygen/html/search/functions_b.js | 4 + doxygen/html/search/functions_c.html | 37 + doxygen/html/search/functions_c.js | 4 + doxygen/html/search/mag_sel.svg | 74 + doxygen/html/search/namespaces_0.html | 37 + doxygen/html/search/namespaces_0.js | 17 + doxygen/html/search/nomatches.html | 13 + doxygen/html/search/pages_0.html | 37 + doxygen/html/search/pages_0.js | 4 + doxygen/html/search/search.css | 257 ++ doxygen/html/search/search.js | 816 +++++ doxygen/html/search/search_l.png | Bin 0 -> 567 bytes doxygen/html/search/search_m.png | Bin 0 -> 158 bytes doxygen/html/search/search_r.png | Bin 0 -> 553 bytes doxygen/html/search/searchdata.js | 42 + doxygen/html/search/typedefs_0.html | 37 + doxygen/html/search/typedefs_0.js | 5 + doxygen/html/search/typedefs_1.html | 37 + doxygen/html/search/typedefs_1.js | 4 + doxygen/html/search/typedefs_2.html | 37 + doxygen/html/search/typedefs_2.js | 4 + doxygen/html/search/typedefs_3.html | 37 + doxygen/html/search/typedefs_3.js | 8 + doxygen/html/search/typedefs_4.html | 37 + doxygen/html/search/typedefs_4.js | 8 + doxygen/html/search/variables_0.html | 37 + doxygen/html/search/variables_0.js | 13 + doxygen/html/search/variables_1.html | 37 + doxygen/html/search/variables_1.js | 10 + doxygen/html/search/variables_10.html | 37 + doxygen/html/search/variables_10.js | 12 + doxygen/html/search/variables_11.html | 37 + doxygen/html/search/variables_11.js | 6 + doxygen/html/search/variables_12.html | 37 + doxygen/html/search/variables_12.js | 4 + doxygen/html/search/variables_13.html | 37 + doxygen/html/search/variables_13.js | 15 + doxygen/html/search/variables_14.html | 37 + doxygen/html/search/variables_14.js | 6 + doxygen/html/search/variables_2.html | 37 + doxygen/html/search/variables_2.js | 4 + doxygen/html/search/variables_3.html | 37 + doxygen/html/search/variables_3.js | 7 + doxygen/html/search/variables_4.html | 37 + doxygen/html/search/variables_4.js | 5 + doxygen/html/search/variables_5.html | 37 + doxygen/html/search/variables_5.js | 8 + doxygen/html/search/variables_6.html | 37 + doxygen/html/search/variables_6.js | 6 + doxygen/html/search/variables_7.html | 37 + doxygen/html/search/variables_7.js | 10 + doxygen/html/search/variables_8.html | 37 + doxygen/html/search/variables_8.js | 5 + doxygen/html/search/variables_9.html | 37 + doxygen/html/search/variables_9.js | 16 + doxygen/html/search/variables_a.html | 37 + doxygen/html/search/variables_a.js | 10 + doxygen/html/search/variables_b.html | 37 + doxygen/html/search/variables_b.js | 8 + doxygen/html/search/variables_c.html | 37 + doxygen/html/search/variables_c.js | 5 + doxygen/html/search/variables_d.html | 37 + doxygen/html/search/variables_d.js | 5 + doxygen/html/search/variables_e.html | 37 + doxygen/html/search/variables_e.js | 4 + doxygen/html/search/variables_f.html | 37 + doxygen/html/search/variables_f.js | 24 + doxygen/html/shl_8cpp.html | 96 + doxygen/html/splitbar.png | Bin 0 -> 314 bytes ...ctvm_1_1handler_1_1handler__t-members.html | 89 + .../structvm_1_1handler_1_1handler__t.html | 194 ++ ...ctvm_1_1handler_1_1profile__t-members.html | 89 + .../structvm_1_1handler_1_1profile__t.html | 194 ++ ...m_1_1instrs_1_1code__block__t-members.html | 87 + .../structvm_1_1instrs_1_1code__block__t.html | 142 + ...ructvm_1_1instrs_1_1jcc__data-members.html | 87 + .../html/structvm_1_1instrs_1_1jcc__data.html | 142 + ...m_1_1instrs_1_1virt__instr__t-members.html | 93 + .../structvm_1_1instrs_1_1virt__instr__t.html | 243 ++ .../structvmp2_1_1v1_1_1entry__t-members.html | 109 + .../html/structvmp2_1_1v1_1_1entry__t.html | 504 ++++ ...uctvmp2_1_1v1_1_1file__header-members.html | 91 + .../structvmp2_1_1v1_1_1file__header.html | 206 ++ .../structvmp2_1_1v2_1_1entry__t-members.html | 109 + .../html/structvmp2_1_1v2_1_1entry__t.html | 504 ++++ ...uctvmp2_1_1v2_1_1file__header-members.html | 95 + .../structvmp2_1_1v2_1_1file__header.html | 270 ++ ...tvmp2_1_1v3_1_1code__block__t-members.html | 89 + .../structvmp2_1_1v3_1_1code__block__t.html | 174 ++ ...uctvmp2_1_1v3_1_1file__header-members.html | 94 + .../structvmp2_1_1v3_1_1file__header.html | 254 ++ .../html/structzydis__instr__t-members.html | 83 + doxygen/html/structzydis__instr__t.html | 138 + doxygen/html/sync_off.png | Bin 0 -> 853 bytes doxygen/html/sync_on.png | Bin 0 -> 845 bytes doxygen/html/tab_a.png | Bin 0 -> 142 bytes doxygen/html/tab_b.png | Bin 0 -> 169 bytes doxygen/html/tab_h.png | Bin 0 -> 177 bytes doxygen/html/tab_s.png | Bin 0 -> 184 bytes doxygen/html/tabs.css | 1 + doxygen/html/transform_8hpp.html | 210 ++ doxygen/html/transform_8hpp_source.html | 344 +++ doxygen/html/vmctx_8cpp.html | 90 + doxygen/html/vmctx_8hpp.html | 101 + doxygen/html/vmctx_8hpp_source.html | 121 + doxygen/html/vmhandler_8cpp.html | 131 + doxygen/html/vmhandlers_8hpp.html | 142 + doxygen/html/vmhandlers_8hpp_source.html | 152 + doxygen/html/vminstrs_8cpp.html | 121 + doxygen/html/vminstrs_8hpp.html | 126 + doxygen/html/vminstrs_8hpp_source.html | 126 + doxygen/html/vmlifters_2add_8cpp.html | 92 + doxygen/html/vmlifters_2jmp_8cpp.html | 92 + doxygen/html/vmlifters_2lconst_8cpp.html | 92 + doxygen/html/vmlifters_2lflags_8cpp.html | 92 + doxygen/html/vmlifters_2lreg_8cpp.html | 92 + doxygen/html/vmlifters_2lvsp_8cpp.html | 92 + doxygen/html/vmlifters_2nand_8cpp.html | 92 + doxygen/html/vmlifters_2pushvsp_8cpp.html | 92 + doxygen/html/vmlifters_2read_8cpp.html | 92 + doxygen/html/vmlifters_2shr_8cpp.html | 92 + doxygen/html/vmlifters_2sreg_8cpp.html | 92 + doxygen/html/vmlifters_2vmexit_8cpp.html | 92 + doxygen/html/vmlifters_8hpp.html | 176 ++ doxygen/html/vmlifters_8hpp_source.html | 190 ++ doxygen/html/vmp2_8hpp.html | 166 + doxygen/html/vmp2_8hpp_source.html | 433 +++ doxygen/html/vmprofiler_8hpp.html | 92 + doxygen/html/vmprofiler_8hpp_source.html | 100 + doxygen/html/vmprofiles_2add_8cpp.html | 96 + doxygen/html/vmprofiles_2jmp_8cpp.html | 96 + doxygen/html/vmprofiles_2lconst_8cpp.html | 96 + doxygen/html/vmprofiles_2lflags_8cpp.html | 96 + doxygen/html/vmprofiles_2lreg_8cpp.html | 96 + doxygen/html/vmprofiles_2lvsp_8cpp.html | 96 + doxygen/html/vmprofiles_2nand_8cpp.html | 96 + doxygen/html/vmprofiles_2pushvsp_8cpp.html | 96 + doxygen/html/vmprofiles_2read_8cpp.html | 96 + doxygen/html/vmprofiles_2shr_8cpp.html | 96 + doxygen/html/vmprofiles_2sreg_8cpp.html | 96 + doxygen/html/vmprofiles_2vmexit_8cpp.html | 96 + doxygen/html/vmprofiles_8hpp.html | 265 ++ doxygen/html/vmprofiles_8hpp_source.html | 322 ++ doxygen/html/vmutils_8cpp.html | 127 + doxygen/html/vmutils_8hpp.html | 310 ++ doxygen/html/vmutils_8hpp_source.html | 155 + doxygen/html/write_8cpp.html | 96 + icon.png | Bin 0 -> 6949 bytes 376 files changed, 32594 insertions(+) create mode 100644 doxygen/Doxyfile create mode 100644 doxygen/html/_r_e_a_d_m_e_8md.html create mode 100644 doxygen/html/annotated.html create mode 100644 doxygen/html/bc_s.png create mode 100644 doxygen/html/bdwn.png create mode 100644 doxygen/html/calc__jmp_8cpp.html create mode 100644 doxygen/html/calc__jmp_8hpp.html create mode 100644 doxygen/html/calc__jmp_8hpp_source.html create mode 100644 doxygen/html/call_8cpp.html create mode 100644 doxygen/html/classes.html create mode 100644 doxygen/html/classvm_1_1ctx__t-members.html create mode 100644 doxygen/html/classvm_1_1ctx__t.html create mode 100644 doxygen/html/closed.png create mode 100644 doxygen/html/dir_34caf5031dac7df8f41881fc650fad9e.html create mode 100644 doxygen/html/dir_41b4d5d37872f2c0144673a67fd94b20.html create mode 100644 doxygen/html/dir_68267d1309a1af8e8297ef4c3efbcdba.html create mode 100644 doxygen/html/dir_d44c64559bbebec7f509842c48db8b23.html create mode 100644 doxygen/html/div_8cpp.html create mode 100644 doxygen/html/doc.png create mode 100644 doxygen/html/doxygen.css create mode 100644 doxygen/html/doxygen.svg create mode 100644 doxygen/html/dynsections.js create mode 100644 doxygen/html/files.html create mode 100644 doxygen/html/folderclosed.png create mode 100644 doxygen/html/folderopen.png create mode 100644 doxygen/html/functions.html create mode 100644 doxygen/html/functions_func.html create mode 100644 doxygen/html/functions_vars.html create mode 100644 doxygen/html/globals.html create mode 100644 doxygen/html/globals_defs.html create mode 100644 doxygen/html/globals_type.html create mode 100644 doxygen/html/icon.png create mode 100644 doxygen/html/index.html create mode 100644 doxygen/html/jquery.js create mode 100644 doxygen/html/md__r_e_a_d_m_e.html create mode 100644 doxygen/html/menu.js create mode 100644 doxygen/html/menudata.js create mode 100644 doxygen/html/mul_8cpp.html create mode 100644 doxygen/html/namespacemembers.html create mode 100644 doxygen/html/namespacemembers_enum.html create mode 100644 doxygen/html/namespacemembers_eval.html create mode 100644 doxygen/html/namespacemembers_func.html create mode 100644 doxygen/html/namespacemembers_type.html create mode 100644 doxygen/html/namespacemembers_vars.html create mode 100644 doxygen/html/namespaces.html create mode 100644 doxygen/html/namespacevm.html create mode 100644 doxygen/html/namespacevm_1_1calc__jmp.html create mode 100644 doxygen/html/namespacevm_1_1handler.html create mode 100644 doxygen/html/namespacevm_1_1handler_1_1profile.html create mode 100644 doxygen/html/namespacevm_1_1handler_1_1table.html create mode 100644 doxygen/html/namespacevm_1_1instrs.html create mode 100644 doxygen/html/namespacevm_1_1lifters.html create mode 100644 doxygen/html/namespacevm_1_1transform.html create mode 100644 doxygen/html/namespacevm_1_1util.html create mode 100644 doxygen/html/namespacevm_1_1util_1_1reg.html create mode 100644 doxygen/html/namespacevmp2.html create mode 100644 doxygen/html/namespacevmp2_1_1v1.html create mode 100644 doxygen/html/namespacevmp2_1_1v2.html create mode 100644 doxygen/html/namespacevmp2_1_1v3.html create mode 100644 doxygen/html/nav_f.png create mode 100644 doxygen/html/nav_g.png create mode 100644 doxygen/html/nav_h.png create mode 100644 doxygen/html/open.png create mode 100644 doxygen/html/pages.html create mode 100644 doxygen/html/search/all_0.html create mode 100644 doxygen/html/search/all_0.js create mode 100644 doxygen/html/search/all_1.html create mode 100644 doxygen/html/search/all_1.js create mode 100644 doxygen/html/search/all_10.html create mode 100644 doxygen/html/search/all_10.js create mode 100644 doxygen/html/search/all_11.html create mode 100644 doxygen/html/search/all_11.js create mode 100644 doxygen/html/search/all_12.html create mode 100644 doxygen/html/search/all_12.js create mode 100644 doxygen/html/search/all_13.html create mode 100644 doxygen/html/search/all_13.js create mode 100644 doxygen/html/search/all_14.html create mode 100644 doxygen/html/search/all_14.js create mode 100644 doxygen/html/search/all_15.html create mode 100644 doxygen/html/search/all_15.js create mode 100644 doxygen/html/search/all_16.html create mode 100644 doxygen/html/search/all_16.js create mode 100644 doxygen/html/search/all_17.html create mode 100644 doxygen/html/search/all_17.js create mode 100644 doxygen/html/search/all_2.html create mode 100644 doxygen/html/search/all_2.js create mode 100644 doxygen/html/search/all_3.html create mode 100644 doxygen/html/search/all_3.js create mode 100644 doxygen/html/search/all_4.html create mode 100644 doxygen/html/search/all_4.js create mode 100644 doxygen/html/search/all_5.html create mode 100644 doxygen/html/search/all_5.js create mode 100644 doxygen/html/search/all_6.html create mode 100644 doxygen/html/search/all_6.js create mode 100644 doxygen/html/search/all_7.html create mode 100644 doxygen/html/search/all_7.js create mode 100644 doxygen/html/search/all_8.html create mode 100644 doxygen/html/search/all_8.js create mode 100644 doxygen/html/search/all_9.html create mode 100644 doxygen/html/search/all_9.js create mode 100644 doxygen/html/search/all_a.html create mode 100644 doxygen/html/search/all_a.js create mode 100644 doxygen/html/search/all_b.html create mode 100644 doxygen/html/search/all_b.js create mode 100644 doxygen/html/search/all_c.html create mode 100644 doxygen/html/search/all_c.js create mode 100644 doxygen/html/search/all_d.html create mode 100644 doxygen/html/search/all_d.js create mode 100644 doxygen/html/search/all_e.html create mode 100644 doxygen/html/search/all_e.js create mode 100644 doxygen/html/search/all_f.html create mode 100644 doxygen/html/search/all_f.js create mode 100644 doxygen/html/search/classes_0.html create mode 100644 doxygen/html/search/classes_0.js create mode 100644 doxygen/html/search/classes_1.html create mode 100644 doxygen/html/search/classes_1.js create mode 100644 doxygen/html/search/classes_2.html create mode 100644 doxygen/html/search/classes_2.js create mode 100644 doxygen/html/search/classes_3.html create mode 100644 doxygen/html/search/classes_3.js create mode 100644 doxygen/html/search/classes_4.html create mode 100644 doxygen/html/search/classes_4.js create mode 100644 doxygen/html/search/classes_5.html create mode 100644 doxygen/html/search/classes_5.js create mode 100644 doxygen/html/search/classes_6.html create mode 100644 doxygen/html/search/classes_6.js create mode 100644 doxygen/html/search/classes_7.html create mode 100644 doxygen/html/search/classes_7.js create mode 100644 doxygen/html/search/close.svg create mode 100644 doxygen/html/search/defines_0.html create mode 100644 doxygen/html/search/defines_0.js create mode 100644 doxygen/html/search/defines_1.html create mode 100644 doxygen/html/search/defines_1.js create mode 100644 doxygen/html/search/enums_0.html create mode 100644 doxygen/html/search/enums_0.js create mode 100644 doxygen/html/search/enums_1.html create mode 100644 doxygen/html/search/enums_1.js create mode 100644 doxygen/html/search/enums_2.html create mode 100644 doxygen/html/search/enums_2.js create mode 100644 doxygen/html/search/enums_3.html create mode 100644 doxygen/html/search/enums_3.js create mode 100644 doxygen/html/search/enums_4.html create mode 100644 doxygen/html/search/enums_4.js create mode 100644 doxygen/html/search/enumvalues_0.html create mode 100644 doxygen/html/search/enumvalues_0.js create mode 100644 doxygen/html/search/enumvalues_1.html create mode 100644 doxygen/html/search/enumvalues_1.js create mode 100644 doxygen/html/search/enumvalues_10.html create mode 100644 doxygen/html/search/enumvalues_10.js create mode 100644 doxygen/html/search/enumvalues_11.html create mode 100644 doxygen/html/search/enumvalues_11.js create mode 100644 doxygen/html/search/enumvalues_2.html create mode 100644 doxygen/html/search/enumvalues_2.js create mode 100644 doxygen/html/search/enumvalues_3.html create mode 100644 doxygen/html/search/enumvalues_3.js create mode 100644 doxygen/html/search/enumvalues_4.html create mode 100644 doxygen/html/search/enumvalues_4.js create mode 100644 doxygen/html/search/enumvalues_5.html create mode 100644 doxygen/html/search/enumvalues_5.js create mode 100644 doxygen/html/search/enumvalues_6.html create mode 100644 doxygen/html/search/enumvalues_6.js create mode 100644 doxygen/html/search/enumvalues_7.html create mode 100644 doxygen/html/search/enumvalues_7.js create mode 100644 doxygen/html/search/enumvalues_8.html create mode 100644 doxygen/html/search/enumvalues_8.js create mode 100644 doxygen/html/search/enumvalues_9.html create mode 100644 doxygen/html/search/enumvalues_9.js create mode 100644 doxygen/html/search/enumvalues_a.html create mode 100644 doxygen/html/search/enumvalues_a.js create mode 100644 doxygen/html/search/enumvalues_b.html create mode 100644 doxygen/html/search/enumvalues_b.js create mode 100644 doxygen/html/search/enumvalues_c.html create mode 100644 doxygen/html/search/enumvalues_c.js create mode 100644 doxygen/html/search/enumvalues_d.html create mode 100644 doxygen/html/search/enumvalues_d.js create mode 100644 doxygen/html/search/enumvalues_e.html create mode 100644 doxygen/html/search/enumvalues_e.js create mode 100644 doxygen/html/search/enumvalues_f.html create mode 100644 doxygen/html/search/enumvalues_f.js create mode 100644 doxygen/html/search/files_0.html create mode 100644 doxygen/html/search/files_0.js create mode 100644 doxygen/html/search/files_1.html create mode 100644 doxygen/html/search/files_1.js create mode 100644 doxygen/html/search/files_2.html create mode 100644 doxygen/html/search/files_2.js create mode 100644 doxygen/html/search/files_3.html create mode 100644 doxygen/html/search/files_3.js create mode 100644 doxygen/html/search/files_4.html create mode 100644 doxygen/html/search/files_4.js create mode 100644 doxygen/html/search/files_5.html create mode 100644 doxygen/html/search/files_5.js create mode 100644 doxygen/html/search/files_6.html create mode 100644 doxygen/html/search/files_6.js create mode 100644 doxygen/html/search/files_7.html create mode 100644 doxygen/html/search/files_7.js create mode 100644 doxygen/html/search/files_8.html create mode 100644 doxygen/html/search/files_8.js create mode 100644 doxygen/html/search/files_9.html create mode 100644 doxygen/html/search/files_9.js create mode 100644 doxygen/html/search/files_a.html create mode 100644 doxygen/html/search/files_a.js create mode 100644 doxygen/html/search/files_b.html create mode 100644 doxygen/html/search/files_b.js create mode 100644 doxygen/html/search/files_c.html create mode 100644 doxygen/html/search/files_c.js create mode 100644 doxygen/html/search/functions_0.html create mode 100644 doxygen/html/search/functions_0.js create mode 100644 doxygen/html/search/functions_1.html create mode 100644 doxygen/html/search/functions_1.js create mode 100644 doxygen/html/search/functions_2.html create mode 100644 doxygen/html/search/functions_2.js create mode 100644 doxygen/html/search/functions_3.html create mode 100644 doxygen/html/search/functions_3.js create mode 100644 doxygen/html/search/functions_4.html create mode 100644 doxygen/html/search/functions_4.js create mode 100644 doxygen/html/search/functions_5.html create mode 100644 doxygen/html/search/functions_5.js create mode 100644 doxygen/html/search/functions_6.html create mode 100644 doxygen/html/search/functions_6.js create mode 100644 doxygen/html/search/functions_7.html create mode 100644 doxygen/html/search/functions_7.js create mode 100644 doxygen/html/search/functions_8.html create mode 100644 doxygen/html/search/functions_8.js create mode 100644 doxygen/html/search/functions_9.html create mode 100644 doxygen/html/search/functions_9.js create mode 100644 doxygen/html/search/functions_a.html create mode 100644 doxygen/html/search/functions_a.js create mode 100644 doxygen/html/search/functions_b.html create mode 100644 doxygen/html/search/functions_b.js create mode 100644 doxygen/html/search/functions_c.html create mode 100644 doxygen/html/search/functions_c.js create mode 100644 doxygen/html/search/mag_sel.svg create mode 100644 doxygen/html/search/namespaces_0.html create mode 100644 doxygen/html/search/namespaces_0.js create mode 100644 doxygen/html/search/nomatches.html create mode 100644 doxygen/html/search/pages_0.html create mode 100644 doxygen/html/search/pages_0.js create mode 100644 doxygen/html/search/search.css create mode 100644 doxygen/html/search/search.js create mode 100644 doxygen/html/search/search_l.png create mode 100644 doxygen/html/search/search_m.png create mode 100644 doxygen/html/search/search_r.png create mode 100644 doxygen/html/search/searchdata.js create mode 100644 doxygen/html/search/typedefs_0.html create mode 100644 doxygen/html/search/typedefs_0.js create mode 100644 doxygen/html/search/typedefs_1.html create mode 100644 doxygen/html/search/typedefs_1.js create mode 100644 doxygen/html/search/typedefs_2.html create mode 100644 doxygen/html/search/typedefs_2.js create mode 100644 doxygen/html/search/typedefs_3.html create mode 100644 doxygen/html/search/typedefs_3.js create mode 100644 doxygen/html/search/typedefs_4.html create mode 100644 doxygen/html/search/typedefs_4.js create mode 100644 doxygen/html/search/variables_0.html create mode 100644 doxygen/html/search/variables_0.js create mode 100644 doxygen/html/search/variables_1.html create mode 100644 doxygen/html/search/variables_1.js create mode 100644 doxygen/html/search/variables_10.html create mode 100644 doxygen/html/search/variables_10.js create mode 100644 doxygen/html/search/variables_11.html create mode 100644 doxygen/html/search/variables_11.js create mode 100644 doxygen/html/search/variables_12.html create mode 100644 doxygen/html/search/variables_12.js create mode 100644 doxygen/html/search/variables_13.html create mode 100644 doxygen/html/search/variables_13.js create mode 100644 doxygen/html/search/variables_14.html create mode 100644 doxygen/html/search/variables_14.js create mode 100644 doxygen/html/search/variables_2.html create mode 100644 doxygen/html/search/variables_2.js create mode 100644 doxygen/html/search/variables_3.html create mode 100644 doxygen/html/search/variables_3.js create mode 100644 doxygen/html/search/variables_4.html create mode 100644 doxygen/html/search/variables_4.js create mode 100644 doxygen/html/search/variables_5.html create mode 100644 doxygen/html/search/variables_5.js create mode 100644 doxygen/html/search/variables_6.html create mode 100644 doxygen/html/search/variables_6.js create mode 100644 doxygen/html/search/variables_7.html create mode 100644 doxygen/html/search/variables_7.js create mode 100644 doxygen/html/search/variables_8.html create mode 100644 doxygen/html/search/variables_8.js create mode 100644 doxygen/html/search/variables_9.html create mode 100644 doxygen/html/search/variables_9.js create mode 100644 doxygen/html/search/variables_a.html create mode 100644 doxygen/html/search/variables_a.js create mode 100644 doxygen/html/search/variables_b.html create mode 100644 doxygen/html/search/variables_b.js create mode 100644 doxygen/html/search/variables_c.html create mode 100644 doxygen/html/search/variables_c.js create mode 100644 doxygen/html/search/variables_d.html create mode 100644 doxygen/html/search/variables_d.js create mode 100644 doxygen/html/search/variables_e.html create mode 100644 doxygen/html/search/variables_e.js create mode 100644 doxygen/html/search/variables_f.html create mode 100644 doxygen/html/search/variables_f.js create mode 100644 doxygen/html/shl_8cpp.html create mode 100644 doxygen/html/splitbar.png create mode 100644 doxygen/html/structvm_1_1handler_1_1handler__t-members.html create mode 100644 doxygen/html/structvm_1_1handler_1_1handler__t.html create mode 100644 doxygen/html/structvm_1_1handler_1_1profile__t-members.html create mode 100644 doxygen/html/structvm_1_1handler_1_1profile__t.html create mode 100644 doxygen/html/structvm_1_1instrs_1_1code__block__t-members.html create mode 100644 doxygen/html/structvm_1_1instrs_1_1code__block__t.html create mode 100644 doxygen/html/structvm_1_1instrs_1_1jcc__data-members.html create mode 100644 doxygen/html/structvm_1_1instrs_1_1jcc__data.html create mode 100644 doxygen/html/structvm_1_1instrs_1_1virt__instr__t-members.html create mode 100644 doxygen/html/structvm_1_1instrs_1_1virt__instr__t.html create mode 100644 doxygen/html/structvmp2_1_1v1_1_1entry__t-members.html create mode 100644 doxygen/html/structvmp2_1_1v1_1_1entry__t.html create mode 100644 doxygen/html/structvmp2_1_1v1_1_1file__header-members.html create mode 100644 doxygen/html/structvmp2_1_1v1_1_1file__header.html create mode 100644 doxygen/html/structvmp2_1_1v2_1_1entry__t-members.html create mode 100644 doxygen/html/structvmp2_1_1v2_1_1entry__t.html create mode 100644 doxygen/html/structvmp2_1_1v2_1_1file__header-members.html create mode 100644 doxygen/html/structvmp2_1_1v2_1_1file__header.html create mode 100644 doxygen/html/structvmp2_1_1v3_1_1code__block__t-members.html create mode 100644 doxygen/html/structvmp2_1_1v3_1_1code__block__t.html create mode 100644 doxygen/html/structvmp2_1_1v3_1_1file__header-members.html create mode 100644 doxygen/html/structvmp2_1_1v3_1_1file__header.html create mode 100644 doxygen/html/structzydis__instr__t-members.html create mode 100644 doxygen/html/structzydis__instr__t.html create mode 100644 doxygen/html/sync_off.png create mode 100644 doxygen/html/sync_on.png create mode 100644 doxygen/html/tab_a.png create mode 100644 doxygen/html/tab_b.png create mode 100644 doxygen/html/tab_h.png create mode 100644 doxygen/html/tab_s.png create mode 100644 doxygen/html/tabs.css create mode 100644 doxygen/html/transform_8hpp.html create mode 100644 doxygen/html/transform_8hpp_source.html create mode 100644 doxygen/html/vmctx_8cpp.html create mode 100644 doxygen/html/vmctx_8hpp.html create mode 100644 doxygen/html/vmctx_8hpp_source.html create mode 100644 doxygen/html/vmhandler_8cpp.html create mode 100644 doxygen/html/vmhandlers_8hpp.html create mode 100644 doxygen/html/vmhandlers_8hpp_source.html create mode 100644 doxygen/html/vminstrs_8cpp.html create mode 100644 doxygen/html/vminstrs_8hpp.html create mode 100644 doxygen/html/vminstrs_8hpp_source.html create mode 100644 doxygen/html/vmlifters_2add_8cpp.html create mode 100644 doxygen/html/vmlifters_2jmp_8cpp.html create mode 100644 doxygen/html/vmlifters_2lconst_8cpp.html create mode 100644 doxygen/html/vmlifters_2lflags_8cpp.html create mode 100644 doxygen/html/vmlifters_2lreg_8cpp.html create mode 100644 doxygen/html/vmlifters_2lvsp_8cpp.html create mode 100644 doxygen/html/vmlifters_2nand_8cpp.html create mode 100644 doxygen/html/vmlifters_2pushvsp_8cpp.html create mode 100644 doxygen/html/vmlifters_2read_8cpp.html create mode 100644 doxygen/html/vmlifters_2shr_8cpp.html create mode 100644 doxygen/html/vmlifters_2sreg_8cpp.html create mode 100644 doxygen/html/vmlifters_2vmexit_8cpp.html create mode 100644 doxygen/html/vmlifters_8hpp.html create mode 100644 doxygen/html/vmlifters_8hpp_source.html create mode 100644 doxygen/html/vmp2_8hpp.html create mode 100644 doxygen/html/vmp2_8hpp_source.html create mode 100644 doxygen/html/vmprofiler_8hpp.html create mode 100644 doxygen/html/vmprofiler_8hpp_source.html create mode 100644 doxygen/html/vmprofiles_2add_8cpp.html create mode 100644 doxygen/html/vmprofiles_2jmp_8cpp.html create mode 100644 doxygen/html/vmprofiles_2lconst_8cpp.html create mode 100644 doxygen/html/vmprofiles_2lflags_8cpp.html create mode 100644 doxygen/html/vmprofiles_2lreg_8cpp.html create mode 100644 doxygen/html/vmprofiles_2lvsp_8cpp.html create mode 100644 doxygen/html/vmprofiles_2nand_8cpp.html create mode 100644 doxygen/html/vmprofiles_2pushvsp_8cpp.html create mode 100644 doxygen/html/vmprofiles_2read_8cpp.html create mode 100644 doxygen/html/vmprofiles_2shr_8cpp.html create mode 100644 doxygen/html/vmprofiles_2sreg_8cpp.html create mode 100644 doxygen/html/vmprofiles_2vmexit_8cpp.html create mode 100644 doxygen/html/vmprofiles_8hpp.html create mode 100644 doxygen/html/vmprofiles_8hpp_source.html create mode 100644 doxygen/html/vmutils_8cpp.html create mode 100644 doxygen/html/vmutils_8hpp.html create mode 100644 doxygen/html/vmutils_8hpp_source.html create mode 100644 doxygen/html/write_8cpp.html create mode 100644 icon.png diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile new file mode 100644 index 0000000..a7c71d8 --- /dev/null +++ b/doxygen/Doxyfile @@ -0,0 +1,2660 @@ +# Doxyfile 1.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = VMProfiler + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = v1.8 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "vmprofiler is a c++ library which is used to statically analyze VMProtect 2 polymorphic virtual machines. This project is inherited in vmprofiler-qt, vmprofiler-cli, and vmemu." + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = D:/vmprofiler-qt/dependencies/vmprofiler/icon.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = D:\vmprofiler-qt\dependencies\vmprofiler\doxygen + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which efficively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = D:\vmprofiler-qt\dependencies\vmprofiler\ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = README.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to +# YES then doxygen will add the directory of each input to the include path. +# The default value is: YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdn.jsdelivr.net/npm/mathjax@2 + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /