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 <fstream>
#include <iostream>
#include <thread>
#include "unpacker.hpp"
#include "vmemu_t.hpp"
#define NUM_THREADS 20
int __cdecl main(int argc, const char *argv[]) {
argparse::argument_parser_t parser("VMEmu",
"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: {
auto reloc_at = reinterpret_cast<std::uintptr_t *>(
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);
break;
}
@ -144,7 +145,6 @@ int __cdecl main(int argc, const char *argv[]) {
}
std::printf("> number of blocks = %d\n", code_blocks.size());
for (auto &code_block : code_blocks) {
std::printf("> code block starts at = %p\n", code_block.vip_begin);
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> > >
virt_rtns;
std::vector<std::thread> threads;
for (const auto &[vm_enter_offset, encrypted_rva, hndlr_tble] : entries) {
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 -1;
if (threads.size() == NUM_THREADS) {
std::for_each(threads.begin(), threads.end(),
[&](std::thread &t) { t.join(); });
threads.clear();
}
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()) {
std::printf("[!] failed to init emulator...\n");
return -1;
}
vm::emu_t emu(&vm_ctx);
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::printf(
"[!] something failed during tracing, review the console for more "
"information...\n");
continue;
}
std::vector<vm::instrs::code_block_t> code_blocks;
if (!emu.get_trace(code_blocks)) {
std::printf(
"[!] something failed during tracing, review the console for "
"more "
"information...\n");
return;
}
std::printf("> number of blocks = %d\n", code_blocks.size());
virt_rtns.push_back({vm_enter_offset, code_blocks});
std::printf("> number of blocks = %d\n", code_blocks.size());
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("> 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::uintptr_t vm_handler_addr;
static std::shared_ptr<vm::ctx_t> _jmp_ctx;
static zydis_routine_t _jmp_stream;
static auto inst_cnt = 0ull;
static ZydisDecodedInstruction instr;
static thread_local std::shared_ptr<vm::ctx_t> _jmp_ctx;
static thread_local zydis_routine_t _jmp_stream;
static thread_local auto inst_cnt = 0ull;
static thread_local ZydisDecodedInstruction instr;
if (!ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(vm::util::g_decoder.get(),
reinterpret_cast<void *>(address),
PAGE_4KB, &instr))) {
std::printf("> failed to decode instruction at = 0x%p\n", address);
if ((err = uc_emu_stop(uc))) {
std::printf("> failed to stop emulation, exiting... reason = %d\n", err);
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
// are gunna stop emulation this is a sanity check to prevent inf loops...
if (++inst_cnt > 0x1000) {
std::printf("> inf loop detected... stopping emulation...\n");
obj->cc_block = nullptr, inst_cnt = 0ull;
uc_emu_stop(uc);
return false;

Loading…
Cancel
Save