feat: Working on the base for Memory CRC32 Protection

- Working on a new feature to allow users to protect obfuscated code with a memory protection mechanism, inspired by VMProtect, where the protector uses CRC32 to validate if a page was modified on disk or in memory.
- This is just the base to start building the feature. It’s still in development and I hope it evolves a lot.
This commit is contained in:
keowu
2025-07-19 22:06:32 -03:00
parent ac2d80c371
commit 0988e8e078
9 changed files with 87 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ public:
bool m_isAntiDebug; // The user wants to avoid debuggers use while running a binary protected by Ryujin bool m_isAntiDebug; // The user wants to avoid debuggers use while running a binary protected by Ryujin
bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress
bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary
bool m_isMemoryProtection; // Memory CRC32 protection
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate
std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate

View File

@@ -21,6 +21,7 @@ public:
bool m_isAntiDebug; // The user wants to avoid debuggers use while running a binary protected by Ryujin bool m_isAntiDebug; // The user wants to avoid debuggers use while running a binary protected by Ryujin
bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress
bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary
bool m_isMemoryProtection; // Memory CRC32 protection
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate - FFI RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate - FFI
std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate
// todo: passes // todo: passes

View File

@@ -1941,6 +1941,15 @@ void RyujinObfuscationCore::insertAntiDump() {
} }
void RyujinObfuscationCore::insertMemoryProtection() {
unsigned char ucTest[]{ 0xDE, 0xAD, 0xBE, 0xEF };
RyujinCRC32Utils crcTest;
std::printf("RyujinObfuscationCore::insertMemoryProtection.TEST: 0x%X\n", crcTest.crc32(ucTest, 4));
}
void RyujinObfuscationCore::updateBasicBlocksContext() { void RyujinObfuscationCore::updateBasicBlocksContext() {
auto new_obfuscated_opcodes = getProcessedProc().getUpdateOpcodes(); auto new_obfuscated_opcodes = getProcessedProc().getUpdateOpcodes();
@@ -1992,7 +2001,11 @@ BOOL RyujinObfuscationCore::Run(bool& RyujinRunOncePass) {
// Update our basic blocks context to rela 1-1 for the new obfuscated opcodes. // Update our basic blocks context to rela 1-1 for the new obfuscated opcodes.
this->updateBasicBlocksContext(); this->updateBasicBlocksContext();
//Insert stub for memory crc32 protection
this->insertMemoryProtection();
RyujinRunOncePass = FALSE; RyujinRunOncePass = FALSE;
} }
//Update basic blocks view based on the new obfuscated //Update basic blocks view based on the new obfuscated

View File

@@ -12,6 +12,7 @@
#include "../Models/RyujinProcedure.hh" #include "../Models/RyujinProcedure.hh"
#include "../Models/RyujinObfuscatorConfig.hh" #include "../Models/RyujinObfuscatorConfig.hh"
#include "../RyujinCore/BasicBlockerBuilder.hh" #include "../RyujinCore/BasicBlockerBuilder.hh"
#include "../Utils/RyujinCRC32Utils.hh"
class RyujinObfuscationCore { class RyujinObfuscationCore {
@@ -31,6 +32,7 @@ private:
void insertVirtualization(); void insertVirtualization();
void insertAntiDebug(); void insertAntiDebug();
void insertAntiDump(); void insertAntiDump();
void insertMemoryProtection();
void insertBreakDecompilers(asmjit::x86::Assembler& a); void insertBreakDecompilers(asmjit::x86::Assembler& a);
std::vector<uint8_t> fix_branch_near_far_short(uint8_t original_opcode, uint64_t jmp_address, uint64_t target_address); std::vector<uint8_t> fix_branch_near_far_short(uint8_t original_opcode, uint64_t jmp_address, uint64_t target_address);
uint32_t findOpcodeOffset(const uint8_t* data, size_t dataSize, const void* opcode, size_t opcodeSize); uint32_t findOpcodeOffset(const uint8_t* data, size_t dataSize, const void* opcode, size_t opcodeSize);

View File

@@ -0,0 +1,41 @@
#include "RyujinCRC32Utils.hh"
auto RyujinCRC32Utils::checksum_crc32gentab() -> void {
unsigned long poly = 0xEDB88320L;
for (int i = 0; i < 256; i++) {
unsigned long crc = i;
for (int j = 8; j > 0; j--) {
if (crc & 1) crc = (crc >> 1) ^ poly;
else crc >>= 1;
}
m_crc_tab[i] = crc;
}
}
auto RyujinCRC32Utils::checksum_crc32(unsigned char* block, unsigned int length) -> uint32_t {
register unsigned long crc = 0xFFFFFFFF;
for (unsigned long i = 0; i < length; i++) crc = ((crc >> 8) & 0x00FFFFFF) ^ m_crc_tab[(crc ^ *block++) & 0xFF];
return (crc ^ 0xFFFFFFFF);
}
auto RyujinCRC32Utils::crc32(unsigned char* block, unsigned int length) -> uint32_t {
if (!m_bInitialized) {
checksum_crc32gentab();
m_bInitialized = TRUE;
}
return checksum_crc32(block, length);
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include <Windows.h>
#include <cstdint>
class RyujinCRC32Utils {
private:
uint32_t m_crc_tab[256];
BOOL m_bInitialized = FALSE;
auto checksum_crc32gentab() -> void;
auto checksum_crc32(unsigned char* block, unsigned int length) -> uint32_t;
public:
auto crc32(unsigned char* block, unsigned int length) -> uint32_t;
};

View File

@@ -188,6 +188,7 @@
<ClInclude Include="Ryujin\Ryujin.hh" /> <ClInclude Include="Ryujin\Ryujin.hh" />
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh" /> <ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh" />
<ClInclude Include="Ryujin\RyujinCore\RyujinObfuscationCore.hh" /> <ClInclude Include="Ryujin\RyujinCore\RyujinObfuscationCore.hh" />
<ClInclude Include="Ryujin\Utils\RyujinCRC32Utils.hh" />
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh" /> <ClInclude Include="Ryujin\Utils\RyujinPESections.hh" />
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh" /> <ClInclude Include="Ryujin\Utils\RyujinUtils.hh" />
</ItemGroup> </ItemGroup>
@@ -197,6 +198,7 @@
<ClCompile Include="Ryujin\Ryujin.cc" /> <ClCompile Include="Ryujin\Ryujin.cc" />
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" /> <ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" />
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc" /> <ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc" />
<ClCompile Include="Ryujin\Utils\RyujinCRC32Utils.cc" />
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc" /> <ClCompile Include="Ryujin\Utils\RyujinPESections.cc" />
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc" /> <ClCompile Include="Ryujin\Utils\RyujinUtils.cc" />
</ItemGroup> </ItemGroup>

View File

@@ -63,6 +63,9 @@
<ClInclude Include="RyujinCore.hh"> <ClInclude Include="RyujinCore.hh">
<Filter>Ryujin</Filter> <Filter>Ryujin</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Ryujin\Utils\RyujinCRC32Utils.hh">
<Filter>Ryujin\Utils</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="RyujinCore.cc"> <ClCompile Include="RyujinCore.cc">
@@ -86,6 +89,9 @@
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc"> <ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc">
<Filter>Ryujin\RyujinCore</Filter> <Filter>Ryujin\RyujinCore</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Ryujin\Utils\RyujinCRC32Utils.cc">
<Filter>Ryujin\Utils</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Ryujin.def"> <None Include="Ryujin.def">

View File

@@ -23,6 +23,7 @@ public:
bool m_isAntiDebug; // The user wants to avoid debuggers use while running a binary protected by Ryujin bool m_isAntiDebug; // The user wants to avoid debuggers use while running a binary protected by Ryujin
bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress bool m_isTrollRerversers; // The user wants to trick and use a special feature to troll reversers when their debugs be detected making they loose all the progress
bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary bool m_isAntiDump; // Enable Anti Dump technic for Ryujin protected binary
bool m_isMemoryProtection; // Memory CRC32 protection
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate - FFI RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate - FFI
std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate