El cifrador Sodin explota una vulnerabilidad de Windows y ciertas características arquitectónicas del procesador

Cuando, en el primer semestre del año 2019, apareció el nuevo cifrador Sodin (también conocido como Sodinokibi y Revile) llamó de inmediato nuestra atención, porque para propagarse utilizaba una vulnerabilidad en Oracle Weblogic y ataques a los proveedores de MSP. Al analizarlo en detalle, encontramos que también usa la vulnerabilidad CVE-2018-8453 para obtener privilegios en el sistema operativo Windows, algo poco frecuente entre los cifradores, y utiliza funciones legítimas del procesador para evadir las soluciones de seguridad.

Según nuestras estadísticas, la mayoría de sus víctimas se encontraban en la región de Asia y el Pacífico: Taiwán, Hong Kong y Corea del Sur.

Geografía de la distribución del cifrador Sodin, abril – junio de 2019

Descripción técnica

Explotación de la vulnerabilidad

Para obtener privilegios, Trojan-Ransom.Win32.Sodin hace uso de una vulnerabilidad en win32k.sys, cuyos intentos de explotación fueron descubiertos por nuestras tecnologías proactivas (Automatic Exploit Protection, AEP) en agosto del año pasado. La vulnerabilidad recibió la denominación CVE-2018-8453. Una vez ejecutado el exploit, el troyano obtiene el nivel máximo de privilegios.

Información sobre el token de proceso después de la ejecución del exploit

Fragmento del exploit para comprobar la clase de la ventana

Dependiendo de la arquitectura del procesador, se ejecuta una de las dos opciones de código de shell contenidas en el cuerpo del troyano:

Procedimiento para seleccionar el código de shell más apropiado

Como el binario que estamos analizando es un archivo ejecutable de 32 bits, nos interesa cómo ejecuta el código de 64 bits en su espacio de direcciones. La captura de pantalla muestra un fragmento del código de shell que permite la ejecución de instrucciones del procesador de 64 bits:

Código de shell consistente en instrucciones de 32 y 64 bits

En un sistema operativo de 64 bits, el selector del segmento de código de modo de usuario de 32 bits es 0x23, y el selector de segmento de 64 bits es 0x33. Es fácil comprobarlo mirando la tabla de descriptores globales de GDT en el depurador de kernel:

Así luce una parte del GDT en el sistema operativo Windows 10 x64

El selector 0x23 apunta al cuarto descriptor de segmento (0x23 >> 3), y el selector 0x33 apunta al sexto (no se usa el descriptor de cero). El marcador Nl indica que el segmento tiene direccionamiento de 32 bits, y el marcador Lo, de 64 bits. ¡Lo importante es que las direcciones base de estos segmentos son iguales! En el momento de la ejecución del shellcode, en el registro de segmento cs habrá un selector 0x23, ya que el código se ejecuta en un espacio de direcciones de 32 bits. Con esto en mente, veamos la lista del comienzo del código de shell:

Almacenamiento de la dirección completa – 0x23:0xC

Después de ejecutar el comando en las direcciones RVA 6 y 7, se almacenará una dirección de retorno larga en la parte superior de la pila en el formato selector:desplazamiento y será similar a 0x23:0x0C. En el desplazamiento 0x11, se coloca un DWORD en la pila, cuya palabra baja contiene el selector 0x33, mientras que la palabra alta tiene codificada la instrucción retf, cuyo código de operación es 0xCB.

Almacenamiento de la dirección completa 0x33:0x1B en el código de 64 bits

Cambio al modo de 64 bits

La siguiente instrucción es call (en la dirección 0x16 RVA), que hace la transición cercana a la instrucción dada retf (RVA 0x14), habiendo enviado previamente a la pila la dirección de retorno más cercana (desplazamiento 0x1b). Así, en el momento en el que se ejecuta la instrucción retf, en la parte superior de la pila estará la dirección en el formato selector:desplazamiento donde el selector es 0x33 y el desplazamiento es 0x1b. Después de ejecutar el comando retf, el procesador comenzará a ejecutar el código en esta dirección, pero ya en modo de 64 bits.

Shellcode de 64 bits

El retorno al modo de 32 bits se lleva a cabo al final del código de shell.

Vuelta al modo de 32 bits

El comando retf realiza una transición a una dirección distante, 0x23:0x0C (ubicada en la pila de instrucciones al comienzo del código de shell, en la dirección RVA 6-7). Una técnica similar para ejecutar el código de 64 bits en un espacio de direcciones de 32 bits denominada Heaven’s Gate fue descrita hace unos 10 años.

Configuración del troyano

El bloque de configuración se almacena cifrado en el cuerpo de cada ejemplar de Sodin, y contiene la configuración y los datos necesarios para el funcionamiento del troyano.

Archivo de configuración del troyano descifrado

En la configuración de Sodin están presentes los siguientes campos:

