Posted March 22, 201510 yr 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 March 22, 201510 yr by TomaHawk
March 22, 201510 yr 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; }
March 22, 201510 yr 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; }
March 22, 201510 yr 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; } }
March 22, 201510 yr Author Align pe DWORD PE_management::PEAlign(DWORD dwTarNum, DWORD dwAlignTo) { return (((dwTarNum + dwAlignTo - 1) / dwAlignTo) * dwAlignTo); }
March 22, 201510 yr 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); }
March 22, 201510 yr 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; }
March 22, 201510 yr You didn't need to make a ton of posts either for each function in the class.. just do it all in one post..
March 22, 201510 yr 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.
Create an account or sign in to comment