i think its working >:)

merge-requests/1/head
_xeroxz 3 years ago
parent 9e7cee53db
commit 9e65de6100

@ -119,6 +119,7 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)..\dependencies\unicorn\include\;$(ProjectDir)..\dependencies\xtils\;$(ProjectDir)..\dependencies\vmprofiler\include\;$(ProjectDir)..\dependencies\cli-parser\;$(ProjectDir)..\dependencies\vmprofiler\dependencies\zydis\include;$(ProjectDir)..\dependencies\vmprofiler\dependencies\zydis\dependencies\zycore\include;$(ProjectDir)..\dependencies\vmprofiler\dependencies\zydis\msvc;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
@ -128,12 +129,14 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(ProjectDir)..\dependencies\unicorn\msvc\x64\Debug\*.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -142,7 +145,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<Optimization>Disabled</Optimization>
<LanguageStandard>stdcpp17</LanguageStandard>
@ -152,7 +155,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(ProjectDir)..\dependencies\unicorn\msvc\x64\Release\*.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(ProjectDir)..\dependencies\unicorn\msvc\x64\Debug\*.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

@ -9,7 +9,8 @@ namespace vm
image_base(image_base),
vm_entry_rva(vm_entry_rva),
vm_handler_table(nullptr),
uc(nullptr)
uc(nullptr),
trace_entries(nullptr)
{}
bool emu_t::init()
@ -24,7 +25,7 @@ namespace vm
return false;
}
//vm::util::deobfuscate(vm_entry);
vm::util::deobfuscate(vm_entry);
vm::util::print(vm_entry);
if (!(vm_handler_table = vm::handler::table::get(vm_entry)))
@ -39,14 +40,20 @@ namespace vm
std::printf("[!] failed to get all vm handlers...\n");
return false;
}
std::printf("> got all vm handlers...\n");
//
// unicorn init stuff...
//
auto err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc);
const auto image_size =
NT_HEADER(module_base)->OptionalHeader.SizeOfImage;
if (err)
std::uintptr_t stack_base = 0x1000000;
std::uintptr_t stack_addr = stack_base + (0x1000 * 20);
uc_err err;
if ((err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc)))
{
std::printf("failed on uc_mem_map() with error returned %u: %s\n",
err, uc_strerror(err));
@ -54,16 +61,7 @@ namespace vm
return false;
}
const auto image_size =
NT_HEADER(module_base)->OptionalHeader.SizeOfImage;
const auto vm_entry = vm_entry_rva + module_base;
constexpr auto stack_addr = 0x1000000 + (0x1000 * 6);
// allocate space for module...
err = uc_mem_map(uc, module_base, image_size, UC_PROT_ALL);
if (err)
if ((err = uc_mem_map(uc, module_base, image_size, UC_PROT_ALL)))
{
std::printf("failed on uc_mem_map() with error returned %u: %s\n",
err, uc_strerror(err));
@ -71,10 +69,7 @@ namespace vm
return false;
}
// allocate 6 pages for stack...
err = uc_mem_map(uc, stack_addr, 0x1000 * 6, UC_PROT_ALL);
if (err)
if ((err = uc_mem_map(uc, 0x1000000, 0x1000 * 20, UC_PROT_ALL)))
{
std::printf("failed on uc_mem_map() with error returned %u: %s\n",
err, uc_strerror(err));
@ -82,16 +77,15 @@ namespace vm
return false;
}
// write the module into memory...
err = uc_mem_write(uc, module_base, reinterpret_cast<void*>(module_base), image_size);
if (err) std::printf("failed on uc_mem_write() with error returned %u: %s\n",
err, uc_strerror(err));
if ((err = uc_mem_write(uc, module_base, reinterpret_cast<void*>(module_base), image_size)))
{
std::printf("failed on uc_mem_write() with error returned %u: %s\n",
err, uc_strerror(err));
// set vm_entry into RIP...
err = uc_reg_write(uc, UC_X86_REG_RIP, &vm_entry);
return false;
}
if (err)
if ((err = uc_reg_write(uc, UC_X86_REG_RIP, &vm_entry)))
{
std::printf("failed on uc_reg_write() with error returned %u: %s\n",
err, uc_strerror(err));
@ -99,10 +93,7 @@ namespace vm
return false;
}
// set stack address up...
err = uc_reg_write(uc, UC_X86_REG_RSP, &stack_addr);
if (err)
if ((err = uc_reg_write(uc, UC_X86_REG_RSP, &stack_addr)))
{
std::printf("failed on uc_reg_write() with error returned %u: %s\n",
err, uc_strerror(err));
@ -110,10 +101,8 @@ namespace vm
return false;
}
err = uc_hook_add(uc, &trace, UC_HOOK_CODE, &jmp_hook,
nullptr, module_base, module_base + image_size);
if (err)
if ((err = uc_hook_add(uc, &trace, UC_HOOK_CODE, &vm::emu_t::hook_code,
this, module_base, module_base + image_size)))
{
std::printf("failed on uc_hook_add() with error returned %u: %s\n",
err, uc_strerror(err));
@ -121,16 +110,14 @@ namespace vm
return false;
}
// emulate machine code in infinite time
err = uc_emu_start(uc, vm_entry, NULL, NULL, NULL);
if (err)
if ((err = uc_hook_add(uc, &trace1, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED,
vm::emu_t::hook_mem_invalid, this, 1, 0)))
{
std::printf("Failed on uc_emu_start() with error returned %u: %s\n",
std::printf("failed on uc_hook_add() with error returned %u: %s\n",
err, uc_strerror(err));
return false;
}
return true;
}
@ -138,4 +125,152 @@ namespace vm
{
if (uc) uc_close(uc);
}
bool emu_t::get_trace(std::vector<vmp2::entry_t>& entries)
{
// hook_code will fill this vector up with values...
trace_entries = &entries;
uc_err err;
if ((err = uc_emu_start(uc, vm_entry_rva + module_base, NULL, NULL, NULL)))
{
std::printf("failed on uc_emu_start() with error returned %u: %s\n",
err, uc_strerror(err));
return false;
}
return true;
}
uc_err emu_t::create_entry(vmp2::entry_t* entry)
{
uc_reg_read(uc, UC_X86_REG_R15, &entry->regs.r15);
uc_reg_read(uc, UC_X86_REG_R14, &entry->regs.r14);
uc_reg_read(uc, UC_X86_REG_R13, &entry->regs.r13);
uc_reg_read(uc, UC_X86_REG_R12, &entry->regs.r12);
uc_reg_read(uc, UC_X86_REG_R11, &entry->regs.r11);
uc_reg_read(uc, UC_X86_REG_R10, &entry->regs.r10);
uc_reg_read(uc, UC_X86_REG_R9, &entry->regs.r9);
uc_reg_read(uc, UC_X86_REG_R8, &entry->regs.r8);
uc_reg_read(uc, UC_X86_REG_RBP, &entry->regs.rbp);
uc_reg_read(uc, UC_X86_REG_RDI, &entry->regs.rdi);
uc_reg_read(uc, UC_X86_REG_RSI, &entry->regs.rsi);
uc_reg_read(uc, UC_X86_REG_RDX, &entry->regs.rdx);
uc_reg_read(uc, UC_X86_REG_RCX, &entry->regs.rcx);
uc_reg_read(uc, UC_X86_REG_RBX, &entry->regs.rbx);
uc_reg_read(uc, UC_X86_REG_RAX, &entry->regs.rax);
uc_reg_read(uc, UC_X86_REG_EFLAGS, &entry->regs.rflags);
entry->vip = entry->regs.rsi;
entry->handler_idx = entry->regs.rax;
entry->decrypt_key = entry->regs.rbx;
uc_err err;
if ((err = uc_mem_read(uc, entry->regs.rdi,
entry->vregs.raw, sizeof entry->vregs.raw)))
return err;
// copy virtual stack values...
for (auto idx = 0u; idx < sizeof(entry->vsp) / 8; ++idx)
if ((err = uc_mem_read(uc, entry->regs.rbp + (idx * 8),
&entry->vsp.qword[idx], sizeof entry->vsp.qword[idx])))
return err;
return UC_ERR_OK;
}
void emu_t::hook_code(uc_engine* uc, uint64_t address, uint32_t size, vm::emu_t* obj)
{
std::printf(">>> Tracing instruction at 0x%p, instruction size = 0x%x\n", address, size);
// grab JMP RDX/RCX <-- this register...
static const auto jmp_reg = obj->vm_entry[obj->vm_entry.size()]
.instr.operands[0]
.reg
.value;
static ZydisDecoder decoder;
static std::once_flag once;
static ZydisDecodedInstruction instr;
static std::uintptr_t reg_val = 0u;
// init zydis decoder just a single time...
std::call_once(once, [&]() -> void {
ZydisDecoderInit(&decoder,
ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64); });
if (address == obj->vm_entry[obj->vm_entry.size()].addr)
{
std::printf("stopped at jmp... addr = 0x%p\n", address);
std::getchar();
vmp2::entry_t new_entry;
if (!obj->create_entry(&new_entry))
{
std::printf("[!] failed to create new entry... exiting...\n");
exit(0);
}
obj->trace_entries->push_back(new_entry);
}
// if we are getting a callback for a JMP RCX/RDX instruction...
else if (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(
&decoder, reinterpret_cast<void*>(address), size, &instr)) &&
instr.mnemonic == ZYDIS_MNEMONIC_JMP &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].reg.value == jmp_reg)
{
switch (jmp_reg)
{
ZYDIS_REGISTER_RDX:
uc_reg_read(uc, UC_X86_REG_RDX, &reg_val);
break;
ZYDIS_REGISTER_RCX:
uc_reg_read(uc, UC_X86_REG_RCX, &reg_val);
break;
default:
std::printf("[!] invalid jump register...\n");
exit(0);
}
// checks to see if the address
// in JMP RDX/RCX is a vm handler address...
static const auto vm_handler_check =
[&](const vm::handler_t& vm_handler) -> bool
{ return vm_handler.address == reg_val; };
if (std::find_if(obj->vm_handlers.begin(), obj->vm_handlers.end(),
vm_handler_check) == obj->vm_handlers.end())
return;
std::printf("stopped at jmp... addr = 0x%p\n", address);
std::getchar();
vmp2::entry_t new_entry;
if (!obj->create_entry(&new_entry))
{
std::printf("[!] failed to create new entry... exiting...\n");
exit(0);
}
obj->trace_entries->push_back(new_entry);
}
}
bool emu_t::hook_mem_invalid(uc_engine* uc, uc_mem_type type,
uint64_t address, int size, int64_t value, vm::emu_t* obj)
{
switch (type)
{
default:
// return false to indicate we want to stop emulation
return false;
case UC_MEM_WRITE_UNMAPPED:
printf(">>> Missing memory is being WRITE at 0x%p, data size = %u, data value = 0x%p\n",
address, size, value);
return false;
case UC_MEM_READ_UNMAPPED:
printf(">>> Missing memory is being READ at 0x%p, data size = %u, data value = 0x%p\n",
address, size, value);
return false;
}
}
}