Campo Propósito
pk clave pública del distribuidor
pid probable Id. del distribuidor
sub probable Id. de la campaña
dbg compilación de depuración
fast modo de cifrado rápido (máximo 0x100000 bytes)
wipe eliminación de ciertos archivos con sobrescritura de sus contenidos con bytes aleatorios
wfld nombres de los directorios en los que el troyano eliminará archivos
wht nombres de directorios, archivos y una lista de extensiones que no se cifrarán
prc nombre de los procesos que se finalizarán
dmn direcciones de servidores a los que se enviarán las estadísticas
net envío de estadísticas de infección
nbody plantilla de texto con las exigencias del pago
nname patrón de nombre de archivo con las exigencias
exp uso del exploit para la escalada de privilegios
img texto para el fondo de escritorio

Esquema criptográfico

Sodin utiliza un esquema híbrido para cifrar los archivos de la víctima. El contenido de los archivos se cifra con el algoritmo de flujo simétrico Salsa20 y las claves para ello se cifran con un algoritmo asimétrico basado en curvas elípticas. Analicemos el esquema en detalle.

Dado que algunos datos se almacenan en el registro, usaremos en el artículo los nombres que utiliza el cifrador. Para aquellas entidades que no son parte del registro, usaremos nombres ficticios.

Datos guardados por el troyano en el registro

Generación de claves

El archivo de configuración de Sodin contiene el campo pk, que también entra en el registro bajo el nombre sub_key. Esta es la clave pública de 32 bytes del distribuidor de troyanos. La clave es un punto en la curva elíptica Curve 25519.

Al ejecutarse, el troyano genera un nuevo par de claves de sesión en la curva elíptica; la clave pública de este par se almacena en el registro con el nombre pk_key, y la privada está cifrada con el algoritmo ECIES en la clave sub_key y se guarda en el registro bajo el nombre sk_key. La implementación de ECIES en este caso incluye la curva Curve 25519, el hash criptográfico SHA3-256 y el cifrado de bloques AES-256 en modo CFB. Anteriormente se encontraron otras implementaciones de ECIES en troyanos, por ejemplo, en el cifrador Synack.

Un punto curioso: la misma clave privada de la sesión se cifrará en otra clave pública, indicada explícitamente en el cuerpo del troyano, sin importar su configuración. La llamaremos clave maestra pública. El resultado del cifrado se almacena en el registro con el nombre 0_key. Entonces, resulta que la persona que conoce la clave privada correspondiente a public skeleton keypodrá descifrar los archivos de la víctima, incluso si no tiene la clave privada de sub_key. Al parecer, el desarrollador del troyano incluyó en el algoritmo una función secreta que le permite descifrar archivos sin que los distribuidores se enteren.

Fragmento del procedimiento que genera los datos de las claves y almacena algunos de ellos en el registro

Cifrado de los archivos

Al cifrar cada archivo, se genera un nuevo par de claves asimétricas en la curva elíptica, que llamaremos file_pub y file_priv. Luego se calcula el SHA3-256 (ECDH (file_priv, pk_key)), y el resultado se utiliza como una clave simétrica para cifrar el contenido del archivo con el algoritmo Salsa20. La siguiente información también se guarda en el archivo cifrado:

Además de los campos ya mencionados, también está nonce (inicialización aleatoria de 8 bytes para cifrado Salsa20), file_pub_crc32 (suma de control de file_pub) flag_fast (si está configurado, significa que solo algunos datos están cifrados en el archivo), zero_encr_by_salsa (dword nulo, encriptado con la misma clave Salsa20 que el contenido del archivo, al parecer para verificar la exactitud del descifrado).

Datos almacenados en cada archivo cifrado

Los archivos cifrados obtienen una nueva extensión arbitraria (la misma para cada caso de infección); el texto con las exigencias se guarda junto a ellos y el fondo de pantalla generado por el malware se instala en el escritorio.

Exigencias de los delincuentes

Fragmento del fondo de escritorio creado por el cifrador

Interacción de red

Si el marcador correspondiente está puesto en el archivo de configuración, el troyano enviará información sobre la máquina infectada a sus servidores. Los datos transmitidos también se cifran utilizando el algoritmo ECIES utilizando otra clave pública indicada explícitamente en el cuerpo de Sodin.

Parte de la configuración de Sodin responsable de la interacción de red

Campo Propósito
ver versión del troyano
pid probable Id. del distribuidor
sub probable Id. de la campaña
pk clave pública del distribuidor
uid Id. de la infección
sk valor de sk_key (ver descripción arriba)
unm nombre del usuario del sistema infectado
net nombre de la máquina
grp dominio o grupo de trabajo de la máquina
lng idioma del sistema
bro idioma o distribución del teclado de la lista (abajo)
os versión del sistema operativo
bit arquitectura
dsk información sobre los discos en el sistema
ext extensión de los archivos cifrados

En el proceso de ejecución, el troyano comprueba el idioma del sistema y las distribuciones de teclado disponibles:

Si se encuentran coincidencias con la lista, el proceso del malware se finaliza y no se procede a enviar las estadísticas.

MITRE ATT&CK techniques


IOC

1ce1ca85bff4517a1ef7e8f9a7c22b16

Publicaciones relacionadas

Deja un comentario

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