El siguiente post es una traducción y adaptación de la publicación Flame, Duqu and Stuxnet: in-depth code analysis of mssecmgr.ocx escrita por nuestros colegas investigadores de ESET, Aleksandr Matrosov y Eugene Rodionov.

El gusano Flame (detectado por ESET como Win32/Flamer) es uno de los ataques dirigidos que mayor interés ha despertado durante este año. A pesar de varios artículos que se han publicado, hay algunas cuestiones relacionadas con su módulo principal (mssecmgr.ocx) que no se han tratado. Es precisamente en este post que se quiere dar algunos detalles sobre este componente.

Ya se han tratado temas relacionados con el análisis de Stuxnet y Duqu. El análisis del código del gusano Stuxnet requirió de un gran esfuerzo para entender su funcionamiento. En el caso de Duqu se ha podido determinar que la arquitectura y la aplicación son muy similares a las de Stuxnet, por lo cual su análisis se hizo más fácil su análisis. En el caso de Flame es otra la historia, ya que tiene varios módulos interconectados, como el almacenamiento interno para la información de configuración, y el payload con un formato hasta ahora desconocido. A pesar de estas dificultades, se presentarán algunos detalles interesantes sobre el módulo principal mssecmgr.ocx.

Relación con Stuxnet y Duqu

Flame es un malware del mismo tipo de Stuxnet y Duqu. Estos códigos maliciosos implementan una lógica bastante compleja, con una elaborada arquitectura y detalles de implementación, que buscan mantener presencia en los sistemas atacados. El estilo orientado a objetos de Flame programado en C++ hace más complejo el análisis de código, ya que el proceso de análisis requiere de la reconstrucción del flujo lógico del gusano y de la lógica del compilador. Por ejemplo, una reconstrucción del método Rc4_GetBufferSize muestra lo siguiente:

En el análisis estático, un problema común es determinar la coincidencia  del valor único que coincida con el valor en VTABLE, el cual es llamado por el apuntador VPTR. En el análisis estático se utilizaron métodos para definir estructura que  emulen objetos de C++. Aunque mssecmgr.ocx hace un uso intensivo de código orientado a objetos es muy diferente a la programación orientada a objetos que se utiliza en Stuxnet y Duqu.

Al analizar los detalles para ciertos objetos se observa que son significativamente diferentes. Por ejemplo, para los objetos que representan los strings, que son el objeto más frecuente en el malware analizado,  son claramente muy diferentes. Lo mismo ocurre con los métodos de aplicación de estos objetos. En la siguiente gráfica pueden apreciarse las estructuras que describen objetos de Stuxnet y Flame:


Estos objetos son responsables de actividades como el procesamiento de archivos, el mapeo de archivos, sincronización de objetos, buffers de memoria, stream de memoria entre otras; las cuales son diferentes de los aplicados en el Stuxnet.
Otra característica distintiva del código de Flame es el frecuente uso de punteros inteligentes como objetos con el fin de manejar punteros a objetos de diferentes tipos. Siendo este enfoque muy conveniente desde el punto de vista de los desarrolladores, utilizar tantos punteros inteligentes hace más complejo el análisis del código.

Análisis del Módulo Principal

Flame almacena sus componentes en varios archivos del sistema de archivos de Windows. Utiliza tres esquemas distintos de nomenclatura para almacenar los archivos. Basado en la información de configuración y el entorno en el que se ejecute, el malware elige un esquema específico. La siguiente gráfica contiene información sobre estos sistemas de nomenclatura.

Arranque de Flame

Cuando el malware se instala en el sistema se registra como un paquete de autenticación LSA en el registro del sistema. Esto genera que la carga de mssecmmgr.ocx sea parte del proceso lsass.exe durante el arranque del sistema. Curiosamente, los paquetes de autenticación tienen asociadas un conjunto de rutinas como interfaz para la LSA, pero ninguna de estas rutinas de interfaz son ejecutados por el módulo principal de Flame.

Sistemas Operativos que pueden ser afectados

Cuando el módulo principal de este gusano se inicia, realiza algunas comprobaciones para verificar si la versión del sistema operativo es apta para la ejecución del código malicioso y si la máquina se ha cargado en modo seguro:

Este código malicioso no se ejecuta en sistemas operativos de 64 bits, pero se ejecuta en todas las versiones de Windows, superiores a Windows 2000, pero no se incluye Windows 8.

Detección

Cuando el módulo principal de Flame se carga verifica cuál es el software de seguridad que está instalado en la máquina infectada. La lista de los programas que se verifican se encuentra guardada en la información de configuración. En las muestras analizadas hay aproximadamente 320 nombres diferentes tipos de software de seguridad. Dependiendo de una serie de condiciones, definidas en la información de configuración el código malicioso puede detener la ejecución del software de seguridad específico si se detecta en el sistema. Los productos detectados se dividen en grupos dependiendo de su funcionalidad: Firewalls Personales, Sistema para la prevención de intrusiones (HIPS), software antivirus, analizadores de paquetes de red, sistemas de control parental, software para el monitoreo del sistema, sistemas DLP, entre otros.

Inyección en procesos

Para poder inyectar código en el espacio de direcciones de otros procesos el malware utiliza cuidadosamente estas rutinas de la API estándar:

  • VirtualAllocEx – Asigna memoria para el módulo que se inyecta en el proceso de destino.
  • WriteProcessMemoryReadProcessMemory – Inyecta el código.
  • CreateRemoteThreadRtlCreateUserThread – Transfiere el control al módulo inyectado.

