Ingeniería

Detección de Cobalt Strike con firmas en la memoria

En Elastic Security, abordamos el desafío de la detección de amenazas con varios métodos. Tradicionalmente, nos hemos enfocado en modelos de machine learning y comportamientos. Estos dos métodos son poderosos porque pueden detectar malware nunca antes visto. Históricamente, hemos creído que las firmas pueden evadirse con demasiada facilidad, pero también reconocemos que esa facilidad de evasión es solo uno de muchos factores a tener en cuenta. El rendimiento y las tasas de falsos positivos también son fundamentales para evaluar la efectividad de una técnica de detección.

Las firmas, si bien no pueden detectar malware desconocido, tienen tasas de falsos positivos cercanas a cero y poseen etiquetas asociadas que ayudan a priorizar alertas. Por ejemplo, una alerta de TrickBot o REvil Ransomware requiere una acción más inmediata que una variante de adware potencialmente no deseada. Incluso si pudiéramos, hipotéticamente, detectar solo la mitad del malware conocido mediante firmas, sigue siendo una gran ventaja en combinación con otras protecciones, teniendo en cuenta los otros beneficios. Siendo realistas, podemos lograr algo incluso mejor.

Un obstáculo para crear firmas que proporcionen valor a largo plazo es el uso generalizado de packers y cargadores de malware desechables. Estos componentes evolucionan rápido para evadir la detección de firmas; sin embargo, la carga de malware final eventualmente se desencripta y ejecuta en la memoria.

Para evitar el problema de los packers y cargadores, podemos enfocar las estrategias de detección de firmas en el contenido en la memoria. Esto amplía efectivamente la vida útil de la firma de días a meses. En este blog, usaremos Cobalt Strike como ejemplo para aprovechar las firmas en la memoria. 

Control con firmas de Cobalt Strike

Cobalt Strike es un marco de trabajo popular para realizar operaciones del equipo rojo y simulación de atacantes. Presumiblemente, debido a su facilidad de uso, estabilidad y características sigilosas, también es una herramienta favorita de los actores malintencionados con intenciones incluso más viles. Ha habido varias técnicas para detectar Beacon, la carga de endpoint de Cobalt Strike. Esto incluye buscar subprocesos sin respaldo y, más recientemente, canalizaciones con nombre integradas. Sin embargo, debido al grado de capacidad de configuración en Beacon, suele haber formas de evadir las estrategias de detección públicas. Aquí intentamos usar las firmas en la memoria como estrategia de detección alternativa.

Beacon por lo general se carga de forma reflectiva en la memoria y nunca toca el disco de una forma directa que permita el control con firmas. Además, Beacon puede configurarse con diversas opciones de ofuscación en la memoria para ocultar su carga. Por ejemplo, la opción ofuscación y suspensión intenta enmascarar partes de la carga de Beacon entre devoluciones de llamadas para evadir específicamente los análisis de memoria basados en firmas. Tendremos que considerar esta opción al desarrollar firmas, pero sigue siendo fácil controlar Beacon con firmas incluso con estas características sigilosas avanzadas.

En profundidad

Comenzaremos por obtener algunas cargas de Beacon con la opción sleep_mask habilitada y deshabilitada con las versiones más recientes (hashes en la sección de referencia). Si comenzamos con una muestra con sleep_mask deshabilitada, después de la detonación, podemos ubicar Beacon en la memoria con Process Hackers si buscamos un subproceso que llame a SleepEx desde una región sin respaldo:

A partir de allí, podemos guardar la región de memoria asociada en el disco para su análisis:

El logro más fácil sería seleccionar algunas cadenas únicas de esta región y usarlas como nuestra firma. A fin de demostrar esto, escribiremos firmas con yara, una herramienta estándar de la industria para tal fin:

rule cobaltstrike_beacon_strings
{
meta:
    author = "Elastic"
    description = "Identifies strings used in Cobalt Strike Beacon DLL."
strings:
    $a = "%02d/%02d/%02d %02d:%02d:%02d"
    $b = "Started service %s on %s"
    $c = "%s as %s\\%s: %d"
condition:
    2 of them
}

Esto nos daría una buena cobertura de base, pero podemos mejorarla si observamos las muestras con sleep_mask habilitada. Si buscamos en la memoria donde normalmente se encontraría el encabezado MZ/PE, ahora vemos que está ofuscado:

