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:
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
152
RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.cc
Normal file
152
RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.cc
Normal 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;
|
||||
}
|
||||
45
RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.hh
Normal file
45
RyujinConsole/RyujinConsole/Ryujin/Utils/RyujinPESections.hh
Normal 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);
|
||||
|
||||
};
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user