|
|
@ -5,12 +5,23 @@ namespace vm
|
|
|
|
std::pair<std::uint64_t, std::uint64_t> decrypt_operand(transform::map_t& transforms,
|
|
|
|
std::pair<std::uint64_t, std::uint64_t> decrypt_operand(transform::map_t& transforms,
|
|
|
|
std::uint64_t operand, std::uint64_t rolling_key)
|
|
|
|
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 key_decrypt = &transforms[transform::type::rolling_key];
|
|
|
|
const auto generic_decrypt_1 = &transforms[transform::type::generic1];
|
|
|
|
const auto generic_decrypt_1 = &transforms[transform::type::generic1];
|
|
|
|
const auto generic_decrypt_2 = &transforms[transform::type::generic2];
|
|
|
|
const auto generic_decrypt_2 = &transforms[transform::type::generic2];
|
|
|
|
const auto generic_decrypt_3 = &transforms[transform::type::generic3];
|
|
|
|
const auto generic_decrypt_3 = &transforms[transform::type::generic3];
|
|
|
|
const auto update_key = &transforms[transform::type::update_key];
|
|
|
|
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...
|
|
|
|
// apply transformation with rolling decrypt key...
|
|
|
|
operand = transform::apply(key_decrypt->operands[0].size,
|
|
|
|
operand = transform::apply(key_decrypt->operands[0].size,
|
|
|
|
key_decrypt->mnemonic, operand, rolling_key);
|
|
|
|
key_decrypt->mnemonic, operand, rolling_key);
|
|
|
@ -62,6 +73,10 @@ namespace vm
|
|
|
|
|
|
|
|
|
|
|
|
void inverse_transforms(transform::map_t& transforms, transform::map_t& inverse)
|
|
|
|
void inverse_transforms(transform::map_t& transforms, transform::map_t& inverse)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
inverse[transform::type::generic0] = transforms[transform::type::generic0];
|
|
|
|
|
|
|
|
inverse[transform::type::generic0].mnemonic =
|
|
|
|
|
|
|
|
transform::inverse[transforms[transform::type::generic0].mnemonic];
|
|
|
|
|
|
|
|
|
|
|
|
inverse[transform::type::rolling_key] = transforms[transform::type::rolling_key];
|
|
|
|
inverse[transform::type::rolling_key] = transforms[transform::type::rolling_key];
|
|
|
|
inverse[transform::type::rolling_key].mnemonic =
|
|
|
|
inverse[transform::type::rolling_key].mnemonic =
|
|
|
|
transform::inverse[transforms[transform::type::rolling_key].mnemonic];
|
|
|
|
transform::inverse[transforms[transform::type::rolling_key].mnemonic];
|
|
|
@ -89,6 +104,7 @@ namespace vm
|
|
|
|
transform::map_t inverse;
|
|
|
|
transform::map_t inverse;
|
|
|
|
inverse_transforms(transforms, 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 key_decrypt = &inverse[transform::type::rolling_key];
|
|
|
|
const auto generic_decrypt_1 = &inverse[transform::type::generic1];
|
|
|
|
const auto generic_decrypt_1 = &inverse[transform::type::generic1];
|
|
|
|
const auto generic_decrypt_2 = &inverse[transform::type::generic2];
|
|
|
|
const auto generic_decrypt_2 = &inverse[transform::type::generic2];
|
|
|
@ -138,6 +154,16 @@ namespace vm
|
|
|
|
operand = transform::apply(key_decrypt->operands[0].size,
|
|
|
|
operand = transform::apply(key_decrypt->operands[0].size,
|
|
|
|
key_decrypt->mnemonic, operand, rolling_key);
|
|
|
|
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 };
|
|
|
|
return { operand, rolling_key };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -413,6 +439,25 @@ namespace vm
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (key_transform == vm_handler.end())
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// look for a primer/instruction that alters RAX prior to the 5 transformations...
|
|
|
|
|
|
|
|
auto generic0 = std::find_if(imm_fetch + 1, key_transform,
|
|
|
|
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return util::reg::compare(
|
|
|
|
|
|
|
|
instr_data.instr.operands[0].reg.value, ZYDIS_REGISTER_RAX) &&
|
|
|
|
|
|
|
|
!util::reg::compare(instr_data.instr.operands[1].reg.value, ZYDIS_REGISTER_RBX);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ZydisDecodedInstruction nogeneric0;
|
|
|
|
|
|
|
|
nogeneric0.mnemonic = ZYDIS_MNEMONIC_INVALID;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
transforms[transform::type::generic0] =
|
|
|
|
|
|
|
|
generic0 != key_transform ? generic0->instr : nogeneric0;
|
|
|
|
|
|
|
|
|
|
|
|
// last transformation is the same as the first except src and dest are swwapped...
|
|
|
|
// last transformation is the same as the first except src and dest are swwapped...
|
|
|
|
transforms[transform::type::rolling_key] = key_transform->instr;
|
|
|
|
transforms[transform::type::rolling_key] = key_transform->instr;
|
|
|
|
auto instr_copy = key_transform->instr;
|
|
|
|
auto instr_copy = key_transform->instr;
|
|
|
@ -420,13 +465,10 @@ namespace vm
|
|
|
|
instr_copy.operands[1].reg.value = key_transform->instr.operands[0].reg.value;
|
|
|
|
instr_copy.operands[1].reg.value = key_transform->instr.operands[0].reg.value;
|
|
|
|
transforms[transform::type::update_key] = instr_copy;
|
|
|
|
transforms[transform::type::update_key] = instr_copy;
|
|
|
|
|
|
|
|
|
|
|
|
if (key_transform == vm_handler.end())
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// three generic transformations...
|
|
|
|
// three generic transformations...
|
|
|
|
auto generic_transform = key_transform;
|
|
|
|
auto generic_transform = key_transform;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto idx = 0u; idx < 3; ++idx)
|
|
|
|
for (auto idx = 2u; idx < 5; ++idx)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
generic_transform = std::find_if(++generic_transform, vm_handler.end(),
|
|
|
|
generic_transform = std::find_if(++generic_transform, vm_handler.end(),
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
|
[](const zydis_instr_t& instr_data) -> bool
|
|
|
@ -441,7 +483,7 @@ namespace vm
|
|
|
|
if (generic_transform == vm_handler.end())
|
|
|
|
if (generic_transform == vm_handler.end())
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
transforms[(transform::type)(idx + 1)] = generic_transform->instr;
|
|
|
|
transforms[(transform::type)(idx)] = generic_transform->instr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|