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.
vmprofiler/src/vminstrs.cpp

191 lines
6.0 KiB

#include <vmprofiler.hpp>
namespace vm
{
namespace instrs
{
std::pair<std::uint64_t, std::uint64_t> decrypt_operand(transform::map_t& transforms,
std::uint64_t operand, std::uint64_t rolling_key)
{
const auto generic_decrypt_0 = &transforms[transform::type::generic0];
const auto key_decrypt = &transforms[transform::type::rolling_key];
const auto generic_decrypt_1 = &transforms[transform::type::generic1];
const auto generic_decrypt_2 = &transforms[transform::type::generic2];
const auto generic_decrypt_3 = &transforms[transform::type::generic3];
const auto update_key = &transforms[transform::type::update_key];
if (generic_decrypt_0->mnemonic != ZYDIS_MNEMONIC_INVALID)
{
operand = transform::apply(
generic_decrypt_0->operands[0].size,
generic_decrypt_0->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_0) ?
generic_decrypt_0->operands[1].imm.value.u : 0);
}
// apply transformation with rolling decrypt key...
operand = transform::apply(key_decrypt->operands[0].size,
key_decrypt->mnemonic, operand, rolling_key);
// apply three generic transformations...
{
operand = transform::apply(
generic_decrypt_1->operands[0].size,
generic_decrypt_1->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_1) ?
generic_decrypt_1->operands[1].imm.value.u : 0);
operand = transform::apply(
generic_decrypt_2->operands[0].size,
generic_decrypt_2->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_2) ?
generic_decrypt_2->operands[1].imm.value.u : 0);
operand = transform::apply(
generic_decrypt_3->operands[0].size,
generic_decrypt_3->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_3) ?
generic_decrypt_3->operands[1].imm.value.u : 0);
}
// update rolling key...
auto result = transform::apply(update_key->operands[0].size,
update_key->mnemonic, rolling_key, operand);
// update decryption key correctly...
switch (update_key->operands[0].size)
{
case 8:
rolling_key = (rolling_key & ~0xFFull) + result;
break;
case 16:
rolling_key = (rolling_key & ~0xFFFFull) + result;
break;
default:
rolling_key = result;
break;
}
return { operand, rolling_key };
}
std::pair<std::uint64_t, std::uint64_t> encrypt_operand(transform::map_t& transforms,
std::uint64_t operand, std::uint64_t rolling_key)
{
transform::map_t inverse;
inverse_transforms(transforms, inverse);
const auto generic_decrypt_0 = &inverse[transform::type::generic0];
const auto key_decrypt = &inverse[transform::type::rolling_key];
const auto generic_decrypt_1 = &inverse[transform::type::generic1];
const auto generic_decrypt_2 = &inverse[transform::type::generic2];
const auto generic_decrypt_3 = &inverse[transform::type::generic3];
const auto update_key = &inverse[transform::type::update_key];
auto result = transform::apply(update_key->operands[0].size,
update_key->mnemonic, rolling_key, operand);
// make sure we update the rolling decryption key correctly...
switch (update_key->operands[0].size)
{
case 8:
rolling_key = (rolling_key & ~0xFFull) + result;
break;
case 16:
rolling_key = (rolling_key & ~0xFFFFull) + result;
break;
default:
rolling_key = result;
break;
}
{
operand = transform::apply(
generic_decrypt_3->operands[0].size,
generic_decrypt_3->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_3) ?
generic_decrypt_3->operands[1].imm.value.u : 0);
operand = transform::apply(
generic_decrypt_2->operands[0].size,
generic_decrypt_2->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_2) ?
generic_decrypt_2->operands[1].imm.value.u : 0);
operand = transform::apply(
generic_decrypt_1->operands[0].size,
generic_decrypt_1->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_1) ?
generic_decrypt_1->operands[1].imm.value.u : 0);
}
operand = transform::apply(key_decrypt->operands[0].size,
key_decrypt->mnemonic, operand, rolling_key);
if (generic_decrypt_0->mnemonic != ZYDIS_MNEMONIC_INVALID)
{
operand = transform::apply(
generic_decrypt_0->operands[0].size,
generic_decrypt_0->mnemonic, operand,
// check to see if this instruction has an IMM...
transform::has_imm(generic_decrypt_0) ?
generic_decrypt_0->operands[1].imm.value.u : 0);
}
return { operand, rolling_key };
}
bool get_rva_decrypt(
const zydis_routine_t& vm_entry, std::vector<zydis_decoded_instr_t>& transform_instrs)
{
//
// find mov esi, [rsp+0xA0]
//
auto result = std::find_if(vm_entry.begin(), vm_entry.end(),
[](const zydis_instr_t& instr_data) -> bool
{
if (instr_data.instr.mnemonic == ZYDIS_MNEMONIC_MOV &&
instr_data.instr.operand_count == 2 &&
instr_data.instr.operands[0].reg.value == ZYDIS_REGISTER_ESI &&
instr_data.instr.operands[1].mem.base == ZYDIS_REGISTER_RSP &&
instr_data.instr.operands[1].mem.disp.has_displacement &&
instr_data.instr.operands[1].mem.disp.value == 0xA0)
return true;
return false;
}
);
if (result == vm_entry.end())
return false;
//
// find the next three instruction with ESI as the dest...
//
for (auto idx = 0u; idx < 3; ++idx)
{
result = std::find_if(++result, vm_entry.end(),
[](const zydis_instr_t& instr_data) -> bool
{
return instr_data.instr.operands[0].reg.value == ZYDIS_REGISTER_ESI;
}
);
if (result == vm_entry.end())
return false;
transform_instrs.push_back(result->instr);
}
return true;
}
}
}