Bueno, pues yo aquí otra vez con una función :xD. Ésta función cambia bastantes cosas en el PE, cambia las secciones de orden (en lo que es en el archivo, en la cabecera no ya que de poco serviría), mete el EOF Data dentro de la última sección y actualiza el CheckSum (me aburría :P). Tambien tenía casi terminado para que cambiara el Align del archivo, pero se me extendía demasiado el código, si necesito terminarla lo posteo en una función aparte.

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: Seleccionar todo

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 ;D.



Saludos

PD: Gracias a Karcrack y Arkangel por escuchar mis lamentos ;D.
Ha Gracias a ti man, esto va bueno...
"Un buen pintor copia, Un gran pintor roba."
Siempre podemos tirar el ordenador a la basura y comprar uno nuevo, pero es una solución demasiado Mac.
Imagen
muy buen aporte gracias, veo que te adentraste en el mundo del pe file format, yo apenas lo comienzo a estudiar ya que avira anda por ese rumbo con sun dropper gen, de ahi sale su deteccion.
saludos.
Responder

Volver a “Fuentes”