feat: Independent "Ryujin Core as a library" for better usability

- Ryujin now includes a component called Core, where the main obfuscator logic resides. It functions as an independent library that can be used anywhere.
- RyujinConsole now operates by loading the RyujinCore library to run the obfuscator.
- This is a preparation step for additional Ryujin components, such as a future Ryujin GUI and more features like passes and advanced obfuscation options.
This commit is contained in:
keowu
2025-06-22 13:48:30 -03:00
parent eb6d14c4f2
commit cbd7fb67f7
25 changed files with 364 additions and 86 deletions

View File

@@ -0,0 +1,12 @@
#pragma once
#include "RyujinInstruction.hh"
class RyujinBasicBlock {
public:
std::vector<RyujinInstruction> instructions;
std::vector<std::vector<ZyanU8>> opcodes;
uintptr_t start_address;
uintptr_t end_address;
};

View File

@@ -0,0 +1,8 @@
#pragma once
struct RyujinInstruction {
ZydisDisassembledInstruction instruction;
uintptr_t addressofinstruction;
};

View File

@@ -0,0 +1,16 @@
#pragma once
#include <string>
class RyujinObfuscatorConfig {
public:
bool m_isRandomSection; // Randomize the name of the new section with the processed code -> ".Ryujin" standard
bool m_isVirtualized; // Virtualize the code [Try as much as possible]
bool m_isIatObfuscation; //Process IAT Obfuscation
bool m_isJunkCode; // Insert junk code to confuse
bool m_isIgnoreOriginalCodeRemove; // Do not remove the original code after processing (replace the original instructions with NOPs)
bool m_isEncryptObfuscatedCode; // The user wants to encrypt all obfuscated code to avoid detection
std::vector<std::string> m_strProceduresToObfuscate; // Names of the procedures to obfuscate
// todo: passes
};

View File

@@ -0,0 +1,35 @@
#pragma once
#include <string>
#include "RyujinBasicBlock.hh"
class RyujinProcedure {
public:
std::string name;
uintptr_t address;
uintptr_t size;
std::vector<RyujinBasicBlock> basic_blocks;
std::vector<ZyanU8> getUpdateOpcodes() {
std::vector<unsigned char> result;
for (auto& block : basic_blocks) {
auto& blocks = block.opcodes;
for (size_t i = 0; i < blocks.size(); ++i) {
const auto& block = blocks[i];
if (!block.empty()) {
for (const auto& byte : block) {
result.emplace_back(byte);
}
}
}
}
return result;
}
};

View File

@@ -0,0 +1,117 @@
#pragma once
#include <windows.h>
#include <dbghelp.h>
#pragma comment(lib, "DbgHelp.lib")
#include "../Models/RyujinProcedure.hh"
#define SymTagFunction 5
class RyujinPdbParsing {
private:
static BOOL CALLBACK EnumSymbolsCallback(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) {
auto* vecSymbols = reinterpret_cast<std::vector<RyujinProcedure>*>(UserContext);
//Daddy, is this symbol a function entry ?!
if (pSymInfo->Tag == SymTagFunction) {
RyujinProcedure proc;
proc.name = pSymInfo->Name;
proc.address = pSymInfo->Address;
proc.size = pSymInfo->Size;
vecSymbols->emplace_back(proc);
}
return TRUE;
}
public:
static std::vector<RyujinProcedure> ExtractProceduresFromPdb(uintptr_t mappedPebase, uintptr_t szFile, const std::string& strInputFilePath, const std::string& strPdbFilePath) {
std::vector<RyujinProcedure> procs;
::SymSetOptions(
_In_ SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME
);
if (!::SymInitialize(
_In_ ::GetCurrentProcess(),
_In_opt_ nullptr,
_In_ NULL
)) {
::OutputDebugStringA(
_In_ "RyujinPdbParsing::ExtractProceduresFromPdb: SymInitialize failed..\n"
);
return procs;
}
auto strPdbDirectory = strPdbFilePath.substr(0, strPdbFilePath.find_last_of("\\/"));
::SymSetSearchPath(
::GetCurrentProcess(),
strPdbDirectory.c_str()
);
auto loadedModuleBase = ::SymLoadModule64(
_In_ ::GetCurrentProcess(),
_In_opt_ nullptr,
_In_opt_ strInputFilePath.c_str(),
_In_opt_ nullptr,
_In_ mappedPebase,
_In_ szFile
);
if (loadedModuleBase == 0) {
::OutputDebugStringA(
_In_ "RyujinPdbParsing::ExtractProceduresFromPdb: Failed to load SymLoadModule64..\n"
);
::SymCleanup(
_In_ ::GetCurrentProcess()
);
return procs;
}
::SymEnumSymbols(
_In_ ::GetCurrentProcess(),
_In_ loadedModuleBase,
_In_opt_ nullptr,
_In_ RyujinPdbParsing::EnumSymbolsCallback,
_In_opt_ &procs
);
::SymCleanup(
_In_::GetCurrentProcess()
);
return procs;
}
};

655
RyujinCore/Ryujin/Ryujin.cc Normal file
View File

