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_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_isMemoryProtection; // Memory CRC32 protection
RyujinObfuscatorProcs m_strProceduresToObfuscate; // 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_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_isMemoryProtection; // Memory CRC32 protection
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate - FFI
std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate
// 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() {
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.
this->updateBasicBlocksContext();
//Insert stub for memory crc32 protection
this->insertMemoryProtection();
RyujinRunOncePass = FALSE;
}
//Update basic blocks view based on the new obfuscated

View File

@@ -12,6 +12,7 @@
#include "../Models/RyujinProcedure.hh"
#include "../Models/RyujinObfuscatorConfig.hh"
#include "../RyujinCore/BasicBlockerBuilder.hh"
#include "../Utils/RyujinCRC32Utils.hh"
class RyujinObfuscationCore {
@@ -31,6 +32,7 @@ private:
void insertVirtualization();
void insertAntiDebug();
void insertAntiDump();
void insertMemoryProtection();
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);
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\RyujinCore\BasicBlockerBuilder.hh" />
<ClInclude Include="Ryujin\RyujinCore\RyujinObfuscationCore.hh" />
<ClInclude Include="Ryujin\Utils\RyujinCRC32Utils.hh" />
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh" />
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh" />
</ItemGroup>
@@ -197,6 +198,7 @@
<ClCompile Include="Ryujin\Ryujin.cc" />
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" />
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc" />
<ClCompile Include="Ryujin\Utils\RyujinCRC32Utils.cc" />
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc" />
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc" />
</ItemGroup>

View File

@@ -63,6 +63,9 @@
<ClInclude Include="RyujinCore.hh">
<Filter>Ryujin</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Utils\RyujinCRC32Utils.hh">
<Filter>Ryujin\Utils</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="RyujinCore.cc">
@@ -86,6 +89,9 @@
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc">
<Filter>Ryujin\RyujinCore</Filter>
</ClCompile>
<ClCompile Include="Ryujin\Utils\RyujinCRC32Utils.cc">
<Filter>Ryujin\Utils</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<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_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_isMemoryProtection; // Memory CRC32 protection
RyujinObfuscatorProcs m_strProceduresToObfuscate; // Names of the procedures to obfuscate - FFI
std::vector<std::string> m_strdProceduresToObfuscate; // Names of the procedures to obfuscate