@ -6,6 +6,7 @@
#include <vm.h>
#include <functional>
#include <mutex>
#include <vmp2.hpp>
namespace vm
{
@ -15,12 +16,18 @@ namespace vm
public:
explicit emu_t(std::uint32_t vm_entry_rva,
std::uintptr_t image_base, std::uintptr_t module_base);
~emu_t();
bool init();
~emu_t();
bool get_trace(std::vector<vmp2::entry_t>& entries);
private:
uc_err create_entry(vmp2::entry_t* entry);
static void hook_code(uc_engine* uc, uint64_t address, uint32_t size, vm::emu_t* obj);
static bool hook_mem_invalid(uc_engine* uc, uc_mem_type type,
uint64_t address, int size, int64_t value, vm::emu_t* obj);
uc_engine* uc;
uc_hook trace;
uc_hook trace, trace1;
std::uintptr_t image_base, module_base;
std::uint32_t vm_entry_rva;
@ -28,61 +35,6 @@ namespace vm
zydis_routine_t vm_entry;
std::uintptr_t* vm_handler_table;
std::vector<vm::handler_t> vm_handlers;
// very janky work around to use classes & callbacks with unicorn... it is what it is...
callback_t jmp_hook =
[&, this](uc_engine* uc, uint64_t address, uint32_t size, void* user_data) -> void
{
// grab JMP RDX/RCX <-- this register...
static auto jmp_reg = vm_entry[
vm_entry.size() - 1].instr.operands[0].reg.value;
static ZydisDecoder decoder;
static std::once_flag once;
static ZydisDecodedInstruction instr;
static std::uintptr_t reg_val = 0u;
// init zydis decoder just a single time...
std::call_once(once, []() -> void {
ZydisDecoderInit(&decoder,
ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64); });
if (address == vm_entry[vm_entry.size() - 1].addr)
{
std::printf("stopped at jmp... addr = 0x%p\n", address);
std::getchar();
}
// if we are getting a callback for a JMP RCX/RDX instruction...
else if (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(
&decoder, reinterpret_cast<void*>(address), size, &instr)) &&
instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
instr.operands[0].reg.value == jmp_reg)
{
switch (jmp_reg)
{
ZYDIS_REGISTER_RDX:
uc_reg_read(uc, UC_X86_REG_RDX, &reg_val);
break;
ZYDIS_REGISTER_RCX:
uc_reg_read(uc, UC_X86_REG_RCX, &reg_val);
break;
default:
throw std::exception("invalid register to jump from...\n");
}
// checks to see if the address
// in JMP RDX/RCX is a vm handler address...
static const auto vm_handler_check =
[&](vm::handler_t& vm_handler) -> bool
{ return vm_handler.address == reg_val; };
if (std::find_if(vm_handlers.begin(), vm_handlers.end(),
vm_handler_check) == vm_handlers.end())
return;
std::printf("stopped at jmp... addr = 0x%p\n", address);
std::getchar();
}
};
std::vector<vmp2::entry_t>* trace_entries;
};
}

