Added load delta and push order

These are necessary for lifting
xtremegamer1 2 years ago
parent 2cc88f60ab
commit 2a72cbffcd

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <vminstrs.hpp> #include <vminstrs.hpp>
#include <vmutils.hpp> #include <vmutils.hpp>
#include <array>
namespace vm { namespace vm {
class vmctx_t { class vmctx_t {
@ -11,12 +12,13 @@ class vmctx_t {
std::uintptr_t vm_entry_rva); std::uintptr_t vm_entry_rva);
bool init(); bool init();
const std::uintptr_t m_module_base, m_image_base, m_vm_entry_rva, const std::uintptr_t m_module_base, m_image_base, m_vm_entry_rva,
m_image_size; m_image_size, m_image_load_delta;
zydis_reg_t get_vip() const { return m_vip; } zydis_reg_t get_vip() const { return m_vip; }
zydis_reg_t get_vsp() const { return m_vsp; } zydis_reg_t get_vsp() const { return m_vsp; }
zydis_rtn_t get_vm_enter() const { return m_vm_entry; } zydis_rtn_t get_vm_enter() const { return m_vm_entry; }
const std::array<ZydisRegister, 16>& get_vmentry_push_order() const;
private: private:
/// <summary> /// <summary>
/// m_vip and m_vsp are set to the native registers used for them by the vm /// m_vip and m_vsp are set to the native registers used for them by the vm
@ -29,5 +31,8 @@ class vmctx_t {
/// the virtual machine enter flattened and deobfuscated... /// the virtual machine enter flattened and deobfuscated...
/// </summary> /// </summary>
zydis_rtn_t m_vm_entry; zydis_rtn_t m_vm_entry;
//using array container instead of c-style array in order to pass by reference.
std::array<ZydisRegister, 16> vmentry_push_order;
}; };
} // namespace vm } // namespace vm

@ -8,7 +8,8 @@ vmctx_t::vmctx_t(std::uintptr_t module_base,
: m_module_base(module_base), : m_module_base(module_base),
m_image_base(image_base), m_image_base(image_base),
m_vm_entry_rva(vm_entry_rva), m_vm_entry_rva(vm_entry_rva),
m_image_size(image_size) {} m_image_size(image_size),
m_image_load_delta(m_module_base - m_image_base) {}
bool vmctx_t::init() { bool vmctx_t::init() {
vm::utils::init(); vm::utils::init();
@ -20,6 +21,40 @@ bool vmctx_t::init() {
vm::utils::deobfuscate(m_vm_entry); vm::utils::deobfuscate(m_vm_entry);
//Get the order in which native registers are pushed
int push_index = 0;
for (const auto& instr : m_vm_entry)
{
if (instr.instr.mnemonic == ZYDIS_MNEMONIC_PUSH &&
instr.instr.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
vm::utils::is_64_bit_gp(instr.instr.operands[0].reg.value))
{
if (std::find(vmentry_push_order.begin(), vmentry_push_order.begin() + push_index,
instr.instr.operands[0].reg.value) != vmentry_push_order.begin() + push_index)
{
//Every register should only be pushed once
std::printf("Error initializing vmctx_t: vmenter pushes could not be parsed.\n");
vm::utils::print(m_vm_entry);
return false;
}
vmentry_push_order[push_index++] = instr.instr.operands[0].reg.value;
}
else if (instr.instr.mnemonic == ZYDIS_MNEMONIC_PUSHFQ)
{
if (std::find(vmentry_push_order.begin(), vmentry_push_order.begin() + push_index,
instr.instr.operands[0].reg.value) != vmentry_push_order.begin() + push_index)
{
// Same shit
std::printf("Error initializing vmctx_t: vmenter pushes could not be parsed.\n");
vm::utils::print(m_vm_entry);
return false;
}
vmentry_push_order[push_index++] = ZYDIS_REGISTER_RFLAGS;
}
if (push_index == 16)
break;
}
// find mov reg, [rsp+0x90]. this register will be VIP... // find mov reg, [rsp+0x90]. this register will be VIP...
const auto vip_fetch = std::find_if( const auto vip_fetch = std::find_if(
m_vm_entry.begin(), m_vm_entry.end(), m_vm_entry.begin(), m_vm_entry.end(),
@ -53,4 +88,8 @@ bool vmctx_t::init() {
m_vsp = vsp_fetch->instr.operands[0].reg.value; m_vsp = vsp_fetch->instr.operands[0].reg.value;
return true; return true;
} }
const std::array<ZydisRegister, 16>& vm::vmctx_t::get_vmentry_push_order() const
{
return vmentry_push_order;
}
} // namespace vm } // namespace vm
Loading…
Cancel
Save