Cyril François

Desempaquetando ICEDID

Un tutorial completo con las herramientas de código abierto de Elastic Security Labs

14 min de lecturaHerramientas
Desempacar ICEDID

Preámbulo

ICEDID es una familia de malware descubiertaen 2017 por investigadores de IBM X-force y está asociada con el robo de credenciales de inicio de sesión, información bancaria y otra información personal. ICEDID siempre fue una familia prevalente, pero logró un crecimiento aún mayor desde la interrupción temporal de EMOTET a principios de 2021. ICEDID se relacionó con la distribución de varias familias de malware distintas, incluidas DarkVNC y COBALT STRIKE. Los reportes regulares de la industria, incluidas las publicaciones de investigación como esta, ayudan a mitigar esta amenaza.

ICEDID es conocido por empaquetar sus cargas útiles empleando formatos de archivo personalizados y un esquema de cifrado personalizado. Siguiendo nuestra última investigación de ICEDID que cubre la cadena de ejecución de variantes de GZip.

En este tutorial, presentaremos estas herramientas desempaquetando una muestra reciente de ICEDID comenzando con la descarga de una copia del binario GZip falso:

El análisis de malware puede ser peligroso para los sistemas y solo debe ser intentado por profesionales experimentados en un entorno controlado, como una máquina virtual aislada o un entorno aislado de análisis. El malware puede diseñar para evadir la detección e infectar otros sistemas, por lo que es importante tomar todas las precauciones necesarias y emplear herramientas especializadas para proteger a sí mismo y a sus sistemas.

54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f

Configuración del entorno

Para este tutorial, estamos usando Windows 10 y Python 3.10.

Elastic Security Labs lanza un conjunto de herramientas para automatizar el proceso de desempaquetado y ayudar a los analistas y a la comunidad a responder a ICEDID.

GuiónDescripciónCompatibilidad
decrypt_file.pyDescifrar el archivo cifrado ICEDIDWindows y otros (no probados)
gzip_variant/extract_gzip.pyExtraiga cargas útiles del archivo GZip falso de ICEDIDWindows y otros (no probados)
gzip_variant/extract_payload_from_core.pyExtraiga y descifre cargas útiles del binario principal de ICEDID reconstruidoWindows y otros (no probados)
gzip_variant/load_core.pyCargue y ejecute un binario de PE personalizado principalSolo para Windows
gzip_variant/read_configuration.pyLeer el archivo de configuración de ICEDID contenido en el falso GZipWindows y otros (no probados)
rebuild_pe.pyReconstruir un PE a partir de un archivo PE personalizado de ICEDIDWindows y otros (no probados)

Para usar las herramientas, clona el repositorio de versiones de Elastic Security Lab e instala el módulo nightMARE.

git clone https://github.com/elastic/labs-releases
cd labs-release
pip install .\nightMARE\

Todas las herramientas de este tutorial emplean el módulo nightMARE , esta biblioteca implementa diferentes algoritmos que necesitamos para desempaquetar las diversas cargas útiles integradas en ICEDID. Estamos lanzando nightMARE porque es necesario para este análisis de ICEDID, pero estén atentos, habrá más por venir a medida que continuamos desarrollando y madurando este marco.

Desempaquetando el falso GZip

El GZip falso de ICEDID es un archivo que se hace pasar por un archivo GZip válido formateado encapsulando los datos reales con un encabezado y un pie de página GZip.

Los bytes mágicos de GZip aparecen en rojo.
El encabezado GZip se representa en verde.
El valor del nombre de archivo ficticio es azul.

Luego del encabezado GZip se encuentra la verdadera estructura de datos, que describimos a continuación.

Usaremos el script labs-releases\tools\icedid\gzip-variant\extract_gzip.py para descomprimir este GZip fraudulento.

usage: extract_gzip.py [--help] input output

positional arguments:
  input       Input file
  output      Output directory

options:
  -h, --help  show this help message and exit

Usaremos extract_gzip.py en el ejemplo de ICEDID vinculado anteriormente y almacenaremos el contenido en una carpeta que creamos llamada " extract " (puede usar cualquier carpeta de salida existente).

python extract_gzip.py 54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f extract

============================================================
Fake Gzip
============================================================
is_dll: True
core: UponBetter/license.dat (354282 bytes)
stage_2: lake_x32.tmp (292352 bytes)

extract\configuration.bin
extract\license.dat
extract\lake_x32.tmp

Este script devuelve tres archivos individuales que constan de:

  • El archivo de configuración cifrado: configuration.bin
  • El binario del núcleo cifrado: license.dat
  • El cargador de persistencia: lake_x32.tmp

Descifrar los archivos binarios y de configuración principales

La configuración y el binario principal que extrajimos se cifran mediante el esquema de cifrado personalizado de ICEDID. Podemos descifrarlos con el script labs-releases\tools\icedid\decrypt_file.py .

