diff --git a/deps/vmprofiler b/deps/vmprofiler index 343c7b9..fa64967 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 343c7b95a4a18f119167a4f371a29cfa1624d404 +Subproject commit fa64967bd77983b8fd3affc1de196a0d525adb52 diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index dce1e89..5a72e40 100644 --- a/include/vmemu_t.hpp +++ b/include/vmemu_t.hpp @@ -26,7 +26,7 @@ class emu_t { ~emu_t(); bool init(); bool emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn); - const bool m_log_instructions = true; + const bool m_log_instructions = false; private: uc_engine* uc; diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 7bc6c99..982f871 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -285,15 +285,7 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, // deobfuscate the instruction stream before profiling... // makes it easier for profiles to be correct... vm::instrs::deobfuscate(obj->cc_trace); - std::printf("> vsp = %s, vip = %s, address = %p (%p)\n", ZydisRegisterGetString(obj->cc_trace.m_vsp), ZydisRegisterGetString(obj->cc_trace.m_vip), - obj->cc_trace.m_begin, obj->cc_trace.m_begin - obj->m_vm->m_module_base + obj->m_vm->m_image_base); - zydis_rtn_t inst_stream; - std::for_each(obj->cc_trace.m_instrs.begin(), - obj->cc_trace.m_instrs.end(), - [&](vm::instrs::emu_instr_t& instr) { - inst_stream.push_back({instr.m_instr}); - }); - vm::utils::print(inst_stream); + /* // find the last MOV REG, DWORD PTR [VIP] in the instruction stream, then // remove any instructions from this instruction to the JMP/RET... const auto rva_fetch = std::find_if( @@ -318,7 +310,7 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, } */ const auto vinstr = vm::instrs::determine(obj->cc_trace); - std::printf("instruction is: %d\n", vinstr.mnemonic); + // -- free the trace since we will start a new one... std::for_each(obj->cc_trace.m_instrs.begin(), obj->cc_trace.m_instrs.end(), [&](const vm::instrs::emu_instr_t& instr) { @@ -328,12 +320,12 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, obj->cc_trace.m_instrs.clear(); if (vinstr.mnemonic != vm::instrs::mnemonic_t::jmp) { -/* if (vinstr.mnemonic != vm::instrs::mnemonic_t::sreg) uc_emu_stop(uc); + if (vinstr.mnemonic != vm::instrs::mnemonic_t::sreg) uc_emu_stop(uc); if (!vinstr.imm.has_imm) uc_emu_stop(uc); if (vinstr.imm.size != 8 || vinstr.imm.val > 8 * VIRTUAL_REGISTER_COUNT) - uc_emu_stop(uc); */ + uc_emu_stop(uc); // stop if done or if instruction is invalid if (vinstr.mnemonic == instrs::mnemonic_t::unknown) @@ -496,7 +488,36 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, std::memcpy(obj->cc_blk->m_jmp.stack, obj->cc_trace.m_stack, STACK_SIZE); } - + if (vinstr.mnemonic == vm::instrs::mnemonic_t::vmexit) + { + int i = 0; + for (const auto& instr_it : obj->cc_trace.m_instrs) + { + if ((instr_it.m_instr.mnemonic == ZYDIS_MNEMONIC_POP || + instr_it.m_instr.mnemonic == ZYDIS_MNEMONIC_POPFQ) && + instr_it.m_instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER) + { + if (i >= 16) + { + std::printf("[!] failed to parse vmexit pops\n"); + return false; + } + auto pushed_reg = instr_it.m_instr.operands[instr_it.m_instr.mnemonic == ZYDIS_MNEMONIC_POPFQ ? 2 : 0].reg.value; + if (std::find(obj->cc_blk->vmexit_pop_order.begin(), obj->cc_blk->vmexit_pop_order.begin() + i, pushed_reg) + != obj->cc_blk->vmexit_pop_order.begin() + i) + { + std::printf("[!] failed to parse vmexit pops\n"); + return false; + } + obj->cc_blk->vmexit_pop_order[i++] = pushed_reg; + } + } + if (i != 16) + { + std::printf("[!] failed to parse vmexit pops\n"); + return false; + } + } if (vinstr.mnemonic == vm::instrs::mnemonic_t::jmp || vinstr.mnemonic == vm::instrs::mnemonic_t::vmexit) uc_emu_stop(obj->uc);