From 3d38dbed365624c6766a63e762b93cfe0f14107c Mon Sep 17 00:00:00 2001 From: xerox Date: Sun, 19 Dec 2021 21:29:34 -0800 Subject: [PATCH] starting to test... --- CMakeLists.txt | 1 + deps/vmprofiler | 2 +- include/vmemu_t.hpp | 65 +++++++++++++++++++++++++++++++++ src/main.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 include/vmemu_t.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b87323b..af161ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ set(vmemu_SOURCES "") list(APPEND vmemu_SOURCES "src/main.cpp" + "include/vmemu_t.hpp" ) list(APPEND vmemu_SOURCES diff --git a/deps/vmprofiler b/deps/vmprofiler index 5e0e7ab..2e7281f 160000 --- a/deps/vmprofiler +++ b/deps/vmprofiler @@ -1 +1 @@ -Subproject commit 5e0e7ab06bea367f70358b24e653a61dfd9c3690 +Subproject commit 2e7281f9001a4cb804a23f886bd26889c4d1ceae diff --git a/include/vmemu_t.hpp b/include/vmemu_t.hpp new file mode 100644 index 0000000..d4523e4 --- /dev/null +++ b/include/vmemu_t.hpp @@ -0,0 +1,65 @@ +#pragma once +#include + +#include +#include +#include +#include +#include + +#define PAGE_4KB 0x1000 +#define STACK_SIZE PAGE_4KB * 512 + +#define STACK_BASE 0xFFFF000000000000 +#define IAT_VECTOR_TABLE 0xFFFFF00000000000 + +namespace vm { +inline bool g_force_emu = false; + +class emu_t { + struct cpu_ctx_t { + std::uintptr_t rip; + uc_context* context; + std::uint8_t stack[STACK_SIZE]; + }; + + struct code_block_data_t { + vm::instrs::code_block_t code_block; + std::shared_ptr cpu_ctx; + std::shared_ptr g_vm_ctx; + }; + + public: + explicit emu_t(vm::ctx_t* vm_ctx); + ~emu_t(); + + bool init(); + bool get_trace(std::vector& code_blocks); + + private: + std::uintptr_t img_base, img_size; + uc_hook code_exec_hook, invalid_mem_hook, int_hook; + + uc_engine* uc_ctx; + vm::ctx_t* g_vm_ctx; + code_block_data_t* cc_block; + + std::vector vip_begins; + std::vector code_blocks; + std::map > vm_ctxs; + + uc_err create_entry(vmp2::v2::entry_t* entry); + static void int_callback(uc_engine* uc, std::uint32_t intno, emu_t* obj); + static bool code_exec_callback(uc_engine* uc, + uint64_t address, + uint32_t size, + 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); +}; +} // namespace vm diff --git a/src/main.cpp b/src/main.cpp index 32f3e1c..5ce06d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "vmemu_t.hpp" #define NUM_THREADS 20 @@ -42,4 +43,90 @@ int __cdecl main(int argc, const char* argv[]) { parser.print_help(); return 0; } + + vm::util::init(); + + std::vector module_data, tmp, unpacked_bin; + if (!vm::util::open_binary_file(parser.get("bin"), + module_data)) { + std::printf("[!] failed to open binary file...\n"); + return -1; + } + + auto img = reinterpret_cast*>(module_data.data()); + auto image_size = img->get_nt_headers()->optional_header.size_image; + const auto image_base = img->get_nt_headers()->optional_header.image_base; + + // page align the vector allocation so that unicorn-engine is happy girl... + tmp.resize(image_size + PAGE_4KB); + const std::uintptr_t module_base = + reinterpret_cast(tmp.data()) + + (PAGE_4KB - (reinterpret_cast(tmp.data()) & 0xFFFull)); + + std::memcpy((void*)module_base, module_data.data(), 0x1000); + std::for_each(img->get_nt_headers()->get_sections(), + img->get_nt_headers()->get_sections() + + img->get_nt_headers()->file_header.num_sections, + [&](const auto& section_header) { + std::memcpy( + (void*)(module_base + section_header.virtual_address), + module_data.data() + section_header.ptr_raw_data, + section_header.size_raw_data); + }); + + auto win_img = reinterpret_cast*>(module_base); + + auto basereloc_dir = + win_img->get_directory(win::directory_id::directory_entry_basereloc); + + auto reloc_dir = reinterpret_cast( + basereloc_dir->rva + module_base); + + win::reloc_block_t* reloc_block = &reloc_dir->first_block; + + // apply relocations to all sections... + while (reloc_block->base_rva && reloc_block->size_block) { + std::for_each(reloc_block->begin(), reloc_block->end(), + [&](win::reloc_entry_t& entry) { + switch (entry.type) { + case win::reloc_type_id::rel_based_dir64: { + auto reloc_at = reinterpret_cast( + entry.offset + reloc_block->base_rva + module_base); + *reloc_at = module_base + ((*reloc_at) - image_base); + break; + } + default: + break; + } + }); + + reloc_block = reloc_block->next(); + } + + std::printf("> image base = %p, image size = %p, module base = %p\n", + image_base, image_size, module_base); + + if (!image_base || !image_size || !module_base) { + std::printf("[!] failed to open binary on disk...\n"); + return -1; + } + + if (parser.exists("vmentry")) { + const auto vm_entry_rva = + std::strtoull(parser.get("vmentry").c_str(), nullptr, 16); + + std::vector code_blocks; + vm::ctx_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 2...\n"); + return -1; + } + + vm::util::print(vmctx.vm_entry); + } } \ No newline at end of file