usage: decompress_file.py [--help] input output

positional arguments:
  input       Input file
  output      Output file

options:
  -h, --help  show this help message and exit

Como se muestra aquí (tenga en cuenta que los archivos descifrados se pueden escribir en cualquier destino válido):

python .\decrypt_file.py .\extract\license.dat .\extract\license.dat.decrypted

python .\decrypt_file.py .\extract\configuration.bin .\extract\configuration.bin.decrypted

El binario principal y la configuración ahora están listos para ser procesados por herramientas adicionales. Vea los datos de la configuración descifrada que se presentan en la siguiente captura de pantalla:

Lectura de la configuración

A continuación se presenta el formato del archivo de configuración.

La configuración se puede leer mediante el script labs-releases\tools\icedid\gzip-variant\read_configuration.py .

usage: read_configuration.py [--help] input

positional arguments:
  input       Input file

options:
  -h, --help  show this help message and exit

Usaremos el script read_configuration.py para leer el archivo configuration.bin.decrypted que recopilamos en el paso anterior.

python .\gzip-variant\read_configuration.py .\extract\configuration.bin.decrypted

============================================================
Configuration
============================================================
botnet_id: 0x3B7D6BA4
auth_var: 0x00000038
uri: /news/
domains:
        alishaskainz.com
        villageskaier.com

Esta configuración contiene dos dominios C2:

  • alishaskainz[.]com
  • villageskaier[.]com

Para este ejemplo, el URI de balizamiento que usa ICEDID es " /news/ ".

Reconstrucción del binario principal para el análisis estático

ICEDID emplea un formato PE personalizado para ofuscar sus cargas útiles, derrotando así a las herramientas de análisis estático o dinámico que esperan tratar con un ejecutable normal de Windows. A continuación se describe el formato de archivo PE personalizado.

Si queremos analizar el binario principal, por ejemplo con IDA Pro, necesitamos reconstruirlo en un PE válido. Usamos el script labs-releases\tools\icedid\rebuild_pe.py .

usage: rebuild_pe.py [--help] [-o OFFSET] input output

positional arguments:
  input                 Input file
  output                Output reconstructed PE

options:
  -h, --help            show this help message and exit
  -o OFFSET, --offset OFFSET
                        Offset to real data, skip possible garbage

Sin embargo, al intentar usar rebuild_pe.py en el binario principal descifrado, license.dat.decrypted , recibimos el siguiente mensaje de error:

python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin
Traceback (most recent call last):
  File "rebuild_pe.py", line 32, in <module>
    main()
  File "rebuild_pe.py", line 28, in main
    custom_pe.CustomPE(data).to_pe().write(args.output)
  File "nightmare\malware\icedid\custom_pe.py", line 86, in __init__
    raise RuntimeError("Failed to parse custom pe")
RuntimeError: Failed to parse custom pe

La sutileza aquí es que los datos de PE personalizados no siempre comienzan al principio del archivo. En este caso, por ejemplo, si abrimos el fichero en un editor hexadecimal como HxD podemos observar una cierta cantidad de bytes basura antes de los datos reales.

Sabemos por nuestra investigación que el tamaño de la basura es de 129 bytes.

Con eso en mente, podemos omitir los bytes de basura y reconstruir el binario principal usando el script rebuild_pe.py usando el parámetro "-o 129". Esta vez, afortunadamente, no recibimos ningún mensaje de error. core.bin almacenará en el directorio de salida, extraer en nuestro ejemplo.

python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin -o 129

El objeto PE reconstruido no se puede ejecutar directamente, pero puede analizarlo estáticamente con el desensamblador de su elección.

Asignamos nombres personalizados a las secciones binarias reconstruidas ( .mare{0,1,2,...} ).

Queremos reconocer y agradecer el trabajo de Hasherezade, en el que nos inspiramos para construir esta herramienta.

Ejecución del binario principal (solo Windows)

El binario principal no se puede ejecutar sin un cargador personalizado que comprenda el formato PE personalizado de ICEDID, así como el prototipo de función de punto de entrada.

A partir de nuestra investigación, sabemos que el punto de entrada espera una estructura a la que nos referimos como estructura de contexto, que contiene las rutas del núcleo y del cargador de persistencia de ICEDID con su configuración cifrada. La estructura del contexto se describe a continuación.

Para ejecutar de forma nativa el binario principal, usamos el script labs-releases\tools\icedid\gzip-variant\load_core.py , pero antes de usarlo necesitamos crear el archivo context.json que contendrá toda la información que necesita este script para construir esta estructura.

Para este ejemplo, copiamos la información contenida en el gzip falso y usamos la ruta al archivo de configuración cifrado. Incluimos un ejemplo en gzip_variant/context.json.example.

