Buenas,

Llevo unos días peleandome con el código y no logro que el ejecutable quede "funcional".
El caso es que estoy intentando meter una nueva sección en un ejecutable:

Código: Seleccionar todo

	PIMAGE_DOS_HEADER IDH;
	PIMAGE_NT_HEADERS INTH;
	PIMAGE_SECTION_HEADER ISH;

	DWORD NewSectionSize = dwStubFileSize;

	LPBYTE Temp = (LPBYTE)malloc( dwOriginalFileSize + NewSectionSize );
	CopyMemory(&Temp[0], lpOriginalFileBuffer, dwOriginalFileSize);
	//CopyMemory(&Temp[ dwOriginalFileSize ], lpStubFileBuffer, dwStubFileSize);
	CopyMemory(&Temp[0], lpOriginalFileBuffer, dwOriginalFileSize);
	memset(&Temp[dwOriginalFileSize], 0, NewSectionSize);

	IDH = (PIMAGE_DOS_HEADER)&Temp[0];
	INTH = (PIMAGE_NT_HEADERS)&Temp[ IDH->e_lfanew ];

	for(DWORD i=0; i < INTH->FileHeader.NumberOfSections; i++)
	{
		ISH = (PIMAGE_SECTION_HEADER)&Temp[ IDH->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * i ];
		ISH->Misc.VirtualSize = ISH->SizeOfRawData;
	}

	DWORD NumberOfSections = INTH->FileHeader.NumberOfSections;
	DWORD e_lfanew = IDH->e_lfanew;

	ISH = (PIMAGE_SECTION_HEADER)&Temp[ IDH->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * (NumberOfSections-1) ];
	DWORD LastVirtualOffset = ISH->VirtualAddress;

	CopyMemory(&Temp[ IDH->e_lfanew - 0x28 ], &lpOriginalFileBuffer[ IDH->e_lfanew ], sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * INTH->FileHeader.NumberOfSections);
	memset(&Temp[ e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * (NumberOfSections - 1) ], 0, 0x28);

	IDH->e_lfanew = IDH->e_lfanew - 0x28;

	INTH = (PIMAGE_NT_HEADERS)&Temp[ IDH->e_lfanew ];

	ISH = (PIMAGE_SECTION_HEADER)&Temp[ e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * (NumberOfSections - 1) ];
	BYTE SectionName[8] = ".newsec";
	CopyMemory( ISH->Name, SectionName, 8 );

	ISH->SizeOfRawData = NewSectionSize;
	ISH->PointerToRawData = dwOriginalFileSize;
	ISH->Characteristics = 0xE0000020;
	ISH->VirtualAddress = LastVirtualOffset + INTH->OptionalHeader.SectionAlignment;
	ISH->Misc.VirtualSize = NewSectionSize;

	INTH->FileHeader.NumberOfSections = INTH->FileHeader.NumberOfSections + 1;
	INTH->OptionalHeader.SizeOfImage = ISH->VirtualAddress + ISH->Misc.VirtualSize;

	DWORD dwBytesWritten;
	HANDLE hNewFile;
	hNewFile = CreateFile(szFinalFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
	if( hStubFile == INVALID_HANDLE_VALUE ) {
		MessageBox(g_hWnd, L"IMPOSIBLE CREAR ARCHIVO!", WINDOW_TITLE, MB_OK | MB_ICONERROR);
		return FALSE;
	}
	WriteFile(hNewFile, Temp, (dwOriginalFileSize + NewSectionSize), &dwBytesWritten, NULL);
	CloseHandle(hNewFile);
He probado varias formas, pero el resultado siempre es el mismo "no es una aplicación Win32 válida"...
Estoy haciendo algo mal? (Bueno, eso esta claro que sí jaja)
Podriais guiarme un poco en que punto fallo?

Muchas gracias por adelanatado.
Mil saludos!

PD: las variables "Stub" y "Original", vienen de más arriba, tan solo son tamaños y datos de 2 archivos que cargo en memoria previamente. Original => seleccionado por el user, Stub => un MessageBox, previamente compilado a parte.
[ Lo importante no es el final, sino el camino recorrido ]
Te recomiendo que leas este tema.
viewtopic.php?f=8&t=39230&hilit=Taller

The Swash habla sobre como agregar una sección, luego le doy una revisada a tu código aunque a simple vista estas tocando los VirtualSize y VirtualAddress y eso no se debe de mover esos son valores que el Loader usa para mapear el ejecutable en la memoria, a menos que realmente desees cambiarlos.

Saludos!
We do what we must, because, we can-> [www.youtube.com/watch?v=Y6ljFaKRTrI]
Pasa a saludar: NeoDark-Labs.BlogSpot.mx
<<<<Proyectos en curso>>>>
[+]Restauración de SSDT
[+]Driver v3 - Ocultar drivers
[+]Anti-rootkit
Gracias por responder :)

Wow... es cierto! Ese post lo leí hace bastante tiempo, y ya no me acordaba de él. Ahora mismo me lo releere enterito a ver si aclaro conceptos.
La verdad es que he tocado tantas veces ese código que al final ya no se ni lo que hacía...

Muchas gracias orlando :P
[ Lo importante no es el final, sino el camino recorrido ]
Ya logré añadir una sección sin morir en el intento!! :)
Es un grandisimo tutorial y no sabes cuanto me ha servido. Ya tengo bastante más claro los conceptos básicos.

