La parte de reordenar las secciones se puede hacer de una forma más rápida y con menos código (Cambiando sólo el PointerToRawData), pero como eso se me ocurrió despues de terminar..
Código
LPSTR RebuildPE(LPSTR FileName,LPSTR lpFileMaped,DWORD FileSize) { PIMAGE_DOS_HEADER IDH; PIMAGE_NT_HEADERS INTH; PIMAGE_SECTION_HEADER ISH; IDH=(PIMAGE_DOS_HEADER)&lpFileMaped[0]; INTH=(PIMAGE_NT_HEADERS)&lpFileMaped[IDH->e_lfanew]; //Creamos un buffer y guardamos una copia del archivo mapeado LPSTR Temp=(LPSTR)GlobalAlloc(GPTR,FileSize); CopyMemory(&Temp[0],&lpFileMaped[0],FileSize); //Cambiamos las secciones en el archivo de orden (no en la cabecera) for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++) { PIMAGE_DOS_HEADER tIDH; PIMAGE_NT_HEADERS tINTH; PIMAGE_SECTION_HEADER tISH; PIMAGE_SECTION_HEADER tISH2; PIMAGE_SECTION_HEADER ISH2; tIDH=(PIMAGE_DOS_HEADER)&Temp[0]; tINTH=(PIMAGE_NT_HEADERS)&Temp[tIDH->e_lfanew]; tISH=(PIMAGE_SECTION_HEADER)&Temp[tIDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*(i+1)]; ISH2=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*(i+1)]; tISH2=(PIMAGE_SECTION_HEADER)&Temp[tIDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; if(i!=INTH->FileHeader.NumberOfSections-1) { CopyMemory(&lpFileMaped[ISH->PointerToRawData],&Temp[tISH->PointerToRawData],tISH->SizeOfRawData); ISH->SizeOfRawData=tISH->SizeOfRawData; ISH->Characteristics=tISH->Characteristics; ISH->VirtualAddress=tISH->VirtualAddress; CopyMemory(&ISH->Name,&tISH->Name,8); ISH2->PointerToRawData=ISH->PointerToRawData+tISH->SizeOfRawData; } else { tISH=(PIMAGE_SECTION_HEADER)&Temp[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)]; ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; CopyMemory(&lpFileMaped[ISH->PointerToRawData],&Temp[tISH->PointerToRawData],tISH->SizeOfRawData); ISH->SizeOfRawData=tISH->SizeOfRawData; ISH->Characteristics=tISH->Characteristics; ISH->VirtualAddress=tISH->VirtualAddress; CopyMemory(&ISH->Name,&tISH->Name,8); } } LPSTR SecTmp=(LPSTR)GlobalAlloc(GPTR,0x28*INTH->FileHeader.NumberOfSections); CopyMemory(&SecTmp[0],&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)],0x28*INTH->FileHeader.NumberOfSections); //Reordenamos las secciones en la cabecera for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++) { if(i==0) { CopyMemory(&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)],&SecTmp[0x28*(INTH->FileHeader.NumberOfSections-1)],0x28); } else { CopyMemory(&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i],&SecTmp[0x28*(i-1)],0x28); } } GlobalFree(Temp); //Obtenemos el PointerToRawData más alto y el tamaño total de todas las secciones DWORD MaxPointerToRawData=0; DWORD TotalSectionsSize=0; for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++) { ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; if(MaxPointerToRawData<ISH->PointerToRawData) { MaxPointerToRawData=ISH->PointerToRawData; } TotalSectionsSize=TotalSectionsSize+(DWORD)(ISH->SizeOfRawData); } //Obtenemos la sección con el PointerToRawData más alto for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++) { ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; //Si es la sección que contiene el PointerToRawData más alto salimos del bucle if(ISH->PointerToRawData==MaxPointerToRawData) { i=INTH->FileHeader.NumberOfSections; } } //Si hay EOF Data if(ISH->PointerToRawData+ISH->SizeOfRawData<FileSize) { //Metemos el EOF Data dentro de la última sección ISH->SizeOfRawData=ISH->SizeOfRawData+(FileSize-(ISH->PointerToRawData+ISH->SizeOfRawData)); } //Obtenemos el SizeOfImage y ajustamos el VirtualSize de las secciones DWORD SizeOfImage=0; for(DWORD i=0;i<INTH->FileHeader.NumberOfSections;i++) { ISH=(PIMAGE_SECTION_HEADER)&lpFileMaped[IDH->e_lfanew+sizeof(IMAGE_NT_HEADERS)+sizeof(IMAGE_SECTION_HEADER)*i]; ISH->Misc.VirtualSize=ISH->SizeOfRawData; if(SizeOfImage<ISH->VirtualAddress) { SizeOfImage=ISH->VirtualAddress+ISH->Misc.VirtualSize; } } //Ajustamos el SizeOfImage INTH->OptionalHeader.SizeOfImage=SizeOfImage; //Recalculamos el CheckSum _MapFileAndCheckSum miMapFileAndCheckSum=NULL; HMODULE hLib=LoadLibraryA("IMAGEHLP.DLL"); miMapFileAndCheckSum=(_MapFileAndCheckSum)GetProcAddress(hLib,"MapFileAndCheckSumA"); DWORD OrignalCheckSum=0; DWORD newCheckSum=0; miMapFileAndCheckSum((PTSTR)FileName,&OrignalCheckSum,&newCheckSum); INTH->OptionalHeader.CheckSum=newCheckSum; return lpFileMaped; }
Como las secciones no están ordenadas por el PointerToRawData en la cabecera, algunos visores del PE (Pe explorer por ejemplo) dice que tiene EOF data, pero no la tiene .
Saludos
PD: Gracias a Karcrack y Arkangel por escuchar mis lamentos .