Jump to content
View in the app

A better way to browse. Learn more.

Tuts 4 You

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

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

Featured Replies

Posted

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

  • Author

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;
}
  • Author

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;
}
  • Author

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;
}
}
  • Author

Align pe



DWORD PE_management::PEAlign(DWORD dwTarNum, DWORD dwAlignTo)
{
return (((dwTarNum + dwAlignTo - 1) / dwAlignTo) * dwAlignTo);
}
  • Author

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);
}
  • Author

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;
}

You should give credits, this is C&P from rohitab


You didn't need to make a ton of posts either for each function in the class.. just do it all in one post..


  • Author

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.


this is just waste of space 


this is just waste of space 

 

I see the irony in your post!

 

Ted.

:woot:


Create an account or sign in to comment

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.