Ahora el problema será añadir los datos leídos de un segundo ejecutable (un MessageBox) para que este se ejecute en primer lugar y después siga el curso normal del ejecutable original. Pero vayamos paso a paso.

De nuevo gracias! :)
Saludos.
[ Lo importante no es el final, sino el camino recorrido ]
Felicidades compañero, vas por muy buen camino.
Es un gusto ayudar y más en temas de programación.

Sobre meter un MessageBox a un ejecutable Thor en su blog habla de eso. Usa ASM y la IT para saber si el ejecutable imprta MessageBox. Te recomiendo leer este [Enlace externo eliminado para invitados] y los temas subsecuentes, ese tema es para que comprendas los términos.

Si tienes alguna duda no dudes en hacerla saber.

Saludos! y suerte
We do what we must, because, we can-> [www.youtube.com/watch?v=Y6ljFaKRTrI]
Pasa a saludar: NeoDark-Labs.BlogSpot.mx
<<<<Proyectos en curso>>>>
[+]Restauración de SSDT
[+]Driver v3 - Ocultar drivers
[+]Anti-rootkit
Hola de nuevo orlando,

Fantástico blog... hay una cantidad de información impresionante acerca del tema y muy bien explicado XD
Lástima que no sepa ASM (y creo que jamás llegare a saberlo usar, muy complicado xD) pero aún así he visto como hacer varias cosas que me interesaban y no sabía por donde empezar (y eso que solo he leído un par de entradas del blog jaja).

Mil gracias!

PD: no encuentro por ningún lado el código de las PETools.cpp/.h, alguien sería tan amable de subirlas? (no sé si esto va aquí o abrir un nuevo hilo jeje)
[ Lo importante no es el final, sino el camino recorrido ]
Me surgió otro problemilla... jeje
No está directamente relacionado con el formato PE, sino con el manejo de la memoria...

Código: Seleccionar todo

printf("\tDOS Signature: 0x%x\n", this->m_ImageDosHeader->e_magic); //OK
//Añadimos algo de espacio libre al final del ejecutable
Append(dwSpace, 0xFF);

printf("\tDOS Signature: 0x%x\n", this->m_ImageDosHeader->e_magic); //sigue OK
	
LPBYTE tmpBuff = (LPBYTE) malloc( m_ImageNtHeaders->OptionalHeader.FileAlignment );
printf("\tDOS Signature: 0x%x\n", this->m_ImageDosHeader->e_magic); // MAL! devuelve 0xcdcd | me esta sobreescribiendo ??


//vamos a reinicializar las cabeceras, a ver que tal...
m_ImageDosHeader = (PIMAGE_DOS_HEADER) &m_FileBuffer[ 0 ];
printf("\tDos Signature: 0x%x\n", m_ImageDosHeader->e_magic); // OK! devuelve el valor correcto

/*
DWORD dwFileSize = this->GetSize();
printf("\tFile size: 0x%x\n", dwFileSize);
printf("\tSizeOfHeaders: 0x%x\n", m_ImageNtHeaders->OptionalHeader.SizeOfHeaders);

//Movemos bytes del 'final del fichero' hasta el 'final de las cabeceras'
for(i = 0, l = dwFileSize - m_ImageNtHeaders->OptionalHeader.SizeOfHeaders; i < l; i += m_ImageNtHeaders->OptionalHeader.FileAlignment)
{
	printf("\tSection (i): %d\n", i);
	//Guardamos un bloque (FileAlignment) en el buffer temporal para realizar el desplazamiento
	memcpy(&tmpBuff, &m_FileBuffer[ dwFileSize - dwSpace - i ], m_ImageNtHeaders->OptionalHeader.FileAlignment);

	printf("\t1st MemCpy done!\n");
	//Recolocamos los datos leidos...
	memcpy(&m_FileBuffer[ (dwFileSize - dwSpace - i) + (dwSpace - 1) ], tmpBuff,  m_ImageNtHeaders->OptionalHeader.FileAlignment);

	printf("\t2nd MemCpy done!\n");
}

//Incrementamos el puntero a la "Raw Data" de cada descción
for(i = m_ImageNtHeaders->FileHeader.NumberOfSections - 1; i >= 0; i--) {
	m_ImageSectionHeaders[ i ].SetPointerToRawData( m_ImageSectionHeaders[ i ].GetPointerToRawData() + dwSpace );
}
*/
free( tmpBuff );
Es muy raro, porque al asignar memoria para una nueva variable, me está machacando la de una variable ya existente (PE::m_FileBuffer)

Que estoy haciendo mal? O_o

Gracias por adelantado! :P

PD el método VOID PE::Append(DWORD, BYTE); agrega espacio al final del ejecutable

Código: Seleccionar todo

VOID PE::Append(DWORD dwBytes, BYTE cValue) {
	m_FileBuffer = (LPBYTE) realloc(m_FileBuffer, (m_FileBufferSize + dwBytes));
	memset(&m_FileBuffer[ m_FileBufferSize ], cValue, dwBytes);
	m_FileBufferSize += dwBytes;
}
Para 'Setear' la memoria a partir de cierta posición... es correcto esto? => memset(&buffer[ dwPosition], ...) ??
[ Lo importante no es el final, sino el camino recorrido ]
Mmmm... lo he probado en otro PC y allí si me funciona... tiene algún sentido?? se me ha "saturado" la memoria o que xDDD
Enfin.. mañana lo volveré a probar con el mismo PC.
[ Lo importante no es el final, sino el camino recorrido ]
Responder

Volver a “C/C++”