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.
This commit is contained in:
keowu
2025-05-25 11:22:15 -03:00
parent 43b50dffe4
commit dff74ed8b9
7 changed files with 342 additions and 76 deletions

View File

@@ -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<unsigned char> tempValued = { 0xDE, 0xAD, 0xBE, 0xEF };
peSections.ProcessOpcodesNewSection(tempValued);
//Fix relocations
//Save output file
peSections.FinishNewSection(m_strOutputFilePath);
}

View File

@@ -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<unsigned char> 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<RyujinProcedure> m_ryujinProcedures;

View File

@@ -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<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.Characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ;
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;
delete[] m_ucModifiedPeMap;
return TRUE;
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include <iostream>
#include <memory>
#include <vector>
#include <Windows.h>
#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<unsigned char>& opcodeData);
BOOL FinishNewSection(const std::string& strOutputFilePath);
};

View File

@@ -123,76 +123,6 @@ namespace RyujinUtils {
return std::make_pair(TRUE, szFile.QuadPart);
}
inline BOOL AddNewSection(std::shared_ptr<unsigned char>& mappedPE, uintptr_t szFile, char chSectionName[8]) {
auto ucModifiedPeMap = new unsigned char[szFile] { 0 };
std::memcpy(
ucModifiedPeMap,
mappedPE.get(),
szFile
);
auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(ucModifiedPeMap);
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
delete[] ucModifiedPeMap;
return FALSE;
}
auto ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(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<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 };
}
};

View File

@@ -134,6 +134,7 @@
<ClCompile Include="RyujinConsole.cc" />
<ClCompile Include="Ryujin\Ryujin.cc" />
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc" />
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc" />
<ClCompile Include="Ryujin\Utils\RyujinUtils.cc" />
</ItemGroup>
<ItemGroup>
@@ -144,6 +145,7 @@
<ClInclude Include="Ryujin\PDB\RyujinPdbParsing.hh" />
<ClInclude Include="Ryujin\Ryujin.hh" />
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh" />
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh" />
<ClInclude Include="Ryujin\Utils\RyujinUtils.hh" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@@ -42,6 +42,9 @@
<ClCompile Include="Ryujin\RyujinCore\BasicBlockerBuilder.cc">
<Filter>Ryujin\RyujinCore</Filter>
</ClCompile>
<ClCompile Include="Ryujin\Utils\RyujinPESections.cc">
<Filter>Ryujin\Utils</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Ryujin\Models\RyujinBasicBlock.hh">
@@ -68,5 +71,8 @@
<ClInclude Include="Ryujin\RyujinCore\BasicBlockerBuilder.hh">
<Filter>Ryujin\RyujinCore</Filter>
</ClInclude>
<ClInclude Include="Ryujin\Utils\RyujinPESections.hh">
<Filter>Ryujin\Utils</Filter>
</ClInclude>
</ItemGroup>
</Project>