Los virus de arranque (I)
Autor: Juan-Mariano de Goyeneche.
Publicado en el Número 8 de Programación Actual.
Son los más fáciles de detectar
y (generalmente) de eliminar. Los virus de ficheros pueden estar
-al menos- en tantos sitios como programas ejecutables haya. Los
de arranque, sin embargo, sólo pueden situarse en dos sectores
concretos del disco (en uno si es un disquete). Y, paradójicamente,
son los virus más extendidos, más populares y que
más estragos causan. En las líneas que siguen serán
estudiados en profundidad.
Esos dos sectores tan característicos (en
seguida se verá el por qué de sus particularidades)
son el de arranque, tanto de discos duros como de disquetes, y
el MBR (Master Boot Record) de los discos duros. Puesto que en
ellos se alojan los virus, lo primero que hace falta es el saber
cómo verlos. Se utilizará, como siempre, el DEBUG.
El sector de arranque es el primer sector lógico
tanto de un disquete como de una partición DOS. En un disquete,
ese sector coincide con el primer sector físico, pero en
un disco duro eso no tiene por qué ser así. Como
es el primer sector que "entiende" el DOS, en ambos
casos se puede leer haciendo tan sólo: -l7c00 0 0 1 (cargar
en el desplazamiento de memoria 7C00h de la unidad 0 -primera
unidad de disquete- el sector 0 -primer sector lógico del
disco- y leer sólo un sector). Para un disco duro sólo
hay que cambiar el número de unidad: -l7C00 2 0 1.
El MBR está fuera de la partición DOS
y, por tanto, no se puede acceder a él directamente. Hay
que hacerlo con la BIOS, concretamente con la interrupción
que maneja unidades de disco: la 13h. La lectura ahora ya no es
de sectores lógicos: empezando por el 0 y de uno en uno
hasta llegar al final. Ahora se trabaja con sectores físicos:
cilindro:cabeza:sector. El MBR está en la cabeza 0, cilindro
0, sector 1. El código para leerlo se dio ya en la anterior
entrega, aunque se repite aquí por conveniencia:
-a
Ahora el sector está en memoria en XXXX:7C00
y se puede ver, estudiar y desensamblar. Se aconseja consultar
las referencias indicadas al final del artículo con el
fin de familiarizarse con las diferentes funciones de la interrupción
13h. Aparte de la 02, ya explicada en el artículo anterior,
que sirve para leer sectores, es de especial interés la
03, que realiza las funciones de escritura. Los restantes registros
mantienen el mismo significado que para la lectura, así
que este mismo fragmento de código se puede utilizar para
escribir en el MBR los 512 bytes que se encuentran a partir de
ES:7c00 con tal de cambiar la primera línea por MOV AX,0301.
Con esta nueva función será con la que se restaure
el MBR original.
Para poder entender la forma de actuación
de estos virus y los cambios que realizan en los mencionados sectores
es imprescindible tener unos conocimientos bastante precisos de
cómo se realiza el arranque convencional del ordenador.
Se verá eso en primer lugar para después
observar cómo un virus real opera en la práctica
modificando estas estructuras.
EL PROCESO DE ARRANQUE
Desde el momento en que se aprieta el botón
de encendido del ordenador hasta que el intérprete de comandos
del sistema operativo elegido se encuentra a la espera de las
órdenes pertinentes, hay toda una serie de complicadas
acciones que a menudo pasan inadvertidas al usuario ordinario,
pero que es imprescindible conocer para entender el funcionamiento
de los virus de arranque.
Puesto que, como se explicó el mes pasado,
estos virus toman el control del ordenador antes incluso de que
llegue a cargarse el sistema operativo, es imprescindible que
alteren el proceso de arranque habitual para cargarse ellos en
memoria, y continúen después como si nada hubiera
pasado para que el usuario no advierta comportamientos extraños.
Se explicará primero el proceso de carga normal, tal y
como lo pensaron en un principio los diseñadores del PC
original de IBM, para ver a continuación el punto en que
el virus tiene ocasión de modificarlo en su provecho y
luego reconducirlo para que el cambio resulte transparente.
Al pulsar el interruptor de encendido, toda una avalancha
de impulsos eléctricos empieza a recorrer el interior del
ordenador. Haciendo abstracción de la parte circuital,
pasado un tiempo (del orden de nanosegundos) los transistores
del microprocesador han adquirido ya unos niveles de tensiones
y corrientes adecuados, y la CPU se encuentra en condiciones de
ejecutar instrucciones. En todos los PCs compatibles esas primeras
instrucciones se encuentran en la misma posición de memoria:
F000:0000, correspondiente a los chips de ROM que alojan la BIOS
(Basic Input Output System) o "Sistema básico de entrada/salida".
En esta zona se encuentran rutinas que realizan comprobaciones
para asegurarse que los componentes necesarios para el buen funcionamiento
del PC se hayan presentes y funcionan satisfactoriamente. Habitualmente
esta parte del proceso de arranque recibe el nombre de POST (Power
On Self Test, o "auto-test de encendido"): tras hacer
una autocomprobación de la propia CPU, se envían
señales por los buses al resto de la circuitería
para comprobar que está presente y funcionando. Se comprueba
la memoria de la tarjeta y se envían señales para
controlar su funcionamiento. En este momento aparecen las primeras
imágenes en la pantalla. Siguiendo con la ejecución
del POST de la ROM-BIOS, se comprueba la RAM escribiendo datos
en cada celda de memoria y leyéndolos a continuación
para comparar que sean idénticos. Un contador de la cantidad
de RAM que se lleva chequeada se muestra por pantalla.
A continuación se envían señales
al teclado, comprobándose de paso si hay alguna tecla pulsada.
Tras ello se envían más señales eléctricas
a todas las unidades de disco, anotándose cuántas
se hayan funcionando. En los PC AT y posteriores existe una memoria
CMOS (conocida también como "el SETUP"), alimentada
por baterías, en la que se guarda información relativa
al hardware del equipo (tipo y número de discos duros,
cantidad de memoria, etc...) que se mantiene aún cuando
el ordenador está apagado. Por ello, si el equipo no es
un XT, los resultados del POST son comparados con lo guardado
en el SETUP, que es el resultado que cabía esperar. Si
todo va bien se emite un único pitido, señal de
que todos los tests han sido completados con éxito. En
caso de haberse detectado problemas, la BIOS trata de informar
de sus posibles causas.
Como es posible que los errores encontrados impidan
el correcto funcionamiento de la pantalla, es muy común
que manifieste los errores mediante combinaciones de pitidos largos
y cortos. Con casi toda probabilidad el lector se habrá
encontrado alguna vez en esta situación. Así un
pitido largo seguido de otro corto indica problemas con la placa
madre, dos pitidos cortos apuntan a fallos del monitor, etc.
Superado el POST de encendido, seguimos en ROM. Ahora
se ejecuta el código que "traerá a la vida"
al sistema operativo. En primer lugar, si el SETUP no dice lo
contrario, se busca la presencia de un disco de arranque en una
disquetera y, en caso de no encontrarse, se trata de arrancar
con el disco duro. Como esto puede traer problemas de seguridad
y, como se verá, infecciones con virus de arranque, se
incluyó posteriormente la posibilidad de cambiar el orden
de arranque en el SETUP para que primero trate de arrancar el
disco duro y, sólo en caso de no lograrlo, la disquetera.
Hay una pequeña diferencia entre el caso de
arrancar con disco duro o con disquete. En el primero la BIOS
lee el "Master Boot Record" (MBR), también llamado
habitualmente "Tabla de Particiones" en reconocimiento
a la importancia de una estructura de datos contenida en el sector,
y le transfiere el control, mientras que en el arranque desde
disquete, al carecer estos de MBR, lo que se lee y ejecuta es
el "Sector de Arranque". Dado que en un arranque desde
disco duro también existen sectores de arranque, y finalmente
se les pasa a ellos también el control, la descripción
del proceso de arranque general se hará suponiendo que
se ha arrancado desde disco duro, bastando olvidar todo lo mencionado
hasta llegar al punto del sector de arranque en el caso de que
se quiera conocer cómo es un arranque desde disquetera.
Como se ha dicho, la BIOS lee y carga en memoria
el Master Boot Record, que está siempre en el primer sector
del disco duro: cabeza 0, cilindro 0, sector 1. La posición
de memoria en que la deposita es, así mismo, constante:
0000:7C00. La ROM-BIOS comprueba que los 2 últimos bytes
del sector sean 55,AA, marca utilizada para asegurarse de que
se trata de un MBR, e inmediatamente el control del ordenador
deja de estar en la ROM y pasa a esa dirección. Lo primero
que hace el MBR es desplazarse a sí mismo (sus 512 bytes)
a la zona de memoria 0000:0600 (como siempre, y mientras no se
diga lo contrario, la dirección se da en hexadecimal),
para hacer sitio al sector de arranque que el propio MBR cargará
y que, por convenio, debe hacerlo también en 0000:7C00.
XXXX:100 mov ax,0201
XXXX:103 mov bx,7c00
XXXX:106 mov cx,1
XXXX:109 mov dx,80
XXXX:10C int 13
XXXX:10E int 20
XXXX:110
-g
TABLA 1: Estructura del sector de particiones (MBR) del disco duro. | ||
---|---|---|
Desplazamiento | Longitud | Contenido |
000h | Variable | Código |
1BEh | 16 bytes | Entrada de la Partición número 1 |
1CEh | 16 bytes | Entrada de la Partición número 2 |
1DEh | 16 bytes | Entrada de la Partición número 3 |
1EEh | 16 bytes | Entrada de la Partición número 4 |
1FEh | 2 bytes | Código de identificación: 55h, AAh. |
La estructura del MBR se detalla en la tabla 1. El código
suele ser bastante breve. Una primera parte se limita a comprobar
que haya una única partición de arranque. Para ello
se empieza a mirar a partir de la posición 0000:07BE (600
+ desplazamiento 1BE dentro del sector) que, como indica la tabla
1, es donde empieza la información de cada partición.
El objetivo es comprobar el primer byte de cada tabla: si es un
00, la partición no es de arranque; si tiene un 80h, lo
es. Seguidamente, una vez identificada ésta de entre las
4 posibles (*), se mira en su entrada en la tabla correspondiente
cuál es el número de cabeza, el número de
cilindro y el número de sector en que comienza la partición
(ver tabla 2). Se lee entonces el sector correspondiente a esa
combinación de cabeza-cilindro-sector, y se guarda en la
posición 0000:7C00.
Este sector debe ser el sector de arranque de la partición,
encargado de cargar el núcleo del sistema operativo, y
a él se salta para continuar con la carga.
TABLA 2: Estructura de una entrada en la Tabla de Particiones. | ||
---|---|---|
Desplazamineto | Longitud | Contenido |
00h | 1 byte | Estado de la partición: 80h = Partición de arranque. 00h = Partición inactiva. |
01h | 1 byte | Cabeza de comienzo de la partición. |
02h | 1 word | Sector y cilindro de comienzo de la partición. |
04h | 1 byte | Tipo de partición: 04h=DOS con FAT de 16 bits, 05h=DOS extendida, 06h=DOS > 32 Mb, 83h=Linux, 82h=Linux swap... |
05h | 1 byte | Cabeza en que termina la partición. |
06h | 1 word | Sector y cilindro en que termina la partición. |
08h | 1 dword | Distancia, en sectores, desde el sector de arranque de la partición al MBR. |
0Ch | 1 dword | Número de sectores en la partición. |
Ya en el sector de arranque, y suponiendo que se trate de una
partición DOS, que es el sistema del que se está
haciendo el estudio de sus virus, se empezará actualizando
una tabla justo al comienzo del sector (tras un JMP al resto del
código) con información sobre el disco (bytes por
sector, sectores por cluster, etc.), y después se mirará
cuál es el sector en que empieza el fichero IO.SYS, que
es lo que podríamos llamar el núcleo del DOS. A
partir de ahí se leen los sectores correspondientes a ese
fichero (llamado también algunas veces IBMBIOS.COM) y se
ejecuta su código.
IO.SYS contiene extensiones de la ROM-BIOS que añade a
la BIOS con la que ya se contaba desde el comienzo del arranque.
Seguidamente se carga también el MSDOS.SYS (en algunos
sistemas, IBMDOS.COM) que añade las llamadas del sistema
operativo (interrupción 21h) con servicios para tratar
con archivos (**): si hasta ahora el ordenador sólo entendía
de cabezas y sectores, según se continúa con la
ejecución el código será capaz de hacer abstracción
y "comprender" el significado de ficheros y directorios.
El MSDOS.SYS lee un fichero de configuración creado por
el usuario, el CONFIG.SYS, con información sobre drivers
de dispositivo y parámetros para el sistema operativo tales
como el número de buffers. Para finalizar se carga
el COMMAND.COM, el intérprete de comandos que "ejecuta"
otro fichero de configuración con las primeras órdenes
que se han de ejecutar en cada arranque: el AUTOEXEC.BAT.
MODIFICANDO EL PROCESO DE ARRANQUE: EL VIRUS SE INTERPONE
Tal y como se ha descrito, el proceso de arranque comienza ejecutando
código que viene con el ordenador pregrabado en unos chips
de ROM. Esto hace que sea inalterable por el virus que sólo
tiene capacidad de actuar y modificar el discurrir habitual de
los hechos cuando se abandona la ROM, es decir, cuando la BIOS
pasa el control de la ejecución al MBR del disco duro o
al sector de arranque del disquete.
El procedimiento, por tanto, para recibir el control tras el POST
consiste en sustituir el código de ese sector por el del
virus, que se acomoda así en memoria, carga otros sectores
si ocupa más de 512 bytes, y continua después con
el proceso normal de carga sin que note nada el usuario, pero
teniendo ya el control del sistema.
Veamos cómo hace esto un virus real: el Anti-Telefónica,
de "producción" española, que se aloja
en el sector de arranque de los disquetes y en el MBR de los discos
duros. Al llegar a los 333 encendidos del ordenador (otras versiones
lo hacen a los 400) sobrescribe el disco duro y muestra por pantalla
el mensaje: "Campaña Anti-TELEFONICA (Barcelona)",
mensaje que guarda encriptado dentro del sector que sustituye
al de arranque original. Se supondrá que ya se ha cargado
el sector infectado en la posición que ocupará cuando
lo ejecute la BIOS: es decir, en el desplazamiento 7C00. Lógicamente
no se puede cargar en el segmento 0 con el debug, porque una vez
cargado el sistema este segmento tiene las direcciones de los
vectores de interrupción, variables de la BIOS, etc.
-u 7c00 0B91:7C00 EB1C JMP 7C1E 0B91:7C02 90 NOP 0B91:7C03 4D DEC BP 0B91:7C04 53 PUSH BX 0B91:7C05 44 INC SP 0B91:7C06 4F DEC DI 0B91:7C07 53 PUSH BX 0B91:7C08 332E3200 XOR BP,[0032] 0B91:7C0C 0202 ADD AL,[BP+SI] 0B91:7C0E 0100 ADD [BX+SI],AX 0B91:7C10 027000 ADD DH,[BX+SI+00] 0B91:7C13 D002 ROL BYTE PTR [BP+SI],1 0B91:7C15 FD STD 0B91:7C16 0200 ADD AL,[BX+SI]
El inicio del código, seguido de datos: obsérvese la falta de coherencia de las "instrucciones" que siguen al JMP. Al no tener el código fuente es importante saber distinguir lo que es código o lo que son datos, puesto que al pedirle al debug que desensamble una zona de memoria, lo hará aunque esa zona no sea de instrucciones. El no tiene forma de distinguir entre unos y otros: debe ser el analista el que lo haga.
-u 7c1e 0B91:7C1E BB007C MOV BX,7C00 0B91:7C21 31C0 XOR AX,AX 0B91:7C23 FA CLI 0B91:7C24 8ED0 MOV SS,AX 0B91:7C26 89DC MOV SP,BX 0B91:7C28 FB STI
Comienza con algunas inicializaciones preliminares
de la pila (stack)...
0B91:7C29 8ED8 MOV DS,AX 0B91:7C2B A11304 MOV AX,[0413] 0B91:7C2E 48 DEC AX 0B91:7C2F A31304 MOV [0413],AX
Decrementa el número de Kbytes de memoria
disponibles (variable localizada en la posición 0000:0413h)
y así se reserva ese Kbyte para el virus.
ELIMINAR UN VIRUS DE ARRANQUE
Para terminar, se ofrece un resumen de los pasos, ordenados, que se sugieren para eliminar un virus de arranque:
Leer el sector original y colocarlo en su lugar,
reescribiendo el virus. Re-arrancar.
Si todo va bien, el proceso ha terminado. De quedarse
colgado el sistema, colocar de nuevo la copia que se hizo del
sector vírico en su lugar, y tratar de identificar el problema.
Téngase en cuenta que algunos virus, sobre todo cuando
atacan a disquetes, no guardan copia del sector original. En tal
caso la única solución consistirá en colocar
un sector de arranque "genérico".
NOTAS
(*) El hecho de que sólo haya 4 posibles particiones
primarias parece obedecer más a razones de convenio que
a limitaciones impuestas por la arquitectura. De hecho, es bastante
fácil rehacer el código del MBR de forma que acepte
más particiones, aunque luego todos los programas que consulten
la tabla (como el fdisk) se atendrán al convenio de empezar
en el desplazamiento 1BEh y no "reconocerán"
las otras...
(**) En todas las versiones del DOS el procedimiento
de carga era el descrito. Sin embargo, con la llegada de Windows
95 ha cambiado ligeramente al integrarse todos los servicios en
el IO.SYS y pasar el MSDOS.SYS a convertirse en fichero de configuración
en modo texto, con datos tales como si se debe arrancar el entorno
de ventanas desde un principio o se debe esperar a que se escriba
"win" para cargarlo, o si se muestra o no el logotipo
de Windows 95 al arrancar.
REFERENCIAS:
Dos referencias obligadas sobre interrupciones y funcionamiento de la BIOS y el DOS son :
Existen programas, muchas veces residentes en memoria, que facilitan esta misma información de forma interactiva, con menús. Uno de ellos es HelpPC, de David Jurgens. También en formato electrónico se puede encontrar la que, casi con toda seguridad, es la recopilación más exhaustiva de interrupciones del PC : la llevada a cabo por Ralf Brown. Todos ellos son fáciles de localizar en Internet. |