jueves, 18 de agosto de 2011

Sencillo programa para encontrar huecos en ejecutables

Seguramente muchos conozcáis la herramienta ToPo un programa, con 12 años a sus espaldas, para buscar huecos en los ejecutables y así poder insertar código sin necesidad de añadir nuevas secciones.

Estos huecos surgen cuando se alinean las secciones del ejecutable en disco con el valor FileAlignment que suele tomar el valor de 0x200. Por ejemplo si un programa tiene una sección que realmente ocupa 0x310 bytes, estará obligado a tener una sección en el ejecutable en disco de tamaño como mínimo 0x400 bytes y gracias a este alineamiento hay 0xF0 bytes al final de la sección que no son utilizados para nada.

El caso es que quería crearme un sencillo programa que encontrara estos huecos, para después usarlo en el crypter y si se puede no añadir una nueva sección aprovechando los huecos.

La idea es recorrer todas las secciones y comprobar una a una si el valor de VirtualSize, el tamaño real de al sección, es menor que el tamaño de al sección en disco, SizeOfRawData. En este caso existe un hueco en esa sección de tamaño SizeOfRawData – VirtualSize.

Aquí os dejo el código, la mayoría de la funcionalidad se encuentra en el fichero PECore.cpp, un fichero donde he sacado las funciones mas comunes ha realizar con ejecutables. Así es mas fácil entender el código.

#include <stdio.h>
#include <windows.h>
#include "PECore\PECore.h"

int main(int argc, char *argv[])
{
	if(argc != 2)
	{
		printf("Se esperaba 1 parametro, el fichero donde se buscarán los huecos\n");
		printf("Ej: %s notepad.exe\n", argv[0]);
		return EXIT_FAILURE;
	}
	MapInfo mapInfo;
	if (OpenAndMapFile(&mapInfo, argv[1]) == -1)
		return EXIT_FAILURE;
	//En cada sección se comprueba si el tamaño virtual es menor que el tamaño en disco de la sección
	//VirtualSize < SizeofRawData, en ese caso hay un hueco que ha surgido de las alineaciones
	PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)mapInfo.viewMappedFile;
	PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)&mapInfo.viewMappedFile[pIDH->e_lfanew];
	for(DWORD i = 0; i < pINH->FileHeader.NumberOfSections; i++)
	{
		PIMAGE_SECTION_HEADER pISH = (PIMAGE_SECTION_HEADER)&mapInfo.viewMappedFile[pIDH->e_lfanew + sizeof(IMAGE_NT_HEADERS) + i*sizeof(IMAGE_SECTION_HEADER)];
		if (pISH->Misc.VirtualSize < pISH->SizeOfRawData)
		{
			//Hay un hueco, imprimimos su ubicación y tamaño
			DWORD Pos = pISH->VirtualAddress + pISH->Misc.VirtualSize;
			printf("Hueco encontrado!\n");
			printf("Section: %s\n", pISH->Name);
			printf("RVA:\t%#x\n", Pos);
			printf("Offset:\t%#x\n", RVAToOffset(mapInfo.viewMappedFile, Pos));
			printf("Size:\t%#x\n\n", pISH->SizeOfRawData - pISH->Misc.VirtualSize);
		}
	}
	CloseAndUnmapFile(&mapInfo);

	return EXIT_SUCCESS;
}

Subo los ficheros PETools.h y PETools.cpp aquí, espero ir mejorándolos con lo que necesite.

Por supuesto ToPo es mucho mas completo, da la posibilidad de redireccionar el EP al hueco, añadir secciones y modificar sus permisos.

Saludos!

2 comentarios:

  1. Thor, sólo quiero que sepas que somos muchos los que te leemos desde HxC y que aunque no haya comentarios tus artículos son geniales.
    Eres una especie de referente para mí (y muchos amigos con los que he hablado de tus artículos) y me alegra saber que existen personas como tú, con esa pasión y esas ganas de aprender. Un saludo y por favor sigue deleitándonos con estos artículos. :)

    ResponderEliminar