#include "PEOptions.h" #if !defined(PE_NO_PEFILEEX) #include #include "PEFileEx.h" #if !defined(PE_NO_MESSAGE) #include "message.h" #endif // !PE_NO_MESSAGE #include "MemLib.h" #include "StrLib.h" #if !defined(PE_NO_LOGFILE) #include "LogFile.h" #endif // !PE_NO_LOGFILE #include #include BOOL BlankFill=FALSE; // Check if EXE is a PE file BOOL bIsPEFile(unsigned char *lpBuffer) { // MZ file if (*(USHORT *)lpBuffer != IMAGE_DOS_SIGNATURE) { #if !defined(PE_NO_MESSAGE) ErrorMessage("Not an EXE file.\n"); #endif // !PE_NO_MESSAGE return(FALSE); } else { // PE file if (*(DWORD *)NTSIGNATURE (lpBuffer) != IMAGE_NT_SIGNATURE) { #if !defined(PE_NO_MESSAGE) ErrorMessage("Not a PE EXE file.\n"); return(FALSE); #endif // !PE_NO_MESSAGE } } return(TRUE); } // To align size :Vital under NT unsigned long ulAlignOn(unsigned long ulValue,unsigned ulAlignment) { if (ulValue>0) ulValue--; ulValue/=ulAlignment;ulValue++;ulValue*=ulAlignment; return(ulValue); } unsigned long ulAlignOnSection(LPPEFILE *lpPEFile,unsigned long ulValue) { PIMAGE_OPTIONAL_HEADER lpPEOptionalHeader=(*lpPEFile)->PEFileHeader.lpPEOptionalHeader; return(ulAlignOn(ulValue,lpPEOptionalHeader->SectionAlignment)); } unsigned long ulAlignOnFile(LPPEFILE *lpPEFile,unsigned long ulValue) { PIMAGE_OPTIONAL_HEADER lpPEOptionalHeader=(*lpPEFile)->PEFileHeader.lpPEOptionalHeader; return(ulAlignOn(ulValue,lpPEOptionalHeader->FileAlignment)); } BOOL bFillSection(LPPEFILE *lpPEFile,int lSectionIndex,unsigned long ulOffset,char *lpBuffer,unsigned long ulSize) { return(FALSE); } // find section with index LPPESECTION lpFindSectionWithIndex(LPPEFILE *lpPEFile,int lSectionIndex) { LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; int n=0; while (lpPESection!=NULL) { if (n==lSectionIndex) { return(lpPESection); } n++; lpPESection=lpPESection->lpNextSection; } return(NULL); } // find section with name LPPESECTION lpFindSectionWithName(LPPEFILE *lpPEFile,char *szName) { LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; while (lpPESection!=NULL) { if (!StringNICompare((char*) lpPESection->lpSectionHeader->Name,szName,StringLength(szName))) { return(lpPESection); } lpPESection=lpPESection->lpNextSection; } return(NULL); } // find section with rva LPPESECTION lpFindSectionWithRVA(LPPEFILE *lpPEFile,DWORD RVA) { LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; while (lpPESection!=NULL) { DWORD dwSize=lpPESection->lpSectionHeader->Misc.VirtualSize; // mouais if (!dwSize) dwSize=lpPESection->lpSectionHeader->SizeOfRawData; if ( (lpPESection->lpSectionHeader->VirtualAddress<=RVA) && (RVAlpSectionHeader->VirtualAddress+dwSize) ) { return(lpPESection); } lpPESection=lpPESection->lpNextSection; } return(NULL); } // find section with file offest LPPESECTION lpFindSectionWithOffset(LPPEFILE *lpPEFile,unsigned long ulOffset) { LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; while (lpPESection!=NULL) { if ( (lpPESection->lpSectionHeader->PointerToRawData<=ulOffset) && (ulOffsetlpSectionHeader->PointerToRawData+lpPESection->lpSectionHeader->SizeOfRawData) ) { return(lpPESection); } lpPESection=lpPESection->lpNextSection; } return(NULL); } // find section with pointer in lpPEFile LPPESECTION lpFindSectionWithPointer(LPPEFILE *lpPEFile,unsigned char *ucPtr) { LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; while (lpPESection!=NULL) { if ( (lpPESection->lpBuffer<=ucPtr) && (ucPtrlpBuffer+lpPESection->ulSize)) { return(lpPESection); } lpPESection=lpPESection->lpNextSection; } return(NULL); } int lGetSectionIndex(LPPEFILE *lpPEFile,LPPESECTION lpPESectionToSearch) { LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; int n=0; while (lpPESection!=NULL) { if (lpPESection==lpPESectionToSearch) { return(n); } lpPESection=lpPESection->lpNextSection; } return(C_INVALID_SECTION); } unsigned char RandomChar() { return((unsigned char) rand()); } void FillWithRandom(unsigned char *lpBuffer,unsigned long ulSize) { unsigned long n; static int init=0; if (!init) { srand( (unsigned)time( NULL ) ); init=1; } if (ulSize>0) { for (n=0;nPEFileHeader.ulSize = ulSize; (*lpPEFile)->PEFileHeader.lpBuffer=lpBuffer; lpBuffer += SIZE_OF_NT_SIGNATURE; (*lpPEFile)->PEFileHeader.lpPEHeader=(PIMAGE_FILE_HEADER) lpBuffer; lpBuffer += sizeof (IMAGE_FILE_HEADER); (*lpPEFile)->PEFileHeader.lpPEOptionalHeader=(PIMAGE_OPTIONAL_HEADER) lpBuffer; lpBuffer += sizeof (IMAGE_OPTIONAL_HEADER); (*lpPEFile)->PEFileHeader.lpSectionHeader=(PIMAGE_SECTION_HEADER) lpBuffer; } void vDonePEStructure(LPPEFILE *lpPEFile) { if(*lpPEFile!=NULL) { unsigned char *lpTempBuffer; // free debug lpTempBuffer=(*lpPEFile)->PEDebug.lpBuffer; if (lpTempBuffer) { MemoryFree((void**) &lpTempBuffer); } // free PESection { int nSections=(*lpPEFile)->PEFileHeader.lpPEHeader->NumberOfSections; int ok=0; LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; LPPESECTION lpPESectionNext=NULL; while (lpPESection!=NULL) { if (lpPESection->lpBuffer!=NULL) { MemoryFree((void**) &lpPESection->lpBuffer); } else { ok=ok; } lpPESectionNext=lpPESection->lpNextSection; MemoryFree((void**) &lpPESection); lpPESection=lpPESectionNext; ok++; } if (ok!=nSections) { #if defined(_DEBUG) __asm int 3; #endif } } // free PEHeader lpTempBuffer=(*lpPEFile)->PEFileHeader.lpBuffer; if (lpTempBuffer) { MemoryFree((void**) &lpTempBuffer); } // free DOSHeader lpTempBuffer=(*lpPEFile)->PEDosHeader.lpBuffer; if (lpTempBuffer) { MemoryFree((void**) &lpTempBuffer); } // free container MemoryFree((void**) lpPEFile); lpPEFile=NULL; } } BOOL bInitPEStructure(char *filename,unsigned char *lpBuffer,unsigned long ulSize,LPPEFILE *lpPEFile) { BOOL bRet=FALSE; if (lpPEFile!=NULL) *lpPEFile=NULL; if ( (lpPEFile!=NULL) && (bIsPEFile(lpBuffer)) ) { // alloc container *lpPEFile=(LPPEFILE) MemoryAlloc(sizeof(PEFILE)); if (*lpPEFile!=NULL) { PIMAGE_DOS_HEADER pDosHeader=(PIMAGE_DOS_HEADER) lpBuffer; PIMAGE_FILE_HEADER pPEHeader=(PIMAGE_FILE_HEADER) PEFHDROFFSET (lpBuffer); PIMAGE_OPTIONAL_HEADER pPEOptionalHeader=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpBuffer); PIMAGE_SECTION_HEADER pSectionHeader=(PIMAGE_SECTION_HEADER) SECHDROFFSET (lpBuffer); int nSections= NumOfSections(lpBuffer); unsigned char *lpTempBuffer=NULL; unsigned long ulTempSize=0; #if defined(_CONSOLE) printf("PE informations : %s\n",filename); printf(" Image base : %08X\n",pPEOptionalHeader->ImageBase); printf(" Entry point : %08X\n",pPEOptionalHeader->AddressOfEntryPoint); printf(" Size of code : %08X\n",pPEOptionalHeader->SizeOfCode); printf(" Size of data : %08X (initialized)\n",pPEOptionalHeader->SizeOfInitializedData); printf(" : %08X (uninitialized)\n",pPEOptionalHeader->SizeOfUninitializedData); printf(" File alignment: %08X\n",pPEOptionalHeader->FileAlignment); printf("\nNumber of object(s) : %d Alignment : %08X \n",nSections,pPEOptionalHeader->SectionAlignment); #else #if !defined(PE_NO_LOGFILE) WriteLogFile("PE informations : %s",filename); WriteLogFile(" Image base : %08X",pPEOptionalHeader->ImageBase); WriteLogFile(" Entry point : %08X",pPEOptionalHeader->AddressOfEntryPoint); WriteLogFile(" Size of code : %08X",pPEOptionalHeader->SizeOfCode); WriteLogFile(" Size of data : %08X (initialized)",pPEOptionalHeader->SizeOfInitializedData); WriteLogFile(" : %08X (uninitialized)",pPEOptionalHeader->SizeOfUninitializedData); WriteLogFile(" File alignment: %08X",pPEOptionalHeader->FileAlignment); WriteLogFile("\nNumber of object(s) : %d Alignment : %08X",nSections,pPEOptionalHeader->SectionAlignment); #endif // !PE_NO_LOGFILE #endif MemorySet(*lpPEFile,0,sizeof(PEFILE)); // alloc DOSHeader ulTempSize=pDosHeader->e_lfanew; lpTempBuffer=(unsigned char *) MemoryAlloc(ulTempSize); if (lpTempBuffer) { (*lpPEFile)->PEDosHeader.ulSize=ulTempSize; (*lpPEFile)->PEDosHeader.lpBuffer=lpTempBuffer; MemoryCopy(lpTempBuffer,pDosHeader,ulTempSize); lpTempBuffer=(*lpPEFile)->PEDosHeader.lpBuffer+(unsigned long) ((unsigned char*) pDosHeader - (unsigned char*) pDosHeader); (*lpPEFile)->PEDosHeader.lpDosHeader=(PIMAGE_DOS_HEADER) lpTempBuffer; // alloc all PEHeader ulTempSize=pPEOptionalHeader->SizeOfHeaders-(*lpPEFile)->PEDosHeader.ulSize; lpTempBuffer=(unsigned char *) MemoryAlloc(ulTempSize); if (lpTempBuffer) { MemoryCopy(lpTempBuffer,((unsigned char*) pPEHeader) - SIZE_OF_NT_SIGNATURE,ulTempSize); vInitPEFileHeader(lpPEFile,lpTempBuffer,ulTempSize); if (BlankFill) { int nSections=(*lpPEFile)->PEFileHeader.lpPEHeader->NumberOfSections; unsigned long ulDeltaSize; ulDeltaSize =(unsigned long) &((*lpPEFile)->PEFileHeader.lpSectionHeader[nSections]); ulDeltaSize-=(unsigned long) lpTempBuffer; ulTempSize-=ulDeltaSize; if (ulTempSize>0) { lpTempBuffer+=ulDeltaSize; FillWithRandom(lpTempBuffer,ulTempSize); } } // alloc sections { int n; int nSections=(*lpPEFile)->PEFileHeader.lpPEHeader->NumberOfSections; LPPESECTION lpPESection=NULL; LPPESECTION lpPEPreviousSection=NULL; LPPESECTION *lplpPEPreviousSection=&((*lpPEFile)->lpPESectionList); for(n=0;nulSize=ulTempSize; lpPESection->lpBuffer=lpTempBuffer; // for patched exe if (pSectionHeader[n].PointerToRawData+ulTempSize>ulSize) { bRet=FALSE; } else { lpTempBuffer=lpBuffer+pSectionHeader[n].PointerToRawData; MemoryCopy(lpPESection->lpBuffer,lpTempBuffer,ulTempSize); } } else { // cf .bss section lpPESection->ulSize=0; lpPESection->lpBuffer=NULL; } lpPESection->lpSectionHeader=&((*lpPEFile)->PEFileHeader.lpSectionHeader[n]); lpPESection->lpPreviousSection=lpPEPreviousSection; lpPESection->lpNextSection=NULL; lpPEPreviousSection=lpPESection; lplpPEPreviousSection=&(lpPESection->lpNextSection); #if defined(_CONSOLE) printf( " Object%02d: %s\n" " RVA : %08X Virtual Size: %08X Flags : %08X\n" " Offset: %08X Real Size : %08X Free Size: %08X\n", n+1, pSectionHeader[n].Name, pSectionHeader[n].VirtualAddress ,pSectionHeader[n].SizeOfRawData ,pSectionHeader[n].Characteristics, pSectionHeader[n].PointerToRawData ,pSectionHeader[n].Misc.VirtualSize ,pSectionHeader[n].SizeOfRawData-pSectionHeader[n].Misc.VirtualSize ); #else #if !defined(PE_NO_LOGFILE) WriteLogFile( " Object%02d: %s\n" " RVA : %08X Virtual Size: %08X Flags : %08X\n" " Offset: %08X Real Size : %08X Free Size: %08X", n+1, pSectionHeader[n].Name, pSectionHeader[n].VirtualAddress ,pSectionHeader[n].SizeOfRawData ,pSectionHeader[n].Characteristics, pSectionHeader[n].PointerToRawData ,pSectionHeader[n].Misc.VirtualSize ,pSectionHeader[n].SizeOfRawData-pSectionHeader[n].Misc.VirtualSize ); #endif // !PE_NO_LOGFILE #endif // Fill blank with random value if (BlankFill) { lpTempBuffer=lpPESection->lpBuffer; if (lpTempBuffer!=NULL) { ulTempSize=pSectionHeader[n].SizeOfRawData-pSectionHeader[n].Misc.VirtualSize; if (((signed long)ulTempSize)>0) { // cf .bss section if (pSectionHeader[n].Misc.VirtualSize) { lpTempBuffer+=pSectionHeader[n].Misc.VirtualSize; FillWithRandom(lpTempBuffer,ulTempSize); } } // dangerous but ....... //pSectionHeader[n].Misc.VirtualSize=pSectionHeader[n].SizeOfRawData; } } } else { break; } } if (n==nSections) { bRet=TRUE; // no debug info if (pPEHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) { bRet=TRUE; } else { // remove debug info (*lpPEFile)->PEFileHeader.lpPEHeader->Characteristics &= ~IMAGE_FILE_DEBUG_STRIPPED; (*lpPEFile)->PEFileHeader.lpPEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress=0; (*lpPEFile)->PEFileHeader.lpPEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size=0; bRet=TRUE; /* (*lpPEFile)->PEFileHeader.lpPEHeader->Characteristics |= IMAGE_FILE_DEBUG_STRIPPED; (*lpPEFile)->PEFileHeader.lpPEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress=0x120000; (*lpPEFile)->PEFileHeader.lpPEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size=0x1FFFFFFF; */ /* { PIMAGE_DEBUG_DIRECTORY pdd,pdd0; PIMAGE_DEBUG_MISC pdm = NULL; ulTempSize=0; if ((pdd0 = (PIMAGE_DEBUG_DIRECTORY)ImageDirectoryOffset (lpBuffer, IMAGE_DIRECTORY_ENTRY_DEBUG))) { pdd=pdd0; while (pdd->SizeOfData) { ulTempSize+=pdd->SizeOfData; pdd++; } } if (ulTempSize!=0) { lpTempBuffer=(unsigned char *) MemoryAlloc(ulTempSize); if (lpTempBuffer) { (*lpPEFile)->PEDebug.ulSize=ulTempSize; (*lpPEFile)->PEDebug.lpBuffer=lpTempBuffer; // source lpTempBuffer=(unsigned char*) pdd0; MemoCopy((*lpPEFile)->PEDebug.lpBuffer,lpTempBuffer,ulTempSize); bRet=TRUE; } } } */ } } } } } } if (bRet==FALSE) { #if !defined(PE_NO_MESSAGE) ErrorMessage("Cannot init PE structure for %s.\n",filename); #endif // !PE_NO_MESSAGE vDonePEStructure(lpPEFile); } /* else { LPPESECTION lpPESection=NULL; if ( ((lpPESection=lpFindSectionWithName(lpPEFile,C_TEXT_SECTION))!=NULL) &&(lpPESection->lpSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) ) { #if !defined(PE_NO_MESSAGE) ErrorMessage("%s already crypted.\n",filename); #endif // !PE_NO_MESSAGE vDonePEStructure(lpPEFile); bRet=FALSE; } } */ } return(bRet); } BOOL bLoadPEFileFromFile(char *filename,unsigned long ulSize,unsigned long ulOffset,LPPEFILE *lpPEFile) { BOOL bRet=FALSE; FILE *fp=NULL; unsigned char *lpBuffer=NULL; #define PE_HEADERS 0x400 unsigned char TempBuffer[PE_HEADERS]; // Load PE file if ( (lpPEFile!=NULL) && ((fp=fopen(filename,"rb"))!=NULL) && (fseek(fp,ulOffset,SEEK_SET)==0) ) { // to avoid message and full loading for nothing if (fread(TempBuffer,1,PE_HEADERS,fp)==PE_HEADERS) { // MZ file ? if (*(USHORT *)TempBuffer == IMAGE_DOS_SIGNATURE) { // PE file ? if (*(DWORD *)NTSIGNATURE (TempBuffer) == IMAGE_NT_SIGNATURE) { if ((lpBuffer=(unsigned char*) MemoryAlloc(ulSize))!=NULL) { // init internal structures MemoryCopy(&lpBuffer[0],TempBuffer,PE_HEADERS); if (fread(&lpBuffer[PE_HEADERS],1,ulSize-PE_HEADERS,fp)==ulSize-PE_HEADERS) { bRet=bInitPEStructure(filename,lpBuffer,ulSize,lpPEFile); } MemoryFree((void**) &lpBuffer); } } } } fclose(fp); } return(bRet); } BOOL bLoadPEFile(char *filename,LPPEFILE *lpPEFile) { BOOL bRet=FALSE; FILE *fp=NULL; unsigned char *lpBuffer=NULL; unsigned long ulSize; // Load PE file if ( (lpPEFile!=NULL) && ((fp=fopen(filename,"rb"))!=NULL) && (fseek(fp,0,SEEK_END)==0) && ((ulSize=ftell(fp))!=-1L) && (fseek(fp,0,SEEK_SET)==0) ) { if ((lpBuffer=(unsigned char*) MemoryAlloc(ulSize))!=NULL) { if (fread(lpBuffer,1,ulSize,fp)==ulSize) { // init internal structures bRet=bInitPEStructure(filename,lpBuffer,ulSize,lpPEFile); } else { #if !defined(PE_NO_MESSAGE) ErrorMessage("Unable to read %d bytes in %d.\n",ulSize,filename); #endif // !PE_NO_MESSAGE } MemoryFree((void**) &lpBuffer); } else { #if !defined(PE_NO_MESSAGE) ErrorMessage("Unable to allocate %d bytes.\n",ulSize); #endif // !PE_NO_MESSAGE } fclose(fp); } else { #if !defined(PE_NO_MESSAGE) ErrorMessage("Unable to open %s for reading.\n",filename); #endif // !PE_NO_MESSAGE } if (!bRet) { #if !defined(PE_NO_MESSAGE) ErrorMessage("PE Loading of %s failed.\n",filename); #endif // !PE_NO_MESSAGE } return(bRet); } BOOL bLoadPEFileWithBlankFill(char *filename,LPPEFILE *lpPEFile) { BlankFill=TRUE; return(bLoadPEFile(filename,lpPEFile)); } BOOL bSavePEFile(char *filename,LPPEFILE *lpPEFile) { BOOL bRet=FALSE; FILE *fp=NULL; if ( (lpPEFile!=NULL) && (*lpPEFile!=NULL) && ((fp=fopen(filename,"wb"))!=NULL) ) { unsigned long ulTempSize; unsigned char *lpTempBuffer; PIMAGE_FILE_HEADER lpPEHeader=(*lpPEFile)->PEFileHeader.lpPEHeader; int nSections=lpPEHeader->NumberOfSections; // write DOS header ulTempSize=(*lpPEFile)->PEDosHeader.ulSize; lpTempBuffer=(*lpPEFile)->PEDosHeader.lpBuffer; if (fwrite(lpTempBuffer,1,ulTempSize,fp)==(size_t) ulTempSize) { // write PE Header ulTempSize=(*lpPEFile)->PEFileHeader.ulSize; lpTempBuffer=(*lpPEFile)->PEFileHeader.lpBuffer; if (fwrite(lpTempBuffer,1,ulTempSize,fp)==(size_t) ulTempSize) { // write all sections int ok=0; LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; while (lpPESection!=NULL) { ulTempSize=lpPESection->ulSize; lpTempBuffer=lpPESection->lpBuffer; if (lpTempBuffer!=NULL) { // Fill with dummy : calc.exe for instance { long lPos; if ( ((lPos=ftell(fp))>=0) && ((unsigned long) lPoslpSectionHeader->PointerToRawData) ) { unsigned long i=0; unsigned long ulSize=lpPESection->lpSectionHeader->PointerToRawData-lPos; unsigned char c=0; for (i=0;ilpSectionHeader->PointerToRawData; if (lPos!=0) { //_asm int 3; break; } } if (fwrite(lpTempBuffer,1,ulTempSize,fp)==(size_t) ulTempSize) { lpPESection=lpPESection->lpNextSection; ok++; } else { break; } } else { lpPESection=lpPESection->lpNextSection; ok++; } } bRet=(ok==nSections); } } fclose(fp); } if (!bRet) { #if !defined(PE_NO_MESSAGE) ErrorMessage("PE Saving of %s failed.\n",filename); #endif // !PE_NO_MESSAGE } return(bRet); } BOOL bChangeSectionSize(LPPEFILE *lpPEFile,int lSectionIndex, unsigned long ulNewSize) { BOOL bRet=FALSE; if (lSectionIndex!=C_INVALID_SECTION) { if ( (lSectionIndex>=0) && (lSectionIndex<(*lpPEFile)->PEFileHeader.lpPEHeader->NumberOfSections) ) { LPPESECTION lpPESection=NULL; if ((lpPESection=lpFindSectionWithIndex(lpPEFile,lSectionIndex))!=NULL) { unsigned char *lpTempBuffer=NULL; unsigned long ulTempSize=ulAlignOnFile(lpPEFile,ulNewSize); unsigned long ulDeltaSize=ulTempSize - lpPESection->ulSize; if (ulDeltaSize==0) { bRet=TRUE; } else if ( (ulDeltaSize>0) && // must not change RVA else it's too complicated (ulAlignOnSection(lpPEFile,lpPESection->lpSectionHeader->Misc.VirtualSize+ulDeltaSize)==ulAlignOnSection(lpPEFile,lpPESection->lpSectionHeader->Misc.VirtualSize) ) && ((lpTempBuffer=(unsigned char *) MemoryAlloc(ulTempSize))!=NULL) ) { MemorySet(lpTempBuffer,0,ulTempSize); MemoryCopy(lpTempBuffer,lpPESection->lpBuffer,lpPESection->ulSize); MemoryFree((void**) &lpPESection->lpBuffer); lpPESection->ulSize=ulTempSize; lpPESection->lpBuffer=lpTempBuffer; lpPESection->lpSectionHeader->SizeOfRawData=ulTempSize; lpPESection->lpSectionHeader->Misc.VirtualSize=ulTempSize; // update subsequent section lpPESection=lpPESection->lpNextSection; while(lpPESection!=NULL) { lpPESection->lpSectionHeader->SizeOfRawData += ulDeltaSize; lpPESection->lpSectionHeader->Misc.VirtualSize += ulDeltaSize; lpPESection=lpPESection->lpNextSection; } bRet=TRUE; } } } } return(bRet); } BOOL bChangeSizeOfPEHeader(LPPEFILE *lpPEFile,unsigned long ulSizeToAdd) { unsigned char *lpTempBuffer; unsigned long ulTempSize=(*lpPEFile)->PEFileHeader.ulSize; int nSections=(*lpPEFile)->PEFileHeader.lpPEHeader->NumberOfSections; unsigned char *lpStart=(*lpPEFile)->PEFileHeader.lpBuffer; unsigned char *lpEnd=((unsigned char*) &((*lpPEFile)->PEFileHeader.lpSectionHeader[nSections]))+ulSizeToAdd; // if not enough place in header if ((unsigned long) (lpEnd-lpStart)>ulTempSize) { ulSizeToAdd=ulAlignOnFile(lpPEFile,ulSizeToAdd); // alloc a new bloc lpTempBuffer=(unsigned char*) MemoryAlloc(ulTempSize+ulSizeToAdd); if (!lpTempBuffer) return(FALSE); MemorySet(lpTempBuffer,0,ulTempSize+ulSizeToAdd); MemoryCopy(lpTempBuffer,lpStart,ulTempSize); MemoryFree((void**) &lpStart); // update headar vInitPEFileHeader(lpPEFile,lpTempBuffer,ulTempSize+ulSizeToAdd); (*lpPEFile)->PEFileHeader.lpPEOptionalHeader->SizeOfHeaders += ulSizeToAdd; // update section { LPPESECTION lpPESection=(*lpPEFile)->lpPESectionList; int n=0; while (lpPESection!=NULL) { lpPESection->lpSectionHeader=&((*lpPEFile)->PEFileHeader.lpSectionHeader[n++]); lpPESection->lpSectionHeader->PointerToRawData += ulSizeToAdd; lpPESection=lpPESection->lpNextSection; } } } return(TRUE); } BOOL bAddSection(LPPEFILE *lpPEFile,char *szSectionName,unsigned long ulSize) { BOOL bRet=FALSE; // check if we can add a section if (bChangeSizeOfPEHeader(lpPEFile,sizeof(IMAGE_SECTION_HEADER))) { PIMAGE_DOS_HEADER lpDosHeader=(*lpPEFile)->PEDosHeader.lpDosHeader; PIMAGE_FILE_HEADER lpPEHeader=(*lpPEFile)->PEFileHeader.lpPEHeader; PIMAGE_OPTIONAL_HEADER lpPEOptionalHeader=(*lpPEFile)->PEFileHeader.lpPEOptionalHeader; PIMAGE_SECTION_HEADER lpSectionHeader=(*lpPEFile)->PEFileHeader.lpSectionHeader; int nSections=lpPEHeader->NumberOfSections; unsigned char *lpTempBuffer=NULL; unsigned long ulTempSize=0; LPPESECTION lpPESection,lpPENewSection; PIMAGE_SECTION_HEADER lpNewSection; // search last section in list lpPESection=(*lpPEFile)->lpPESectionList; while (lpPESection->lpNextSection!=NULL) { lpPESection=lpPESection->lpNextSection; } // alloc a new section lpPENewSection=NULL; lpTempBuffer=NULL; ulTempSize=ulAlignOnFile(lpPEFile,ulSize); if ( ((lpPENewSection=(LPPESECTION) MemoryAlloc(sizeof(PESECTION)))!=NULL) && ((lpTempBuffer=(unsigned char*) MemoryAlloc(ulTempSize))!=NULL) ) { DWORD VirtualAddress; DWORD VirtualSize; DWORD PointerToRawData; DWORD SizeOfRawData; // init buffer to check it works if (BlankFill) { FillWithRandom(lpTempBuffer,ulTempSize); } else { MemorySet(lpTempBuffer,0x55,ulTempSize); MemorySet(lpTempBuffer,0xFF,ulSize); } // chain previous lpPESection->lpNextSection=lpPENewSection; // init section lpPENewSection->ulSize=ulTempSize; lpPENewSection->lpBuffer=lpTempBuffer; lpPENewSection->lpSectionHeader=&((*lpPEFile)->PEFileHeader.lpSectionHeader[nSections]); lpPENewSection->lpPreviousSection=lpPESection; lpPENewSection->lpNextSection=NULL; lpNewSection=lpPENewSection->lpSectionHeader; // Section Virtual Address : based on previous section : Important under NT : Need to be aligned if ( (lpSectionHeader[nSections-1].Misc.VirtualSize==0) && (lpSectionHeader[nSections-1].PointerToRawData!=0) ) { // .bss section have no rawdata VirtualAddress=lpSectionHeader[nSections-1].VirtualAddress+lpSectionHeader[nSections-1].SizeOfRawData; } else { VirtualAddress=lpSectionHeader[nSections-1].VirtualAddress+lpSectionHeader[nSections-1].Misc.VirtualSize; } VirtualAddress=ulAlignOnSection(lpPEFile,VirtualAddress); //Section Virtual Size : Important under NT : Need to be aligned //SizeOfRawData=ulSize; ????? SizeOfRawData=ulTempSize; VirtualSize=ulAlignOnSection(lpPEFile,SizeOfRawData); // PointerToRawData : based on previous section : Important under NT : Need to be aligned PointerToRawData=lpSectionHeader[nSections-1].PointerToRawData+lpSectionHeader[nSections-1].SizeOfRawData; PointerToRawData=ulAlignOnFile(lpPEFile,PointerToRawData); // Fill section MemorySet(lpNewSection,0,sizeof(IMAGE_SECTION_HEADER)); StringNCopy((char*) lpNewSection->Name,szSectionName,IMAGE_SIZEOF_SHORT_NAME); lpNewSection->Name[IMAGE_SIZEOF_SHORT_NAME-1]=0; lpNewSection->Misc.VirtualSize=VirtualSize; lpNewSection->VirtualAddress=VirtualAddress; lpNewSection->SizeOfRawData=SizeOfRawData; lpNewSection->PointerToRawData=PointerToRawData; lpNewSection->Characteristics=IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; // 0xC0000040 // update section number lpPEHeader->NumberOfSections++; // update image size lpPEOptionalHeader->SizeOfImage += VirtualSize; bRet=TRUE; } if ((!bRet) && (lpTempBuffer!=NULL)) { MemoryFree((void**) &lpTempBuffer); } } return(bRet); } #endif // !PE_NO_PEFILEEX