Jump to content
Tuts 4 You

[C++ Source] - Important PE functions (x86 & x64)


TomaHawk

Recommended Posts

Source code in OOP C++ for the Windows PE.


 


In the next post I will post the source code of the functions, in this one I will post the header of it.


Note that the most of the functions are coded by steve10120, but I modified/added some things to make it work for x64 files too and for windows 7+.


 


PE.h



#ifndef PEH
#define PEH
#include <vcl.h>
class PE_management
{
protected:
HANDLE hOpenFile;
HANDLE hOpenFileMapping; public:
HANDLE hFile; PIMAGE_DOS_HEADER pIDH;
PIMAGE_NT_HEADERS32 pINH;
PIMAGE_SECTION_HEADER pIFS;
PIMAGE_SECTION_HEADER sectionHeaderOfOEP;
PIMAGE_IMPORT_DESCRIPTOR pIID; String fileName;
unsigned int sizeOfFile;
DWORD oep;
DWORD imageBase;
int sectionCount; bool mapFile(const wchar_t* szFilePath, unsigned int newSectionSize);
bool unmapFile();
bool AddSection(AnsiString sectionName, unsigned int sectionSize, DWORD permission);
DWORD Rva2Offset(DWORD rva, PIMAGE_SECTION_HEADER psh, PIMAGE_NT_HEADERS32 pnt);
DWORD PEAlign(DWORD dwRealSize, DWORD dwAlign);
PIMAGE_SECTION_HEADER getSectionHeaderFromAddress(DWORD address);
};
#endif

Edited by TomaHawk
Link to comment

Map PE into memory



/** Description:
Map the file in memory so we are able to modify the file.
When modifying is done, we have to call the unmapFile()-function
to save the modifications. Return:
Success: TRUE || Failure: FALSE **/
bool PE_management::mapFile(const wchar_t* szFilePath, unsigned int newSectionSize)
{
this->hOpenFile = 0;
this->hOpenFileMapping = 0;
this->hFile = 0; this->pIDH = 0;
this->pINH = 0;
this->pIFS = 0;
this->pIID = 0;
this->sizeOfFile = 0;
this->imageBase = 0;
this->oep = 0;
this->fileName = 0; // Check if the target is a 32-bit or a 64-bit file.
/**
unsigned long type = 0;
if (GetBinaryTypeW(szFilePath, &type) == false)
{
return false;
}
else if (type != SCS_32BIT_BINARY)
{
return false;
}
**/
// Open and map the file into memory.
this->hOpenFile = CreateFileW(szFilePath, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (this->hOpenFile == INVALID_HANDLE_VALUE)
{
return false;
} this->sizeOfFile = GetFileSize(this->hOpenFile, NULL);
if (this->sizeOfFile == INVALID_FILE_SIZE)
{
CloseHandle(this->hOpenFile); return false;
} // Update the file-size when a new section is added.
this->sizeOfFile += newSectionSize; this->hOpenFileMapping = CreateFileMapping(this->hOpenFile, NULL, PAGE_READWRITE, 0, this->sizeOfFile, NULL);
if (this->hOpenFileMapping == NULL)
{
CloseHandle(this->hOpenFile); return false;
}
this->hFile = (LPBYTE)MapViewOfFile(this->hOpenFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, this->sizeOfFile);
if (this->hFile == NULL)
{
CloseHandle(this->hOpenFileMapping);
CloseHandle(this->hOpenFile); return false;
} // Collect information from the mapped target.
this->fileName = szFilePath;
this->pIDH = (PIMAGE_DOS_HEADER) this->hFile;
this->pINH = (PIMAGE_NT_HEADERS32) (DWORD(hFile) + this->pIDH->e_lfanew);
this->pIFS = IMAGE_FIRST_SECTION(this->pINH);
this->sectionCount = pINH->FileHeader.NumberOfSections;
this->pIID = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)this->hFile + Rva2Offset(this->pINH->OptionalHeader.DataDirectory[1].VirtualAddress, this->pIFS, this->pINH)); this->imageBase = this->pINH->OptionalHeader.ImageBase;
this->oep = this->pINH->OptionalHeader.AddressOfEntryPoint;
this->sectionHeaderOfOEP = this->getSectionHeaderFromAddress(this->oep); return true;
}
  • Like 1
