From c56fd3f6da98751944c1b22481e2cc8e1f03d515 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sat, 8 Oct 2022 00:14:09 -0600 Subject: [PATCH 01/29] I don't understand how to use git --- include/vmemu_t.hpp | 31 +++++++-- src/vmemu_t.cpp | 157 ++++++++++++++++++++++++++------------------ 2 files changed, 118 insertions(+), 70 deletions(-) diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index b833e3d..205c5d2 100644 --- a/include/vmemu_t.hpp +++ b/include/vmemu_t.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -14,12 +15,19 @@ #define STACK_BASE 0xFFFF000000000000 namespace vm { +namespace reg_names +{ + const std::array prefixes = {{"Red", "Blue", "Pink", "Green", "Orange", "Yellow", "Black", "White"}}; + const std::array suffixes = {{"Crewmate", "Engineer", "Imposter", "Shapeshifter"}}; +} class emu_t { public: + explicit emu_t(vm::vmctx_t* vm_ctx, bool log); explicit emu_t(vm::vmctx_t* vm_ctx); ~emu_t(); bool init(); bool emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn); + std::vector& get_il_bytecode(); private: uc_engine* uc; @@ -51,6 +59,11 @@ class emu_t { /// uc_hook code_exec_hook, invalid_mem_hook, int_hook, branch_pred_hook; + bool log_bytecode; + + // Logged bytecode for lifting + std::vector il_bytecode; + /// /// code execution callback for executable memory ranges of the vmprotect'ed /// module... essentially used to single step the processor over virtual @@ -61,7 +74,9 @@ class emu_t { /// /// /// - static bool code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, + static bool code_exec_callback(uc_engine* uc, + uint64_t address, + uint32_t size, emu_t* obj); /// @@ -74,8 +89,10 @@ class emu_t { /// /// /// - static bool branch_pred_spec_exec(uc_engine* uc, uint64_t address, - uint32_t size, emu_t* obj); + static bool branch_pred_spec_exec(uc_engine* uc, + uint64_t address, + uint32_t size, + emu_t* obj); /// /// invalid memory access handler. no runtime values can possibly effect the @@ -88,8 +105,12 @@ class emu_t { /// size of the memory access... /// value being read... /// emu_t object pointer... - static void invalid_mem(uc_engine* uc, uc_mem_type type, uint64_t address, - int size, int64_t value, emu_t* obj); + static void invalid_mem(uc_engine* uc, + uc_mem_type type, + uint64_t address, + int size, + int64_t value, + emu_t* obj); /// /// interrupt callback for unicorn engine. this is used to advance rip over diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 03b06a7..970c63e 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -1,8 +1,9 @@ #include #include - namespace vm { -emu_t::emu_t(vm::vmctx_t* vm_ctx) : m_vm(vm_ctx) {} +emu_t::emu_t(vm::vmctx_t* vm_ctx, bool log) : m_vm(vm_ctx), + log_bytecode(log) {} +emu_t::emu_t(vm::vmctx_t* vm_ctx) : m_vm(vm_ctx) {}; emu_t::~emu_t() { if (uc) uc_close(uc); @@ -86,14 +87,14 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { cc_trace.m_vip = cc_blk->m_vm.vip; cc_trace.m_vsp = cc_blk->m_vm.vsp; - std::printf("> beginning execution at = %p\n", rip); + std::printf("> beginning execution at = %p (%p)\n", rip, rip - m_vm->m_module_base + m_vm->m_image_base); if ((err = uc_emu_start(uc, rip, 0ull, 0ull, 0ull))) { std::printf("> error starting emu... reason = %d\n", err); return false; } extract_branch_data(); - std::printf("> emulated blk_%p\n\n", cc_blk->m_vip.img_base); + std::printf("> emulated blk_%p\n\n", cc_blk->m_vip.img_based); // keep track of the emulated blocks... by their addresses... std::vector blk_addrs; @@ -124,14 +125,14 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { // emulate the branch... uc_mem_write(uc, vsp, &br, sizeof br); - std::printf("> beginning execution at = %p\n", blk.m_jmp.rip); + std::printf("> beginning execution at = %p (%p)\n", rip, rip - m_vm->m_module_base + m_vm->m_image_base); if ((err = uc_emu_start(uc, blk.m_jmp.rip, 0ull, 0ull, 0ull))) { std::printf("> error starting emu... reason = %d\n", err); return false; } extract_branch_data(); - std::printf("> emulated blk_%p\n", cc_blk->m_vip.img_base); + std::printf("> emulated blk_%p\n", cc_blk->m_vip.img_based); } } } @@ -148,62 +149,62 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { } void emu_t::extract_branch_data() { - auto br_info = could_have_jcc(cc_blk->m_vinstrs); - if (br_info.has_value()) { - auto [br1, br2] = br_info.value(); - // convert to absolute addresses... - br1 -= m_vm->m_image_base; - br2 -= m_vm->m_image_base; - br1 += m_vm->m_module_base; - br2 += m_vm->m_module_base; - - auto br1_legit = legit_branch(*cc_blk, br1); - auto br2_legit = legit_branch(*cc_blk, br2); - std::printf("> br1 legit: %d, br2 legit: %d\n", br1_legit, br2_legit); - - if (br1_legit && br2_legit) { - std::printf("> virtual jcc uncovered... br1 = %p, br2 = %p\n", br1, br2); - cc_blk->branch_type = vm::instrs::vbranch_type::jcc; - cc_blk->branches.push_back(br1); - cc_blk->branches.push_back(br2); - } else if (br1_legit || br2_legit) { - std::printf("> absolute virtual jmp uncovered... branch = %p\n", - br1_legit ? br1 : br2); - cc_blk->branch_type = vm::instrs::vbranch_type::absolute; - cc_blk->branches.push_back(br1_legit ? br1 : br2); - } else { - std::printf("> unknown branch type...\n"); - } - } else if (cc_blk->m_vinstrs.back().mnemonic == - vm::instrs::mnemonic_t::vmexit) { - cc_blk->branch_type = vm::instrs::vbranch_type::none; - } else if (cc_blk->m_vinstrs.back().mnemonic == vm::instrs::mnemonic_t::jmp) { - // see if there is 1 lconst... - if (auto last_lconst = std::find_if( - cc_blk->m_vinstrs.rbegin(), cc_blk->m_vinstrs.rend(), - [&](vm::instrs::vinstr_t& vinstr) -> bool { - return vinstr.mnemonic == vm::instrs::mnemonic_t::lconst && - vinstr.imm.size == 64; - }); - last_lconst != cc_blk->m_vinstrs.rend()) { - const auto imm_img_based = last_lconst->imm.val; - const auto imm_mod_based = - (imm_img_based - m_vm->m_image_base) + m_vm->m_module_base; - - // check to see if the imm is inside of the module... and if the ptr lands - // inside of an executable section... then lastly check to see if its a - // legit branch or not... - if (imm_img_based >= m_vm->m_image_base && - imm_img_based < m_vm->m_image_base + m_vm->m_image_size && - vm::utils::scn::executable(m_vm->m_module_base, imm_mod_based)) { - cc_blk->branches.push_back(imm_mod_based); + auto br_info = could_have_jcc(cc_blk->m_vinstrs); + if (br_info.has_value()) { + auto [br1, br2] = br_info.value(); + // convert to absolute addresses... + br1 -= m_vm->m_image_base; + br2 -= m_vm->m_image_base; + br1 += m_vm->m_module_base; + br2 += m_vm->m_module_base; + + auto br1_legit = legit_branch(*cc_blk, br1); + auto br2_legit = legit_branch(*cc_blk, br2); + std::printf("> br1 legit: %d, br2 legit: %d\n", br1_legit, br2_legit); + + if (br1_legit && br2_legit) { + std::printf("> virtual jcc uncovered... br1 = %p, br2 = %p\n", br1, br2); + cc_blk->branch_type = vm::instrs::vbranch_type::jcc; + cc_blk->branches.push_back(br1); + cc_blk->branches.push_back(br2); + } else if (br1_legit || br2_legit) { + std::printf("> absolute virtual jmp uncovered... branch = %p\n", + br1_legit ? br1 : br2); cc_blk->branch_type = vm::instrs::vbranch_type::absolute; - } - } else { - std::printf("> jump table detected... review instruction stream...\n"); - uc_emu_stop(uc); + cc_blk->branches.push_back(br1_legit ? br1 : br2); + } else { + std::printf("> unknown branch type...\n"); + } + } else if (cc_blk->m_vinstrs.back().mnemonic == + vm::instrs::mnemonic_t::vmexit) { + cc_blk->branch_type = vm::instrs::vbranch_type::none; + } else if (cc_blk->m_vinstrs.back().mnemonic == vm::instrs::mnemonic_t::jmp) { + // see if there is 1 lconst... + if (auto last_lconst = std::find_if( + cc_blk->m_vinstrs.rbegin(), cc_blk->m_vinstrs.rend(), + [&](vm::instrs::vinstr_t& vinstr) -> bool { + return vinstr.mnemonic == vm::instrs::mnemonic_t::lconst && + vinstr.imm.size == 64; + }); + last_lconst != cc_blk->m_vinstrs.rend()) { + const auto imm_img_based = last_lconst->imm.val; + const auto imm_mod_based = + (imm_img_based - m_vm->m_image_base) + m_vm->m_module_base; + + // check to see if the imm is inside of the module... and if the ptr lands + // inside of an executable section... then lastly check to see if its a + // legit branch or not... + if (imm_img_based >= m_vm->m_image_base && + imm_img_based < m_vm->m_image_base + m_vm->m_image_size && + vm::utils::scn::executable(m_vm->m_module_base, imm_mod_based)) { + cc_blk->branches.push_back(imm_mod_based); + cc_blk->branch_type = vm::instrs::vbranch_type::absolute; + } + } else { + std::printf("> jump table detected... review instruction stream...\n"); + uc_emu_stop(uc); + } } - } } void emu_t::int_callback(uc_engine* uc, std::uint32_t intno, emu_t* obj) { @@ -373,7 +374,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, obj->cc_trace.m_instrs.end()); // set the virtual code block vip address information... - if (!obj->cc_blk->m_vip.rva || !obj->cc_blk->m_vip.img_base) { + if (!obj->cc_blk->m_vip.rva || !obj->cc_blk->m_vip.img_based) { // find the last write done to VIP... auto vip_write = std::find_if( obj->cc_trace.m_instrs.rbegin(), obj->cc_trace.m_instrs.rend(), @@ -393,17 +394,38 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uc_reg_read(uc, vm::instrs::reg_map[obj->cc_trace.m_vip], &vip_addr); obj->cc_blk->m_vip.rva = vip_addr -= obj->m_vm->m_module_base; - obj->cc_blk->m_vip.img_base = vip_addr += obj->m_vm->m_image_base; + obj->cc_blk->m_vip.img_based = vip_addr += obj->m_vm->m_image_base; uc_context_restore(uc, backup); uc_context_free(backup); } else { const auto vinstr = vm::instrs::determine(obj->cc_trace); if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { + if (obj->log_bytecode) + { + obj->il_bytecode.emplace_back(static_cast(vinstr.mnemonic)); + if (vinstr.imm.has_imm) + { + obj->il_bytecode.emplace_back(vinstr.imm.size); + for(int i = 0; i < (vinstr.imm.size / 8); ++i) + { + obj->il_bytecode.emplace_back(*(reinterpret_cast(&vinstr.imm.val) + i)); + } + } + else + obj->il_bytecode.emplace_back(0); + } + std::printf("%p: ", obj->cc_trace.m_begin + obj->m_vm->m_image_base - obj->m_vm->m_module_base); if (vinstr.imm.has_imm) - std::printf("> %s %p\n", - vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(), - vinstr.imm.val); + if (vinstr.mnemonic == instrs::mnemonic_t::lreg || vinstr.mnemonic == instrs::mnemonic_t::sreg) + std::printf("> %s %s_%s\n", + vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(), + vm::reg_names::prefixes[(vinstr.imm.val / 8) % 8].c_str(), + vm::reg_names::suffixes[(vinstr.imm.val / 8) / 8].c_str()); + else + std::printf("> %s %p\n", + vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(), + vinstr.imm.val); else std::printf("> %s\n", vm::instrs::get_profile(vinstr.mnemonic)->name.c_str()); @@ -592,4 +614,9 @@ std::optional> emu_t::could_have_jcc( return {{lconst1->imm.val, lconst2->imm.val}}; } + + std::vector& emu_t::get_il_bytecode() + { + return il_bytecode; + } } // namespace vm \ No newline at end of file -- 2.36.3 From da27678b61cc725743f30edb5106fbd9daf0ec20 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sat, 8 Oct 2022 01:44:15 -0600 Subject: [PATCH 02/29] fixed dependency --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 83f3f3f..e0fdbd9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "deps/vmprofiler"] path = deps/vmprofiler - url = https://githacks.org/vmp3/vmprofiler + url = https://github.com/xtremegamer1/vmprofiler -- 2.36.3 From 5e20af15f34c002e8024de5463757df05cb059be Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sat, 8 Oct 2022 02:52:11 -0600 Subject: [PATCH 03/29] Changed instruction enum to 1 byte for encoding --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index b01ba0e..0b4fcae 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit b01ba0ef77198161b14c666f99c5c0cd073bda0f +Subproject commit 0b4fcae0cadabbb1c5933f5b2f0e2b5b16009e40 -- 2.36.3 From 96188edc42aa6503be0557b0b93ca59838ba615d Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sat, 8 Oct 2022 03:31:55 -0600 Subject: [PATCH 04/29] Guarantee that there is an instruction after the last write to VIP. Also fix mistake when writing to img_based. --- src/vmemu_t.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 970c63e..5384677 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -370,7 +370,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, }); if (rva_fetch != obj->cc_trace.m_instrs.rend()) - obj->cc_trace.m_instrs.erase((rva_fetch + 1).base(), + obj->cc_trace.m_instrs.erase(rva_fetch.base(), obj->cc_trace.m_instrs.end()); // set the virtual code block vip address information... @@ -394,7 +394,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uc_reg_read(uc, vm::instrs::reg_map[obj->cc_trace.m_vip], &vip_addr); obj->cc_blk->m_vip.rva = vip_addr -= obj->m_vm->m_module_base; - obj->cc_blk->m_vip.img_based = vip_addr += obj->m_vm->m_image_base; + obj->cc_blk->m_vip.img_based = obj->cc_blk->m_vip.rva += obj->m_vm->m_image_base; uc_context_restore(uc, backup); uc_context_free(backup); -- 2.36.3 From 7a27d0779299767a800663a9d459bf8c80a23edb Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 9 Oct 2022 13:14:49 -0600 Subject: [PATCH 05/29] Added empty check to extract_branch_data --- src/vmemu_t.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 5384677..7694db4 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -149,6 +149,11 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { } void emu_t::extract_branch_data() { + if (cc_blk->m_vinstrs.empty()) + { + cc_blk->branch_type = vm::instrs::vbranch_type::none; + return; + } auto br_info = could_have_jcc(cc_blk->m_vinstrs); if (br_info.has_value()) { auto [br1, br2] = br_info.value(); @@ -370,8 +375,8 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, }); if (rva_fetch != obj->cc_trace.m_instrs.rend()) - obj->cc_trace.m_instrs.erase(rva_fetch.base(), - obj->cc_trace.m_instrs.end()); + obj->cc_trace.m_instrs.erase((rva_fetch + 1).base(), + --obj->cc_trace.m_instrs.end()); // set the virtual code block vip address information... if (!obj->cc_blk->m_vip.rva || !obj->cc_blk->m_vip.img_based) { @@ -394,13 +399,13 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uc_reg_read(uc, vm::instrs::reg_map[obj->cc_trace.m_vip], &vip_addr); obj->cc_blk->m_vip.rva = vip_addr -= obj->m_vm->m_module_base; - obj->cc_blk->m_vip.img_based = obj->cc_blk->m_vip.rva += obj->m_vm->m_image_base; + obj->cc_blk->m_vip.img_based = vip_addr += obj->m_vm->m_image_base; uc_context_restore(uc, backup); uc_context_free(backup); } else { const auto vinstr = vm::instrs::determine(obj->cc_trace); - if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { + if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { //TODO: Remove and add this after the code block is made if (obj->log_bytecode) { obj->il_bytecode.emplace_back(static_cast(vinstr.mnemonic)); -- 2.36.3 From a1cf60cf2dd7477e60aa7f1d4e9a59cdf1c0f816 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 9 Oct 2022 16:49:17 -0600 Subject: [PATCH 06/29] among us --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 0b4fcae..04661e6 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 0b4fcae0cadabbb1c5933f5b2f0e2b5b16009e40 +Subproject commit 04661e6e0878b63df9ebf2cc9a5a6bd788298f6d -- 2.36.3 From c94ef3f9e1df60a4dbbb77c5b48797664c55b43e Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 9 Oct 2022 19:12:45 -0600 Subject: [PATCH 07/29] pweeze work --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 04661e6..48eaabf 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 04661e6e0878b63df9ebf2cc9a5a6bd788298f6d +Subproject commit 48eaabf52622d24aad465fbde0f70f42f53f08dd -- 2.36.3 From 385e2ac444f9889ef4eb532aadfd99d3707acf76 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 9 Oct 2022 23:57:06 -0600 Subject: [PATCH 08/29] deps r working thank god --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 48eaabf..4b80be1 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 48eaabf52622d24aad465fbde0f70f42f53f08dd +Subproject commit 4b80be1bdfd4cdcc4efab319fafbdd145bf3e2b2 -- 2.36.3 From c3acbbc9cd93a4a1dc4cffd0f1314db5c43101dd Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Mon, 10 Oct 2022 00:58:28 -0600 Subject: [PATCH 09/29] why my deps keep fucking up --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 4b80be1..e14d4f6 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 4b80be1bdfd4cdcc4efab319fafbdd145bf3e2b2 +Subproject commit e14d4f67e822957b19bec62d1b2a211152c5f2a6 -- 2.36.3 From f72850f31b5b9e4cb2c453ed47edbb512d2616c9 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Wed, 12 Oct 2022 14:43:21 -0600 Subject: [PATCH 10/29] Added more vmprofilers --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index e14d4f6..4151506 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit e14d4f67e822957b19bec62d1b2a211152c5f2a6 +Subproject commit 415150657d928b4d58436dadfcc9a634c268e78c -- 2.36.3 From 943de5b10cda358fa0f072b599ba5ac4fab61cf5 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Wed, 12 Oct 2022 14:43:41 -0600 Subject: [PATCH 11/29] Deleted the retarded stuff I added --- include/vmemu_t.hpp | 6 ------ src/vmemu_t.cpp | 26 +++----------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index 205c5d2..b5d4b6b 100644 --- a/include/vmemu_t.hpp +++ b/include/vmemu_t.hpp @@ -22,7 +22,6 @@ namespace reg_names } class emu_t { public: - explicit emu_t(vm::vmctx_t* vm_ctx, bool log); explicit emu_t(vm::vmctx_t* vm_ctx); ~emu_t(); bool init(); @@ -59,11 +58,6 @@ class emu_t { /// uc_hook code_exec_hook, invalid_mem_hook, int_hook, branch_pred_hook; - bool log_bytecode; - - // Logged bytecode for lifting - std::vector il_bytecode; - /// /// code execution callback for executable memory ranges of the vmprotect'ed /// module... essentially used to single step the processor over virtual diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 7694db4..4588a5b 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -1,8 +1,6 @@ #include #include namespace vm { -emu_t::emu_t(vm::vmctx_t* vm_ctx, bool log) : m_vm(vm_ctx), - log_bytecode(log) {} emu_t::emu_t(vm::vmctx_t* vm_ctx) : m_vm(vm_ctx) {}; emu_t::~emu_t() { @@ -405,21 +403,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uc_context_free(backup); } else { const auto vinstr = vm::instrs::determine(obj->cc_trace); - if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { //TODO: Remove and add this after the code block is made - if (obj->log_bytecode) - { - obj->il_bytecode.emplace_back(static_cast(vinstr.mnemonic)); - if (vinstr.imm.has_imm) - { - obj->il_bytecode.emplace_back(vinstr.imm.size); - for(int i = 0; i < (vinstr.imm.size / 8); ++i) - { - obj->il_bytecode.emplace_back(*(reinterpret_cast(&vinstr.imm.val) + i)); - } - } - else - obj->il_bytecode.emplace_back(0); - } + if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { std::printf("%p: ", obj->cc_trace.m_begin + obj->m_vm->m_image_base - obj->m_vm->m_module_base); if (vinstr.imm.has_imm) if (vinstr.mnemonic == instrs::mnemonic_t::lreg || vinstr.mnemonic == instrs::mnemonic_t::sreg) @@ -446,7 +430,8 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, "> err: please define the following vm handler (at = %p):\n", (obj->cc_trace.m_begin - obj->m_vm->m_module_base) + obj->m_vm->m_image_base); - + std::printf("vsp: %s, vip: %s\n", ZydisRegisterGetString(obj->cc_blk->m_vm.vsp), + ZydisRegisterGetString(obj->cc_blk->m_vm.vip)); vm::utils::print(inst_stream); uc_emu_stop(uc); return false; @@ -619,9 +604,4 @@ std::optional> emu_t::could_have_jcc( return {{lconst1->imm.val, lconst2->imm.val}}; } - - std::vector& emu_t::get_il_bytecode() - { - return il_bytecode; - } } // namespace vm \ No newline at end of file -- 2.36.3 From e2e578bf55082b39bc89fe5bc00003dec54da473 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Thu, 13 Oct 2022 19:08:00 -0600 Subject: [PATCH 12/29] Fixed a memory leak --- include/vmemu_t.hpp | 1 - src/vmemu_t.cpp | 52 ++++++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index b5d4b6b..e76fb33 100644 --- a/include/vmemu_t.hpp +++ b/include/vmemu_t.hpp @@ -26,7 +26,6 @@ class emu_t { ~emu_t(); bool init(); bool emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn); - std::vector& get_il_bytecode(); private: uc_engine* uc; diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 4588a5b..36bc967 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -82,9 +82,6 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { return false; } - cc_trace.m_vip = cc_blk->m_vm.vip; - cc_trace.m_vsp = cc_blk->m_vm.vsp; - std::printf("> beginning execution at = %p (%p)\n", rip, rip - m_vm->m_module_base + m_vm->m_image_base); if ((err = uc_emu_start(uc, rip, 0ull, 0ull, 0ull))) { std::printf("> error starting emu... reason = %d\n", err); @@ -123,7 +120,8 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { // emulate the branch... uc_mem_write(uc, vsp, &br, sizeof br); - std::printf("> beginning execution at = %p (%p)\n", rip, rip - m_vm->m_module_base + m_vm->m_image_base); + std::printf("> beginning execution at = %p (%p)\n", blk.m_jmp.rip, + blk.m_jmp.rip - m_vm->m_module_base + m_vm->m_image_base); if ((err = uc_emu_start(uc, blk.m_jmp.rip, 0ull, 0ull, 0ull))) { std::printf("> error starting emu... reason = %d\n", err); return false; @@ -138,7 +136,7 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { // free all virtual code block virtual jmp information... std::for_each(vrtn.m_blks.begin(), vrtn.m_blks.end(), [&](vm::instrs::vblk_t& blk) { - if (blk.m_jmp.ctx) uc_context_free(blk.m_jmp.ctx); + if (blk.m_jmp.ctx) uct_context_free(blk.m_jmp.ctx); if (blk.m_jmp.stack) delete[] blk.m_jmp.stack; }); @@ -259,11 +257,13 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, if (instr.mnemonic == ZYDIS_MNEMONIC_INVALID) return false; uc_context* ctx; - uc_context_alloc(uc, &ctx); + uct_context_alloc(uc, &ctx); uc_context_save(uc, ctx); // if this is the first instruction of this handler then save the stack... if (!obj->cc_trace.m_instrs.size()) { + obj->cc_trace.m_vip = obj->cc_blk->m_vm.vip; + obj->cc_trace.m_vsp = obj->cc_blk->m_vm.vsp; obj->cc_trace.m_stack = new std::uint8_t[STACK_SIZE]; uc_mem_read(uc, STACK_BASE, obj->cc_trace.m_stack, STACK_SIZE); } @@ -292,15 +292,21 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, }); if (rva_fetch != obj->cc_trace.m_instrs.rend()) + { + for (auto itr = (rva_fetch + 1).base(); itr < obj->cc_trace.m_instrs.end(); itr++) + { + uct_context_free(itr->m_cpu); + } obj->cc_trace.m_instrs.erase((rva_fetch + 1).base(), obj->cc_trace.m_instrs.end()); + } const auto vinstr = vm::instrs::determine(obj->cc_trace); // -- 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) { - uc_context_free(instr.m_cpu); + uct_context_free(instr.m_cpu); }); delete[] obj->cc_trace.m_stack; @@ -339,11 +345,13 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, if (instr.mnemonic == ZYDIS_MNEMONIC_INVALID) return false; uc_context* ctx; - uc_context_alloc(uc, &ctx); + uct_context_alloc(uc, &ctx); uc_context_save(uc, ctx); // if this is the first instruction of this handler then save the stack... if (!obj->cc_trace.m_instrs.size()) { + obj->cc_trace.m_vip = obj->cc_blk->m_vm.vip; + obj->cc_trace.m_vsp = obj->cc_blk->m_vm.vsp; obj->cc_trace.m_stack = new std::uint8_t[STACK_SIZE]; obj->cc_trace.m_begin = address; uc_mem_read(uc, STACK_BASE, obj->cc_trace.m_stack, STACK_SIZE); @@ -373,8 +381,14 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, }); if (rva_fetch != obj->cc_trace.m_instrs.rend()) + { + for (auto itr = (rva_fetch + 1).base(); itr < --obj->cc_trace.m_instrs.end(); ++itr) + { + uct_context_free(itr->m_cpu); + } obj->cc_trace.m_instrs.erase((rva_fetch + 1).base(), --obj->cc_trace.m_instrs.end()); + } // set the virtual code block vip address information... if (!obj->cc_blk->m_vip.rva || !obj->cc_blk->m_vip.img_based) { @@ -389,10 +403,10 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, }); uc_context* backup; - uc_context_alloc(uc, &backup); + uct_context_alloc(uc, &backup); uc_context_save(uc, backup); uc_context_restore(uc, (--vip_write)->m_cpu); - + std::uintptr_t vip_addr = 0ull; uc_reg_read(uc, vm::instrs::reg_map[obj->cc_trace.m_vip], &vip_addr); @@ -400,7 +414,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, obj->cc_blk->m_vip.img_based = vip_addr += obj->m_vm->m_image_base; uc_context_restore(uc, backup); - uc_context_free(backup); + uct_context_free(backup); } else { const auto vinstr = vm::instrs::determine(obj->cc_trace); if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { @@ -430,8 +444,8 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, "> err: please define the following vm handler (at = %p):\n", (obj->cc_trace.m_begin - obj->m_vm->m_module_base) + obj->m_vm->m_image_base); - std::printf("vsp: %s, vip: %s\n", ZydisRegisterGetString(obj->cc_blk->m_vm.vsp), - ZydisRegisterGetString(obj->cc_blk->m_vm.vip)); + std::printf("vsp: %s, vip: %s\n", ZydisRegisterGetString(obj->cc_trace.m_vsp), + ZydisRegisterGetString(obj->cc_trace.m_vip)); vm::utils::print(inst_stream); uc_emu_stop(uc); return false; @@ -442,8 +456,8 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uc_context *backup, *copy; // backup current unicorn-engine context... - uc_context_alloc(uc, &backup); - uc_context_alloc(uc, ©); + uct_context_alloc(uc, &backup); + uct_context_alloc(uc, ©); uc_context_save(uc, backup); // make a copy of the first cpu context of the jmp handler... @@ -452,7 +466,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, // restore the unicorn-engine context... also free the backup... uc_context_restore(uc, backup); - uc_context_free(backup); + uct_context_free(backup); // set current code block virtual jmp instruction information... obj->cc_blk->m_jmp.ctx = copy; @@ -474,7 +488,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, // -- 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) { - uc_context_free(instr.m_cpu); + uct_context_free(instr.m_cpu); }); delete[] obj->cc_trace.m_stack; @@ -521,7 +535,7 @@ bool emu_t::legit_branch(vm::instrs::vblk_t& vblk, std::uintptr_t branch_addr) { // make a backup of the current emulation state... uc_context* backup; - uc_context_alloc(uc, &backup); + uct_context_alloc(uc, &backup); uc_context_save(uc, backup); std::uint8_t* stack = new std::uint8_t[STACK_SIZE]; uc_mem_read(uc, STACK_BASE, stack, STACK_SIZE); @@ -542,7 +556,7 @@ bool emu_t::legit_branch(vm::instrs::vblk_t& vblk, std::uintptr_t branch_addr) { // restore original cpu and stack... uc_mem_write(uc, STACK_BASE, stack, STACK_SIZE); uc_context_restore(uc, backup); - uc_context_free(backup); + uct_context_free(backup); delete[] stack; // add normal execution callback back... -- 2.36.3 From 64d2adebc715cbdae180e12c851eef91b4bcc903 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Fri, 14 Oct 2022 07:16:44 -0600 Subject: [PATCH 13/29] Fixed the godawful branch execution loop and added more prints --- include/vmemu_t.hpp | 1 + src/vmemu_t.cpp | 72 +++++++++++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index e76fb33..9249e23 100644 --- a/include/vmemu_t.hpp +++ b/include/vmemu_t.hpp @@ -26,6 +26,7 @@ class emu_t { ~emu_t(); bool init(); bool emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn); + static const bool s_log_instructions = true; private: uc_engine* uc; diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 36bc967..6089f47 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -1,5 +1,8 @@ #include #include +#include + +int g_new_delete_tracker; namespace vm { emu_t::emu_t(vm::vmctx_t* vm_ctx) : m_vm(vm_ctx) {}; @@ -58,6 +61,8 @@ bool emu_t::init() { } bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { + std::printf("\nSTARTING FROM NEW VMENTER AT %p (%p)\n\n", vmenter_rva + m_vm->m_module_base, + vmenter_rva + m_vm->m_image_base); uc_err err; vrtn.m_rva = vmenter_rva; @@ -83,6 +88,8 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { } std::printf("> beginning execution at = %p (%p)\n", rip, rip - m_vm->m_module_base + m_vm->m_image_base); + std::printf("vsp: %s, vip: %s\n", ZydisRegisterGetString(cc_blk->m_vm.vsp), + ZydisRegisterGetString(cc_blk->m_vm.vip)); if ((err = uc_emu_start(uc, rip, 0ull, 0ull, 0ull))) { std::printf("> error starting emu... reason = %d\n", err); return false; @@ -92,8 +99,8 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { std::printf("> emulated blk_%p\n\n", cc_blk->m_vip.img_based); // keep track of the emulated blocks... by their addresses... - std::vector blk_addrs; - blk_addrs.push_back(blk.m_vip.rva + m_vm->m_module_base); + std::unordered_set blk_addrs; + blk_addrs.insert(blk.m_vip.rva + m_vm->m_module_base); // the vector containing the vblk's grows inside of this for loop // thus we cannot use an advanced for loop (which uses itr's)... @@ -103,8 +110,7 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { // force the emulation of all branches... for (const auto br : blk.branches) { // only emulate blocks that havent been emulated before... - if (std::find(blk_addrs.begin(), blk_addrs.end(), br) != - blk_addrs.end()) + if (blk_addrs.find(br) != blk_addrs.end()) continue; std::uintptr_t vsp = 0ull; @@ -119,9 +125,12 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { cc_blk = &new_blk; // emulate the branch... + // The stack is now set up with vsp pointing to the next branch to execute, therefore the jmp will go to that branch. uc_mem_write(uc, vsp, &br, sizeof br); std::printf("> beginning execution at = %p (%p)\n", blk.m_jmp.rip, blk.m_jmp.rip - m_vm->m_module_base + m_vm->m_image_base); + std::printf("vsp: %s, vip: %s\n", ZydisRegisterGetString(cc_blk->m_vm.vsp), + ZydisRegisterGetString(cc_blk->m_vm.vip)); if ((err = uc_emu_start(uc, blk.m_jmp.rip, 0ull, 0ull, 0ull))) { std::printf("> error starting emu... reason = %d\n", err); return false; @@ -129,6 +138,8 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { extract_branch_data(); std::printf("> emulated blk_%p\n", cc_blk->m_vip.img_based); + // We needn't execute a block more than once for a single vrtn. + blk_addrs.insert(br); } } } @@ -138,7 +149,7 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { [&](vm::instrs::vblk_t& blk) { if (blk.m_jmp.ctx) uct_context_free(blk.m_jmp.ctx); - if (blk.m_jmp.stack) delete[] blk.m_jmp.stack; + if (blk.m_jmp.stack) delete[] blk.m_jmp.stack; if (blk.m_jmp.stack) g_new_delete_tracker--; }); return true; @@ -200,6 +211,7 @@ void emu_t::extract_branch_data() { vm::utils::scn::executable(m_vm->m_module_base, imm_mod_based)) { cc_blk->branches.push_back(imm_mod_based); cc_blk->branch_type = vm::instrs::vbranch_type::absolute; + std::printf("> absolute virtual jmp uncovered... branch = %p\n", imm_mod_based); } } else { std::printf("> jump table detected... review instruction stream...\n"); @@ -264,7 +276,7 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, if (!obj->cc_trace.m_instrs.size()) { obj->cc_trace.m_vip = obj->cc_blk->m_vm.vip; obj->cc_trace.m_vsp = obj->cc_blk->m_vm.vsp; - obj->cc_trace.m_stack = new std::uint8_t[STACK_SIZE]; + obj->cc_trace.m_stack = new std::uint8_t[STACK_SIZE]; g_new_delete_tracker++; uc_mem_read(uc, STACK_BASE, obj->cc_trace.m_stack, STACK_SIZE); } @@ -309,7 +321,7 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, uct_context_free(instr.m_cpu); }); - delete[] obj->cc_trace.m_stack; + delete[] obj->cc_trace.m_stack; if (obj->cc_trace.m_stack) g_new_delete_tracker--; obj->cc_trace.m_instrs.clear(); if (vinstr.mnemonic != vm::instrs::mnemonic_t::jmp) { @@ -352,7 +364,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, if (!obj->cc_trace.m_instrs.size()) { obj->cc_trace.m_vip = obj->cc_blk->m_vm.vip; obj->cc_trace.m_vsp = obj->cc_blk->m_vm.vsp; - obj->cc_trace.m_stack = new std::uint8_t[STACK_SIZE]; + obj->cc_trace.m_stack = new std::uint8_t[STACK_SIZE]; g_new_delete_tracker++; obj->cc_trace.m_begin = address; uc_mem_read(uc, STACK_BASE, obj->cc_trace.m_stack, STACK_SIZE); } @@ -369,7 +381,9 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, // 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( + // This may be more performant and elegant, but it fucks my new jmp profiler. + // I will keep it in as a comment for now in case I can make a jmp profiler compatible with this. +/* const auto rva_fetch = std::find_if( obj->cc_trace.m_instrs.rbegin(), obj->cc_trace.m_instrs.rend(), [& vip = obj->cc_trace.m_vip]( const vm::instrs::emu_instr_t& instr) -> bool { @@ -388,7 +402,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, } obj->cc_trace.m_instrs.erase((rva_fetch + 1).base(), --obj->cc_trace.m_instrs.end()); - } + } */ // set the virtual code block vip address information... if (!obj->cc_blk->m_vip.rva || !obj->cc_blk->m_vip.img_based) { @@ -418,20 +432,22 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, } else { const auto vinstr = vm::instrs::determine(obj->cc_trace); if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { - std::printf("%p: ", obj->cc_trace.m_begin + obj->m_vm->m_image_base - obj->m_vm->m_module_base); - if (vinstr.imm.has_imm) - if (vinstr.mnemonic == instrs::mnemonic_t::lreg || vinstr.mnemonic == instrs::mnemonic_t::sreg) - std::printf("> %s %s_%s\n", - vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(), - vm::reg_names::prefixes[(vinstr.imm.val / 8) % 8].c_str(), - vm::reg_names::suffixes[(vinstr.imm.val / 8) / 8].c_str()); + if (s_log_instructions) { + std::printf("%p: ", obj->cc_trace.m_begin + obj->m_vm->m_image_base - obj->m_vm->m_module_base); + if (vinstr.imm.has_imm) + if (vinstr.mnemonic == instrs::mnemonic_t::lreg || vinstr.mnemonic == instrs::mnemonic_t::sreg) + std::printf("> %s %s_%s\n", + vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(), + vm::reg_names::prefixes[(vinstr.imm.val / 8) % 8].c_str(), + vm::reg_names::suffixes[(vinstr.imm.val / 8) / 8].c_str()); + else + std::printf("> %s %p\n", + vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(), + vinstr.imm.val); else - std::printf("> %s %p\n", - vm::instrs::get_profile(vinstr.mnemonic)->name.c_str(), - vinstr.imm.val); - else - std::printf("> %s\n", - vm::instrs::get_profile(vinstr.mnemonic)->name.c_str()); + std::printf("> %s\n", + vm::instrs::get_profile(vinstr.mnemonic)->name.c_str()); + } } else { zydis_rtn_t inst_stream; std::for_each(obj->cc_trace.m_instrs.begin(), @@ -444,8 +460,6 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, "> err: please define the following vm handler (at = %p):\n", (obj->cc_trace.m_begin - obj->m_vm->m_module_base) + obj->m_vm->m_image_base); - std::printf("vsp: %s, vip: %s\n", ZydisRegisterGetString(obj->cc_trace.m_vsp), - ZydisRegisterGetString(obj->cc_trace.m_vip)); vm::utils::print(inst_stream); uc_emu_stop(uc); return false; @@ -471,7 +485,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, // set current code block virtual jmp instruction information... obj->cc_blk->m_jmp.ctx = copy; obj->cc_blk->m_jmp.rip = obj->cc_trace.m_begin; - obj->cc_blk->m_jmp.stack = new std::uint8_t[STACK_SIZE]; + obj->cc_blk->m_jmp.stack = new std::uint8_t[STACK_SIZE]; g_new_delete_tracker++; obj->cc_blk->m_jmp.m_vm = {obj->cc_trace.m_vip, obj->cc_trace.m_vsp}; std::memcpy(obj->cc_blk->m_jmp.stack, obj->cc_trace.m_stack, STACK_SIZE); @@ -491,7 +505,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uct_context_free(instr.m_cpu); }); - delete[] obj->cc_trace.m_stack; + delete[] obj->cc_trace.m_stack; if (obj->cc_trace.m_stack) g_new_delete_tracker--; obj->cc_trace.m_instrs.clear(); } return true; @@ -537,7 +551,7 @@ bool emu_t::legit_branch(vm::instrs::vblk_t& vblk, std::uintptr_t branch_addr) { uc_context* backup; uct_context_alloc(uc, &backup); uc_context_save(uc, backup); - std::uint8_t* stack = new std::uint8_t[STACK_SIZE]; + std::uint8_t* stack = new std::uint8_t[STACK_SIZE]; g_new_delete_tracker++; uc_mem_read(uc, STACK_BASE, stack, STACK_SIZE); // restore cpu and stack back to the virtual jump handler... @@ -557,7 +571,7 @@ bool emu_t::legit_branch(vm::instrs::vblk_t& vblk, std::uintptr_t branch_addr) { uc_mem_write(uc, STACK_BASE, stack, STACK_SIZE); uc_context_restore(uc, backup); uct_context_free(backup); - delete[] stack; + delete[] stack; if (stack) g_new_delete_tracker--; // add normal execution callback back... uc_hook_del(uc, branch_pred_hook); -- 2.36.3 From 85f93c7a824248fdf5efafb19a2e94d54a37b58d Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Fri, 14 Oct 2022 07:16:57 -0600 Subject: [PATCH 14/29] So basically, I --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 4151506..4de96fb 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 415150657d928b4d58436dadfcc9a634c268e78c +Subproject commit 4de96fbaef64bbae7e85c37e32d287e6f29fe5f1 -- 2.36.3 From 2bc8425e837b1e53684c23e24ced0d4f4ddc4405 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sat, 15 Oct 2022 00:40:31 -0600 Subject: [PATCH 15/29] Now every vrtn is lifting without error --- include/vmemu_t.hpp | 2 +- src/vmemu_t.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index 9249e23..a6e184a 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); - static const bool s_log_instructions = true; + static const bool s_log_instructions = false; private: uc_engine* uc; diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 6089f47..fb675a1 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -61,7 +61,9 @@ bool emu_t::init() { } bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { - std::printf("\nSTARTING FROM NEW VMENTER AT %p (%p)\n\n", vmenter_rva + m_vm->m_module_base, + static int vmenter_number = 0; + std::printf("\n[%.4d] STARTING FROM NEW VMENTER AT %p (%p)\n\n", vmenter_number++, + vmenter_rva + m_vm->m_module_base, vmenter_rva + m_vm->m_image_base); uc_err err; vrtn.m_rva = vmenter_rva; -- 2.36.3 From 9ae253078db33ebf1bed807c5f9efbed8fafce8b Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Tue, 1 Nov 2022 02:38:26 -0600 Subject: [PATCH 16/29] changed variable name and disabled warning --- include/vmemu_t.hpp | 2 +- src/vmemu_t.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index a6e184a..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); - static const bool s_log_instructions = false; + const bool m_log_instructions = false; private: uc_engine* uc; diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index fb675a1..91bb16c 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -2,6 +2,10 @@ #include #include +#ifdef _WIN32 +#pragma warning(disable : 4477) +#endif() + int g_new_delete_tracker; namespace vm { emu_t::emu_t(vm::vmctx_t* vm_ctx) : m_vm(vm_ctx) {}; @@ -434,7 +438,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, } else { const auto vinstr = vm::instrs::determine(obj->cc_trace); if (vinstr.mnemonic != vm::instrs::mnemonic_t::unknown) { - if (s_log_instructions) { + if (obj->m_log_instructions) { std::printf("%p: ", obj->cc_trace.m_begin + obj->m_vm->m_image_base - obj->m_vm->m_module_base); if (vinstr.imm.has_imm) if (vinstr.mnemonic == instrs::mnemonic_t::lreg || vinstr.mnemonic == instrs::mnemonic_t::sreg) -- 2.36.3 From f098127c23fc1ec2a1cdac0a5b9bf90d8d70690b Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Tue, 1 Nov 2022 02:41:02 -0600 Subject: [PATCH 17/29] update deps --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 4de96fb..fcdc386 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 4de96fbaef64bbae7e85c37e32d287e6f29fe5f1 +Subproject commit fcdc3866c658145d352e7b9f4bdf5fde0f30aaf3 -- 2.36.3 From 907bbb32aa337ef1ae09bb157cf3de573ad85daa Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Thu, 3 Nov 2022 21:42:37 -0600 Subject: [PATCH 18/29] theres no more tools tbh --- cmake.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake.toml b/cmake.toml index 9f6f6c6..d58f890 100644 --- a/cmake.toml +++ b/cmake.toml @@ -2,7 +2,6 @@ name = "vmemu" [subdir.deps] -[subdir.tools] [target.vmemu] type = "static" -- 2.36.3 From 4767c79d42cc03c24fb48ffb059b9a102f47ee86 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Wed, 9 Nov 2022 05:19:37 -0700 Subject: [PATCH 19/29] fixed speculative execution which was broken --- src/vmemu_t.cpp | 75 +++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index fb675a1..9e09422 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -172,6 +172,7 @@ void emu_t::extract_branch_data() { br1 += m_vm->m_module_base; br2 += m_vm->m_module_base; + // We need to handle the case that the jump points to another jump auto br1_legit = legit_branch(*cc_blk, br1); auto br2_legit = legit_branch(*cc_blk, br2); std::printf("> br1 legit: %d, br2 legit: %d\n", br1_legit, br2_legit); @@ -269,19 +270,10 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, } if (instr.mnemonic == ZYDIS_MNEMONIC_INVALID) return false; - uc_context* ctx; uct_context_alloc(uc, &ctx); uc_context_save(uc, ctx); - // if this is the first instruction of this handler then save the stack... - if (!obj->cc_trace.m_instrs.size()) { - obj->cc_trace.m_vip = obj->cc_blk->m_vm.vip; - obj->cc_trace.m_vsp = obj->cc_blk->m_vm.vsp; - obj->cc_trace.m_stack = new std::uint8_t[STACK_SIZE]; g_new_delete_tracker++; - uc_mem_read(uc, STACK_BASE, obj->cc_trace.m_stack, STACK_SIZE); - } - obj->cc_trace.m_instrs.push_back({instr, ctx}); // RET or JMP REG means the end of a vm handler... @@ -292,7 +284,7 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, // 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 +/* // 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(), @@ -303,7 +295,7 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, 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()) { @@ -313,17 +305,16 @@ bool emu_t::branch_pred_spec_exec(uc_engine* uc, uint64_t address, } obj->cc_trace.m_instrs.erase((rva_fetch + 1).base(), obj->cc_trace.m_instrs.end()); - } + } */ const auto vinstr = vm::instrs::determine(obj->cc_trace); - + // -- 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) { uct_context_free(instr.m_cpu); }); - delete[] obj->cc_trace.m_stack; if (obj->cc_trace.m_stack) g_new_delete_tracker--; obj->cc_trace.m_instrs.clear(); if (vinstr.mnemonic != vm::instrs::mnemonic_t::jmp) { @@ -565,6 +556,10 @@ bool emu_t::legit_branch(vm::instrs::vblk_t& vblk, std::uintptr_t branch_addr) { uc_reg_read(uc, UC_X86_REG_RIP, &rip); uc_reg_read(uc, vm::instrs::reg_map[vblk.m_vm.vsp], &vsp); uc_mem_write(uc, vsp, &branch_addr, sizeof branch_addr); + + // reset vsp and vip to their pre-jmp status in the current code trace + // this will be reset when the jmp instruction is emulated again + cc_trace.m_vsp = cc_blk->m_vm.vsp, cc_trace.m_vip = cc_blk->m_vm.vip; m_sreg_cnt = 0u; uc_emu_start(uc, rip, 0ull, 0ull, 0ull); @@ -606,31 +601,37 @@ std::optional> emu_t::could_have_jcc( return v.mnemonic == vm::instrs::mnemonic_t::lconst && v.imm.size == 64; }; - const auto lconst1 = - std::find_if(vinstrs.rbegin(), vinstrs.rend(), lconst64_chk); - - if (lconst1 == vinstrs.rend()) return {}; - - const auto lconst2 = std::find_if(lconst1 + 1, vinstrs.rend(), lconst64_chk); + static const auto valid_mem = [=](uintptr_t loc) + { + // check to see if the imm val is inside of the image... + if (loc > m_vm->m_image_base + m_vm->m_image_size || + loc < m_vm->m_image_base || + 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; + }; + auto lconst1 = vinstrs.rbegin(); + do { + lconst1 = + std::find_if(lconst1 + 1, vinstrs.rend(), lconst64_chk); + if (lconst1 == vinstrs.rend()) return {}; + } while (!valid_mem(lconst1->imm.val)); + + auto lconst2 = lconst1; + do { + lconst2 = + std::find_if(lconst2 + 1, vinstrs.rend(), lconst64_chk); if (lconst2 == vinstrs.rend()) return {}; - - // check to see if the imm val is inside of the image... - if (lconst1->imm.val > m_vm->m_image_base + m_vm->m_image_size || - lconst1->imm.val < m_vm->m_image_base || - lconst2->imm.val > m_vm->m_image_base + m_vm->m_image_size || - lconst2->imm.val < m_vm->m_image_base) - return {}; - - // 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, - (lconst1->imm.val - m_vm->m_image_base) + m_vm->m_module_base) || - !vm::utils::scn::executable( - m_vm->m_module_base, - (lconst2->imm.val - m_vm->m_image_base) + m_vm->m_module_base)) - return {}; + } while (!valid_mem(lconst1->imm.val)); return {{lconst1->imm.val, lconst2->imm.val}}; } -- 2.36.3 From 768a2dc6d0eebab45fc34544047a2301f12a41af Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Wed, 9 Nov 2022 05:19:45 -0700 Subject: [PATCH 20/29] update deps --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 4de96fb..e3abc95 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 4de96fbaef64bbae7e85c37e32d287e6f29fe5f1 +Subproject commit e3abc955e14349a1a01d2ea1f998feafa7486de0 -- 2.36.3 From aa993288204669d42e489f8f026449ece1568f21 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Thu, 10 Nov 2022 15:47:11 -0700 Subject: [PATCH 21/29] switched vmprofiler branch to master (main is cringe) --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index e3abc95..63c10f7 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit e3abc955e14349a1a01d2ea1f998feafa7486de0 +Subproject commit 63c10f71dd5c96c6b2a96f5ae5b7fd2a93fa07f3 -- 2.36.3 From 93d03c0fb5f08d5baefb6378db67b6b1622a4e9c Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sat, 12 Nov 2022 04:24:37 -0700 Subject: [PATCH 22/29] made it so that branching data is better 4 lifting --- deps/vmprofiler | 2 +- src/vmemu_t.cpp | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 63c10f7..d63f9b1 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 63c10f71dd5c96c6b2a96f5ae5b7fd2a93fa07f3 +Subproject commit d63f9b1af1b2eb42334f4c34a594f7faabd20903 diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 2637ce1..ebfc8ab 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -65,10 +65,6 @@ bool emu_t::init() { } bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { - static int vmenter_number = 0; - std::printf("\n[%.4d] STARTING FROM NEW VMENTER AT %p (%p)\n\n", vmenter_number++, - vmenter_rva + m_vm->m_module_base, - vmenter_rva + m_vm->m_image_base); uc_err err; vrtn.m_rva = vmenter_rva; @@ -128,6 +124,7 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { auto& new_blk = vrtn.m_blks.emplace_back(); new_blk.m_vip = {0ull, 0ull}; new_blk.m_vm = {blk.m_jmp.m_vm.vip, blk.m_jmp.m_vm.vsp}; + new_blk.is_branch = true; cc_blk = &new_blk; // emulate the branch... @@ -176,7 +173,6 @@ void emu_t::extract_branch_data() { br1 += m_vm->m_module_base; br2 += m_vm->m_module_base; - // We need to handle the case that the jump points to another jump auto br1_legit = legit_branch(*cc_blk, br1); auto br2_legit = legit_branch(*cc_blk, br2); std::printf("> br1 legit: %d, br2 legit: %d\n", br1_legit, br2_legit); @@ -416,7 +412,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uc_context* backup; uct_context_alloc(uc, &backup); uc_context_save(uc, backup); - uc_context_restore(uc, (--vip_write)->m_cpu); + uc_context_restore(uc, vip_write->m_cpu); std::uintptr_t vip_addr = 0ull; uc_reg_read(uc, vm::instrs::reg_map[obj->cc_trace.m_vip], &vip_addr); @@ -461,8 +457,8 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, uc_emu_stop(uc); return false; } - - if (obj->cc_blk->m_vinstrs.size()) { + //I don't think this if statement is neccesary + //if (obj->cc_blk->m_vinstrs.size()) { if (vinstr.mnemonic == vm::instrs::mnemonic_t::jmp) { uc_context *backup, *copy; @@ -491,8 +487,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, if (vinstr.mnemonic == vm::instrs::mnemonic_t::jmp || vinstr.mnemonic == vm::instrs::mnemonic_t::vmexit) uc_emu_stop(obj->uc); - } - + //} obj->cc_blk->m_vinstrs.push_back(vinstr); } @@ -506,7 +501,7 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, obj->cc_trace.m_instrs.clear(); } return true; -} + } void emu_t::invalid_mem(uc_engine* uc, uc_mem_type type, uint64_t address, int size, int64_t value, emu_t* obj) { -- 2.36.3 From 97908a1e33bb8720ed7a0f68772513f9c3d800ba Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 4 Dec 2022 08:09:18 -0700 Subject: [PATCH 23/29] fixed svsp --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index d63f9b1..80b5c20 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit d63f9b1af1b2eb42334f4c34a594f7faabd20903 +Subproject commit 80b5c20795aa18bd5a46b813b4c8207e3a7c79ce -- 2.36.3 From 6cf93a5fcbb904d3f3ba2326d2f147a90e170ab6 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Fri, 9 Dec 2022 19:50:48 -0700 Subject: [PATCH 24/29] still working on branch detection and emulation --- deps/vmprofiler | 2 +- include/vmemu_t.hpp | 2 +- src/vmemu_t.cpp | 34 +++++++++++++++++++++------------- 3 files changed, 23 insertions(+), 15 deletions(-) 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 -- 2.36.3 From 9fed462a0a4b7907d90188ddd2ec8b3fe05ddc61 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 11 Dec 2022 22:27:50 -0700 Subject: [PATCH 25/29] update deps --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index 1516e2a..f65c840 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 1516e2a2783308b778109659cce62ea2d78e4c82 +Subproject commit f65c84050d39210c8057ab741b8cbaf9f1e2e17d -- 2.36.3 From 3f124088b3d553106b6e81a93df18e8a167a3c1f Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 11 Dec 2022 23:00:18 -0700 Subject: [PATCH 26/29] fixed deps --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e0fdbd9..add8634 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "deps/vmprofiler"] path = deps/vmprofiler - url = https://github.com/xtremegamer1/vmprofiler + url = https://git.back.engineering/Manifold/vmprofiler -- 2.36.3 From 0100a88d82b51a7d79080fbd469bc778ef61e303 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 11 Dec 2022 23:00:18 -0700 Subject: [PATCH 27/29] update submodule --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e0fdbd9..add8634 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "deps/vmprofiler"] path = deps/vmprofiler - url = https://github.com/xtremegamer1/vmprofiler + url = https://git.back.engineering/Manifold/vmprofiler -- 2.36.3 From 71b1705804c67d06f8ace04c5b0687de6a3748b6 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Sun, 11 Dec 2022 23:33:27 -0700 Subject: [PATCH 28/29] update deps --- deps/vmprofiler | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/vmprofiler b/deps/vmprofiler index f65c840..343c7b9 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit f65c84050d39210c8057ab741b8cbaf9f1e2e17d +Subproject commit 343c7b95a4a18f119167a4f371a29cfa1624d404 -- 2.36.3 From 8eef5d9706211f80c65c04ed1eb8ee1ca1741a33 Mon Sep 17 00:00:00 2001 From: xtremegamer1 Date: Thu, 15 Dec 2022 02:01:33 -0700 Subject: [PATCH 29/29] fix issue with sreg handler --- deps/vmprofiler | 2 +- include/vmemu_t.hpp | 2 +- src/vmemu_t.cpp | 47 ++++++++++++++++++++++++++++++++------------- 3 files changed, 36 insertions(+), 15 deletions(-) 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); -- 2.36.3