reman3/Rayman_X/cpa/tempgrp/PTC/PE/PEFileEx.c

989 lines
26 KiB
C

#include "PEOptions.h"
#if !defined(PE_NO_PEFILEEX)
#include <stdio.h>
#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 <time.h>
#include <stdlib.h>
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) &&
(RVA</*=*/lpPESection->lpSectionHeader->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) &&
(ulOffset</*=*/lpPESection->lpSectionHeader->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) && (ucPtr</*=*/lpPESection->lpBuffer+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;n<ulSize;n++)
{
*lpBuffer++=RandomChar();
}
}
}
void vInitPEFileHeader(LPPEFILE *lpPEFile,unsigned char *lpBuffer,unsigned long ulSize)
{
(*lpPEFile)->PEFileHeader.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;n<nSections;n++)
{
ulTempSize=pSectionHeader[n].SizeOfRawData;
if (
((lpPESection=(LPPESECTION) MemoryAlloc(sizeof(PESECTION)))!=NULL) &&
(
(pSectionHeader[n].PointerToRawData==0) ||
((lpTempBuffer=(unsigned char*) MemoryAlloc(ulTempSize))!=NULL)
)
)
{
*lplpPEPreviousSection=lpPESection;
if (pSectionHeader[n].PointerToRawData!=0)
{
lpPESection->ulSize=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) lPos<lpPESection->lpSectionHeader->PointerToRawData)
)
{
unsigned long i=0;
unsigned long ulSize=lpPESection->lpSectionHeader->PointerToRawData-lPos;
unsigned char c=0;
for (i=0;i<ulSize;i++)
{
if (BlankFill)
{
c=RandomChar();
}
if (fwrite(&c,1,sizeof(c),fp)!=(size_t) sizeof(c))
{
break;
}
}
}
lPos=ftell(fp)-lpPESection->lpSectionHeader->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