Link to comment

Unmap the file from memory



/** Description:
Unmap the file from memory and save any changes made to the file-map. Return:
Success: TRUE || Failure: FALSE **/
bool PE_management::unmapFile()
{
if (UnmapViewOfFile(this->hFile) == false)
{
ShowMessage(LoadStr(12));
return false;
} if (CloseHandle(this->hOpenFileMapping) == false)
{
ShowMessage(LoadStr(13));
return false;
} if (CloseHandle(this->hOpenFile) == false)
{
ShowMessage(LoadStr(14));
return false;
} return true;
}
Link to comment

Add a new section to the PE file (partial credits to steve10120)



/** Description:
Adds a new PE-section to the target. (x86 & x64) Return:
Success: TRUE || Failure: FALSE **/
bool PE_management::AddSection(AnsiString sectionName, unsigned int sectionSize, DWORD permission)
{
DWORD roffset = 0;
DWORD rsize = 0;
DWORD voffset = 0;
DWORD vsize = 0;
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(this->pINH) + this->pINH->FileHeader.NumberOfSections - 1;
int sectionNameLenght = 0;
if (pSection == 0)
{
return false;
}
rsize = PEAlign(sectionSize, this->pINH->OptionalHeader.SectionAlignment);;
vsize = sectionSize;
roffset = PEAlign(pSection->PointerToRawData + pSection->SizeOfRawData, this->pINH->OptionalHeader.FileAlignment);
voffset = PEAlign(pSection->VirtualAddress + pSection->Misc.VirtualSize, this->pINH->OptionalHeader.SectionAlignment);
// Since the bound imports are no longer effective with the introduction of ASLR (Windows Vista+),
// we can just set its RVA and size fields to zero. Also this prevent crashing for 64-bit files.
this->pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
this->pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
pSection++;
memset(pSection, 0, (size_t)sizeof(IMAGE_SECTION_HEADER));
pSection->PointerToRawData = roffset;
pSection->VirtualAddress = voffset;
pSection->SizeOfRawData = rsize;
pSection->Misc.VirtualSize = vsize;
pSection->Characteristics = permission; this->pINH->FileHeader.NumberOfSections += 1;
this->pINH->OptionalHeader.SizeOfImage = pSection->VirtualAddress + pSection->Misc.VirtualSize;
// Assign new section-name, which shouldn't be more then 8 chars in length.
sectionNameLenght = sectionName.Length();
if (sectionNameLenght <= 8)
{
memcpy(pSection->Name, sectionName.c_str(), sectionNameLenght); return true;
}
else
{
return false;
}
}
Link to comment

Align pe



DWORD PE_management::PEAlign(DWORD dwTarNum, DWORD dwAlignTo)
{
return (((dwTarNum + dwAlignTo - 1) / dwAlignTo) * dwAlignTo);
}
Link to comment

Relative address to offset address



DWORD PE_management::Rva2Offset(DWORD rva,PIMAGE_SECTION_HEADER psh, PIMAGE_NT_HEADERS pnt)
{
signed int i = 0;
PIMAGE_SECTION_HEADER pSeh; if (rva == 0)
{
return (rva);
} pSeh = psh;
for (i = 0; i < pnt->FileHeader.NumberOfSections; i++)
{
if (rva >= pSeh->VirtualAddress && rva < pSeh->VirtualAddress + pSeh->Misc.VirtualSize)
{
break;
} pSeh++;
}
return (rva - pSeh->VirtualAddress + pSeh->PointerToRawData);
}
Link to comment

Get the section header from a address



PIMAGE_SECTION_HEADER PE_management::getSectionHeaderFromAddress(DWORD address)
{
PIMAGE_SECTION_HEADER sectionheader = this->pIFS;
for (int count = 0; count < this->sectionCount; count++)
{
// Check if address is between the section start and section end.
if (address >= sectionheader->VirtualAddress && address < sectionheader->VirtualAddress + sectionheader->Misc.VirtualSize)
{
return sectionheader;
break;
}
sectionheader++;
} return 0;
}
Link to comment

SomethingDarkInsideMe, partically you're wrong. From rohitab, no, from steve10120, yes.


Also not just c/p, some of the functions needed small fixes to work for windows 7+.


 


But let me add credits to the first post where needed.


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...