diff --git a/deps/vmprofiler b/deps/vmprofiler index 80b5c20..1516e2a 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 80b5c20795aa18bd5a46b813b4c8207e3a7c79ce +Subproject commit 1516e2a2783308b778109659cce62ea2d78e4c82 diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index 5a72e40..dce1e89 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 = false; + const bool m_log_instructions = true; private: uc_engine* uc; diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index ebfc8ab..7bc6c99 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -269,11 +269,13 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, return false; } - if (instr.mnemonic == ZYDIS_MNEMONIC_INVALID) return false; + if (instr.mnemonic == ZYDIS_MNEMONIC_INVALID) {std::printf("> bad instruction\n"); return false;} uc_context* ctx; uct_context_alloc(uc, &ctx); uc_context_save(uc, ctx); + if (obj->cc_trace.m_instrs.empty()) + obj->cc_trace.m_begin = address; obj->cc_trace.m_instrs.push_back({instr, ctx}); // RET or JMP REG means the end of a vm handler... @@ -283,7 +285,15 @@ 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( @@ -308,7 +318,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) { @@ -318,13 +328,16 @@ 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) + uc_emu_stop(uc); // -- stop after 10 legit SREG's... if (++obj->m_sreg_cnt == 10) uc_emu_stop(uc); } @@ -608,14 +621,7 @@ std::optional> emu_t::could_have_jcc( loc > m_vm->m_image_base + m_vm->m_image_size || loc < m_vm->m_image_base) return false; - - // check to see if the imm's points to something inside of an executable - // section... - if (!vm::utils::scn::executable( - m_vm->m_module_base, - (loc - m_vm->m_image_base) + m_vm->m_module_base)) - return false; - return true; + return true; }; auto lconst1 = vinstrs.rbegin(); @@ -632,6 +638,8 @@ std::optional> emu_t::could_have_jcc( if (lconst2 == vinstrs.rend()) return {}; } while (!valid_mem(lconst1->imm.val)); + std::printf("possible jcc: %p, %p\n", lconst1->imm.val, lconst2->imm.val); + return {{lconst1->imm.val, lconst2->imm.val}}; } } // namespace vm \ No newline at end of file