A veces, el malware que encontramos aquí en Huntress simplemente nos hace reír.
No porque sea gracioso (¿alguna vez el malware es gracioso?) — sino porque el código que revisamos a veces no hace ningún esfuerzo por ocultar sus acciones.
Hablamos de ofuscación en muchas publicaciones del blog, donde los hackers al menos intentan cubrir sus técnicas. La ofuscación consiste en oscurecer el código fuente original haciéndolo difícil de entender con nombres de variables confusos o esquemas de codificación.
¿Es esto algún tipo de broma?
No, en serio, nuestros analistas han visto realmente binarios maliciosos que incluyen las credenciales root (administrativas) para acceder al servidor de preparación del hacker, directamente en texto plano.
Hace poco, encontramos esta muestra de malware escrita en JavaScript, con el nombre de archivo explorer.js. Échale un vistazo: sin trucos bajo la manga, el código contiene los servidores C2 sin ninguna ofuscación.
Bueno, ¡no tuvimos que esforzarnos mucho para descubrirlo! No se necesitó trabajo de detective.
Esta lista COMMAND_C2 contiene dominios tanto falsos como legítimos. Si bien estos últimos ciertamente parecen sospechosos, se sabe que el dominio redirector.gvt1.com pertenece a Google. Es poco probable que aloje malware o se use en operaciones C2 — si acaso, el implante podría comunicarse con él para esconderse junto al tráfico de red normal y "parecer legítimo".
Si no has visto antes estos otros dominios, puedes agregarlos a tu biblioteca de IOC o bloquearlos:
- http://onecs-live.azureedge.net
- http://ipm-provider.ff.avast.com
- http://tauhutxiga.com
- http://monsuperentrepreneur.com
- http://tangocation.com
- http://e4a24fb0e.com
- http://f78efaf43b.com
Ese es el remate
La conclusión aquí es que algunos hackers son audaces y tienen el descaro de incluir estos detalles confidenciales directamente en su ataque. Si lo piensas bien… ¿para qué molestarse en ofuscar? Si este malware sigue siendo efectivo, y tu antivirus o solución EDR no lo detecta, ¿quién necesita pasar por todos esos pasos adicionales?
Queríamos compartir esto contigo porque, esperamos, también te saque una sonrisa. ¿Quizás tenemos un sentido del humor extraño al reírnos del malware?
Pero espera, ¡hay más!
No sería una publicación del blog de Huntress si no hiciéramos al menos algo de análisis de este malware, ¿verdad? Tras más investigación, parece que esta muestra es conocida en la comunidad como "Valak".
Así que profundicemos en el resto de este código JavaScript. Debajo de la definición de client_config que viste arriba, el código continúa con esto:
Aquí se está definiendo un objeto Client, y se incorpora una propiedad CoMainObject para que pueda acceder a la funcionalidad de WScript.Shell.
Dijimos que esto era código JavaScript, pero debido a que carga un ActiveXObject podemos afirmar con seguridad que es JScript (el dialecto específico de Microsoft de JavaScript, que puede acceder a más funciones internas de Windows a través de Internet Explorer).
Usa este WScript.Shell en una función en línea LoadLibraryReg, que podemos ver que lee el contenido de un valor del Registro de Windows. Este dato del Registro debe ser algo plantado previamente junto con el malware.
HKEY_CURRENT_USER\Software\ApplicationContainer\Appsw64\WebLib32
Podemos ver justo después que la función LibraryLoadContext parece ejecutar con eval el contenido de ese valor del Registro. La instrucción eval ejecuta un valor de cadena como si fuera código. Justo después, se establecen más propiedades para el objeto Client, como .Windows y .GlobalStrings, todas tomadas de una variable con un nombre correspondiente. Entonces, podemos deducir que ese valor del Registro contenía más código JavaScript que ahora se ha traído a este contexto.
Una propiedad interesante que se ha establecido es la variable .DataTools. La veremos usada en el resto del código.
Creando un endpoint de C2
Esta siguiente función definida en el código JScript parece construir un endpoint que se puede usar para C2. Curiosamente, ahora comenzamos a ver algo de ofuscación, obteniendo un .Random.String con una longitud de 12 para un valor nonce (creado dentro de esa propiedad .DataTools), y un RotString que podemos suponer es un cifrado de rotación.
Además, vemos una llamada a Base64Encode, que es una función realmente incluida en la muestra de malware. Simplemente realiza una codificación Base64 sobre el argumento pasado. Con eso, la función devuelve un posible endpoint que se puede usar para el trabajo sucio de C2.
¡Listos, preparados, ejecutar!
En el siguiente segmento de código vemos dos funciones nuevas, PrepareExectionTask y ExecutePlugin. Sí, ese error tipográfico realmente está en el código fuente — en efecto, es Exection.
La función PrepareExectionTask es interesante, porque vemos que calcula la hora actual y luego la maneja correctamente como una cadena, e incluso agrega un minuto de margen. Luego vemos que el código prepara tanto un execCommand como un taskCommand por separado, usando Windows Management Instrumentation (WMI) y una “tarea” para ejecutar el código.
Esta preparación de una variable time, agregando un minuto adicional a la hora actual, junto con la creación de una variable “task”, nos lleva a creer que el malware de hecho está creando una tarea programada para ejecutar lo que necesita. Las propiedades .GlobalStrings WMIC_EXEC y TASK_CREATE se usan para crear un comando personalizado que se completa con los argumentos pasados.
La función ExecutePlugin parece preparar un comando, utilizando un archivo presente en el directorio TEMP basado en el número de identificación único de este objetivo específico. De nuevo, prepara un comando WMIC y lo ejecuta — esta vez sin usar una tarea programada.
Considerando que este pluginID se pasa como argumento al archivo único .bin mencionado en el código, es probable que ese archivo .bin ya esté presente en la víctima, plantado previamente igual que el valor del Registro. Estos actúan como balizas y este código C2 controla los implantes para ejecutar comandos y continuar las operaciones posteriores a la explotación.
¿Cuáles son mis órdenes de marcha?
Personalmente, creo que esta es la función más interesante de revisar.
Esta es la función .GetTask que nuestro objeto Client puede ejecutar — y comienza con un bucle for, que recorre todos los servidores C2 que vimos anteriormente, para verificar si hay una nueva tarea que ejecutar.
Usar este bucle en cada uno de los dominios que descubrimos al comienzo de esta publicación le da a los atacantes mucho control, porque hay varios. Si un dominio fuera "quemado" (es decir, descubierto por los analistas), todavía quedan más en el bolsillo trasero del hacker. Además, tener un dominio quemado es mucho mejor que tener una dirección IP quemada. Los dominios son prescindibles para los hackers. Se pueden reemplazar fácilmente. ¿Direcciones IP? No tanto: eso requiere más infraestructura para redirectores, proxies y más esfuerzo que simplemente cambiar un nombre de dominio.
Podemos ver en el código que hace una solicitud HTTP a cada servidor C2 con la URL del endpoint que generó el cliente anteriormente. Recopila esta respuesta, la decodifica con su magia de DataTools y luego examina el contenido.
if(response.indexOf("--TASK") !== -1){
Esta condición verifica si el marcador --TASK está presente en la respuesta. Si lo está, comienza a extraer los detalles. Vemos esto con las llamadas .replace() y .split() usando -- como delimitador.
Parece que la respuesta decodificada puede tener un formato como este:
--TASK----JXd0dGFoeCUlam5nb3ElJXBhcGJldCUlZ3dkb3klJWxram1qJSVudHFpJSVza214YiUleXhicXhmJSVudHFpJSVkcHBtdG8lJWRibGNqeSUleGpiZ2IlJWZiYWt4byUldHF3bnVxJSV4aW1nbnklJXFxb3UlJXBhcGJldCUld2J5dCUlbnRxaSUleGhwbm5kJSVvcGZsciUlZG1obGp2JSVtdGJyb2IlJW50cWklJWh3YWd0diUlaGJqZXdqJSVqd2R1YiUlanBzZmhnJSVtcWhvZmUlJWVsbHBqJSVvbnFkd3IlJXRycGpxJSVkcndjJSVubWRsJSVudHFpJSVodGJxY2klJXlhdHR5JSVsZ3F3b24lJXJ1bHIlJW93bWRuJQo=--taskname
El código indica que el executionTask se recibe como datos Base64, y luego sigue el nombre de la tarea, separado por esos -- delimitadores. Prepara la tarea con las funciones que vimos antes y, como sabemos por ese análisis, la ejecuta.
Con esa funcionalidad en su lugar, los hackers tienen una solución casera para manejar las comunicaciones de comando y control en la víctima. Han preparado suficientes primitivas y bloques de construcción para al menos lograr ejecución de código y operar en el objetivo, todo dentro de JScript.
Hay muchas otras funciones peculiares e interesantes, especialmente dentro del código de registro cargado. Algunas que vale la pena revisar:
- Loader.DeployClient, estableciendo el objetivo
- Loader.Persist, colocando este explorer.js stub y datos de registro
- Execute, GetEnv, CreateFile, GetArch y otras funciones de enumeración útiles
Para los curiosos ninjas cibernéticos l33t, pueden encontrar el código fuente del stub C2 original que descubrimos aquí, y el arsenal extra cargado desde el registro aquí.
Mencionamos brevemente que esta era una variación del conocido malware "Valak". En ese objeto original client_config dentro del código fuente, se pueden ver números definidos para SOFT_VERSION y SOFT_SIG, que parecen referirse a la cepa específica del malware usada en el objetivo. Si te interesan otras buenas investigaciones o artículos sobre Valak, puedes buscar en Google o revisar artículos como estos.
¿Y entonces?
Ahora que terminamos con toda la jerga técnica, podemos entender por qué esto resulta tan relevante.
Decimos todo el tiempo: "los hackers se están volviendo más inteligentes", "los hackers son cada vez más sofisticados", "los hackers usan nuevos trucos", etcétera. Aunque esto comenzó siendo motivo de risa, con el implante que ni siquiera ofuscaba los servidores C2, demuestra que a veces hasta eso puede pasar desapercibido.
Si miramos hacia atrás lo que podríamos atrevernos a llamar "seguridad tradicional", nos vemos con un firewall y un antivirus genéricos. Accionamos el interruptor, los encendemos y dejamos que hagan su magia con una mentalidad de configúralo y olvídalo. Con suerte, la herramienta de seguridad automatizada encuentra lo malicioso, te notifica y procede a solucionarlo… pero ¿qué pasa si no lo hace?
¿Qué pasa si la solución automatizada falla?
Buscar activamente evidencia de compromiso es lo que nos lleva a una mejor defensa. Con el análisis manual complementando el análisis automatizado, tu stack de seguridad tiene menos falsos positivos, menos falsos negativos y el problema se puede detener en la fuente.
¿Revisar el código a fondo y mirar bajo el capó para ver cómo funciona cierto malware? Eso nos ayuda a encontrar esos indicadores de compromiso, las tácticas y técnicas que usan los actores maliciosos, y qué medidas defensivas podemos implementar para mitigar ataques como este.
Así como los hackers están elevando su juego, nosotros, como investigadores de seguridad, debemos hacer lo mismo.
Si te interesa profundizar en este tema, mira un webinar donde hablo sobre cómo los hackers pueden exfiltrar datos o ejecutar post-explotación con su propio C2.