From 99f00be5d3729932af2264b4dc386633c0cd42f1 Mon Sep 17 00:00:00 2001 From: John Doe Date: Tue, 21 Dec 2021 19:04:16 -0800 Subject: [PATCH] printing debug info and still making vmprofiler, also updated vmprofiler dep... --- .gitignore | 1 + deps/vmprofiler | 2 +- src/vmemu_t.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index d8c5a70..0221aa4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.userosscache *.sln.docstates *.o +*.exe # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/deps/vmprofiler b/deps/vmprofiler index 79c3695..eb91191 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 79c369582866ed888741b283bd6dca6677bf3a9d +Subproject commit eb91191526dc63f9c972ad7d9c1f03be36dc2e51 diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 8fa68fb..7d550e8 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -141,21 +141,55 @@ bool emu_t::code_exec_callback(uc_engine* uc, if (instr.mnemonic == ZYDIS_MNEMONIC_INVALID) return false; + // save the current cpu's context (all register values and such)... + // create a new emu_instr_t with this information... this info will be used by + // profiles to grab decrypted values and such... uc_context* cpu_ctx; uc_context_alloc(obj->uc, &cpu_ctx); vm::instrs::emu_instr_t emu_instr{instr, cpu_ctx}; obj->cc_trace->m_instrs.push_back(emu_instr); + // RET or JMP REG means the end of a vm handler... if (instr.mnemonic == ZYDIS_MNEMONIC_RET || (instr.mnemonic == ZYDIS_MNEMONIC_JMP && instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER)) { + // deobfuscate the instruction stream before profiling... + // makes it easier for profiles to be correct... + vm::instrs::deobfuscate(*obj->cc_trace); + + // 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( + obj->cc_trace->m_instrs.rbegin(), obj->cc_trace->m_instrs.rend(), + [&vip = obj->vip](const vm::instrs::emu_instr_t& instr) -> bool { + const auto& i = instr.m_instr; + return i.mnemonic == ZYDIS_MNEMONIC_MOV && + i.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + i.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && + i.operands[1].mem.base == vip && i.operands[1].size == 32; + }); + + if (rva_fetch != obj->cc_trace->m_instrs.rend()) + obj->cc_trace->m_instrs.erase((rva_fetch + 1).base(), + obj->cc_trace->m_instrs.end()); + const auto vinstr = vm::instrs::determine(obj->vip, obj->vsp, *obj->cc_trace); - if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { + if (vinstr.mnemonic == vm::instrs::mnemonic_t::unknown) { + 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); + std::printf("========\n"); + std::getchar(); + } else { std::printf("> %s\n", vm::instrs::get_profile(vinstr.mnemonic)->name.c_str()); - std::getchar(); } if (vinstr.mnemonic == vm::instrs::mnemonic_t::jmp) {