You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
2.6 KiB
115 lines
2.6 KiB
#include "vmctx.h"
|
|
|
|
namespace vm
|
|
{
|
|
vmctx_t::vmctx_t(
|
|
vmp2::file_header* file_header,
|
|
vmp2::entry_t* entry_list,
|
|
std::vector<vm::handler_t>& vm_handlers,
|
|
std::uintptr_t module_base,
|
|
std::uintptr_t image_base
|
|
)
|
|
: module_base(module_base),
|
|
image_base(image_base),
|
|
entry_list(entry_list),
|
|
file_header(file_header),
|
|
vm_handlers(vm_handlers),
|
|
idx(0)
|
|
{}
|
|
|
|
std::pair<std::string, const vmp2::entry_t*> vmctx_t::step() const
|
|
{
|
|
if (idx >= file_header->entry_count)
|
|
return {};
|
|
|
|
const auto vm_handler = &vm_handlers[entry_list[idx].handler_idx];
|
|
|
|
if (vm_handler->imm_size)
|
|
{
|
|
const auto operand = get_imm(file_header->advancement,
|
|
entry_list[idx].vip, vm_handler->imm_size / 8);
|
|
|
|
auto transforms = vm_handler->transforms;
|
|
auto [decrypted_operand, rolling_key] =
|
|
vm::decrypt_operand(transforms,
|
|
operand, entry_list[idx].decrypt_key);
|
|
|
|
if (vm_handler->profile)
|
|
{
|
|
if (vm_handler->profile->extention ==
|
|
vm::handler::extention_t::sign_extend)
|
|
{
|
|
switch (vm_handler->imm_size)
|
|
{
|
|
case 8:
|
|
{
|
|
if ((u8)(decrypted_operand >> 7))
|
|
decrypted_operand += ~0xFFull;
|
|
break;
|
|
}
|
|
case 16:
|
|
{
|
|
if ((u16)(decrypted_operand >> 15))
|
|
decrypted_operand += ~0xFFFFull;
|
|
break;
|
|
}
|
|
case 32:
|
|
{
|
|
if ((u32)(decrypted_operand >> 31))
|
|
decrypted_operand += ~0xFFFFFFFFull;
|
|
break;
|
|
}
|
|
default:
|
|
throw std::invalid_argument(
|
|
"invalid imm size for sign extention...\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
char buff[256];
|
|
if (vm_handler->profile)
|
|
{
|
|
snprintf(buff, sizeof buff, "%s 0x%p",
|
|
vm_handler->profile->name, decrypted_operand);
|
|
}
|
|
else
|
|
{
|
|
snprintf(buff, sizeof buff, "UNK(%d) 0x%p",
|
|
entry_list[idx].handler_idx, decrypted_operand);
|
|
}
|
|
|
|
return { buff, &entry_list[idx++] };
|
|
}
|
|
|
|
if (vm_handler->profile)
|
|
return { vm_handler->profile->name, &entry_list[idx++] };
|
|
|
|
char buff[256];
|
|
snprintf(buff, sizeof buff, "UNK(%d)", entry_list[idx++].handler_idx);
|
|
return { buff, &entry_list[idx++] };
|
|
}
|
|
|
|
std::uintptr_t vmctx_t::get_imm(vmp2::exec_type_t exec_type_t,
|
|
std::uint32_t vip_offset, std::uint8_t imm_size) const
|
|
{
|
|
std::uintptr_t operand = 0u;
|
|
if (file_header->advancement == vmp2::exec_type_t::forward)
|
|
{
|
|
const auto operand_ptr =
|
|
reinterpret_cast<void*>((entry_list[idx].vip -
|
|
file_header->module_base) + module_base);
|
|
|
|
memcpy(&operand, operand_ptr, imm_size);
|
|
}
|
|
else
|
|
{
|
|
const auto operand_ptr =
|
|
reinterpret_cast<void*>(((entry_list[idx].vip -
|
|
file_header->module_base) + module_base) - imm_size);
|
|
|
|
memcpy(&operand, operand_ptr, imm_size);
|
|
}
|
|
|
|
return operand;
|
|
}
|
|
} |