diff --git a/RyujinConsole/RyujinConsole/Ryujin/Models/RyujinObfuscatorConfig.hh b/RyujinConsole/RyujinConsole/Ryujin/Models/RyujinObfuscatorConfig.hh index 966eb48..1c8f13f 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Models/RyujinObfuscatorConfig.hh +++ b/RyujinConsole/RyujinConsole/Ryujin/Models/RyujinObfuscatorConfig.hh @@ -2,8 +2,9 @@ class RyujinObfuscatorConfig { public: - bool m_isRandomSection; // Randomize the name of the new section with the processed code -> Ryujin standard + 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) std::vector m_strProceduresToObfuscate; // Names of the procedures to obfuscate diff --git a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc index 224e593..f72446b 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc +++ b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc @@ -97,7 +97,12 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) { if (it == config.m_strProceduresToObfuscate.end()) continue; - std::printf("[WORKING ON]: %s\n", proc.name.c_str()); + std::printf( + + "[WORKING ON]: %s\n", + proc.name.c_str() + + ); // Is a valid procedure ? if (proc.size == 0) { @@ -125,11 +130,30 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) { 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 ? + if (config.m_isVirtualized) todoAction(); + if (config.m_isIatObfuscation) todoAction(); + if (config.m_isJunkCode) todoAction(); + + //TODO: Custom passes support + //Clean up opcodes delete[] ucOpcodes; } + //More obfuscation + if (config.m_isIgnoreOriginalCodeRemove) todoAction(); + + //Add section + char chSectionName[8]{ '.', 'R', 'y', 'u', 'j', 'i', 'n', '\0' }; + if (config.m_isRandomSection) RyujinUtils::randomizeSectionName(chSectionName); + RyujinUtils::AddNewSection(m_mappedPE, m_szFile, chSectionName); + + //Fix relocations + + //Save output file + } void Ryujin::listRyujinProcedures() { diff --git a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh index b32a8cb..bbe290e 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh +++ b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh @@ -20,6 +20,8 @@ private: BOOL m_isInitialized; std::vector 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); diff --git a/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh index 6290b77..68e04fb 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh +++ b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh @@ -3,6 +3,8 @@ #include #include +#define ALIGN_UP(value, alignment) ((value + alignment - 1) & ~(alignment - 1)) + namespace RyujinUtils { inline std::pair MapPortableExecutableFileIntoMemory(const std::string& m_strInputFilePath, std::shared_ptr& mappedPE) { @@ -121,5 +123,83 @@ namespace RyujinUtils { return std::make_pair(TRUE, szFile.QuadPart); } + inline BOOL AddNewSection(std::shared_ptr& mappedPE, uintptr_t szFile, char chSectionName[8]) { + + auto ucModifiedPeMap = new unsigned char[szFile] { 0 }; + std::memcpy( + + ucModifiedPeMap, + mappedPE.get(), + szFile + + ); + + auto dosHeader = reinterpret_cast(ucModifiedPeMap); + if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + + delete[] ucModifiedPeMap; + + return FALSE; + } + + auto ntHeaders = reinterpret_cast(ucModifiedPeMap + dosHeader->e_lfanew); + if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) { + + delete[] ucModifiedPeMap; + + return FALSE; + } + + auto sectionTableSize = ntHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); + if (dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sectionTableSize > ntHeaders->OptionalHeader.SizeOfHeaders) { + + //No space to insert a new section on this PE FILE :( + + delete[] ucModifiedPeMap; + + return FALSE; + } + + //Adding the new section + IMAGE_SECTION_HEADER newSection{ 0 }; + std::memcpy( + + newSection.Name, + chSectionName, + sizeof(chSectionName) + + ); + + auto imgLastSection = IMAGE_FIRST_SECTION(ntHeaders) + (ntHeaders->FileHeader.NumberOfSections - 1); + + newSection.VirtualAddress = ALIGN_UP( + imgLastSection->VirtualAddress + imgLastSection->Misc.VirtualSize, + ntHeaders->OptionalHeader.SectionAlignment + ); + + newSection.PointerToRawData = ALIGN_UP( + imgLastSection->PointerToRawData + imgLastSection->SizeOfRawData, + ntHeaders->OptionalHeader.FileAlignment + ); + + newSection.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ; + + //Return the following in order to put data and calculate relocs: + //newSection.VirtualAddress + //newSection.Misc.VirtualSize = size of new code; + //newSection.SizeOfRawData = ALIGN_UP(size of new code, ntHeaders->OptionalHeader.FileAlignment); + //Maybe is better wrap this things in a full new class ?? + + return FALSE; + } + + 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'; + + } + };