Tenga en cuenta que los valores "field_0" y "stage_2_export" deben encontrar al invertir la muestra.

Aquí usamos valores de nuestra investigación anterior como marcadores de posición, pero no tenemos garantía de que la muestra funcione al 100%. Por ejemplo, en este ejemplo, no sabemos si la exportación ordinal #1 es el punto de entrada real del cargador de persistencia.

También reproducimos el comportamiento de la primera etapa creando el directorio UponBetter y moviendo el archivo license.dat a él.

Ejecutamos el script labs-releases\tools\icedid\gzip_variant\load_core.py empleando el binario principal descifrado : license.dat.decrypted , el archivo context.json .

ADVERTENCIA: El binario va a ser cargado/ejecutado de forma nativa por este script, Elastic Security Labs no se hace responsable de ningún daño a su sistema. Ejecute solo dentro de un entorno seguro.

usage: load_core.py [--help] [-o OFFSET] core_path ctx_path

positional arguments:
  core_path             Core custom PE
  ctx_path              Path to json file defining core's context

options:
  -h, --help            show this help message and exit
  -o OFFSET, --offset OFFSET
                        Offset to real data, skip possible garbage

Debido a que tenemos el mismo problema de bytes basura que se indicó en la sección anterior, usamos el parámetro "-o 129" para omitir los bytes basura.

python .\gzip-variant\load_core.py .\extract\license.dat.decrypted .\gzip-variant\context.example.json -o 129

============================================================
Core Loader
============================================================
Base address: 0x180000000
Entrypoint: 0x180001390

Press a key to call entrypoint...

Cuando se inicia, el script esperará la entrada del usuario antes de llamar al punto de entrada. Podemos anexar fácilmente un depurador al proceso de Python y establecer un punto de interrupción en el punto de entrada del núcleo ICEDID (en este ejemplo 0x180001390 ).

Una vez pulsada la tecla, llegamos al punto de entrada.

Si dejamos que se ejecute el binario, vemos que se crean hilos ICEDID (como se indica en la siguiente captura de pantalla).

Desempaquetar y reconstruir cargas útiles del binario principal reconstruido

Para extraer cualquiera de las cargas útiles que están incrustadas dentro del binario principal, usaremos el script labs-releases\tools\icedid\gzip-variant\extract_payloads_from_core.py

usage: extract_payloads_from_core.py [--help] input output

positional arguments:
  input       Input file
  output      Output directory

options:
  -h, --help  show this help message and exit

Usaremos este script en el binario principal reconstruido.

python .\gzip-variant\extract_payloads_from_core.py .\extract\core.bin core_extract

core_extract\browser_hook_payload_0.cpe
core_extract\browser_hook_payload_1.cpe

A partir de aquí, generamos dos binarios correspondientes a las cargas útiles de ICEDID para las capacidades de enlace del navegador sitio web, sin embargo, todavía están en su formato PE personalizado.

Basándonos en nuestra investigación, sabemos que browser_hook_payload_0.cpe es la versión x64 de la carga útil del gancho del navegador y browser_hook_payload_1.cpe es la versión x86.

Para reconstruirlos, volvemos a emplear el script rebuild_pe.py , esta vez no hay bytes de basura que saltar.

python .\rebuild_pe.py .\core_extract\browser_hook_payload_0.cpe .\core_extract\browser_hook_payload_0.bin

python .\rebuild_pe.py .\core_extract\browser_hook_payload_1.cpe .\core_extract\browser_hook_payload_1.bin

Ahora tenemos dos binarios de PE ( browser_hook_payload_0.bin y browser_hook_payload_1.bin ) que podemos analizar más a fondo.

Los lectores atentos pueden observar que nos saltamos el desempaquetado del servidor VNC del binario principal, una decisión que tomamos intencionalmente. Lo lanzaremos junto con otras herramientas en próximas investigaciones, ¡así que estad atentos!

Conclusión

En este tutorial cubrimos el desempaquetado de variantes de ICEDID GZip, comenzando con la extracción del binario GZip falso, seguido de la reconstrucción del binario central y el desempaquetado de sus cargas útiles.

ICEDID está en constante evolución, y vamos a continuar monitoreando cambios importantes y actualizando nuestras herramientas junto con nuestra investigación. No dudes en abrir un problema o enviarnos un mensaje si algo está roto o no funciona como se esperaba.

Elastic Security Labs es un equipo de investigadores e ingenieros de seguridad dedicados que se enfocan en interrumpir a los adversarios a través de la publicación de lógica de detección detallada, protecciones e investigación aplicada de amenazas.

Síganos en @elasticseclabsy visite nuestro portal de investigación para obtener más recursos e investigaciones.

Referencias

A lo largo de la investigación anterior se hizo referencia a lo siguiente: