From 05c8f779d0848d4853a62f9fe169a2708628f29e Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Sun, 23 May 2021 18:26:15 -0700 Subject: [PATCH] testing new vmprofiler lambda zydis instr... --- include/transform.hpp | 4 +- include/vm.h | 8 +- include/vmprofiler.hpp | 370 +++++------------------------------------ include/vmutils.h | 13 +- src/vm.cpp | 26 +-- src/vmutils.cpp | 16 +- 6 files changed, 69 insertions(+), 368 deletions(-) diff --git a/include/transform.hpp b/include/transform.hpp index b6d568f..a6aaf29 100644 --- a/include/transform.hpp +++ b/include/transform.hpp @@ -56,7 +56,7 @@ namespace vm update_key }; - using map_t = std::map; + using map_t = std::map; template inline const auto _bswap = [](T a, T b) -> T @@ -193,7 +193,7 @@ namespace vm } } - inline bool has_imm(ZydisDecodedInstruction* instr) + inline bool has_imm(zydis_decoded_instr_t* instr) { return instr->operand_count > 1 && (instr->operands[1].type & ZYDIS_OPERAND_TYPE_IMMEDIATE); diff --git a/include/vm.h b/include/vm.h index ad8a28b..3145f5b 100644 --- a/include/vm.h +++ b/include/vm.h @@ -14,7 +14,7 @@ namespace vm void inverse_transforms(transform::map_t& transforms, transform::map_t& inverse); bool get_calc_jmp(const zydis_routine_t& vm_entry, zydis_routine_t& calc_jmp); bool get_vinstr_rva_transform( - const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr); + const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr); struct handler_t { @@ -42,10 +42,10 @@ namespace vm namespace table { std::uintptr_t* get(const zydis_routine_t& vm_entry); - bool get_transform(const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr); + bool get_transform(const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr); - std::uint64_t encrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val); - std::uint64_t decrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val); + 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); } } } \ No newline at end of file diff --git a/include/vmprofiler.hpp b/include/vmprofiler.hpp index c8fba9b..8acf8cd 100644 --- a/include/vmprofiler.hpp +++ b/include/vmprofiler.hpp @@ -5,6 +5,8 @@ namespace vm { namespace handler { + using instr_callback_t = bool(*)(const zydis_decoded_instr_t& instr); + enum extention_t { none, @@ -16,351 +18,57 @@ namespace vm { const char* name; u8 imm_size; - std::vector> signature; + std::vector signature; extention_t extention; }; namespace profile { - // store a value from the stack into scratch register X (RDI+X)... - // where X is an 8bit immediate value... + // MOV RDX, [RBP] + // ADD RBP, 8 + // MOV [RAX+RDI], RDX inline vm::handler::profile_t sregq = { "SREGQ", 8, { - { 0x48, 0x8B, 0x55, 0x0 }, // mov rdx, [rbp+0] - { 0x48, 0x83, 0xC5, 0x8 }, // add rbp, 8 - { 0x48, 0x89, 0x14, 0x38 }, // mov [rax+rdi], rdx - } - }; - - inline vm::handler::profile_t sregdw = - { - "SREGDW", 8, - { - { 0x8B, 0x55, 0x00 }, - { 0x48, 0x83, 0xC5, 0x04 }, - { 0x89, 0x14, 0x38 } - } - }; - - inline vm::handler::profile_t sregw = - { - "SREGW", 8, - { - { 0x66, 0x8B, 0x55, 0x00 }, // mov dx, [rbp] - { 0x48, 0x83, 0xC5, 0x02 }, // add rbp, 0x02 - { 0x66, 0x89, 0x14, 0x38 } // mov [rax+rdi], dx - } - }; - - // load scratch register value onto virtual stack... - inline vm::handler::profile_t lregq = - { - "LREGQ", 8, - { - {0x48, 0x8B, 0x14, 0x38}, // mov rdx, [rax+rdi] - {0x48, 0x83, 0xED, 0x08}, // sub rbp, 8 - {0x48, 0x89, 0x55, 0x0} // mov [rbp+0], rdx - } - }; - - /* - > 0x00007FF64724445C mov edx, [rax+rdi*1] - > 0x00007FF647244463 sub rbp, 0x04 - > 0x00007FF647246333 mov [rbp], edx - */ - inline vm::handler::profile_t lregdw = - { - "LREGDW", 8, - { - { 0x8B, 0x14, 0x38 }, - { 0x48, 0x83, 0xED, 0x04 }, - { 0x89, 0x55, 0x00 } - } - }; - - // load constant value into stack.... - inline vm::handler::profile_t lconstq = - { - "LCONSTQ", 64, - { - {0x48, 0x83, 0xED, 0x08}, // sub rbp, 8 - {0x48, 0x89, 0x45, 0x00} // mov [rbp+0], rax - } - }; - - // load 1 byte constant zero extended into 2bytes on the stack... - inline vm::handler::profile_t lconstbzx = - { - "LCONSTBZX", 8, - { - {0x48, 0x83, 0xED, 0x02}, // sub rbp, 2 - {0x66, 0x89, 0x45, 0x00} // mov [rbp+0], ax - } - }; - - inline vm::handler::profile_t lconstbsx = - { - "LCONSTBSX", 8, - { - { 0x98 }, - { 0x48, 0x83, 0xED, 0x04 }, - { 0x89, 0x45, 0x00 } - }, - vm::handler::extention_t::sign_extend - }; - - // load 4 byte constant value sign extended qword into vsp... - inline vm::handler::profile_t lconstbsx1 = - { - "LCONSTBSX", 8, - { - {0x48, 0x98}, // cdqe - {0x48, 0x83, 0xED, 0x8}, // sub rbp, 8 - {0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax - }, - vm::handler::extention_t::sign_extend - }; - - // load 4 byte constant value sign extended qword into vsp... - inline vm::handler::profile_t lconstdsx = - { - "LCONSTDSX", 32, - { - {0x48, 0x98}, // cdqe - {0x48, 0x83, 0xED, 0x8}, // sub rbp, 8 - {0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax - }, - vm::handler::extention_t::sign_extend - }; - - // load 2 byte constant value sign extended qword into vsp... - inline vm::handler::profile_t lconstwsx = - { - "LCONSTWSX", 16, - { - {0x48, 0x98}, // cdqe - {0x48, 0x83, 0xED, 0x8}, // sub rbp, 8 - {0x48, 0x89, 0x45, 0x0}, // mov [rbp+0], rax - }, - vm::handler::extention_t::sign_extend - }; - - inline vm::handler::profile_t lconstw = - { - "LCONSTW", 8, - { - { 0x48, 0x83, 0xED, 0x02 }, // sub rbp, 0x02 - { 0x66, 0x89, 0x45, 0x00 } // mov [rbp], ax - } - }; - - inline vm::handler::profile_t lconstdw = - { - "LCONSTDW", 32, - { - { 0x48, 0x83, 0xED, 0x04 }, - { 0x89, 0x45, 0x00 } - } - }; - - inline vm::handler::profile_t pushvsp = - { - "PUSHVSP", 0, - { - {0x48, 0x89, 0xE8}, // mov rax, rbp - {0x48, 0x83, 0xED, 0x08}, // sub rbp, 8 - {0x48, 0x89, 0x45, 0x0} // mov [rbp+0], rax - } - }; - - // add two stack values together... - inline vm::handler::profile_t addq = - { - "ADDQ", 0, - { - {0x48, 0x1, 0x45, 0x8}, // add [rbp+8], rax - {0x9C}, // pushfq - {0x8F, 0x45, 0x0} // pop qword ptr [rbp+0] - } - }; - - inline vm::handler::profile_t adddw = - { - "ADDDW", 0, - { - { 0x01, 0x45, 0x08 }, // add [rbp+0x08], eax - { 0x9C }, // pushfq - { 0x8F, 0x45, 0x00 } // pop [rbp] - } - }; - - // two qwords on the top of the stack together then not the result... - // ~(VSP[0] | VSP[1])... - inline vm::handler::profile_t nandq = - { - "NANDQ", 0, - { - {0x48, 0x8B, 0x45, 0x0}, // mov rax, [rbp+0] - {0x48, 0x8B, 0x55, 0x8}, // mov rdx, [rbp+8] - {0x48, 0xF7, 0xD0}, // not rax - {0x48, 0xF7, 0xD2}, // not rdx - {0x48, 0x21, 0xD0}, // and rax, rdx - {0x48, 0x89, 0x45, 0x8}, // mov [rbp+8], rax - {0x9C}, // pushfq - {0x8F, 0x45, 0x0} // pop qword ptr [rbp+0] - } - }; - - // leaves the virtual machine... - inline vm::handler::profile_t vmexit = - { - "VMEXIT", 0, - { - {0x48, 0x89, 0xec}, // mov rsp, rbp - {0x9d}, // popfq - {0xc3} // ret - } - }; - - inline vm::handler::profile_t jmp = - { - "JMP", 0, - { - { 0x8B, 0x75, 0x00 }, // mov esi, [rbp] - { 0x48, 0x01, 0xC6 }, // add rsi, rax - { 0x48, 0x89, 0xF3 }, // mov rbx, rsi - { 0x48, 0x03, 0x75, 0x00 } // add rsi, [rbp] - } - }; - - inline vm::handler::profile_t readw = - { - "READW", 0, - { - { 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp] - { 0x48, 0x83, 0xC5, 0x06 }, // add rbp, 0x06 - { 0x36, 0x66, 0x8B, 0x00 }, // mov ax, ss:[rax] - { 0x66, 0x89, 0x45, 0x00 } // mov [rbp], ax - } - }; - - inline vm::handler::profile_t writeq = - { - "WRITEQ", 0, - { - { 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp] - { 0x48, 0x8B, 0x55, 0x08 }, // mov rdx, [rbp+0x08] - { 0x48, 0x83, 0xC5, 0x10 }, // add rbp, 0x10 - { 0x36, 0x48, 0x89, 0x10 }, // mov ss:[rax], rdx - } - }; - - inline vm::handler::profile_t writeq1 = - { - "WRITEQ", 0, - { - { 0x48, 0x8B, 0x45, 0x00 }, // mov rax, [rbp] - { 0x48, 0x8B, 0x55, 0x08 }, // mov rdx, [rbp+0x08] - { 0x48, 0x83, 0xC5, 0x10 }, // add rbp, 0x10 - { 0x48, 0x89, 0x10 } // mov [rax], rdx - } - }; - - inline vm::handler::profile_t shrw = - { - "SHRW", 0, - { - { 0x66, 0x8B, 0x45, 0x00 }, - { 0x8A, 0x4D, 0x02 }, - { 0x48, 0x83, 0xED, 0x06 }, - { 0x66, 0xD3, 0xE8 }, - { 0x66, 0x89, 0x45, 0x08 }, - { 0x9C }, - { 0x8F, 0x45, 0x00 } - } - }; - - inline vm::handler::profile_t shrdw = - { - "SHRDW", 0, - { - { 0x8B, 0x45, 0x00 }, - { 0x8A, 0x4D, 0x04 }, - { 0x48, 0x83, 0xED, 0x06 }, - { 0xD3, 0xE8 }, - { 0x89, 0x45, 0x08 }, - { 0x9C }, - { 0x8F, 0x45, 0x00 } - } - }; - - inline vm::handler::profile_t shrq = - { - "SHRQ", 0, - { - { 0x48, 0x8B, 0x45, 0x00 }, - { 0x8A, 0x4D, 0x08 }, - { 0x48, 0x83, 0xED, 0x06 }, - { 0x48, 0xD3, 0xE8 }, - { 0x48, 0x89, 0x45, 0x08 }, - { 0x9C }, - { 0x8F, 0x45, 0x00 }, - } - }; - - inline vm::handler::profile_t nanddw = - { - "NANDDW", 0, - { - { 0x48, 0xF7, 0x55, 0x00 }, // not qword ptr [rbp+0] - { 0x8B, 0x45, 0x00 }, // mov eax, [rbp+0] - { 0x48, 0x83, 0xED, 0x04 }, // sub rbp, 4 - { 0x21, 0x45, 0x08 }, // and [rbp+8], eax - { 0x9C }, // pushfq - { 0x8F, 0x45, 0x00 } // pop qword ptr [rbp+0] - } - }; - - inline vm::handler::profile_t lvsp = - { - "LVSP", 0, - { - { 0x48, 0x8B, 0x6D, 0x00 } // mov rbp, [rbp] + { + // 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 + [](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; + } + } } }; inline std::vector all = { - &sregq, - &lregq, - &lconstq, - &lconstdsx, - &lconstwsx, - &lconstbzx, - &addq, - &nandq, - &pushvsp, - &vmexit, - &jmp, - &adddw, - &writeq, - &sregw, - &lconstw, - &shrw, - &shrq, - &writeq1, - &readw, - &lregdw, - &shrdw, - &sregdw, - &lconstbsx, - &lconstbsx1, - &shrq, - &lvsp, - &lconstdw, - &nanddw + &sregq }; } } diff --git a/include/vmutils.h b/include/vmutils.h index b0fb25b..e900a8b 100644 --- a/include/vmutils.h +++ b/include/vmutils.h @@ -10,9 +10,12 @@ using u32 = unsigned int; using u64 = unsigned long long; using u128 = __m128; +using zydis_decoded_instr_t = ZydisDecodedInstruction; +using zydis_register_t = ZydisRegister; + struct zydis_instr_t { - ZydisDecodedInstruction instr; + zydis_decoded_instr_t instr; std::vector raw; std::uintptr_t addr; }; @@ -26,13 +29,13 @@ namespace vm namespace reg { // converts say... AL to RAX... - ZydisRegister to64(ZydisRegister reg); - bool compare(ZydisRegister a, ZydisRegister b); + zydis_register_t to64(zydis_register_t reg); + bool compare(zydis_register_t a, zydis_register_t b); } void print(zydis_routine_t& routine); - void print(const ZydisDecodedInstruction& instr); - bool is_jmp(const ZydisDecodedInstruction& instr); + 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); diff --git a/src/vm.cpp b/src/vm.cpp index 7a76cb4..0438aa4 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -194,7 +194,7 @@ namespace vm } bool get_vinstr_rva_transform( - const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr) + const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr) { // // find mov esi, [rsp+0xA0] @@ -314,7 +314,7 @@ namespace vm 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_handlers) { - ZydisDecodedInstruction instr; + zydis_decoded_instr_t instr; if (!vm::handler::table::get_transform(vm_entry, &instr)) return false; @@ -452,7 +452,7 @@ namespace vm } ); - ZydisDecodedInstruction nogeneric0; + zydis_decoded_instr_t nogeneric0; nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID; transforms[transform::type::generic0] = @@ -505,17 +505,7 @@ namespace vm vm_handler->instrs.end(), [&](zydis_instr_t& instr_data) -> bool - { - if (instr_data.raw.size() != instr.size()) - return false; - - return std::equal - ( - instr_data.raw.begin(), - instr_data.raw.end(), - instr.begin() - ); - } + { return instr(instr_data.instr); } ); if (contains == vm_handler->instrs.end()) @@ -562,9 +552,9 @@ namespace vm return reinterpret_cast(ptr); } - bool get_transform(const zydis_routine_t& vm_entry, ZydisDecodedInstruction* transform_instr) + bool get_transform(const zydis_routine_t& vm_entry, zydis_decoded_instr_t* transform_instr) { - ZydisRegister rcx_or_rdx = ZYDIS_REGISTER_NONE; + zydis_register_t rcx_or_rdx = ZYDIS_REGISTER_NONE; auto handler_fetch = std::find_if( vm_entry.begin(), vm_entry.end(), @@ -616,7 +606,7 @@ namespace vm return true; } - std::uint64_t encrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val) + 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..."); @@ -629,7 +619,7 @@ namespace vm return vm::transform::apply(bitsize, operation, val, imm); } - std::uint64_t decrypt(ZydisDecodedInstruction& transform_instr, std::uint64_t val) + 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..."); diff --git a/src/vmutils.cpp b/src/vmutils.cpp index 294c137..fba1588 100644 --- a/src/vmutils.cpp +++ b/src/vmutils.cpp @@ -7,7 +7,7 @@ namespace vm { namespace reg { - ZydisRegister to64(ZydisRegister reg) + zydis_register_t to64(zydis_register_t reg) { switch (reg) { @@ -119,13 +119,13 @@ namespace vm return reg; } - bool compare(ZydisRegister a, ZydisRegister b) + bool compare(zydis_register_t a, zydis_register_t b) { return to64(a) == to64(b); } } - void print(const ZydisDecodedInstruction& instr) + void print(const zydis_decoded_instr_t& instr) { char buffer[256]; ZydisFormatter formatter; @@ -152,7 +152,7 @@ namespace vm } } - bool is_jmp(const ZydisDecodedInstruction& instr) + bool is_jmp(const zydis_decoded_instr_t& instr) { switch (instr.mnemonic) { @@ -188,7 +188,7 @@ namespace vm bool flatten(zydis_routine_t& routine, std::uintptr_t routine_addr, bool keep_jmps) { ZydisDecoder decoder; - ZydisDecodedInstruction instr; + zydis_decoded_instr_t instr; ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64); while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, reinterpret_cast( @@ -229,7 +229,7 @@ namespace vm void deobfuscate(zydis_routine_t& routine) { static const auto _uses = - [](ZydisDecodedOperand& op, ZydisRegister reg) -> bool + [](ZydisDecodedOperand& op, zydis_register_t reg) -> bool { switch (op.type) { @@ -247,7 +247,7 @@ namespace vm }; static const auto _writes = - [](ZydisDecodedInstruction& inst) -> bool + [](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) @@ -258,7 +258,7 @@ namespace vm static const auto _remove = [](zydis_routine_t& routine, zydis_routine_t::iterator itr, - ZydisRegister reg, u32 opcode_size) -> void + zydis_register_t reg, u32 opcode_size) -> void { for (; itr >= routine.begin(); --itr) {