project is now multi-threaded

master
IDontCode 2 years ago
parent f593704796
commit 9b05ac43e6

@ -1 +1 @@
Subproject commit 8779ab1160b541cc8e0d4862aee66d075bfb2362 Subproject commit eed247229fa832c2d2a1486e5467a129ce10debb

@ -1,10 +1,13 @@
#include <cli-parser.hpp> #include <cli-parser.hpp>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <thread>
#include "unpacker.hpp" #include "unpacker.hpp"
#include "vmemu_t.hpp" #include "vmemu_t.hpp"
#define NUM_THREADS 20
int __cdecl main(int argc, const char *argv[]) { int __cdecl main(int argc, const char *argv[]) {
argparse::argument_parser_t parser("VMEmu", argparse::argument_parser_t parser("VMEmu",
"VMProtect 2 VM Handler Emulator"); "VMProtect 2 VM Handler Emulator");
@ -92,8 +95,6 @@ int __cdecl main(int argc, const char *argv[]) {
case win::reloc_type_id::rel_based_dir64: { case win::reloc_type_id::rel_based_dir64: {
auto reloc_at = reinterpret_cast<std::uintptr_t *>( auto reloc_at = reinterpret_cast<std::uintptr_t *>(
entry.offset + reloc_block->base_rva + module_base); entry.offset + reloc_block->base_rva + module_base);
std::printf("> handling reloc at = %x\n",
entry.offset + reloc_block->base_rva);
*reloc_at = module_base + ((*reloc_at) - image_base); *reloc_at = module_base + ((*reloc_at) - image_base);
break; break;
} }
@ -144,7 +145,6 @@ int __cdecl main(int argc, const char *argv[]) {
} }
std::printf("> number of blocks = %d\n", code_blocks.size()); std::printf("> number of blocks = %d\n", code_blocks.size());
for (auto &code_block : code_blocks) { for (auto &code_block : code_blocks) {
std::printf("> code block starts at = %p\n", code_block.vip_begin); std::printf("> code block starts at = %p\n", code_block.vip_begin);
std::printf("> number of virtual instructions = %d\n", std::printf("> number of virtual instructions = %d\n",
@ -280,39 +280,56 @@ int __cdecl main(int argc, const char *argv[]) {
std::pair<std::uintptr_t, std::vector<vm::instrs::code_block_t> > > std::pair<std::uintptr_t, std::vector<vm::instrs::code_block_t> > >
virt_rtns; virt_rtns;
std::vector<std::thread> threads;
for (const auto &[vm_enter_offset, encrypted_rva, hndlr_tble] : entries) { for (const auto &[vm_enter_offset, encrypted_rva, hndlr_tble] : entries) {
std::printf("> emulating vm enter at rva = 0x%x\n", vm_enter_offset); if (threads.size() == NUM_THREADS) {
vm::ctx_t vm_ctx(module_base, image_base, image_size, vm_enter_offset); std::for_each(threads.begin(), threads.end(),
[&](std::thread &t) { t.join(); });
if (!vm_ctx.init()) { threads.clear();
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::emu_t emu(&vm_ctx); threads.emplace_back(std::thread([vm_enter_offset = vm_enter_offset,
module_base = module_base,
image_base = image_base,
image_size = image_size,
&virt_rtns = virt_rtns]() {
std::printf("> emulating vm enter at rva = 0x%x\n", vm_enter_offset);
vm::ctx_t vm_ctx(module_base, image_base, image_size, vm_enter_offset);
if (!vm_ctx.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;
}
if (!emu.init()) { vm::emu_t emu(&vm_ctx);
std::printf("[!] failed to init emulator...\n");
return -1;
}
std::vector<vm::instrs::code_block_t> code_blocks; if (!emu.init()) {
std::printf("[!] failed to init emulator...\n");
return;
}
if (!emu.get_trace(code_blocks)) { std::vector<vm::instrs::code_block_t> code_blocks;
std::printf(
"[!] something failed during tracing, review the console for more " if (!emu.get_trace(code_blocks)) {
"information...\n"); std::printf(
continue; "[!] something failed during tracing, review the console for "
} "more "
"information...\n");
return;
}
std::printf("> number of blocks = %d\n", code_blocks.size()); std::printf("> number of blocks = %d\n", code_blocks.size());
virt_rtns.push_back({vm_enter_offset, code_blocks}); virt_rtns.push_back({vm_enter_offset, code_blocks});
}));
} }
std::for_each(threads.begin(), threads.end(),
[&](std::thread &t) { t.join(); });
std::printf("> traced %d virtual routines...\n", virt_rtns.size()); std::printf("> traced %d virtual routines...\n", virt_rtns.size());
std::printf("> serializing results....\n"); std::printf("> serializing results....\n");

@ -382,16 +382,15 @@ bool emu_t::code_exec_callback(uc_engine *uc, uint64_t address, uint32_t size,
std::uint8_t vm_handler_table_idx = 0u; std::uint8_t vm_handler_table_idx = 0u;
std::uintptr_t vm_handler_addr; std::uintptr_t vm_handler_addr;
static std::shared_ptr<vm::ctx_t> _jmp_ctx; static thread_local std::shared_ptr<vm::ctx_t> _jmp_ctx;
static zydis_routine_t _jmp_stream; static thread_local zydis_routine_t _jmp_stream;
static auto inst_cnt = 0ull; static thread_local auto inst_cnt = 0ull;
static ZydisDecodedInstruction instr; static thread_local ZydisDecodedInstruction instr;
if (!ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(vm::util::g_decoder.get(), if (!ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(vm::util::g_decoder.get(),
reinterpret_cast<void *>(address), reinterpret_cast<void *>(address),
PAGE_4KB, &instr))) { PAGE_4KB, &instr))) {
std::printf("> failed to decode instruction at = 0x%p\n", address); std::printf("> failed to decode instruction at = 0x%p\n", address);
if ((err = uc_emu_stop(uc))) { if ((err = uc_emu_stop(uc))) {
std::printf("> failed to stop emulation, exiting... reason = %d\n", err); std::printf("> failed to stop emulation, exiting... reason = %d\n", err);
exit(0); exit(0);
@ -408,6 +407,7 @@ bool emu_t::code_exec_callback(uc_engine *uc, uint64_t address, uint32_t size,
// if there are over 4k instructions executed before a JMP is found then we // if there are over 4k instructions executed before a JMP is found then we
// are gunna stop emulation this is a sanity check to prevent inf loops... // are gunna stop emulation this is a sanity check to prevent inf loops...
if (++inst_cnt > 0x1000) { if (++inst_cnt > 0x1000) {
std::printf("> inf loop detected... stopping emulation...\n");
obj->cc_block = nullptr, inst_cnt = 0ull; obj->cc_block = nullptr, inst_cnt = 0ull;
uc_emu_stop(uc); uc_emu_stop(uc);
return false; return false;

Loading…
Cancel
Save