diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp index b833e3d..559945e 100644 --- a/include/vmemu_t.hpp +++ b/include/vmemu_t.hpp @@ -13,6 +13,9 @@ #define STACK_SIZE PAGE_4KB * 512 #define STACK_BASE 0xFFFF000000000000 +#define STRING_POOL 0xFFFFF00000000000 +#define STRING_POOL_SIZE PAGE_4KB * 512 + namespace vm { class emu_t { public: diff --git a/src/vmemu_t.cpp b/src/vmemu_t.cpp index 03b06a7..08a0630 100644 --- a/src/vmemu_t.cpp +++ b/src/vmemu_t.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #include #include @@ -20,6 +23,17 @@ bool emu_t::init() { return false; } + if ((err = uc_mem_map(uc, STRING_POOL, STRING_POOL_SIZE, UC_PROT_ALL))) { + std::printf("> uc_mem_map stack err, reason = %d\n", err); + return false; + } + + std::uintptr_t str_pool_addr = STRING_POOL; + uc_reg_write(uc, UC_X86_REG_RAX, &str_pool_addr); + uc_reg_write(uc, UC_X86_REG_RBP, &str_pool_addr); + uc_reg_write(uc, UC_X86_REG_RDX, &str_pool_addr); + uc_reg_write(uc, UC_X86_REG_RSI, &str_pool_addr); + if ((err = uc_mem_map(uc, m_vm->m_module_base, m_vm->m_image_size, UC_PROT_ALL))) { std::printf("> map memory failed, reason = %d\n", err); @@ -140,7 +154,6 @@ bool emu_t::emulate(std::uint32_t vmenter_rva, vm::instrs::vrtn_t& vrtn) { 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.stack) delete[] blk.m_jmp.stack; }); @@ -321,6 +334,8 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, emu_t* obj) { uc_err err; static thread_local zydis_decoded_instr_t instr; + static thread_local unsigned instr_cnt = 0; + if (!ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(vm::utils::g_decoder.get(), reinterpret_cast(address), PAGE_4KB, &instr))) { @@ -332,6 +347,11 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, return false; } + if (instr_cnt > 500) { + instr_cnt = 0; + return false; + } + if (instr.mnemonic == ZYDIS_MNEMONIC_INVALID) return false; uc_context* ctx; @@ -421,8 +441,8 @@ bool emu_t::code_exec_callback(uc_engine* uc, uint64_t address, uint32_t size, obj->m_vm->m_image_base); vm::utils::print(inst_stream); - uc_emu_stop(uc); - return false; + // uc_emu_stop(uc); + return true; } if (obj->cc_blk->m_vinstrs.size()) { @@ -454,6 +474,31 @@ 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); + + if (vinstr.mnemonic == vm::instrs::mnemonic_t::vmexit) { + std::stringstream fname, cmd; + fname << std::hex << std::showbase + << obj->m_vm->m_vm_entry_rva + obj->m_vm->m_image_base << "_" + << "stack.bin"; + + std::uint8_t* buff = new std::uint8_t[STACK_SIZE]; + std::ofstream file(fname.str(), std::ios::binary); + uc_mem_read(uc, STACK_BASE, buff, STACK_SIZE); + file.write((char*)buff, STACK_SIZE); + uc_mem_read(uc, STRING_POOL, buff, STRING_POOL_SIZE); + file.write((char*)buff, STRING_POOL_SIZE); + file.close(); + delete[] buff; + + cmd << "strings -e b " << fname.str() << " >> BEDaisy.strings.txt"; + system(cmd.str().c_str()); + + cmd.str(""); + cmd << "strings " << fname.str() << " >> BEDaisy.strings.txt"; + system(cmd.str().c_str()); + + std::filesystem::remove(fname.str()); + } } obj->cc_blk->m_vinstrs.push_back(vinstr); diff --git a/tools/vmemu-cli/src/main.cpp b/tools/vmemu-cli/src/main.cpp index cfef154..56c0db4 100644 --- a/tools/vmemu-cli/src/main.cpp +++ b/tools/vmemu-cli/src/main.cpp @@ -113,29 +113,28 @@ int __cdecl main(int argc, const char* argv[]) { const auto vm_entries = vm::locate::get_vm_entries(module_base, image_size); std::printf("> number of vm entries = %d\n", vm_entries.size()); - const auto vm_entry_rva = - std::strtoull(parser.get("vmentry").c_str(), nullptr, 16); - - vm::vmctx_t vmctx(module_base, image_base, image_size, vm_entry_rva); - if (!vmctx.init()) { - std::printf( - "[!] failed to init vmctx... this can be for many reasons..." - " try validating your vm entry rva... make sure the binary is " - "unpacked and is" - "protected with VMProtect 3...\n"); - return -1; + for (auto& [rva, e_rva] : vm_entries) { + vm::vmctx_t vmctx(module_base, image_base, image_size, rva); + if (!vmctx.init()) { + std::printf( + "[!] failed to init vmctx... this can be for many reasons..." + " try validating your vm entry rva... make sure the binary is " + "unpacked and is" + "protected with VMProtect 3...\n"); + return -1; + } + + vm::emu_t emu(&vmctx); + if (!emu.init()) { + std::printf( + "[!] failed to init vm::emu_t... read above in the console for " + "the " + "reason...\n"); + return -1; + } + + vm::instrs::vrtn_t virt_rtn; + emu.emulate(rva, virt_rtn); } - - vm::emu_t emu(&vmctx); - if (!emu.init()) { - std::printf( - "[!] failed to init vm::emu_t... read above in the console for the " - "reason...\n"); - return -1; - } - - // TODO: rewrite this... using it to define profiles atm... - vm::instrs::vrtn_t virt_rtn; - emu.emulate(vm_entry_rva, virt_rtn); } } \ No newline at end of file