diff --git a/include/transform.hpp b/include/transform.hpp index 3dc6f11..b6d568f 100644 --- a/include/transform.hpp +++ b/include/transform.hpp @@ -48,6 +48,7 @@ namespace vm enum class type { + generic0, rolling_key, generic1, generic2, diff --git a/src/vm.cpp b/src/vm.cpp index de43506..7a76cb4 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -5,12 +5,23 @@ namespace vm std::pair 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); @@ -62,6 +73,10 @@ namespace vm 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].mnemonic = transform::inverse[transforms[transform::type::rolling_key].mnemonic]; @@ -89,6 +104,7 @@ namespace vm 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]; @@ -138,6 +154,16 @@ namespace vm 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 }; } @@ -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... transforms[transform::type::rolling_key] = 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; transforms[transform::type::update_key] = instr_copy; - if (key_transform == vm_handler.end()) - return false; - // three generic transformations... 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(), [](const zydis_instr_t& instr_data) -> bool @@ -441,7 +483,7 @@ namespace vm if (generic_transform == vm_handler.end()) return false; - transforms[(transform::type)(idx + 1)] = generic_transform->instr; + transforms[(transform::type)(idx)] = generic_transform->instr; } return true; diff --git a/src/vmprofiler.vcxproj b/src/vmprofiler.vcxproj index 27bc20e..b22d99f 100644 --- a/src/vmprofiler.vcxproj +++ b/src/vmprofiler.vcxproj @@ -1,6 +1,10 @@ + + DBG + x64 + Release x64 @@ -22,6 +26,13 @@ true Unicode + + StaticLibrary + false + v142 + true + Unicode + @@ -30,11 +41,18 @@ + + + false $(ProjectDir);$(ProjectDir)..\dependencies\zydis\msvc;$(ProjectDir)..\dependencies\zydis\dependencies\zycore\include;$(ProjectDir)..\include;$(ProjectDir)..\dependencies\zydis\include;$(IncludePath) + + false + $(ProjectDir);$(ProjectDir)..\dependencies\zydis\msvc;$(ProjectDir)..\dependencies\zydis\dependencies\zycore\include;$(ProjectDir)..\include;$(ProjectDir)..\dependencies\zydis\include;$(IncludePath) + Level3 @@ -45,6 +63,30 @@ true stdcpplatest Disabled + MultiThreadedDLL + + + Console + true + true + true + $(ProjectDir)..\libs\*;%(AdditionalDependencies) + + + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpplatest + Disabled + MultiThreadedDebugDLL Console diff --git a/src/vmutils.cpp b/src/vmutils.cpp index 14d4847..294c137 100644 --- a/src/vmutils.cpp +++ b/src/vmutils.cpp @@ -124,7 +124,7 @@ namespace vm return to64(a) == to64(b); } } - + void print(const ZydisDecodedInstruction& instr) { char buffer[256]; @@ -156,31 +156,31 @@ namespace vm { switch (instr.mnemonic) { - case ZYDIS_MNEMONIC_JB: - case ZYDIS_MNEMONIC_JBE: - case ZYDIS_MNEMONIC_JCXZ: - case ZYDIS_MNEMONIC_JECXZ: - case ZYDIS_MNEMONIC_JKNZD: - case ZYDIS_MNEMONIC_JKZD: - case ZYDIS_MNEMONIC_JL: - case ZYDIS_MNEMONIC_JLE: - case ZYDIS_MNEMONIC_JMP: - case ZYDIS_MNEMONIC_JNB: - case ZYDIS_MNEMONIC_JNBE: - case ZYDIS_MNEMONIC_JNL: - case ZYDIS_MNEMONIC_JNLE: - case ZYDIS_MNEMONIC_JNO: - case ZYDIS_MNEMONIC_JNP: - case ZYDIS_MNEMONIC_JNS: - case ZYDIS_MNEMONIC_JNZ: - case ZYDIS_MNEMONIC_JO: - case ZYDIS_MNEMONIC_JP: - case ZYDIS_MNEMONIC_JRCXZ: - case ZYDIS_MNEMONIC_JS: - case ZYDIS_MNEMONIC_JZ: - return true; - default: - break; + case ZYDIS_MNEMONIC_JB: + case ZYDIS_MNEMONIC_JBE: + case ZYDIS_MNEMONIC_JCXZ: + case ZYDIS_MNEMONIC_JECXZ: + case ZYDIS_MNEMONIC_JKNZD: + case ZYDIS_MNEMONIC_JKZD: + case ZYDIS_MNEMONIC_JL: + case ZYDIS_MNEMONIC_JLE: + case ZYDIS_MNEMONIC_JMP: + case ZYDIS_MNEMONIC_JNB: + case ZYDIS_MNEMONIC_JNBE: + case ZYDIS_MNEMONIC_JNL: + case ZYDIS_MNEMONIC_JNLE: + case ZYDIS_MNEMONIC_JNO: + case ZYDIS_MNEMONIC_JNP: + case ZYDIS_MNEMONIC_JNS: + case ZYDIS_MNEMONIC_JNZ: + case ZYDIS_MNEMONIC_JO: + case ZYDIS_MNEMONIC_JP: + case ZYDIS_MNEMONIC_JRCXZ: + case ZYDIS_MNEMONIC_JS: + case ZYDIS_MNEMONIC_JZ: + return true; + default: + break; } return false; } @@ -190,7 +190,7 @@ namespace vm ZydisDecoder decoder; ZydisDecodedInstruction instr; ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_ADDRESS_WIDTH_64); - + while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, reinterpret_cast( routine_addr), 0x1000, &instr))) { @@ -233,14 +233,14 @@ namespace vm { switch (op.type) { - case ZYDIS_OPERAND_TYPE_MEMORY: - { - return reg::compare(op.mem.base, reg) || reg::compare(op.mem.index, reg); - } - case ZYDIS_OPERAND_TYPE_REGISTER: - { - return reg::compare(op.reg.value, reg); - } + case ZYDIS_OPERAND_TYPE_MEMORY: + { + return reg::compare(op.mem.base, reg) || reg::compare(op.mem.index, reg); + } + case ZYDIS_OPERAND_TYPE_REGISTER: + { + return reg::compare(op.reg.value, reg); + } } return false; @@ -298,7 +298,7 @@ namespace vm for (const auto& instr_data : routine) { - if (routine.empty() || routine.size() == 1 || + if (routine.empty() || routine.size() == 1 || instr_data.instr.mnemonic == ZYDIS_MNEMONIC_JMP) continue; @@ -330,5 +330,5 @@ namespace vm } } } - } + } } \ No newline at end of file