feat: Finalize memory protection logic, add GUI/CLI options, and fix README typos

- Added the original source code that generates the memory protection stub as a comment in the stub.
- Added a memory protection flag to the CLI and an option to the GUI.
- Improved CLI help text to be more detailed and explanatory.
- Updated README.md.
This commit is contained in:
keowu
2025-07-25 20:30:20 -03:00
parent b8a571871d
commit 487f061d6c
5 changed files with 158 additions and 2 deletions

View File

@@ -19,7 +19,7 @@
- Troll Reversers(Exclusive)
- Anti-Dump
- Anti-Disassembly + Anti-Decompiler
- Memory Protection(CRC32 - Planned - **TODO**)
- Memory Protection(CRC32)
- Custom Passes(Planned - **TODO**)
---

View File

@@ -24,6 +24,10 @@ Options:
--iat Enable IAT obfuscation
--random-section Use random PE section
--keep-original Keep original code (don't remove it)
--AntiDebug Inserts anti-debugging capabilities and terminates the protected binary if a debugger is detected.
--Troll Crashes the entire OS if a debugger is detected (requires --AntiDebug).
--AntiDump Inserts anti-dump mechanisms that break the binary in memory, making dumps harder to analyze.
--MemoryProtection Protects obfuscated code against in-memory or on-disk patching.
--procs <comma,separated,names> Procedures to obfuscate (default: main, invoke_main, ...)
--help Show this help message
@@ -87,6 +91,7 @@ auto main(int argc, char* argv[]) -> int {
config.m_isTrollRerversers = has_flag(args, "--troll");
config.m_isAntiDebug = has_flag(args, "--AntiDebug");
config.m_isAntiDump = has_flag(args, "--AntiDump");
config.m_isMemoryProtection = has_flag(args, "--MemoryProtection");
if (has_flag(args, "--procs")) {
auto rawList = args["--procs"];

View File

@@ -1990,7 +1990,144 @@ void RyujinObfuscationCore::insertMemoryProtection() {
std::vector<unsigned char> memoryProtectionShellcode = {
/*
TODO
#pragma optimize("", off)
__declspec(noinline) __declspec(safebuffers) void RyujinMemoryCrc32Protection() {
#ifdef _M_X64
auto* peb = reinterpret_cast<PEB*>(__readgsqword(0x60));
#else
auto* peb = reinterpret_cast<PEB*>(__readfsdword(0x30));
#endif
if (!peb || !peb->ImageBaseAddress || !peb->Ldr) return;
auto* base = reinterpret_cast<BYTE*>(peb->ImageBaseAddress);
auto* dos = reinterpret_cast<IMAGE_DOS_HEADER*>(base);
if (dos->e_magic != IMAGE_DOS_SIGNATURE) return;
auto* nt = reinterpret_cast<IMAGE_NT_HEADERS*>(base + dos->e_lfanew);
if (nt->Signature != IMAGE_NT_SIGNATURE) return;
auto* section = IMAGE_FIRST_SECTION(nt);
char ryujinName[8] { '.', 'R', 'y', 'u', 'j', 'i', 'n', 0 };
IMAGE_SECTION_HEADER* ryujin = nullptr;
for (int i = 0; i < nt->FileHeader.NumberOfSections; ++i, ++section) {
bool isMatch = true;
for (int j = 0; j < 8; ++j)
if (section->Name[j] != ryujinName[j]) {
isMatch = false;
break;
}
if (isMatch) {
ryujin = section;
break;
}
}
if (!ryujin) return;
wchar_t ntdllStr[] { 'n','t','d','l','l','.','d','l','l', 0 };
char ntTermStr[] { 'N','t','T','e','r','m','i','n','a','t','e','P','r','o','c','e','s','s', 0 };
BYTE* ntdllBase = nullptr;
for (auto* link = peb->Ldr->InMemoryOrderModuleList.Flink; link != &peb->Ldr->InMemoryOrderModuleList; link = link->Flink) {
auto* entry = CONTAINING_RECORD(link, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
if (!entry->BaseDllName.Buffer) continue;
auto* modName = entry->BaseDllName.Buffer;
auto* target = ntdllStr;
bool match = true;
for (; *target && *modName; ++target, ++modName) {
wchar_t ca = (*modName >= 'A' && *modName <= 'Z') ? *modName + 0x20 : *modName;
wchar_t cb = (*target >= 'A' && *target <= 'Z') ? *target + 0x20 : *target;
if (ca != cb) { match = false; break; }
}
if (match && !*target && !*modName) {
ntdllBase = reinterpret_cast<BYTE*>(entry->DllBase);
break;
}
}
if (!ntdllBase) return;
auto* dosHdr = reinterpret_cast<IMAGE_DOS_HEADER*>(ntdllBase);
auto* ntHdr = reinterpret_cast<IMAGE_NT_HEADERS*>(ntdllBase + dosHdr->e_lfanew);
auto& dir = ntHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (!dir.VirtualAddress) return;
auto* exportDir = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(ntdllBase + dir.VirtualAddress);
auto* names = reinterpret_cast<DWORD*>(ntdllBase + exportDir->AddressOfNames);
auto* ordinals = reinterpret_cast<WORD*>(ntdllBase + exportDir->AddressOfNameOrdinals);
auto* functions = reinterpret_cast<DWORD*>(ntdllBase + exportDir->AddressOfFunctions);
NtTerminateProcess_t pNtTerminate = nullptr;
for (DWORD i = 0; i < exportDir->NumberOfNames; ++i) {
const char* fname = reinterpret_cast<const char*>(ntdllBase + names[i]);
bool match = true;
for (int j = 0; ntTermStr[j] || fname[j]; ++j)
if (ntTermStr[j] != fname[j]) { match = false; break; }
if (match) {
pNtTerminate = reinterpret_cast<NtTerminateProcess_t>(
ntdllBase + functions[ordinals[i]]);
break;
}
}
if (pNtTerminate) {
const uint8_t* data = base + ryujin->VirtualAddress;
uint32_t crc = 0xFFFFFFFF;
for (size_t i = 0; i < ryujin->NumberOfLinenumbers; ++i) {
crc ^= data[i];
for (int j = 0; j < 8; ++j) {
if (crc & 1)
crc = (crc >> 1) ^ 0xB0B0C400;
else
crc >>= 1;
}
}
auto crcvalue = crc ^ 0xFFFFFFFF;
if (ryujin->PointerToLinenumbers != crcvalue)
pNtTerminate(reinterpret_cast<HANDLE>(-1), crcvalue);
}
}
#pragma optimize("", on)
*/
0x48, 0x81, 0xEC, 0x58, 0x01, 0x00, 0x00, 0x65, 0x48, 0x8B, 0x04, 0x25,
0x60, 0x00, 0x00, 0x00, 0x48, 0x89, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00,

View File

@@ -206,6 +206,13 @@ bool RyujinApp::OnInit() {
);
m_isMemoryProtection = DrawnStyledCheckbox(
panel,
"Memory Protection"
);
optionsSizer->Add(
m_virtualize
@@ -250,6 +257,11 @@ bool RyujinApp::OnInit() {
m_isAntiDump
);
optionsSizer->Add(
m_isMemoryProtection
);
optionsBox->Add(
@@ -697,6 +709,7 @@ auto RyujinApp::BindRunEvent(wxFrame* frame) -> void {
core.m_isRandomSection = m_randomSection->IsChecked();
core.m_isVirtualized = m_virtualize->IsChecked();
core.m_isAntiDump = m_isAntiDump->IsChecked();
core.m_isMemoryProtection = m_isMemoryProtection->IsChecked();
if (m_isAntiDebugWithTroll->IsChecked()) {

View File

@@ -23,6 +23,7 @@ private:
wxCheckBox* m_isAntiDebugWithTroll = nullptr;
wxCheckBox* m_isAntiDebugNormal = nullptr;
wxCheckBox* m_isAntiDump = nullptr;
wxCheckBox* m_isMemoryProtection = nullptr;
wxListBox* m_procList = nullptr;
wxGauge* m_progress = nullptr;