what the dog doing?

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

@ -10,6 +10,7 @@
#include <vector>
#include <vmprofiler.hpp>
#define PACKED_FILE_HANDLE 0x69420
#define PAGE_4KB 0x1000
#define STACK_SIZE PAGE_4KB * 512
@ -23,6 +24,14 @@
#define LOCAL_FREE_VECTOR 3
#define LOAD_LIBRARY_VECTOR 4
#define NT_QUERY_SYSTEM_INFO_VECTOR 5
#define GET_MODULE_FILE_NAME_W_VECTOR 6
#define CREATE_FILE_W_VECTOR 7
#define GET_FILE_SIZE_VECTOR 8
#define CREATE_FILE_MAPPING_VECTOR 9
#define MAP_VIEW_OF_FILE_VECTOR 10
#define UNMAP_VIEW_OF_FILE_VECTOR 11
#define CLOSE_HANDLE_VECTOR 12
#define VIRTUAL_PROTECT_VECTOR 13
#define MOV_RAX_0_SIG "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x00"
#define MOV_RAX_0_MASK "xxxxxxxxxx"
@ -33,7 +42,8 @@ static_assert(sizeof MOV_RAX_0_SIG == sizeof MOV_RAX_0_MASK,
namespace engine {
class unpack_t {
public:
explicit unpack_t(const std::vector<std::uint8_t> &bin);
explicit unpack_t(const std::string &module_name,
const std::vector<std::uint8_t> &bin);
~unpack_t(void);
bool init(void);
@ -45,6 +55,7 @@ class unpack_t {
uc_engine *uc_ctx;
std::vector<uint8_t> bin, map_bin;
std::vector<uc_hook *> uc_hooks;
std::string module_name;
std::uintptr_t img_base, img_size, heap_offset, pack_section_offset;
win::image_t<> *win_img;
@ -52,7 +63,17 @@ class unpack_t {
static void local_alloc_hook(uc_engine *, unpack_t *);
static void local_free_hook(uc_engine *, unpack_t *);
static void load_library_hook(uc_engine *, unpack_t *);
static void uc_strcpy(uc_engine *, char *buff, std::uintptr_t addr);
static void get_module_file_name_w_hook(uc_engine *, unpack_t *);
static void create_file_w_hook(uc_engine *, unpack_t *);
static void get_file_size_hook(uc_engine *, unpack_t *);
static void create_file_mapping_hook(uc_engine *, unpack_t *);
static void map_view_of_file_hook(uc_engine *, unpack_t *);
static void unmap_view_of_file_hook(uc_engine *, unpack_t *);
static void close_handle_hook(uc_engine *, unpack_t *);
static void virtual_protect_hook(uc_engine *, unpack_t *);
static void uc_strcpy(uc_engine *uc, char *buff, std::uintptr_t addr);
static void uc_strcpy(uc_engine *uc, std::uintptr_t addr, char *buff);
static bool iat_dispatcher(uc_engine *uc, uint64_t address, uint32_t size,
unpack_t *unpack);
@ -61,9 +82,6 @@ class unpack_t {
uint64_t address, int size, int64_t value,
unpack_t *unpack);
static bool code_exec_callback(uc_engine *uc, uint64_t address, uint32_t size,
unpack_t *unpack);
static void invalid_mem(uc_engine *uc, uc_mem_type type, uint64_t address,
int size, int64_t value, unpack_t *unpack);
@ -71,6 +89,17 @@ class unpack_t {
std::map<std::string, std::pair<std::uint32_t, iat_hook_t> > iat_hooks = {
{"LocalAlloc", {LOCAL_ALLOC_VECTOR, &local_alloc_hook}},
{"LocalFree", {LOCAL_FREE_VECTOR, &local_free_hook}},
{"LoadLibraryA", {LOAD_LIBRARY_VECTOR, &load_library_hook}}};
{"LoadLibraryA", {LOAD_LIBRARY_VECTOR, &load_library_hook}},
{"GetModuleFileNameW",
{GET_MODULE_FILE_NAME_W_VECTOR, &get_module_file_name_w_hook}},
{"CreateFileW", {CREATE_FILE_W_VECTOR, &create_file_w_hook}},
{"GetFileSize", {GET_FILE_SIZE_VECTOR, &get_file_size_hook}},
{"CreateFileMappingW",
{CREATE_FILE_MAPPING_VECTOR, &create_file_mapping_hook}},
{"MapViewOfFile", {MAP_VIEW_OF_FILE_VECTOR, &map_view_of_file_hook}},
{"UnmapViewOfFile",
{UNMAP_VIEW_OF_FILE_VECTOR, &unmap_view_of_file_hook}},
{"CloseHandle", {CLOSE_HANDLE_VECTOR, &close_handle_hook}},
{"VirtualProtect", {VIRTUAL_PROTECT_VECTOR, &virtual_protect_hook}}};
};
} // namespace engine

@ -252,7 +252,7 @@ int __cdecl main(int argc, const char *argv[]) {
});
output.close();
} else if (parser.exists("unpack")) {
engine::unpack_t unpacker(module_data);
engine::unpack_t unpacker(parser.get<std::string>("bin"), module_data);
if (!unpacker.init()) {
std::printf("> failed to init unpacker...\n");

@ -1,8 +1,10 @@
#include <unpacker.hpp>
namespace engine {
unpack_t::unpack_t(const std::vector<std::uint8_t> &packed_bin)
: bin(packed_bin),
unpack_t::unpack_t(const std::string &module_name,
const std::vector<std::uint8_t> &packed_bin)
: module_name(module_name),
bin(packed_bin),
uc_ctx(nullptr),
heap_offset(0ull),
pack_section_offset(0ull) {
@ -99,7 +101,7 @@ bool unpack_t::init(void) {
reloc_block = reloc_block->next();
}
// iat hook specific function...
// install iat hooks...
for (auto import_dir = reinterpret_cast<win::import_directory_t *>(
win_img->get_directory(win::directory_id::directory_entry_import)
->rva +
@ -113,11 +115,15 @@ bool unpack_t::init(void) {
auto iat_name = reinterpret_cast<win::image_named_import_t *>(
iat_thunk->address + map_bin.data());
if (iat_hooks.find(iat_name->name) != iat_hooks.end())
if (iat_hooks.find(iat_name->name) != iat_hooks.end()) {
std::printf("> iat hooking %s to vector table %p\n", iat_name->name,
iat_hooks[iat_name->name].first + IAT_VECTOR_TABLE);
iat_thunk->function =
iat_hooks[iat_name->name].first + IAT_VECTOR_TABLE;
}
}
}
// map the entire map buffer into unicorn-engine since we have set everything
// else up...
@ -162,18 +168,7 @@ bool unpack_t::init(void) {
std::printf("> failed to add hook... reason = %d\n", err);
return;
}
pack_section_offset = header.virtual_address + header.virtual_size;
} else if (header.characteristics.mem_execute) {
uc_hooks.push_back(new uc_hook);
if ((err = uc_hook_add(
uc_ctx, uc_hooks.back(), UC_HOOK_CODE,
(void *)&engine::unpack_t::code_exec_callback, this,
header.virtual_address + img_base,
header.virtual_address + header.virtual_size + img_base))) {
std::printf("> failed to add hook... reason = %d\n", err);
return;
}
}
});
@ -347,6 +342,115 @@ void unpack_t::local_free_hook(uc_engine *uc_ctx, unpack_t *obj) {
}
}
void unpack_t::unmap_view_of_file_hook(uc_engine *uc, unpack_t *obj) {
std::uintptr_t rcx, rax = true;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
std::printf("> UnmapViewOfFile(%p)\n", rcx);
}
void unpack_t::close_handle_hook(uc_engine *uc, unpack_t *obj) {
std::uintptr_t rcx, rax = true;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
std::printf("> CloseHandle(%x)\n", rcx);
}
void unpack_t::get_module_file_name_w_hook(uc_engine *uc, unpack_t *obj) {
uc_err err;
std::uintptr_t rcx, rdx, r8;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_reg_read(uc, UC_X86_REG_RDX, &rdx);
uc_reg_read(uc, UC_X86_REG_R8, &r8);
std::printf("> GetModuleFileNameW(%p, %p, %d)\n", rcx, rdx, r8);
uc_strcpy(uc, rdx, (char *)obj->module_name.c_str());
std::uint32_t size = obj->module_name.size();
uc_reg_write(uc, UC_X86_REG_RAX, &size);
}
void unpack_t::create_file_w_hook(uc_engine *uc, unpack_t *obj) {
char buff[256];
std::uintptr_t rcx, rax = PACKED_FILE_HANDLE;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_strcpy(uc, buff, rcx);
std::printf("> CreateFileW(%s)\n", buff);
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
}
void unpack_t::get_file_size_hook(uc_engine *uc, unpack_t *obj) {
std::uintptr_t rcx, rdx, rax;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_reg_read(uc, UC_X86_REG_RDX, &rdx);
std::printf("> GetFileSize(%x, %p)\n", rcx, rdx);
if (rcx == PACKED_FILE_HANDLE) {
rax = obj->bin.size();
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
} else {
std::printf("> asking for file size to unknown handle = %x\n", rcx);
uc_emu_stop(uc);
}
}
void unpack_t::create_file_mapping_hook(uc_engine *uc, unpack_t *obj) {
std::uintptr_t rcx, r8, rax = PACKED_FILE_HANDLE;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_reg_read(uc, UC_X86_REG_R8, &r8);
std::printf("> CreateFileMappingW(%x, %x)\n", rcx, r8);
if (rcx == PACKED_FILE_HANDLE) {
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
} else {
std::printf("> asking to create mapping for unknown handle = %x\n", rcx);
uc_emu_stop(uc);
}
}
void unpack_t::map_view_of_file_hook(uc_engine *uc, unpack_t *obj) {
std::uintptr_t rcx, rdx, r8, r9, rax;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_reg_read(uc, UC_X86_REG_RDX, &rdx);
uc_reg_read(uc, UC_X86_REG_R8, &r8);
uc_reg_read(uc, UC_X86_REG_R9, &r9);
std::printf("> MapViewOfFile(%x, %x, %x, %x)\n", rcx, rdx, r8, r9);
if (rcx == PACKED_FILE_HANDLE) {
uc_err err;
auto size = ((obj->bin.size() + PAGE_4KB) & ~0xFFFull);
if ((err =
uc_mem_map(uc, HEAP_BASE + obj->heap_offset, size, UC_PROT_ALL))) {
std::printf("> failed to allocate memory... reason = %d\n", err);
return;
}
rax = HEAP_BASE + obj->heap_offset;
obj->heap_offset += size;
if ((err = uc_mem_write(uc, rax, obj->bin.data(), obj->bin.size()))) {
std::printf("> failed to map view of file... reason = %d\n", err);
return;
}
if ((err = uc_reg_write(uc, UC_X86_REG_RAX, &rax))) {
std::printf("> failed to write rax... reason = %d\n", err);
return;
}
} else {
std::printf("> asking to map file for unknown handle = %x\n", rcx);
uc_emu_stop(uc);
}
}
void unpack_t::virtual_protect_hook(uc_engine *uc, unpack_t *obj) {
std::uintptr_t rcx, rdx, r8, r9, rax = true;
uc_reg_read(uc, UC_X86_REG_RCX, &rcx);
uc_reg_read(uc, UC_X86_REG_RDX, &rdx);
uc_reg_read(uc, UC_X86_REG_R8, &r8);
uc_reg_read(uc, UC_X86_REG_R9, &r9);
std::printf("> VirtualProtect(%p, %x, %x, %p)\n", rcx, rdx, r8, r9);
uc_reg_write(uc, UC_X86_REG_RAX, &rax);
}
void unpack_t::load_library_hook(uc_engine *uc_ctx, unpack_t *obj) {
uc_err err;
std::uintptr_t rcx = 0ull;
@ -365,7 +469,7 @@ void unpack_t::load_library_hook(uc_engine *uc_ctx, unpack_t *obj) {
std::vector<std::uint8_t> module_data, tmp;
if (!vm::util::open_binary_file(buff, module_data)) {
std::printf(
"[!] failed to open a dependency... please put %s in the same folder "
"> failed to open a dependency... please put %s in the same folder "
"as vmemu...\n",
buff);
exit(-1);
@ -387,10 +491,35 @@ void unpack_t::load_library_hook(uc_engine *uc_ctx, unpack_t *obj) {
});
const auto module_base = reinterpret_cast<std::uintptr_t>(tmp.data());
img = reinterpret_cast<win::image_t<> *>(module_base);
const auto image_base = img->get_nt_headers()->optional_header.image_base;
const auto alloc_addr = module_base & ~0xFFFull;
obj->loaded_modules[buff] = alloc_addr;
// install iat hooks...
for (auto import_dir = reinterpret_cast<win::import_directory_t *>(
img->get_directory(win::directory_id::directory_entry_import)
->rva +
module_base);
import_dir->rva_name; ++import_dir) {
for (auto iat_thunk = reinterpret_cast<win::image_thunk_data_t<> *>(
import_dir->rva_first_thunk + module_base);
iat_thunk->address; ++iat_thunk) {
if (iat_thunk->is_ordinal) continue;
auto iat_name = reinterpret_cast<win::image_named_import_t *>(
iat_thunk->address + module_base);
if (obj->iat_hooks.find(iat_name->name) != obj->iat_hooks.end()) {
std::printf("> iat hooking %s to vector table %p\n", iat_name->name,
obj->iat_hooks[iat_name->name].first + IAT_VECTOR_TABLE);
iat_thunk->function =
obj->iat_hooks[iat_name->name].first + IAT_VECTOR_TABLE;
}
}
}
if ((err = uc_mem_map(uc_ctx, alloc_addr, image_size, UC_PROT_ALL))) {
std::printf("> failed to load library... reason = %d\n", err);
return;
@ -423,17 +552,28 @@ void unpack_t::uc_strcpy(uc_engine *uc_ctx, char *buff, std::uintptr_t addr) {
auto idx = 0ul;
do {
if ((err = uc_mem_read(uc_ctx, addr + idx, &i, sizeof i))) break;
if ((err = uc_mem_read(uc_ctx, addr + idx, &i, sizeof i))) {
std::printf("[!] error reading string byte... reason = %d\n", err);
break;
}
} while ((buff[idx++] = i));
}
void unpack_t::uc_strcpy(uc_engine *uc, std::uintptr_t addr, char *buff) {
uc_err err;
for (char idx = 0u, c = buff[idx]; buff[idx]; ++idx, c = buff[idx]) {
if ((err = uc_mem_write(uc, addr + idx, &c, sizeof c))) {
std::printf("[!] error writing string byte... reason = %d\n", err);
break;
}
}
}
bool unpack_t::iat_dispatcher(uc_engine *uc, uint64_t address, uint32_t size,
unpack_t *unpack) {
auto vec = address - IAT_VECTOR_TABLE;
for (auto &[iat_name, iat_hook_data] : unpack->iat_hooks) {
if (iat_hook_data.first == vec) {
std::printf("> hooking import = %s\n", iat_name.c_str());
iat_hook_data.second(uc, unpack);
return true;
}
@ -441,39 +581,11 @@ bool unpack_t::iat_dispatcher(uc_engine *uc, uint64_t address, uint32_t size,
return false;
}
bool unpack_t::code_exec_callback(uc_engine *uc, uint64_t address,
uint32_t size, unpack_t *unpack) {
static ZydisDecodedInstruction instr;
auto instr_ptr = reinterpret_cast<void *>(unpack->map_bin.data() +
(address - unpack->img_base));
if (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(vm::util::g_decoder.get(),
instr_ptr, PAGE_4KB, &instr))) {
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 > unpack->img_base + unpack->img_size ||
rax < unpack->img_base) // skip calls outside the packed module...
{
std::printf(">>> skipping external call to addr = %p\n", rax);
rip += instr.length;
uc_reg_write(uc, UC_X86_REG_RIP, &rip);
}
}
}
return true;
}
bool unpack_t::unpack_section_callback(uc_engine *uc, uc_mem_type type,
uint64_t address, int size,
int64_t value, unpack_t *unpack) {
if (address == unpack->pack_section_offset + unpack->img_base) {
std::printf("> dumping...\n");
std::printf("> last byte written to unpack section... dumping...\n");
uc_emu_stop(uc);
return false;
}

Loading…
Cancel
Save