C++: Insertar un ejecutable dentro de otro… y luego ejecutarlo

On jueves, 8 de septiembre de 2011 4 comentarios

C++: Insertar un ejecutable dentro de otro… y luego ejecutarlo

Vamos a explicar cómo tomar un ejecutable (o cualquier otro fichero binario), insertarlo dentro de un ejecutable y posteriormente cómo recuperar ese ejecutable embebido, soltarlo a disco y ejecutarlo. El escenario típico es borrar el propio ejecutable que actúa como hospedante, pero seguro que a las mentes calenturientas de mis lectores se les ocurren más aplicaciones.
El problema no existía en Windows 95 y siguientes: un programa podía borrar su propio ejecutable y terminar sin ningún problema (o casi). Pero en los núcleos NT hacer eso es harina de otro costal. Teóricamente se puede hacer mientras que el ejecutable a borrar no abra ningún handle… pero evidentemente cualquier ejecutable suele abrir no uno, sino infinidad de ellos.
La solución consiste entonces en disponer de dos ejecutables en disco. El primero hará su tarea y llamará al segundo antes de terminar, que tras unos instantes procederá a borrar el primero, quedando éste último en disco. Pero entonces tenemos que distribuir dos ficheros y colocarlos en el mismo sitio, por lo que la mejor solución es que el primero contenga al segundo en sus entrañas y lo use a voluntad. Incidentalmente el segundo podría decir a Windows que lo borre en el siguiente reinicio, pero no vamos a entrar en detalles sobre esto.
Primer paso: Insertar el ejecutable
Suponiendo que tengamos ya construido nuestro ejecutable (que vamos a llamar “borra.exe”), insertar un recurso del tipo RCDATA en un fichero ejecutable es una tarea trivial. Basta con abrir el fichero de recursos del ejecutable (el .rc) como texto e insertar la línea:
ELEXE RCDATA "..\\final\\Win32\\Release\\borra.exe"
Recompilamos y ya tenemos el ejecutable como recurso binario embebido en nuestro propio ejecutable. Evidentemente no estamos limitados a ningún tipo de archivo en concreto. Podríamos hacerlo incluso con recursos normales (mapas de bits, iconos, cadenas, etc.). La única diferencia es la forma de recuperar un recurso binario de uno almacenado como estándar.
Segundo paso: Sacar el ejecutable y ponerlo en disco
Cuando queramos volcar nuestro ejecutable a disco, debemos ejecutar algo parecido a lo siguiente:
HRSRC res=FindResource(NULL,_T("ELEXE"),RT_RCDATA);
if(res==NULL)
     return GetLastError();

int size=SizeofResource(NULL,res);
HGLOBAL hRes=LoadResource(NULL,res);
unsigned char *pRes=(unsigned char *)LockResource(hRes);

HANDLE hFile=CreateFile(szT2Path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if(hFile==INVALID_HANDLE_VALUE)
     return GetLastError();

WriteFile(hFile,pRes,size,&bytesWritten,NULL);
CloseHandle(hFile);

ShellExecute(HWND_DESKTOP,NULL,szT2Path,NULL,NULL,SW_SHOWNORMAL);
El primer paso consiste en llamar a FindResource con el nombre y el tipo de recurso. Si nuestro fichero hubiera estado almacenado en otro lugar que no fuera nuestro propio ejecutable, el primer parámetro a pasar es la instancia del fichero externo.
Tras tener un handle válido, tenemos que mirar el tamaño que ocupa el recurso almacenado, lo que hacemos con SizeofResource.
Ahora viene cargar el recurso en memoria y obtener un handle de memoria (LoadResource). Pero todavía no podemos acceder a los bytes de nuestro fichero, debemos bloquear el acceso a los mismos mediante LockResource, lo que nos devolverá un área de memoria accesible.
Aquí el autor lo ha asignado a un buffer de caracteres sin signo, pero realmente cualquier tipo de dato es perfectamente válido, aunque tenemos que tener en cuenta de no guardar ningún byte de más en el fichero final. Haciéndolo con un buffer de caracteres nos aseguramos de guardar el tamaño correcto.
Ya solo nos queda guardar el buffer a disco y hacer la llamada para ejecutar el fichero extraído.
Quizás nos preguntemos por qué no hemos liberado la memoria apuntada por pRes: está expresamente descrito en la documentación de la MSDN: no debemos hacerlo nosotros, ya lo hará el sistema cuando corresponda.
Consideraciones finales
Evidentemente una solución más sencilla sería marcar el propio ejecutable para ser borrado en el siguiente reinicio en lugar de hacer toda esta parafernalia, pero a veces puede no interesarnos que dicho fichero esté en disco hasta ese momento.
De todos modos aplicaciones para esto las hay a montones. Soltar un ejecutable que haga algo, termine y luego sea borrado por el programa principal, forzar un reinicio del programa principal, distribuir un solo exe que luego suelte todos los ficheros que necesite…

Origen: http://geeks.ms/blogs/rfog/archive/2008/09/11/c-insertar-un-ejecutable-dentro-de-otro-y-luego-ejecutarlo.aspx

4 comentarios:

Anónimo dijo...

hey can u teach me how to make hack wolfteam??

Anónimo dijo...

c0l0

wath the fuck

admin dijo...

Hello,
Wolfteam turkey hacks don't working now.
25.01.2012 login but don't work and ban later.
28.12.2012 can't enter game.

Anónimo dijo...

Como quito o libero un hacker de publicidad y lo hago directo ?

Publicar un comentario