Si echamos una mirada rápida a esto, podemos ver muchos bytes repetidos (0x80 en este caso) en donde, en realidad, esperaríamos bytes nulos. Esto puede ser un indicio de que Beacon está usando una ofuscación XOR de un byte simple. Para confirmarlo, podemos usar CyberChef:

Como puedes ver, la cadena "This program cannot be run in DOS mode" (Este programa no se puede ejecutar en modo DOS) aparece después de la decodificación, lo que confirma nuestra teoría. Como un XOR de un solo byte es uno de los trucos más antiguos, yara en realidad soporta la detección nativa con el modificador xor:

rule cobaltstrike_beacon_xor_strings
{
meta:
    author = "Elastic"
    description = "Identifies XOR'd strings used in Cobalt Strike Beacon DLL."
strings:
    $a = "%02d/%02d/%02d %02d:%02d:%02d" xor(0x01-0xff)
    $b = "Started service %s on %s" xor(0x01-0xff)
    $c = "%s as %s\\%s: %d" xor(0x01-0xff)
condition:
    2 of them
}

Podemos confirmar la detección de nuestras reglas de yara hasta aquí proporcionando una PID durante el análisis:

Sin embargo, aún no acabamos. Después de probar esta firma en una muestra con la versión más reciente de Beacon (4.2, al momento de escribir este blog), la rutina de ofuscación se mejoró. La rutina puede encontrarse siguiendo la pila de llamadas, como mostramos antes. Ahora usa una clave XOR de 13 bytes, como se muestra en el fragmento siguiente de IDA Pro:


Afortunadamente, la opción de ofuscación y suspensión de Beacon solo ofusca cadenas y datos, y deja la sección completa de código lista para el control con firmas. La pregunta de para qué función en la sección de código deberíamos desarrollar una firma merece su propio blog. Por ahora, podemos crear simplemente una firma en la rutina de desofuscación, lo cual debería funcionar bien:

rule cobaltstrike_beacon_4_2_decrypt
{
meta:
    author = "Elastic"
    description = "Identifies deobfuscation routine used in Cobalt Strike Beacon DLL version 4.2."
strings:
    $a_x64 = {4C 8B 53 08 45 8B 0A 45 8B 5A 04 4D 8D 52 08 45 85 C9 75 05 45 85 DB 74 33 45 3B CB 73 E6 49 8B F9 4C 8B 03}
    $a_x86 = {8B 46 04 8B 08 8B 50 04 83 C0 08 89 55 08 89 45 0C 85 C9 75 04 85 D2 74 23 3B CA 73 E6 8B 06 8D 3C 08 33 D2}
condition:
     any of them
}

Podemos validar que podemos detectar Beacon incluso cuando está en estado de suspensión sigiloso (tanto en las variantes de 32 como 64 bits):

Para convertir esta en una detección más robusta, podríamos analizar con regularidad todos los procesos del sistema (o de la empresa completa). Esto podría hacerse con la línea única de powershell siguiente:

powershell -command "Get-Process | ForEach-Object {c:\yara64.exe my_rules.yar $_.ID}"

Resumen

La detección basada en firmas, si bien suele subestimarse, es una estrategia de detección valiosa; en especial, cuando consideramos el análisis en la memoria. Con solo algunas firmas, podemos detectar Cobalt Strike sin importar la configuración o características sigilosas habilitadas, con una tasa cero real de falsos positivos.

Hashes de referencia

7d2c09a06d731a56bca7af2f5d3badef53624f025d77ababe6a14be28540a17a
277c2a0a18d7dc04993b6dc7ce873a086ab267391a9acbbc4a140e9c4658372a
A0788b85266fedd64dab834cb605a31b81fd11a3439dc3a6370bb34e512220e2
2db56e74f43b1a826beff9b577933135791ee44d8e66fa111b9b2af32948235c
3d65d80b1eb8626cf327c046db0c20ba4ed1b588b8c2f1286bc09b8f4da204f2

Conoce más sobre Elastic Security

Familiarízate (si aún no lo has hecho) con las capacidades poderosas de protección, detección y respuesta del agente de Elastic. Comienza tu prueba gratuita de 14 días (no se requiere tarjeta de crédito) o descarga nuestros productos, gratis, para tu implementación en las instalaciones. Y aprovecha nuestra capacitación de Inicio rápido para prepararte para tener éxito.