From 06d5d8751b68aa528d62dff02955a3292ff91cdd Mon Sep 17 00:00:00 2001 From: keowu Date: Thu, 19 Jun 2025 18:37:41 -0300 Subject: [PATCH] feat: Base for implementing the "Encrypt obfuscated code" feature. - Started working on the logic to obfuscate opcodes in the Ryujin section to prevent static analysis. This is just the initial groundwork for the feature. --- RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc | 24 +++++++++++++++---- RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh | 2 +- .../RyujinCore/RyujinObfuscationCore.cc | 8 +++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc index 7b1dd47..86d1f83 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc +++ b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc @@ -224,7 +224,25 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) { } // Encrypt all obfuscated code - if (config.m_isEncryptObfuscatedCode) todoAction(); + /* + Para "encriptar" todo o código ofuscado: + 1 - Vamos criptografar byte por byte do nosso vector que carrega os novos opcodes para a section. + 2 - Vamos inserir a stub que descriptografa e seus referidos opcodes no vector de novos opcodes. + 3 - Vamos substituir o entrypoint original pela nossa stub. e nossa stub vai saltar no entrypoint original após desofuscar. + 4 - Teremos o código pronto a ser devidamente executado. + */ + if (config.m_isEncryptObfuscatedCode) { + + // Logica para criptografar código executável. + for (auto& byte : opcodesWithRelocsFixed) + byte ^= 0x37; // TODO: Make this better - XOR não é criptografia. + + // Log + std::printf("[!] OEP: %llx - Inserting Decryption code routine on: %llx\n", imgNt->OptionalHeader.AddressOfEntryPoint, offsetVA); + + + + } //Process new opcodes peSections.ProcessOpcodesNewSection(opcodesWithRelocsFixed); @@ -263,7 +281,3 @@ void Ryujin::listRyujinProcedures() { std::printf("==========================\n"); } - -Ryujin::~Ryujin() { - -} diff --git a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh index 07ad19b..f95dcf3 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh +++ b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh @@ -28,7 +28,7 @@ public: Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath); bool run(const RyujinObfuscatorConfig& config); void listRyujinProcedures(); - ~Ryujin(); + ~Ryujin() { } }; diff --git a/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc b/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc index 1ce183d..d1332e3 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc +++ b/RyujinConsole/RyujinConsole/Ryujin/RyujinCore/RyujinObfuscationCore.cc @@ -1194,18 +1194,26 @@ void RyujinObfuscationCore::InsertMiniVmEnterProcedureAddress(uintptr_t imageBas //Inserting Ryujin MiniVm Address on each vm entry reference if (m_config.m_isVirtualized) { + // Data and sizes of the opcodes to be worked on auto size = new_opcodes.size(); auto data = new_opcodes.data(); + // Signature of the pattern that we must replace with the referenced RVA of our MiniVmEntry unsigned char ucSignature[]{ 0x48, 0x05, 0x88, 0x00, 0x00, 0x00 }; + // Let's search for the pattern to replace for (auto i = 0; i < size; i++) + // If we find it if (std::memcmp(&*(data + i), ucSignature, 6) == 0) { + // Just log it std::printf("[OK] Inserting MiniVmEnter at %llx\n", imageBase + virtualAddress + i); + // We will remove the value 0x88 and ensure there are no other offsets std::memset(&*(data + i + 2), 0, 4); + + // Finally, we will insert our new RVA for the MiniVmEntry procedure std::memcpy(&*(data + i + 2), &virtualAddress, sizeof(uint32_t)); }