Como resultado, el espacio de direcciones del proceso de destino se verá así:

Lo que hace que Flame sea difícil de detectar es un truco interesante con la librería shell32.dll. Para asignar el espacio del módulo inyectado, Flame lo hace utilizando el módulo shell32.dll. El código responsable de hacer esto se parece a lo siguiente, cuando es descompilado:

Esto da como resultado la creación de todas las estructuras del sistema necesarias para la inyección y como resultado se ve como un módulo correctamente cargado.

Cuando todos los datos y el código se escriben en el espacio de direcciones objetivo, Flame crea un hilo de ejecución remoto, mediante la llamada de CreateRemoteThread o RtlCreateUserThread y la creación del Stub 2 como punto de entrada y los datos inyectados como parámetro.

El Stub 2 contiene el código que busca asignar el módulo inyectado en el espacio de direcciones del proceso, siguiendo los siguientes pasos:

  • Asignar memoria para la imagen.
  • Aplicar los movimientos en el espacio de memoria.
  • Inicializar la importación de la tabla de direcciones.
  • Llame al punto de entrada.

Los datos inyectados se utilizan como una estructura auxiliar que contiene la dirección de todas las rutinas necesarias y las constantes suplementarias. Una parte del código responsable de la inicialización de esta estructura se ve como sigue:

Otra cosa que hace el Stub 2 es conectar el punto de entrada, msvcrt.dll, con  el código del Stub 1. Más adelante se demostrará por qué y cómo se lleva a cabo la conexión. La principal funcionalidad de código del Stub 1 es llamar al punto de entrada del módulo de inyección cada vez que el punto de entrada de msvcrt.dll se llama. Como resultado, el módulo inyectado es capaz de obtener todos los eventos que msvcrt.dll recibe. Esto permite que el software malicioso emule el entorno de ejecución como lo hace un módulo legítimamente cargado. Flame conecta msvcrt.dll de una manera bastante inusual. En lugar de empalmar el código, sobrescribe el campo correspondiente de la estructura PEB_LDR_DATA en InLoadOrderModuleList que se encuentra en el PEB (Process Environment Block). Después de completada la inyección el código malicioso limpia los rastros de la inserción en el espacio de direcciones del proceso.

Información de configuración

La forma en que Flame almacena la información de configuración es bastante complicada y es muy diferente a nivel de ejecución de lo que es Stuxnet o Duqu. Cuando el código malicioso penetra inicialmente en el sistema, todos los datos de configuración están contenidos dentro de los recursos que pertenecen al módulo principal. En el módulo principal Flame tiene un recurso identificado con el ID 146 en el directorio de recursos. Este es el lugar donde todos los datos de configuración se guardan. Dependiendo de la versión del malware el tamaño del recurso puede variar, normalmente está entre 37 Kb y 3Mb. A diferencia de Stuxnet y Duqu, que almacenan datos de configuración en un archivo binario simple, Flame emplea un tipo más sofisticado de almacenamiento que no es fácil de analizar.

Para poder tener acceso a la información de configuración se necesita descifrar el recurso y descomprimir los datos descifrados. El algoritmo de cifrado es bastante simple, tal como se presenta en la siguiente gráfica.

Cuando los datos se descifran, son descomprimidos en paquetes de datos pequeños (menos de un kilobyte cada uno), y utilizando la rutina de API Sleep espera 10 milisegundos entre cada paquete de datos; lo cual hace que el proceso de descompresión sea bastante robusto:

Finalmente, después de la descompresión, del recurso descifrado, Flame aplica sobre este una permutación definida por el siguiente arreglo de bytes:

Todos los datos de configuración de Flame son divididos en bloques con la siguiente estructura:

El primer byte describe el tipo de contenido en el bloque. La información puede ser de dos tipos:

  • Información suplementaria de los elementos de información de configuración.
  • Valores de los elementos de información de configuración.

Los campos de datos para los bloques que contienen información suplementaria están organizados de la siguiente forma:

Es decir, se especifica el offset del bloque con los datos del elemento, el offset del bloque que contiene información adicional sobre la configuración del siguiente elemento de datos, y el nombre del elemento. La raíz se encuentra en la posición 0x1A al inicio de los datos de configuración. En la siguiente figura se puede ver un bloque que describe la configuración del elemento RTS.MEDIA_SETUP.FILES_TO_DELETE:

A diferencia de Stuxnet y Duqu, donde los elementos con información de configuración no tenían nombre, para Flame los investigadores de malware aprovecharon esta característica para facilitar la comprensión de las funcionalidades del malware.

El tipo de datos de los elementos con información de configuración puede ser determinado por el valor del block byte. Éstos son algunos valores correspondientes a diferentes tipos de elementos:

  • 0×08 – DWORD (4-byte integer);
  • 0×06 – WORD (2-byte integer);
  • 0×09 – QWORD (8-byte integer)
  • 0×05 – NULL-terminated Unicode string;
  • 0×04 – raw binary data;
  • 0×03 – item description block (see Figure 10)
  • 0×02 – root block.

Dependiendo de una serie de condiciones, cuando el código malicioso infecta el sistema almacena la información de configuración en un archivo con el nombre mscrypt.da0 o wpgfilter.da0.

H. Camilo Gutiérrez Amaya
Especialista de Awareness & Research