unpacker is still broke but --emuall works...

merge-requests/14/head
IDontCode 3 years ago
parent 1e62befcf0
commit 1e9a94994c

@ -67,9 +67,6 @@ class unpack_t {
static void invalid_mem(uc_engine *uc, uc_mem_type type, uint64_t address, static void invalid_mem(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, unpack_t *unpack); int size, int64_t value, unpack_t *unpack);
static void dep_read_watch(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, unpack_t *unpack);
std::map<std::string, std::uintptr_t> loaded_modules; std::map<std::string, std::uintptr_t> loaded_modules;
std::map<std::string, std::pair<std::uint32_t, iat_hook_t> > iat_hooks = { std::map<std::string, std::pair<std::uint32_t, iat_hook_t> > iat_hooks = {
{"LocalAlloc", {LOCAL_ALLOC_VECTOR, &local_alloc_hook}}, {"LocalAlloc", {LOCAL_ALLOC_VECTOR, &local_alloc_hook}},

@ -347,11 +347,6 @@ void unpack_t::local_free_hook(uc_engine *uc_ctx, unpack_t *obj) {
} }
} }
void unpack_t::dep_read_watch(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, unpack_t *unpack) {
std::printf("> reading address = %p, size = %d\n", address, size);
}
void unpack_t::load_library_hook(uc_engine *uc_ctx, unpack_t *obj) { void unpack_t::load_library_hook(uc_engine *uc_ctx, unpack_t *obj) {
uc_err err; uc_err err;
std::uintptr_t rcx = 0ull; std::uintptr_t rcx = 0ull;
@ -411,12 +406,6 @@ void unpack_t::load_library_hook(uc_engine *uc_ctx, unpack_t *obj) {
std::printf("> failed to set rax... reason = %d\n", err); std::printf("> failed to set rax... reason = %d\n", err);
return; return;
} }
obj->uc_hooks.push_back(new uc_hook);
uc_hook_add(uc_ctx, obj->uc_hooks.back(), UC_HOOK_MEM_READ,
(void *)&engine::unpack_t::dep_read_watch, obj, alloc_addr,
alloc_addr + image_size);
std::printf("> mapped %s to base address %p\n", buff, alloc_addr); std::printf("> mapped %s to base address %p\n", buff, alloc_addr);
} else { } else {
const auto alloc_addr = obj->loaded_modules[buff]; const auto alloc_addr = obj->loaded_modules[buff];
@ -468,8 +457,9 @@ bool unpack_t::code_exec_callback(uc_engine *uc, uint64_t address,
uc_reg_read(uc, UC_X86_REG_RIP, &rip); uc_reg_read(uc, UC_X86_REG_RIP, &rip);
if (rax > unpack->img_base + unpack->img_size || if (rax > unpack->img_base + unpack->img_size ||
rax < unpack->img_base) // skip calls to kernel32.dll... rax < unpack->img_base) // skip calls outside the packed module...
{ {
std::printf(">>> skipping external call to addr = %p\n", rax);
rip += instr.length; rip += instr.length;
uc_reg_write(uc, UC_X86_REG_RIP, &rip); uc_reg_write(uc, UC_X86_REG_RIP, &rip);
} }

@ -23,6 +23,40 @@ bool emu_t::init() {
return false; return false;
} }
if ((err = uc_mem_map(uc_ctx, IAT_VECTOR_TABLE, PAGE_4KB, UC_PROT_ALL))) {
std::printf("> uc_mem_map iat vector table err = %d\n", err);
return false;
}
// init iat vector table full of 'ret' instructions...
auto c3_page = malloc(PAGE_4KB);
{
memset(c3_page, 0xC3, PAGE_4KB);
if ((err = uc_mem_write(uc_ctx, IAT_VECTOR_TABLE, c3_page, PAGE_4KB))) {
std::printf("> failed to init iat vector table...\n");
free(c3_page);
return false;
}
}
free(c3_page);
auto win_img = reinterpret_cast<win::image_t<> *>(g_vm_ctx->module_base);
// iat hook all imports to return...
for (auto import_dir = reinterpret_cast<win::import_directory_t *>(
win_img->get_directory(win::directory_id::directory_entry_import)
->rva +
g_vm_ctx->module_base);
import_dir->rva_name; ++import_dir) {
for (auto iat_thunk = reinterpret_cast<win::image_thunk_data_t<> *>(
import_dir->rva_first_thunk + g_vm_ctx->module_base);
iat_thunk->address; ++iat_thunk) {
if (iat_thunk->is_ordinal) continue;
iat_thunk->function = IAT_VECTOR_TABLE;
}
}
if ((err = if ((err =
uc_mem_map(uc_ctx, g_vm_ctx->module_base, img_size, UC_PROT_ALL))) { uc_mem_map(uc_ctx, g_vm_ctx->module_base, img_size, UC_PROT_ALL))) {
std::printf("> map memory failed, reason = %d\n", err); std::printf("> map memory failed, reason = %d\n", err);
@ -53,7 +87,7 @@ bool emu_t::init() {
if ((err = if ((err =
uc_hook_add(uc_ctx, &invalid_mem_hook, uc_hook_add(uc_ctx, &invalid_mem_hook,
UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED | UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED |
UC_HOOK_MEM_FETCH_UNMAPPED | UC_HOOK_INSN_INVALID, UC_HOOK_MEM_FETCH_UNMAPPED,
(void *)&vm::emu_t::invalid_mem, this, true, false))) { (void *)&vm::emu_t::invalid_mem, this, true, false))) {
std::printf("> uc_hook_add error, reason = %d\n", err); std::printf("> uc_hook_add error, reason = %d\n", err);
return false; return false;
@ -379,23 +413,6 @@ bool emu_t::code_exec_callback(uc_engine *uc, uint64_t address, uint32_t size,
return false; return false;
} }
// skip calls entirely since the virtual machine will execute to make calls...
// only time calls legit happen are with the CALL handler used only by the
// packer...
if (instr.mnemonic == ZYDIS_MNEMONIC_CALL &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].reg.value == ZYDIS_REGISTER_RAX) {
std::uintptr_t rax = 0u, rip = 0u;
uc_reg_read(uc, UC_X86_REG_RAX, &rax);
uc_reg_read(uc, UC_X86_REG_RIP, &rip);
if (rax > obj->g_vm_ctx->module_base + obj->img_size ||
rax < obj->g_vm_ctx->module_base) {
rip += instr.length;
uc_reg_write(uc, UC_X86_REG_RIP, &rip);
}
}
// if the native instruction is a jmp rcx/rdx... then AL will contain the vm // if the native instruction is a jmp rcx/rdx... then AL will contain the vm
// handler table index of the vm handler that the emulator is about to jmp // handler table index of the vm handler that the emulator is about to jmp
// too... // too...
@ -665,6 +682,14 @@ void emu_t::invalid_mem(uc_engine *uc, uc_mem_type type, uint64_t address,
case UC_MEM_FETCH_UNMAPPED: { case UC_MEM_FETCH_UNMAPPED: {
std::printf(">>> fetching invalid instructions at address = %p\n", std::printf(">>> fetching invalid instructions at address = %p\n",
address); address);
std::uintptr_t rip, rsp;
uc_reg_read(uc, UC_X86_REG_RSP, &rsp);
uc_mem_read(uc, rsp, &rip, sizeof rip);
rsp += 8;
uc_reg_write(uc, UC_X86_REG_RSP, &rsp);
uc_reg_write(uc, UC_X86_REG_RIP, &rip);
std::printf(">>> injecting return to try and recover... rip = %p\n", rip);
break; break;
} }
default: default:

Loading…
Cancel
Save