@@ -0,0 +1,655 @@
#include "Ryujin.hh"
Ryujin::Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath) {
m_strInputFilePath.assign(strInputFilePath.begin(), strInputFilePath.end());
m_strOutputFilePath.assign(strOutputFilePath.begin(), strOutputFilePath.end());
m_strPdbFilePath.assign(strPdbFilePath.begin(), strPdbFilePath.end());
auto mappedInfo = RyujinUtils::MapPortableExecutableFileIntoMemory(m_strInputFilePath, m_mappedPE);
m_szFile = mappedInfo.second;
m_isInitialized = mappedInfo.first;
if (!m_isInitialized) {
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: failed to initilize.\n"
);
}
m_ryujinProcedures = RyujinPdbParsing::ExtractProceduresFromPdb(
reinterpret_cast<uintptr_t>(m_mappedPE.get()),
m_szFile,
m_strInputFilePath,
m_strPdbFilePath
);
if (m_ryujinProcedures.size() == 0) {
m_isInitialized = FALSE;
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: No Associate PDB file found for the input binary.."
);
}
}
bool Ryujin::run(const RyujinObfuscatorConfig& config) {
auto imgDos = reinterpret_cast<PIMAGE_DOS_HEADER>(m_mappedPE.get());
if (imgDos->e_magic != IMAGE_DOS_SIGNATURE) {
::OutputDebugStringA(
_In_ "Ryujin::run: Invalid PE File.\n"
);
return FALSE;
}
auto imgNt = reinterpret_cast<PIMAGE_NT_HEADERS>(m_mappedPE.get() + imgDos->e_lfanew);
if (imgNt->Signature != IMAGE_NT_SIGNATURE) {
::OutputDebugStringA(
_In_ "Ryujin::run: Invalid NT headers for the input PE File.\n"
);
return FALSE;
}
if (!m_isInitialized) {
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: not initilized.\n"
);
return FALSE;
}
if (config.m_strProceduresToObfuscate.size() == 0) {
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: not provided functions to obfuscate.\n"
);
return FALSE;
}
std::vector<RyujinObfuscationCore> processed_procs;
for (auto& proc : m_ryujinProcedures) {
auto it = std::find(config.m_strProceduresToObfuscate.begin(), config.m_strProceduresToObfuscate.end(), proc.name);
if (it == config.m_strProceduresToObfuscate.end()) continue;
std::printf(
"[WORKING ON]: %s\n",
proc.name.c_str()
);
// Is a valid procedure ?
if (proc.size == 0) {
::OutputDebugStringA(
_In_ "Ryujin::Ryujin: The candidate is a ghost function cannot obfuscate this..\n"
);
continue;
}
//Get procedure opcodes from mapped pe file
auto ucOpcodes = new unsigned char[proc.size] { 0 };
std::memcpy(
ucOpcodes,
reinterpret_cast<void*>(proc.address),
proc.size
);
//Create basic blocks
RyujinBasicBlockerBuilder rybb(ZYDIS_MACHINE_MODE_LONG_64, ZydisStackWidth_::ZYDIS_STACK_WIDTH_64);
proc.basic_blocks = rybb.createBasicBlocks(ucOpcodes, proc.size, proc.address);
//Is time to obfuscate ?
RyujinObfuscationCore obc(config, proc, reinterpret_cast<uintptr_t>(m_mappedPE.get()));
obc.Run();
//TODO: Custom passes support
//Storing processed procs
processed_procs.push_back(obc);
//Clean up opcodes
delete[] ucOpcodes;
}
//Add section
char chSectionName[8]{ '.', 'R', 'y', 'u', 'j', 'i', 'n', '\0' };
if (config.m_isRandomSection) RyujinUtils::randomizeSectionName(chSectionName);
RyujinPESections peSections;
peSections.AddNewSection(m_strInputFilePath, chSectionName);
uintptr_t offsetVA = 0, miniVmEnterAddress = 0;
std::vector<unsigned char> opcodesWithRelocsFixed;
//Insert minivm enter routine
if (config.m_isVirtualized) {
// Ryujin MiniVM Routine
std::vector<unsigned char> miniVmEnter {
/*
#pragma optimize("", off)
__declspec(noinline) __declspec(safebuffers)uintptr_t miniVmExecute(uintptr_t rcx, uintptr_t rdx) {
unsigned char reg = (rdx >> 16) & 0xFF;
unsigned char op = (rdx >> 8) & 0xFF;
uint64_t value = rdx & 0xFF;
uintptr_t result = rcx;
switch (op) {
case 1:
result += value;
break;
case 2:
result -= value;
break;
case 3:
result *= value;
break;
case 4:
result /= value;
break;
default:
result = 0;
break;
}
return result;
}
#pragma optimize("", on)
*/
0x48, 0x89, 0x54, 0x24, 0x10, 0x48, 0x89, 0x4C, 0x24, 0x08, 0x48, 0x83,
0xEC, 0x28, 0x48, 0x8B, 0x44, 0x24, 0x38, 0x48, 0xC1, 0xE8, 0x10, 0x48,
0x25, 0xFF, 0x00, 0x00, 0x00, 0x88, 0x44, 0x24, 0x01, 0x48, 0x8B, 0x44,
0x24, 0x38, 0x48, 0xC1, 0xE8, 0x08, 0x48, 0x25, 0xFF, 0x00, 0x00, 0x00,
0x88, 0x04, 0x24, 0x48, 0x8B, 0x44, 0x24, 0x38, 0x48, 0x25, 0xFF, 0x00,
0x00, 0x00, 0x48, 0x89, 0x44, 0x24, 0x10, 0x48, 0x8B, 0x44, 0x24, 0x30,
0x48, 0x89, 0x44, 0x24, 0x08, 0x0F, 0xB6, 0x04, 0x24, 0x88, 0x44, 0x24,
0x04, 0x80, 0x7C, 0x24, 0x04, 0x01, 0x74, 0x17, 0x80, 0x7C, 0x24, 0x04,
0x02, 0x74, 0x27, 0x80, 0x7C, 0x24, 0x04, 0x03, 0x74, 0x37, 0x80, 0x7C,
0x24, 0x04, 0x04, 0x74, 0x42, 0xEB, 0x53, 0x48, 0x8B, 0x44, 0x24, 0x10,
0x48, 0x8B, 0x4C, 0x24, 0x08, 0x48, 0x03, 0xC8, 0x48, 0x8B, 0xC1, 0x48,
0x89, 0x44, 0x24, 0x08, 0xEB, 0x45, 0x48, 0x8B, 0x44, 0x24, 0x10, 0x48,
0x8B, 0x4C, 0x24, 0x08, 0x48, 0x2B, 0xC8, 0x48, 0x8B, 0xC1, 0x48, 0x89,
0x44, 0x24, 0x08, 0xEB, 0x2E, 0x48, 0x8B, 0x44, 0x24, 0x08, 0x48, 0x0F,
0xAF, 0x44, 0x24, 0x10, 0x48, 0x89, 0x44, 0x24, 0x08, 0xEB, 0x1C, 0x33,
0xD2, 0x48, 0x8B, 0x44, 0x24, 0x08, 0x48, 0xF7, 0x74, 0x24, 0x10, 0x48,
0x89, 0x44, 0x24, 0x08, 0xEB, 0x09, 0x48, 0xC7, 0x44, 0x24, 0x08, 0x00,
0x00, 0x00, 0x00, 0x48, 0x8B, 0x44, 0x24, 0x08, 0x48, 0x83, 0xC4, 0x28,
0xC3
};
// Inserting the Ryujin MiniVm stub at the beginning of Ryujin section
opcodesWithRelocsFixed.insert(opcodesWithRelocsFixed.end(), miniVmEnter.begin(), miniVmEnter.end());
// Storing the MiniVm Stub Offset
miniVmEnterAddress = peSections.getRyujinSectionVA();
// Calculating the size of the MiniVM Stub
offsetVA += miniVmEnter.size();
}
for (auto& obc : processed_procs) {
// Getting new obfuscated opcodes
auto tempValued = obc.getProcessedProc().getUpdateOpcodes();
// Fix relocations
obc.applyRelocationFixupsToInstructions(reinterpret_cast<uintptr_t>(imgDos), peSections.getRyujinSectionVA() + offsetVA, tempValued);
// Removing and adding a jump in the original procedure and removing original opcodes for a jump to the new obfuscated code
obc.removeOldOpcodeRedirect(peSections.mappedPeDiskBaseAddress(), peSections.getRyujinMappedPeSize(), reinterpret_cast<uintptr_t>(imgDos) + peSections.getRyujinSectionVA() + offsetVA, config.m_isIgnoreOriginalCodeRemove);
// Inserindo MiniVMEnter
if (config.m_isVirtualized) obc.InsertMiniVmEnterProcedureAddress(reinterpret_cast<uintptr_t>(imgDos), miniVmEnterAddress, tempValued);
// Destructing class
obc.~RyujinObfuscationCore();
// Inserting procedures into the list of corrected opcodes
opcodesWithRelocsFixed.insert(opcodesWithRelocsFixed.end(), tempValued.begin(), tempValued.end());
// Incrementing the offset with the size of the opcodes in question
offsetVA += tempValued.size();
}
// Encrypt all obfuscated code
if (config.m_isEncryptObfuscatedCode && !config.m_isRandomSection) {
/*
To "encrypt" all the obfuscated code:
1 - We will encrypt byte by byte of our vector that contains the new opcodes for the section.
2 - We will insert the stub that decrypts and its respective opcodes into the vector of new opcodes.
3 - We will replace the original entry point with our stub. Our stub will jump to the original entry point after deobfuscation.
4 - We will then have the code ready to be properly executed.
*/
/*
Begin TeaDelKew algorithm Implementation
(C) Jo<4A>o Vitor(@Keowu) avaliable on https://github.com/keowu/gamespy/blob/main/code_base/Kurumi/TeaDelKewTests/TeaDelKewAlgo.hh#L2
*/
// Aligning the data so we can run TeaDelKew
while (opcodesWithRelocsFixed.size() % 8 != 0) {
opcodesWithRelocsFixed.push_back(0x00);
offsetVA += 1;
}
// TEADELKEW key
uint32_t key[4] = {
0x77122545, 0x88998877, 0x9944DEAD, 0x10CAFEB4
};
// TEADELKEW KeyBox
uint32_t kew_box[12] = {
0x77122545, 0x88998877, 0x9944DEAD, 0x10CAFEB4,
0x45B0B0C4, 0x35DEADDE, 0x25C4C4C4, 0x85634897,
0x56123456, 0x11454545, 0x12323232, 0x95959595
};
// Encrypting all the opcode generated by the obfuscator using the TeaDelKew algorithm
for (size_t i = 0; i < opcodesWithRelocsFixed.size(); i += 8) {
uint32_t* block = reinterpret_cast<uint32_t*>(&opcodesWithRelocsFixed[i]);
uint32_t v0 = ~block[0];
uint32_t v1 = ~block[1];
uint32_t sum = 0;
uint32_t delta = 0x00B0B0C4;
uint32_t k0 = key[0] ^ 0xDEADBEEF;
uint32_t k1 = key[1] ^ 0xDEADBEEF;
uint32_t k2 = key[2] ^ 0xDEADBEEF;
uint32_t k3 = key[3] ^ 0xDEADBEEF;
for (int j = 0; j < 2048; j++) {
v1 ^= kew_box[j % 12];
v0 ^= kew_box[j % 12];
v1 ^= (j * 0x44444444 ^ ~j);
v0 ^= (j * 0x44444444 ^ ~j);
}
for (int j = 0; j < 2048; j++) {
v0 += ~((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k0);
sum += delta;
v1 += ~((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k1);
}
block[0] = v0;
block[1] = v1;
}
// Entry point stub to decrypt the obfuscated code
std::vector<unsigned char> entryPoint = {
/*
#pragma optimize("", off)
__declspec(noinline) __declspec(safebuffers)void ryujinEntryPoint() {
auto peb = reinterpret_cast<PVOID>(__readgsqword(0x60));
if (!peb) return;
auto imageBase = *reinterpret_cast<PVOID*>(reinterpret_cast<BYTE*>(peb) + 0x10);
if (!imageBase) return;
auto dos = reinterpret_cast<PIMAGE_DOS_HEADER>(imageBase);
if (dos->e_magic != 0x5A4D) return;
auto nt = reinterpret_cast<PIMAGE_NT_HEADERS64>(reinterpret_cast<BYTE*>(imageBase) + dos->e_lfanew);
if (nt->Signature != 0x00004550) return;
auto numSections = nt->FileHeader.NumberOfSections;
auto section = IMAGE_FIRST_SECTION(nt);
char name[9] { 0 };
char chLookingName[9] { '.', 'R', 'y', 'u', 'j', 'i', 'n', '\0' };
uintptr_t rvaEntryPointOriginal = 0x9999999999999999;
uintptr_t szStub = 0x8888888888888888;
for (auto i = 0; i < numSections; ++i, ++section) {
for (auto j = 0; j < 8; ++j) name[j] = section->Name[j];
name[8] = 0;
auto rva = section->VirtualAddress;
auto size = section->Misc.VirtualSize;
auto va = reinterpret_cast<uintptr_t>((BYTE*)imageBase + rva);
if (name[0] == chLookingName[0] && name[1] == chLookingName[1] && name[2] == chLookingName[2] && name[3] == chLookingName[3]
&& name[4] == chLookingName[4] && name[5] == chLookingName[5] && name[6] == chLookingName[6]) {
uint32_t kew_box[12] = {
0x77122545, 0x88998877, 0x9944DEAD, 0x10CAFEB4,
0x45B0B0C4, 0x35DEADDE, 0x25C4C4C4, 0x85634897,
0x56123456, 0x11454545, 0x12323232, 0x95959595
};
for (auto i = 0; i < (size - szStub); i += 8) {
if ((i + 8) > (size - szStub)) break;
auto* block = reinterpret_cast<uint32_t*>(va + i);
auto v0 = block[0];
auto v1 = block[1];
uint32_t key[4] = {
0x77122545, 0x88998877,
0x9944DEAD, 0x10CAFEB4
};
uint32_t sum = 0x85862000, delta = 0x00B0B0C4;
uint32_t k0 = key[0] ^ 0xDEADBEEF, k1 = key[1] ^ 0xDEADBEEF,
k2 = key[2] ^ 0xDEADBEEF, k3 = key[3] ^ 0xDEADBEEF;
for (auto j = 0; j < 2048; j++) {
v1 -= ~((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k1);
sum -= delta;
v0 -= ~((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k0);
}
for (auto j = 0; j < 2048; j++) {
v1 ^= kew_box[j % 12];
v0 ^= kew_box[j % 12];
v1 ^= (j * 0x44444444 ^ ~j);
v0 ^= (j * 0x44444444 ^ ~j);
}
block[0] = ~v0;
block[1] = ~v1;
}
using tpdEntryPoint = void(__stdcall*)();
tpdEntryPoint oep = reinterpret_cast<tpdEntryPoint>(reinterpret_cast<uintptr_t>(imageBase) + rvaEntryPointOriginal);
oep();
}
}
}
#pragma optimize("", on)
*/
0x40, 0x57, 0x48, 0x81, 0xEC, 0x20, 0x01, 0x00, 0x00, 0x65, 0x48, 0x8B,
0x04, 0x25, 0x60, 0x00, 0x00, 0x00, 0x48, 0x89, 0x84, 0x24, 0xB0, 0x00,
0x00, 0x00, 0x48, 0x83, 0xBC, 0x24, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x75,
0x05, 0xE9, 0x26, 0x06, 0x00, 0x00, 0x48, 0x8B, 0x84, 0x24, 0xB0, 0x00,
0x00, 0x00, 0x48, 0x8B, 0x40, 0x10, 0x48, 0x89, 0x44, 0x24, 0x78, 0x48,
0x83, 0x7C, 0x24, 0x78, 0x00, 0x75, 0x05, 0xE9, 0x08, 0x06, 0x00, 0x00,
0x48, 0x8B, 0x44, 0x24, 0x78, 0x48, 0x89, 0x84, 0x24, 0xB8, 0x00, 0x00,
0x00, 0x48, 0x8B, 0x84, 0x24, 0xB8, 0x00, 0x00, 0x00, 0x0F, 0xB7, 0x00,
0x3D, 0x4D, 0x5A, 0x00, 0x00, 0x74, 0x05, 0xE9, 0xE4, 0x05, 0x00, 0x00,
0x48, 0x8B, 0x84, 0x24, 0xB8, 0x00, 0x00, 0x00, 0x48, 0x63, 0x40, 0x3C,
0x48, 0x8B, 0x4C, 0x24, 0x78, 0x48, 0x03, 0xC8, 0x48, 0x8B, 0xC1, 0x48,
0x89, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x84, 0x24, 0x80,
0x00, 0x00, 0x00, 0x81, 0x38, 0x50, 0x45, 0x00, 0x00, 0x74, 0x05, 0xE9,
0xB0, 0x05, 0x00, 0x00, 0x48, 0x8B, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00,
0x0F, 0xB7, 0x40, 0x06, 0x66, 0x89, 0x44, 0x24, 0x58, 0x48, 0x8B, 0x84,
0x24, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xB7, 0x40, 0x14, 0x48, 0x8B, 0x8C,
0x24, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x44, 0x01, 0x18, 0x48, 0x89,
0x44, 0x24, 0x68, 0x48, 0x8D, 0x44, 0x24, 0x48, 0x48, 0x8B, 0xF8, 0x33,
0xC0, 0xB9, 0x09, 0x00, 0x00, 0x00, 0xF3, 0xAA, 0xC6, 0x44, 0x24, 0x30,
0x2E, 0xC6, 0x44, 0x24, 0x31, 0x52, 0xC6, 0x44, 0x24, 0x32, 0x79, 0xC6,
0x44, 0x24, 0x33, 0x75, 0xC6, 0x44, 0x24, 0x34, 0x6A, 0xC6, 0x44, 0x24,
0x35, 0x69, 0xC6, 0x44, 0x24, 0x36, 0x6E, 0xC6, 0x44, 0x24, 0x37, 0x00,
0x48, 0x8D, 0x44, 0x24, 0x38, 0x48, 0x8B, 0xF8, 0x33, 0xC0, 0xB9, 0x01,
0x00, 0x00, 0x00, 0xF3, 0xAA, 0x48, 0xB8, 0x99, 0x99, 0x99, 0x99, 0x99,
0x99, 0x99, 0x99, 0x48, 0x89, 0x84, 0x24, 0x08, 0x01, 0x00, 0x00, 0x48,
0xB8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x48, 0x89, 0x84,
0x24, 0xC0, 0x00, 0x00, 0x00, 0xC7, 0x44, 0x24, 0x5C, 0x00, 0x00, 0x00,
0x00, 0xEB, 0x18, 0x8B, 0x44, 0x24, 0x5C, 0xFF, 0xC0, 0x89, 0x44, 0x24,
0x5C, 0x48, 0x8B, 0x44, 0x24, 0x68, 0x48, 0x83, 0xC0, 0x28, 0x48, 0x89,
0x44, 0x24, 0x68, 0x0F, 0xB7, 0x44, 0x24, 0x58, 0x39, 0x44, 0x24, 0x5C,
0x0F, 0x8D, 0xE2, 0x04, 0x00, 0x00, 0xC7, 0x44, 0x24, 0x40, 0x00, 0x00,
0x00, 0x00, 0xEB, 0x0A, 0x8B, 0x44, 0x24, 0x40, 0xFF, 0xC0, 0x89, 0x44,
0x24, 0x40, 0x83, 0x7C, 0x24, 0x40, 0x08, 0x7D, 0x19, 0x48, 0x63, 0x44,
0x24, 0x40, 0x48, 0x63, 0x4C, 0x24, 0x40, 0x48, 0x8B, 0x54, 0x24, 0x68,
0x0F, 0xB6, 0x04, 0x02, 0x88, 0x44, 0x0C, 0x48, 0xEB, 0xD6, 0xB8, 0x01,
0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x08, 0xC6, 0x44, 0x04, 0x48, 0x00,
0x48, 0x8B, 0x44, 0x24, 0x68, 0x8B, 0x40, 0x0C, 0x89, 0x84, 0x24, 0x90,
0x00, 0x00, 0x00, 0x48, 0x8B, 0x44, 0x24, 0x68, 0x8B, 0x40, 0x08, 0x89,
0x44, 0x24, 0x64, 0x8B, 0x84, 0x24, 0x90, 0x00, 0x00, 0x00, 0x48, 0x8B,
0x4C, 0x24, 0x78, 0x48, 0x03, 0xC8, 0x48, 0x8B, 0xC1, 0x48, 0x89, 0x84,
0x24, 0x00, 0x01, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x6B,
0xC0, 0x00, 0x0F, 0xBE, 0x44, 0x04, 0x48, 0xB9, 0x01, 0x00, 0x00, 0x00,
0x48, 0x6B, 0xC9, 0x00, 0x0F, 0xBE, 0x4C, 0x0C, 0x30, 0x3B, 0xC1, 0x0F,
0x85, 0x42, 0x04, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x6B,
0xC0, 0x01, 0x0F, 0xBE, 0x44, 0x04, 0x48, 0xB9, 0x01, 0x00, 0x00, 0x00,
0x48, 0x6B, 0xC9, 0x01, 0x0F, 0xBE, 0x4C, 0x0C, 0x30, 0x3B, 0xC1, 0x0F,
0x85, 0x1E, 0x04, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x6B,
0xC0, 0x02, 0x0F, 0xBE, 0x44, 0x04, 0x48, 0xB9, 0x01, 0x00, 0x00, 0x00,
0x48, 0x6B, 0xC9, 0x02, 0x0F, 0xBE, 0x4C, 0x0C, 0x30, 0x3B, 0xC1, 0x0F,
0x85, 0xFA, 0x03, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x6B,
0xC0, 0x03, 0x0F, 0xBE, 0x44, 0x04, 0x48, 0xB9, 0x01, 0x00, 0x00, 0x00,
0x48, 0x6B, 0xC9, 0x03, 0x0F, 0xBE, 0x4C, 0x0C, 0x30, 0x3B, 0xC1, 0x0F,
0x85, 0xD6, 0x03, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x6B,
0xC0, 0x04, 0x0F, 0xBE, 0x44, 0x04, 0x48, 0xB9, 0x01, 0x00, 0x00, 0x00,
0x48, 0x6B, 0xC9, 0x04, 0x0F, 0xBE, 0x4C, 0x0C, 0x30, 0x3B, 0xC1, 0x0F,
0x85, 0xB2, 0x03, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x6B,
0xC0, 0x05, 0x0F, 0xBE, 0x44, 0x04, 0x48, 0xB9, 0x01, 0x00, 0x00, 0x00,
0x48, 0x6B, 0xC9, 0x05, 0x0F, 0xBE, 0x4C, 0x0C, 0x30, 0x3B, 0xC1, 0x0F,
0x85, 0x8E, 0x03, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x00, 0x48, 0x6B,
0xC0, 0x06, 0x0F, 0xBE, 0x44, 0x04, 0x48, 0xB9, 0x01, 0x00, 0x00, 0x00,
0x48, 0x6B, 0xC9, 0x06, 0x0F, 0xBE, 0x4C, 0x0C, 0x30, 0x3B, 0xC1, 0x0F,
0x85, 0x6A, 0x03, 0x00, 0x00, 0xC7, 0x84, 0x24, 0xC8, 0x00, 0x00, 0x00,
0x45, 0x25, 0x12, 0x77, 0xC7, 0x84, 0x24, 0xCC, 0x00, 0x00, 0x00, 0x77,
0x88, 0x99, 0x88, 0xC7, 0x84, 0x24, 0xD0, 0x00, 0x00, 0x00, 0xAD, 0xDE,
0x44, 0x99, 0xC7, 0x84, 0x24, 0xD4, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xCA,
0x10, 0xC7, 0x84, 0x24, 0xD8, 0x00, 0x00, 0x00, 0xC4, 0xB0, 0xB0, 0x45,
0xC7, 0x84, 0x24, 0xDC, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xDE, 0x35, 0xC7,
0x84, 0x24, 0xE0, 0x00, 0x00, 0x00, 0xC4, 0xC4, 0xC4, 0x25, 0xC7, 0x84,
0x24, 0xE4, 0x00, 0x00, 0x00, 0x97, 0x48, 0x63, 0x85, 0xC7, 0x84, 0x24,
0xE8, 0x00, 0x00, 0x00, 0x56, 0x34, 0x12, 0x56, 0xC7, 0x84, 0x24, 0xEC,
0x00, 0x00, 0x00, 0x45, 0x45, 0x45, 0x11, 0xC7, 0x84, 0x24, 0xF0, 0x00,
0x00, 0x00, 0x32, 0x32, 0x32, 0x12, 0xC7, 0x84, 0x24, 0xF4, 0x00, 0x00,
0x00, 0x95, 0x95, 0x95, 0x95, 0x48, 0xC7, 0x44, 0x24, 0x70, 0x00, 0x00,
0x00, 0x00, 0xEB, 0x0E, 0x48, 0x8B, 0x44, 0x24, 0x70, 0x48, 0x83, 0xC0,
0x08, 0x48, 0x89, 0x44, 0x24, 0x70, 0x8B, 0x44, 0x24, 0x64, 0x48, 0x2B,
0x84, 0x24, 0xC0, 0x00, 0x00, 0x00, 0x48, 0x39, 0x44, 0x24, 0x70, 0x0F,
0x83, 0x93, 0x02, 0x00, 0x00, 0x48, 0x8B, 0x44, 0x24, 0x70, 0x48, 0x83,
0xC0, 0x08, 0x8B, 0x4C, 0x24, 0x64, 0x48, 0x2B, 0x8C, 0x24, 0xC0, 0x00,
0x00, 0x00, 0x48, 0x3B, 0xC1, 0x76, 0x05, 0xE9, 0x74, 0x02, 0x00, 0x00,
0x48, 0x8B, 0x44, 0x24, 0x70, 0x48, 0x8B, 0x8C, 0x24, 0x00, 0x01, 0x00,
0x00, 0x48, 0x03, 0xC8, 0x48, 0x8B, 0xC1, 0x48, 0x89, 0x84, 0x24, 0x88,
0x00, 0x00, 0x00, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x00,
0x48, 0x8B, 0x8C, 0x24, 0x88, 0x00, 0x00, 0x00, 0x8B, 0x04, 0x01, 0x89,
0x44, 0x24, 0x20, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x01,
0x48, 0x8B, 0x8C, 0x24, 0x88, 0x00, 0x00, 0x00, 0x8B, 0x04, 0x01, 0x89,
0x44, 0x24, 0x24, 0xC7, 0x84, 0x24, 0xA0, 0x00, 0x00, 0x00, 0x45, 0x25,
0x12, 0x77, 0xC7, 0x84, 0x24, 0xA4, 0x00, 0x00, 0x00, 0x77, 0x88, 0x99,
0x88, 0xC7, 0x84, 0x24, 0xA8, 0x00, 0x00, 0x00, 0xAD, 0xDE, 0x44, 0x99,
0xC7, 0x84, 0x24, 0xAC, 0x00, 0x00, 0x00, 0xB4, 0xFE, 0xCA, 0x10, 0xC7,
0x44, 0x24, 0x44, 0x00, 0x20, 0x86, 0x85, 0xC7, 0x84, 0x24, 0x98, 0x00,
0x00, 0x00, 0xC4, 0xB0, 0xB0, 0x00, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48,
0x6B, 0xC0, 0x00, 0x8B, 0x84, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x35, 0xEF,
0xBE, 0xAD, 0xDE, 0x89, 0x84, 0x24, 0x9C, 0x00, 0x00, 0x00, 0xB8, 0x04,
0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x01, 0x8B, 0x84, 0x04, 0xA0, 0x00,
0x00, 0x00, 0x35, 0xEF, 0xBE, 0xAD, 0xDE, 0x89, 0x84, 0x24, 0x94, 0x00,
0x00, 0x00, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC0, 0x02, 0x8B,
0x84, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x35, 0xEF, 0xBE, 0xAD, 0xDE, 0x89,
0x84, 0x24, 0xF8, 0x00, 0x00, 0x00, 0xB8, 0x04, 0x00, 0x00, 0x00, 0x48,
0x6B, 0xC0, 0x03, 0x8B, 0x84, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x35, 0xEF,
0xBE, 0xAD, 0xDE, 0x89, 0x84, 0x24, 0xFC, 0x00, 0x00, 0x00, 0xC7, 0x44,
0x24, 0x60, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x0A, 0x8B, 0x44, 0x24, 0x60,
0xFF, 0xC0, 0x89, 0x44, 0x24, 0x60, 0x81, 0x7C, 0x24, 0x60, 0x00, 0x08,
0x00, 0x00, 0x7D, 0x7E, 0x8B, 0x44, 0x24, 0x20, 0xC1, 0xE0, 0x04, 0x8B,
0x4C, 0x24, 0x20, 0xC1, 0xE9, 0x05, 0x33, 0xC1, 0x03, 0x44, 0x24, 0x20,
0xF7, 0xD0, 0x8B, 0x8C, 0x24, 0x94, 0x00, 0x00, 0x00, 0x8B, 0x54, 0x24,
0x44, 0x03, 0xD1, 0x8B, 0xCA, 0x33, 0xC1, 0x8B, 0x4C, 0x24, 0x24, 0x2B,
0xC8, 0x8B, 0xC1, 0x89, 0x44, 0x24, 0x24, 0x8B, 0x84, 0x24, 0x98, 0x00,
0x00, 0x00, 0x8B, 0x4C, 0x24, 0x44, 0x2B, 0xC8, 0x8B, 0xC1, 0x89, 0x44,
0x24, 0x44, 0x8B, 0x44, 0x24, 0x24, 0xC1, 0xE0, 0x04, 0x8B, 0x4C, 0x24,
0x24, 0xC1, 0xE9, 0x05, 0x33, 0xC1, 0x03, 0x44, 0x24, 0x24, 0xF7, 0xD0,
0x8B, 0x8C, 0x24, 0x9C, 0x00, 0x00, 0x00, 0x8B, 0x54, 0x24, 0x44, 0x03,
0xD1, 0x8B, 0xCA, 0x33, 0xC1, 0x8B, 0x4C, 0x24, 0x20, 0x2B, 0xC8, 0x8B,
0xC1, 0x89, 0x44, 0x24, 0x20, 0xE9, 0x6E, 0xFF, 0xFF, 0xFF, 0xC7, 0x44,
0x24, 0x28, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x0A, 0x8B, 0x44, 0x24, 0x28,
0xFF, 0xC0, 0x89, 0x44, 0x24, 0x28, 0x81, 0x7C, 0x24, 0x28, 0x00, 0x08,
0x00, 0x00, 0x0F, 0x8D, 0x83, 0x00, 0x00, 0x00, 0x8B, 0x44, 0x24, 0x28,
0x99, 0xB9, 0x0C, 0x00, 0x00, 0x00, 0xF7, 0xF9, 0x8B, 0xC2, 0x48, 0x98,
0x8B, 0x84, 0x84, 0xC8, 0x00, 0x00, 0x00, 0x8B, 0x4C, 0x24, 0x24, 0x33,
0xC8, 0x8B, 0xC1, 0x89, 0x44, 0x24, 0x24, 0x8B, 0x44, 0x24, 0x28, 0x99,
0xB9, 0x0C, 0x00, 0x00, 0x00, 0xF7, 0xF9, 0x8B, 0xC2, 0x48, 0x98, 0x8B,
0x84, 0x84, 0xC8, 0x00, 0x00, 0x00, 0x8B, 0x4C, 0x24, 0x20, 0x33, 0xC8,
0x8B, 0xC1, 0x89, 0x44, 0x24, 0x20, 0x69, 0x44, 0x24, 0x28, 0x44, 0x44,
0x44, 0x44, 0x8B, 0x4C, 0x24, 0x28, 0xF7, 0xD1, 0x33, 0xC1, 0x8B, 0x4C,
0x24, 0x24, 0x33, 0xC8, 0x8B, 0xC1, 0x89, 0x44, 0x24, 0x24, 0x69, 0x44,
0x24, 0x28, 0x44, 0x44, 0x44, 0x44, 0x8B, 0x4C, 0x24, 0x28, 0xF7, 0xD1,
0x33, 0xC1, 0x8B, 0x4C, 0x24, 0x20, 0x33, 0xC8, 0x8B, 0xC1, 0x89, 0x44,
0x24, 0x20, 0xE9, 0x65, 0xFF, 0xFF, 0xFF, 0x8B, 0x44, 0x24, 0x20, 0xF7,
0xD0, 0xB9, 0x04, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC9, 0x00, 0x48, 0x8B,
0x94, 0x24, 0x88, 0x00, 0x00, 0x00, 0x89, 0x04, 0x0A, 0x8B, 0x44, 0x24,
0x24, 0xF7, 0xD0, 0xB9, 0x04, 0x00, 0x00, 0x00, 0x48, 0x6B, 0xC9, 0x01,
0x48, 0x8B, 0x94, 0x24, 0x88, 0x00, 0x00, 0x00, 0x89, 0x04, 0x0A, 0xE9,
0x48, 0xFD, 0xFF, 0xFF, 0x48, 0x8B, 0x84, 0x24, 0x08, 0x01, 0x00, 0x00,
0x48, 0x8B, 0x4C, 0x24, 0x78, 0x48, 0x03, 0xC8, 0x48, 0x8B, 0xC1, 0x48,
0x89, 0x84, 0x24, 0x10, 0x01, 0x00, 0x00, 0xFF, 0x94, 0x24, 0x10, 0x01,
0x00, 0x00, 0x90, 0xE9, 0xF7, 0xFA, 0xFF, 0xFF, 0x48, 0x81, 0xC4, 0x20,
0x01, 0x00, 0x00, 0x5F, 0xC3
};
// Parsing the PE file
auto imgDos = reinterpret_cast<PIMAGE_DOS_HEADER>(peSections.mappedPeDiskBaseAddress());
auto ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<uint8_t*>(imgDos) + imgDos->e_lfanew);
// Finding the OEP (Original Entry Point) to store it
DWORD OEP = ntHeader->OptionalHeader.AddressOfEntryPoint;
// Storing the size of the entry point stub, which will be the only non-encrypted code in the obfuscated code section
SIZE_T sizeOep = entryPoint.size();
// Setting a new entry point as the entry point stub that will decrypt the obfuscated executable code
ntHeader->OptionalHeader.AddressOfEntryPoint = peSections.getRyujinSectionVA() + offsetVA;
// Modifying the stub to adapt to the OEP of the original entry point
std::vector<unsigned char> pattern = {
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99
};
auto it = std::search(entryPoint.begin(), entryPoint.end(), pattern.begin(), pattern.end());
std::memset(&*(it), 0, 8);
std::memcpy(&*(it), &OEP, sizeof(OEP));
/*
Modifying the stub to adapt and ignore the entry point stub decryption code itself,
in a way that skips its size so it doesn<73>t break the stub
when it decrypts the executable code.
*/
pattern.assign({
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88
});
it = std::search(entryPoint.begin(), entryPoint.end(), pattern.begin(), pattern.end());
std::memset(&*(it), 0, 8);
std::memcpy(&*(it), &sizeOep, sizeof(sizeOep));
// Inserting the opcodes of our stub into our vector along with the rest of the obfuscated and encrypted code
opcodesWithRelocsFixed.insert(opcodesWithRelocsFixed.end(), entryPoint.begin(), entryPoint.end());
// Log to inform the user that our code has been properly encrypted.
std::printf("[!] OEP: %llx - Inserting Decryption code routine on: %llx\n", imgNt->OptionalHeader.AddressOfEntryPoint, offsetVA);
}
//Process new opcodes
peSections.ProcessOpcodesNewSection(opcodesWithRelocsFixed);
//Save output file
peSections.FinishNewSection(m_strOutputFilePath);
}
void Ryujin::listRyujinProcedures() {
if (!m_isInitialized) {
::OutputDebugStringA(
_In_ "Ryujin::listRyujinProcedures: not initialized.\n"
);
return;
}
std::printf("=== Ryujin Procedures ===\n");
for (const auto& procedure : m_ryujinProcedures) {
std::printf(
"Name: %-30s | Address: 0x%016llx | Size: 0x%llx\n",
procedure.name.c_str(),
procedure.address,
procedure.size
);
}
std::printf("==========================\n");
}