Binary file not shown.

@ -11,6 +11,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zydis", "dependencies\vmpro
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
DBG|x64 = DBG|x64
DBG|x86 = DBG|x86
Debug Kernel|x64 = Debug Kernel|x64
Debug Kernel|x86 = Debug Kernel|x86
Debug MD DLL|x64 = Debug MD DLL|x64
@ -37,6 +39,9 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.DBG|x64.ActiveCfg = Debug|x64
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.DBG|x64.Build.0 = Debug|x64
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.DBG|x86.ActiveCfg = Debug|x64
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.Debug Kernel|x64.ActiveCfg = Debug|x64
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.Debug Kernel|x64.Build.0 = Debug|x64
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.Debug Kernel|x86.ActiveCfg = Release|x64
@ -83,12 +88,15 @@ Global
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.Release|x64.ActiveCfg = Release|x64
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.Release|x64.Build.0 = Release|x64
{F0D51879-E659-4BD3-B688-7864DB3C82AA}.Release|x86.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.DBG|x64.ActiveCfg = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.DBG|x64.Build.0 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.DBG|x86.ActiveCfg = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x64.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x64.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x86.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug Kernel|x86.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x64.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x64.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x64.ActiveCfg = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x64.Build.0 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x86.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD DLL|x86.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MD|x64.ActiveCfg = Release|x64
@ -103,8 +111,8 @@ Global
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x64.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x86.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug MT|x86.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x64.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x64.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x64.ActiveCfg = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x64.Build.0 = DBG|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x86.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Debug|x86.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release Kernel|x64.ActiveCfg = Release|x64
@ -130,6 +138,10 @@ Global
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release|x64.ActiveCfg = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release|x64.Build.0 = Release|x64
{D0B6092A-9944-4F24-9486-4B7DAE372619}.Release|x86.ActiveCfg = Release|x64
{88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x64.ActiveCfg = Debug MT|x64
{88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x64.Build.0 = Debug MT|x64
{88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x86.ActiveCfg = Debug MT|Win32
{88A23124-5640-35A0-B890-311D7A67A7D2}.DBG|x86.Build.0 = Debug MT|Win32
{88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x64.ActiveCfg = Debug Kernel|x64
{88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x64.Build.0 = Debug Kernel|x64
{88A23124-5640-35A0-B890-311D7A67A7D2}.Debug Kernel|x64.Deploy.0 = Debug Kernel|x64

Loading…
Cancel
Save