diff --git a/CMakeLists.txt b/CMakeLists.txt index f7b5290..7e8f691 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,7 @@ list(APPEND vmprofiler_SOURCES "src/vmprofiles/shr.cpp" "src/vmprofiles/sreg.cpp" "src/vmprofiles/svsp.cpp" + "src/vmprofiles/vmexit.cpp" "src/vmprofiles/write.cpp" "src/vmutils.cpp" "include/vmctx.hpp" diff --git a/include/vminstrs.hpp b/include/vminstrs.hpp index ef3c0c9..0855859 100644 --- a/include/vminstrs.hpp +++ b/include/vminstrs.hpp @@ -150,13 +150,14 @@ extern profiler_t read; extern profiler_t write; extern profiler_t imul; extern profiler_t shr; +extern profiler_t vmexit; /// /// unsorted vector of profiles... they get sorted once at runtime... /// -inline std::vector profiles = {&shr, &imul, &nor, &write, &svsp, - &read, &nand, &lvsp, &add, &jmp, - &sreg, &lreg, &lconst}; +inline std::vector profiles = { + &vmexit, &shr, &imul, &nor, &write, &svsp, &read, + &nand, &lvsp, &add, &jmp, &sreg, &lreg, &lconst}; /// /// no i did not make this by hand, you cannot clown upon me! diff --git a/src/vmprofiles/vmexit.cpp b/src/vmprofiles/vmexit.cpp new file mode 100644 index 0000000..744f28b --- /dev/null +++ b/src/vmprofiles/vmexit.cpp @@ -0,0 +1,143 @@ +#include + +namespace vm::instrs { +profiler_t vmexit = { + "VMEXIT", + mnemonic_t::vmexit, + {{// MOV RSP, VSP + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + 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 == vsp; + }, + // POP R13 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R13; + }, + // POP RCX + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_RCX; + }, + // POP RBP + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_RBP; + }, + // POP R8 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R8; + }, + // POP R15 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R15; + }, + // POP RDX + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_RDX; + }, + // POP RDI + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_RDI; + }, + // POP R11 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R11; + }, + // POP RAX + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_RAX; + }, + // POP R9 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R9; + }, + // POP RSI + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_RSI; + }, + // POP R14 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R14; + }, + // POP R12 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R12; + }, + // POP R11 + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POP && + instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + instr.operands[0].reg.value == ZYDIS_REGISTER_R11; + }, + // POPFQ + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_POPFQ; + }, + // RET + [&](const zydis_reg_t vip, + const zydis_reg_t vsp, + const zydis_decoded_instr_t& instr) -> bool { + return instr.mnemonic == ZYDIS_MNEMONIC_RET; + }}}, + [&](zydis_reg_t& vip, zydis_reg_t& vsp, hndlr_trace_t& hndlr) + -> std::optional { return vinstr_t{mnemonic_t::vmexit}; }}; +} \ No newline at end of file