TomaHawk Posted March 22, 2015 Posted March 22, 2015 (edited) 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, 2015 by TomaHawk
TomaHawk Posted March 22, 2015 Author Posted March 22, 2015 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; } 1
TomaHawk Posted March 22, 2015 Author Posted March 22, 2015 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; }
TomaHawk Posted March 22, 2015 Author Posted March 22, 2015 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; } }
TomaHawk Posted March 22, 2015 Author Posted March 22, 2015 Align pe DWORD PE_management::PEAlign(DWORD dwTarNum, DWORD dwAlignTo) { return (((dwTarNum + dwAlignTo - 1) / dwAlignTo) * dwAlignTo); }
TomaHawk Posted March 22, 2015 Author Posted March 22, 2015 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); }
TomaHawk Posted March 22, 2015 Author Posted March 22, 2015 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; }
SomethingDarkInsideMe Posted March 22, 2015 Posted March 22, 2015 You should give credits, this is C&P from rohitab
atom0s Posted March 22, 2015 Posted March 22, 2015 You didn't need to make a ton of posts either for each function in the class.. just do it all in one post.. 1
TomaHawk Posted March 22, 2015 Author Posted March 22, 2015 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.
Teddy Rogers Posted March 23, 2015 Posted March 23, 2015 this is just waste of space I see the irony in your post! Ted. 2
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now