989 lines
26 KiB
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
|
|
|
|
|
|
|
|
|
|
|