View File

@@ -0,0 +1,34 @@
#pragma once
#include <Zydis/Zydis.h>
#include <Zydis/SharedTypes.h>
#include <iostream>
#include <memory>
#include <vector>
#include "PDB/RyujinPdbParsing.hh"
#include "Utils/RyujinUtils.hh"
#include "Models/RyujinObfuscatorConfig.hh"
#include "RyujinCore/BasicBlockerBuilder.hh"
#include "RyujinCore/RyujinObfuscationCore.hh"
#include "Utils/RyujinPESections.hh"
class Ryujin {
private:
std::shared_ptr<unsigned char> m_mappedPE;
std::string m_strInputFilePath;
std::string m_strPdbFilePath;
std::string m_strOutputFilePath;
uintptr_t m_szFile;
BOOL m_isInitialized;
std::vector<RyujinProcedure> m_ryujinProcedures;
bool todoAction() { return FALSE; }
public:
Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath);
bool run(const RyujinObfuscatorConfig& config);
void listRyujinProcedures();
~Ryujin() { }
};

View File

@@ -0,0 +1,100 @@
#include "BasicBlockerBuilder.hh"
bool RyujinBasicBlockerBuilder::isControlFlow(const ZydisDecodedInstruction& instruction) const {
return (instruction.meta.category == ZYDIS_CATEGORY_CALL ||
instruction.meta.category == ZYDIS_CATEGORY_RET ||
instruction.meta.category == ZYDIS_CATEGORY_UNCOND_BR ||
instruction.meta.category == ZYDIS_CATEGORY_COND_BR ||
instruction.meta.category == ZYDIS_CATEGORY_SYSTEM ||
instruction.meta.category == ZYDIS_CATEGORY_INTERRUPT ||
instruction.meta.category == ZYDIS_CATEGORY_SYSCALL);
}
RyujinBasicBlockerBuilder::RyujinBasicBlockerBuilder(ZydisMachineMode machine, ZydisStackWidth stack) {
::ZydisDecoderInit(
_Inout_ &decoder,
_In_ machine,
_In_ stack
);
}
std::vector<RyujinBasicBlock> RyujinBasicBlockerBuilder::createBasicBlocks(const unsigned char* chOpcode, size_t szOpcode, uintptr_t start_address) {
std::vector<RyujinBasicBlock> blocks;
std::size_t offset = 0;
uintptr_t curr_addr = start_address;
while (offset < szOpcode) {
RyujinBasicBlock block;
block.start_address = start_address;
std::size_t inner = offset;
while (inner < szOpcode) {
ZydisDisassembledInstruction instr;
if (!ZYAN_SUCCESS(::ZydisDisassembleIntel(
_In_ ZYDIS_MACHINE_MODE_LONG_64,
_In_ curr_addr + (inner - offset),
_In_ chOpcode + inner,
_In_ szOpcode - inner,
_Out_ &instr
))) {
std::printf(
"RyujinBasicBlockerBuilder::createBasicBlocks: Zydis disam failed %llx\n",
inner
);
break;
}
//Storing the instruction relative to the basic block
RyujinInstruction inst;
inst.addressofinstruction = curr_addr + (inner - offset);
inst.instruction = instr;
block.instructions.push_back(
inst
);
//Storing the original opcodes from basic block
block.opcodes.emplace_back(
chOpcode + inner,
chOpcode + inner + instr.info.length
);
inner += instr.info.length;
//Theres a branch ? so let's preparate the next block
if (isControlFlow(
instr.info
)) break;
}
block.end_address = curr_addr + (inner - offset);
blocks.push_back(std::move(block));
curr_addr = block.end_address;
offset = inner;
}
return blocks;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <Zydis/Zydis.h>
#include <Zydis/SharedTypes.h>
#include <vector>
#include "../Models/RyujinBasicBlock.hh"
class RyujinBasicBlockerBuilder {
private:
ZydisDecoder decoder;
bool isControlFlow(const ZydisDecodedInstruction& instruction) const;
public:
RyujinBasicBlockerBuilder(ZydisMachineMode machine, ZydisStackWidth stack);
std::vector<RyujinBasicBlock> createBasicBlocks(const unsigned char* chOpcode, size_t szOpcode, uintptr_t start_address);
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
#pragma once
#include <Windows.h>
#include <vector>
#include <set>
#include <cstdint>
#include <random>
#include <functional>
#include <unordered_map>
#include <asmjit/asmjit.h>
#include <Zydis/Zydis.h>
#include <Zydis/SharedTypes.h>
#include "../Models/RyujinProcedure.hh"
#include "../Models/RyujinObfuscatorConfig.hh"
#include "../RyujinCore/BasicBlockerBuilder.hh"
class RyujinObfuscationCore {
private:
const int MAX_PADDING_SPACE_INSTR = 7;
const int MAX_JUNK_GENERATION_ITERATION = 5;
std::vector<ZydisRegister> m_unusedRegisters;
std::vector<RyujinBasicBlock> m_obfuscated_bb;
uintptr_t m_ProcImageBase;
RyujinProcedure m_proc;
RyujinObfuscatorConfig m_config;
BOOL extractUnusedRegisters();
void updateBasicBlocksContext();
void addPaddingSpaces();
void obfuscateIat();
void insertJunkCode();
void insertVirtualization();
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);
inline std::pair<int, int> findBlockId(ZyanU8 uopcode, ZyanI64 value, ZyanU8 idx, ZyanU8 szData) {
int block_id = 0;
int opcode_id = 0;
for (auto& block : m_proc.basic_blocks) {
opcode_id = 0;
for (auto& opcode : block.opcodes) {
auto data = opcode.data();
auto size = opcode.size();
if (data[0] == uopcode) //0xFF ?
if (std::memcmp(&*(data + idx), &value, szData) == 0) // Is it the same memory immediate?
return std::make_pair(block_id, opcode_id);
opcode_id++;
}
block_id++;
}
return std::make_pair(-1, -1);
};
public:
RyujinObfuscationCore(const RyujinObfuscatorConfig& config, const RyujinProcedure& proc, uintptr_t ProcImageBase);
void applyRelocationFixupsToInstructions(uintptr_t imageBase, DWORD virtualAddress, std::vector<unsigned char>& new_opcodes);
void removeOldOpcodeRedirect(uintptr_t newMappedPE, std::size_t szMapped, uintptr_t newObfuscatedAddress, bool isIgnoreOriginalCodeRemove = false);
void InsertMiniVmEnterProcedureAddress(uintptr_t imageBase, uintptr_t virtualAddress, std::vector<unsigned char>& new_opcodes);
BOOL Run();
RyujinProcedure getProcessedProc();
~RyujinObfuscationCore();
};

View File

@@ -0,0 +1,158 @@
#include "RyujinPESections.hh"
BOOL RyujinPESections::AddNewSection(const std::string& strInputFilePath, char chSectionName[8]) {
auto mappedDiskPE = RyujinUtils::MapDiskPE(strInputFilePath);
m_szFile = mappedDiskPE.second;
m_ucModifiedPeMap = new unsigned char[m_szFile]{ 0 };
std::memcpy(
m_ucModifiedPeMap,
mappedDiskPE.first,
m_szFile
);
::UnmapViewOfFile(
_In_ mappedDiskPE.first
);
m_dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(m_ucModifiedPeMap);
if (m_dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
delete[] m_ucModifiedPeMap;
return FALSE;
}
m_ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(m_ucModifiedPeMap + m_dosHeader->e_lfanew);
if (m_ntHeader->Signature != IMAGE_NT_SIGNATURE) {
delete[] m_ucModifiedPeMap;
return FALSE;
}
auto sectionTableSize = m_ntHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
if (m_dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sectionTableSize > m_ntHeader->OptionalHeader.SizeOfHeaders) {
//No space to insert a new section on this PE FILE :(
delete[] m_ucModifiedPeMap;
return FALSE;
}
//Adding the new section
std::memcpy(
m_newSection.Name,
chSectionName,
sizeof(chSectionName)
);
auto imgLastSection = IMAGE_FIRST_SECTION(m_ntHeader) + (m_ntHeader->FileHeader.NumberOfSections - 1);
m_newSection.VirtualAddress = ALIGN_UP(
imgLastSection->VirtualAddress + imgLastSection->Misc.VirtualSize,
m_ntHeader->OptionalHeader.SectionAlignment
);
m_newSection.PointerToRawData = ALIGN_UP(
imgLastSection->PointerToRawData + imgLastSection->SizeOfRawData,
m_ntHeader->OptionalHeader.FileAlignment
);
m_newSection.PointerToRelocations = JACKPOTNUMBER;
m_newSection.NumberOfRelocations = JACKPOTNUMBER;
m_newSection.PointerToLinenumbers = JACKPOTNUMBER;
m_newSection.NumberOfLinenumbers = JACKPOTNUMBER;
m_newSection.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
return TRUE;
}
BOOL RyujinPESections::ProcessOpcodesNewSection(std::vector<unsigned char>& opcodeData) {
m_newSection.Misc.VirtualSize = opcodeData.size();
m_newSection.SizeOfRawData = ALIGN_UP(opcodeData.size(), m_ntHeader->OptionalHeader.FileAlignment);
//Let's add a new section entry on the section table
auto newSectionEntry = IMAGE_FIRST_SECTION(m_ntHeader) + m_ntHeader->FileHeader.NumberOfSections;
std::memcpy(
newSectionEntry,
&m_newSection,
sizeof(IMAGE_SECTION_HEADER)
);
//Let's incement section number
m_ntHeader->FileHeader.NumberOfSections++;
//Updating size of img
m_ntHeader->OptionalHeader.SizeOfImage = ALIGN_UP(m_newSection.VirtualAddress + m_newSection.Misc.VirtualSize, m_ntHeader->OptionalHeader.SectionAlignment);
//New PE Sz
m_szNewSec = m_newSection.PointerToRawData + m_newSection.SizeOfRawData;
m_ucResizedPE = reinterpret_cast<unsigned char*>(std::realloc(
m_ucModifiedPeMap,
m_szNewSec
));
if (!m_ucResizedPE) {
//Failed to realocate PE
delete[] m_ucModifiedPeMap;
delete[] m_ucResizedPE;
return FALSE;
}
//Zeroing the extended PE region
if (m_szNewSec > m_szFile) std::memset(
m_ucResizedPE + m_szFile,
0,
m_szNewSec - m_szFile
);
//Copying the new opcodes to the new section
std::memcpy(
m_ucResizedPE + m_newSection.PointerToRawData,
opcodeData.data(),
opcodeData.size()
);
//In order to allow fix relocs latter we want:
//allow get va out of this class
//give acess to the new allocated area
//give access to the new size
return TRUE;
}
BOOL RyujinPESections::FinishNewSection(const std::string& strOutputFilePath) {
auto bSucess = RyujinUtils::SaveBuffer(strOutputFilePath, m_ucResizedPE, m_szNewSec);
if (!bSucess) return FALSE;
return TRUE;
}

View File

@@ -0,0 +1,56 @@
#pragma once
#include <iostream>
#include <memory>
#include <vector>
#include <Windows.h>
#include "RyujinUtils.hh"
#define ALIGN_UP(value, alignment) ((value + alignment - 1) & ~(alignment - 1))
#define JACKPOTNUMBER 0x777
class RyujinPESections {
private:
IMAGE_SECTION_HEADER m_newSection;
PIMAGE_DOS_HEADER m_dosHeader;
PIMAGE_NT_HEADERS m_ntHeader;
unsigned char* m_ucModifiedPeMap;
uintptr_t m_szFile;
unsigned char* m_ucResizedPE;
uintptr_t m_szNewSec;
public:
uintptr_t getRyujinSectionVA() {
return m_newSection.VirtualAddress;
}
unsigned char* getRyujinSection() {
return m_ucResizedPE;
}
uintptr_t mappedPeDiskBaseAddress() {
return reinterpret_cast<uintptr_t>(m_dosHeader);
}
uintptr_t getRyujinSectionSize() {
return m_szNewSec;
}
uintptr_t getRyujinMappedPeSize() {
return m_szFile;
}
BOOL AddNewSection(const std::string& strInputFilePath, char chSectionName[8]);
BOOL ProcessOpcodesNewSection(std::vector<unsigned char>& opcodeData);
BOOL FinishNewSection(const std::string& strOutputFilePath);
};

View File

@@ -0,0 +1 @@
#include "RyujinUtils.hh"

View File

@@ -0,0 +1,254 @@
#pragma once
#include <iostream>
#include <memory>
#include <Windows.h>
#define ALIGN_UP(value, alignment) ((value + alignment - 1) & ~(alignment - 1))
namespace RyujinUtils {
inline std::pair<BOOL, uintptr_t> MapPortableExecutableFileIntoMemory(const std::string& m_strInputFilePath, std::shared_ptr<unsigned char>& mappedPE) {
auto hFile = ::CreateFileA(
_In_ m_strInputFilePath.c_str(),
_In_ GENERIC_READ,
_In_ FILE_SHARE_READ | FILE_SHARE_DELETE,
_In_opt_ nullptr,
_In_ OPEN_EXISTING,
_In_ FILE_ATTRIBUTE_NORMAL,
_In_opt_ nullptr
);
if (hFile == INVALID_HANDLE_VALUE) {
OutputDebugStringA(
_In_opt_ "RyujinUtils::MapExecutableFileIntoMemory: failed because cannot open a handle for input PE FILE\n"
);
return std::make_pair(FALSE, 0);
}
LARGE_INTEGER szFile;
if (!::GetFileSizeEx(
_In_ hFile,
_Out_ &szFile
)) {
::OutputDebugStringA(
_In_opt_ "RyujinUtils::MapExecutableFileIntoMemory: was not possible to get filesizeru for the PE FILE\n"
);
::CloseHandle(
_In_ hFile
);
return std::make_pair(FALSE, 0);
}
auto hMap = ::CreateFileMappingA(
_In_ hFile,
_In_opt_ nullptr,
_In_ PAGE_READONLY | SEC_IMAGE,
_In_ NULL,
_In_ NULL,
_In_opt_ nullptr
);
if (!hMap) {
::OutputDebugStringA(
_In_opt_ "RyujinUtils::MapExecutableFileIntoMemory: was not possible to create a mapping to the PE FILE.\n"
);
::CloseHandle(
_In_ hMap
);
return std::make_pair(FALSE, 0);
}
mappedPE = std::shared_ptr<unsigned char>(
reinterpret_cast<unsigned char*>(
::MapViewOfFile(
_In_ hMap,
_In_ FILE_MAP_READ,
_In_ NULL,
_In_ NULL,
_In_ NULL
)
),
[](unsigned char* p) {
if (p) ::UnmapViewOfFile(
_In_ p
);
}
);
::CloseHandle(
_In_ hMap
);
::CloseHandle(
_In_ hFile
);
return std::make_pair(TRUE, szFile.QuadPart);
}
inline void randomizeSectionName(char* chName) {
const char charset[] { "abcdefghijklmnopqrstuvwxyz" };
for (size_t i = 0; i < 8 - 1; ++i) chName[i] = charset[std::rand() % (sizeof(charset) - 1)];
chName[8 - 1] = '\0';
}
inline BOOL SaveBuffer(const std::string& strPath, unsigned char* ucBuffer, uintptr_t szBuffer) {
auto hFile = ::CreateFileA(
_In_ strPath.c_str(),
_In_ GENERIC_WRITE,
_In_ 0,
_In_opt_ nullptr,
_In_ CREATE_ALWAYS,
_In_ FILE_ATTRIBUTE_NORMAL,
_In_opt_ nullptr
);
if (hFile == INVALID_HANDLE_VALUE) return FALSE;
DWORD szWritten{ 0 };
::WriteFile(
_In_ hFile,
_In_ ucBuffer,
_In_ szBuffer,
_Out_ &szWritten,
_Inout_opt_ nullptr
);
::CloseHandle(
_In_ hFile
);
return szWritten == szBuffer;
}
inline std::pair<unsigned char*, SIZE_T> MapDiskPE(const std::string& strPath) {
auto hFile = ::CreateFileA(
_In_ strPath.c_str(),
_In_ GENERIC_READ,
_In_ FILE_SHARE_READ,
_In_opt_ nullptr,
_In_ OPEN_EXISTING,
_In_ FILE_ATTRIBUTE_NORMAL,
_In_opt_ nullptr
);
if (hFile == INVALID_HANDLE_VALUE) return { nullptr, 0 };
LARGE_INTEGER fileSize;
if (!::GetFileSizeEx(
_In_ hFile,
_Out_ &fileSize
) || fileSize.QuadPart == 0) {
::CloseHandle(
_In_ hFile
);
return { nullptr, 0 };
}
SIZE_T outSize = static_cast<SIZE_T>(fileSize.QuadPart);
HANDLE hMapping = ::CreateFileMappingA(
_In_ hFile,
_In_opt_ nullptr,
_In_ PAGE_READONLY,
_In_ 0,
_In_ 0,
_In_opt_ nullptr
);
if (!hMapping) {
::CloseHandle(
_In_ hFile
);
return { nullptr, 0 };
}
auto outData = static_cast<unsigned char*>(::MapViewOfFile(
_In_ hMapping,
_In_ FILE_MAP_READ,
_In_ 0,
_In_ 0,
_In_ 0
));
::CloseHandle(
_In_ hMapping
);
::CloseHandle(
_In_ hFile
);
if (!outData) return { nullptr, 0 };
return { outData, outSize };
}
};

14
RyujinCore/RyujinCore.cc Normal file
View File

@@ -0,0 +1,14 @@
#include "RyujinCore.hh"
RYUJINCORE_API BOOL __stdcall RunRyujinCore(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath, RyujinObfuscatorConfig& config) {
std::unique_ptr<Ryujin> ryujin = std::make_unique<Ryujin>(strInputFilePath, strPdbFilePath, strOutputFilePath);
ryujin.get()->listRyujinProcedures();
ryujin.get()->run(config);
ryujin.reset();
return TRUE;
}

8
RyujinCore/RyujinCore.hh Normal file
View File

@@ -0,0 +1,8 @@
#ifdef RYUJINCORE_EXPORTS
#define RYUJINCORE_API __declspec(dllexport)
#else
#define RYUJINCORE_API __declspec(dllimport)
#endif
#include "Ryujin/Ryujin.hh"
RYUJINCORE_API BOOL __stdcall RunRyujinCore(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath, RyujinObfuscatorConfig &config);

View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{aeff626b-1317-4c8f-94b3-b3d405ae65b2}</ProjectGuid>
<RootNamespace>RyujinCore</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetName>RyujinCore</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>RyujinCore</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>RyujinCore</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TargetName>RyujinCore</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;RYUJINCORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;RYUJINCORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;RYUJINCORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;RYUJINCORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="RyujinCore.hh" />
<ClInclude Include="Ryujin\Models\RyujinBasicBlock.hh" />
<ClInclude Include="Ryujin\Models\RyujinInstruction.hh" />
<ClInclude Include="Ryujin\Models\RyujinObfuscatorConfig.hh" />
<ClInclude Include="Ryujin\Models\RyujinProcedure.hh" />
<ClInclude Include="Ryujin\PDB\RyujinPdbParsing.hh" />
<ClInclude Include="Ryujin\Ryujin.hh" />
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh" />
<ClInclude Include="Ryujin\RyujinCore\RyujinObfuscationCore.hh" />
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh" />
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cc" />
<ClCompile Include="RyujinCore.cc" />
<ClCompile Include="Ryujin\Ryujin.cc" />
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" />
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc" />
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc" />
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Ryujin">
<UniqueIdentifier>{75c5a07c-f3a0-4780-a2d6-82b6c759efbb}</UniqueIdentifier>
</Filter>
<Filter Include="Ryujin\Models">
<UniqueIdentifier>{cf207520-50f1-4f26-9b7d-0a6ad7fd1fb1}</UniqueIdentifier>
</Filter>
<Filter Include="Ryujin\PDB">
<UniqueIdentifier>{81beb1cb-a0b6-4118-8a39-bd558f8f5522}</UniqueIdentifier>
</Filter>
<Filter Include="Ryujin\RyujinCore">
<UniqueIdentifier>{49f30cd7-8ed7-42f3-b599-9f7fddf5c547}</UniqueIdentifier>
</Filter>
<Filter Include="Ryujin\Utils">
<UniqueIdentifier>{4284f652-8f94-493b-acb5-178e17622669}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="RyujinCore.hh">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Ryujin.hh">
<Filter>Ryujin</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Models\RyujinBasicBlock.hh">
<Filter>Ryujin\Models</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Models\RyujinInstruction.hh">
<Filter>Ryujin\Models</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Models\RyujinObfuscatorConfig.hh">
<Filter>Ryujin\Models</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Models\RyujinProcedure.hh">
<Filter>Ryujin\Models</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh">
<Filter>Ryujin\Utils</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh">
<Filter>Ryujin\Utils</Filter>
</ClInclude>
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh">
<Filter>Ryujin\RyujinCore</Filter>
</ClInclude>
<ClInclude Include="Ryujin\RyujinCore\RyujinObfuscationCore.hh">
<Filter>Ryujin\RyujinCore</Filter>
</ClInclude>
<ClInclude Include="Ryujin\PDB\RyujinPdbParsing.hh">
<Filter>Ryujin\PDB</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="RyujinCore.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cc">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Ryujin\Ryujin.cc">
<Filter>Ryujin</Filter>
</ClCompile>
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc">
<Filter>Ryujin\Utils</Filter>
</ClCompile>
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc">
<Filter>Ryujin\Utils</Filter>
</ClCompile>
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc">
<Filter>Ryujin\RyujinCore</Filter>
</ClCompile>
<ClCompile Include="Ryujin\RyujinCore\RyujinObfuscationCore.cc">
<Filter>Ryujin\RyujinCore</Filter>
</ClCompile>
</ItemGroup>
</Project>

2
RyujinCore/cpp.hint Normal file
View File

@@ -0,0 +1,2 @@
#define RYUJINCORE_API __declspec(dllexport)
#define RYUJINCORE_API __declspec(dllimport)

17
RyujinCore/dllmain.cc Normal file
View File

@@ -0,0 +1,17 @@
#include <Windows.h>
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}