From dff74ed8b9235c2b1c063f685b3ca6c7e6eb635c Mon Sep 17 00:00:00 2001 From: keowu Date: Sun, 25 May 2025 11:22:15 -0300 Subject: [PATCH] feat: Finished logic for add new section, Fixed variable bugs, New Utils functions and mroe - Finished the logic for add new segments. - Moved the segments code to a independent class for PESections. - New method utils. - Bug fixies. - Code organization. --- RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc | 16 +- RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh | 7 +- .../Ryujin/Utils/RyujinPESections.cc | 152 ++++++++++++++ .../Ryujin/Utils/RyujinPESections.hh | 45 +++++ .../RyujinConsole/Ryujin/Utils/RyujinUtils.hh | 190 +++++++++++------- .../RyujinConsole/RyujinConsole.vcxproj | 2 + .../RyujinConsole.vcxproj.filters | 6 + 7 files changed, 342 insertions(+), 76 deletions(-) create mode 100644 RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.cc create mode 100644 RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.hh diff --git a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc index f72446b..763498a 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc +++ b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.cc @@ -1,7 +1,10 @@ #include "Ryujin.hh" -Ryujin::Ryujin(const std::string& strInputFilePath, const std::string& strPdbFilePath, const std::string& strOutputFilePath) : -m_strInputFilePath(strInputFilePath), m_strOutputFilePath(strOutputFilePath), m_strPdbFilePath(strPdbFilePath) { +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); @@ -148,11 +151,18 @@ bool Ryujin::run(const RyujinObfuscatorConfig& config) { //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); + + RyujinPESections peSections; + peSections.AddNewSection(m_strInputFilePath, chSectionName); + + //Process new opcodes + std::vector tempValued = { 0xDE, 0xAD, 0xBE, 0xEF }; + peSections.ProcessOpcodesNewSection(tempValued); //Fix relocations //Save output file + peSections.FinishNewSection(m_strOutputFilePath); } diff --git a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh index bbe290e..875b5b5 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh +++ b/RyujinConsole/RyujinConsole/Ryujin/Ryujin.hh @@ -8,14 +8,15 @@ #include "Utils/RyujinUtils.hh" #include "Models/RyujinObfuscatorConfig.hh" #include "RyujinCore/BasicBlockerBuilder.hh" +#include "Utils/RyujinPESections.hh" class Ryujin { private: std::shared_ptr m_mappedPE; - const std::string& m_strInputFilePath; - const std::string& m_strPdbFilePath; - const std::string& m_strOutputFilePath; + std::string m_strInputFilePath; + std::string m_strPdbFilePath; + std::string m_strOutputFilePath; uintptr_t m_szFile; BOOL m_isInitialized; std::vector m_ryujinProcedures; diff --git a/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.cc b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.cc new file mode 100644 index 0000000..dc2c8c8 --- /dev/null +++ b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.cc @@ -0,0 +1,152 @@ +#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(m_ucModifiedPeMap); + if (m_dosHeader->e_magic != IMAGE_DOS_SIGNATURE) { + + delete[] m_ucModifiedPeMap; + + return FALSE; + } + + m_ntHeader = reinterpret_cast(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.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ; + + return TRUE; +} + +BOOL RyujinPESections::ProcessOpcodesNewSection(std::vector& 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(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; + + delete[] m_ucModifiedPeMap; + + return TRUE; +} \ No newline at end of file diff --git a/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.hh b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.hh new file mode 100644 index 0000000..1fc55e5 --- /dev/null +++ b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.hh @@ -0,0 +1,45 @@ +#pragma once +#include +#include +#include +#include + +#include "RyujinUtils.hh" + +#define ALIGN_UP(value, alignment) ((value + alignment - 1) & ~(alignment - 1)) + +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 getRyujinSectionSize() { + + return m_szNewSec; + } + + BOOL AddNewSection(const std::string& strInputFilePath, char chSectionName[8]); + + BOOL ProcessOpcodesNewSection(std::vector& opcodeData); + + BOOL FinishNewSection(const std::string& strOutputFilePath); + +}; \ No newline at end of file diff --git a/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh index 68e04fb..8dc92f9 100644 --- a/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh +++ b/RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinUtils.hh @@ -123,76 +123,6 @@ 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" }; @@ -201,5 +131,125 @@ namespace RyujinUtils { } + 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 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(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(::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 }; + } + }; diff --git a/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj b/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj index e4934a2..2c0ed01 100644 --- a/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj +++ b/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj @@ -134,6 +134,7 @@ + @@ -144,6 +145,7 @@ + diff --git a/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj.filters b/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj.filters index e20b699..0c91088 100644 --- a/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj.filters +++ b/RyujinConsole/RyujinConsole/RyujinConsole.vcxproj.filters @@ -42,6 +42,9 @@ Ryujin\RyujinCore + + Ryujin\Utils + @@ -68,5 +71,8 @@ Ryujin\RyujinCore + + Ryujin\Utils + \ No newline at end of file