Resumen
- SharpRhino se basa en el proyecto de código abierto ThunderShell.
- Se distribuye a las víctimas como un programa de instalación NSIS que ejecuta automáticamente scripts de PowerShell.
- Los scripts de PowerShell contienen ensamblados de .NET codificados.
- La carga útil .NET se utiliza para comunicarse con el servidor C2.
- Puede ejecutar comandos de forma remota.
- El tráfico de red se cifra con RC4 y se codifica en formato Base64.
Introducción
Hunters International, un grupo de ciberdelincuentes conocido por sus operaciones de ransomware como servicio, ha empezado a utilizar un nuevo malware RAT. El primer incidente en el que aparecía este software se detectó a principios de agosto de 2024 y se denominó SharpRhino por su lenguaje C#. El troyano se introduce en los equipos y dispositivos de las víctimas como un software legítimo y concede acceso remoto a ellos. Con este software, los atacantes pueden ejecutar distintos comandos y propagar otros malware.
Detalles técnicos
Descripción general
La muestra analizada se entrega a las víctimas como un programa de instalación que se ha creado con Nullsoft Scriptable Install System (NSIS). Este archivo tiene "Angryip.org" en la descripción y un certificado digital válido, pero el nombre de la empresa es falso y no existe.

Por otro lado, este programa de instalación contiene un programa de instalación adicional, un archivo comprimido protegido con contraseña y archivos adicionales que se utilizarán durante la ejecución del malware.

Instalación
Al ejecutarse, la muestra descarga todos los archivos incrustados en la carpeta "C:\ProgramData\Microsoft\WindowsUpdate24" y ejecuta un archivo "ipscan-3.9.1-setup.exe", que es un programa de instalación del software legítimo Angry IP Scanner.

Mientras el usuario se distrae con este programa de instalación, el malware extrae archivos del archivo comprimido protegido con contraseña UpdateFull.zip. Para descomprimir el archivo comprimido, utiliza el programa 7za.exe, que está incrustado. En la línea de comandos podemos ver la contraseña del archivo comprimido:
C:\ProgramData\Microsoft\WindowsUpdate24\7za.exe x C:\ProgramData\Microsoft\WindowsUpdate24\UpdateFull.7z -pTG98HJerxsdqWE45 -oC:\ProgramData\Microsoft\WindowsUpdate24
El contenido del archivo comprimido es el siguiente:

La muestra crea una nueva carpeta —"C:\ProgramData\Microsoft\LogUpdateWindows"— después de la extracción, y copia los archivos extraídos del archivo comprimido a la nueva carpeta. El uso de dos carpetas de instalación diferentes puede ayudar a los atacantes a conseguir persistencia y permanecer en el sistema en caso de que se elimine una de las carpetas, ya que los archivos de esas carpetas son similares en el proceso de ejecución. A continuación, agrega una nueva clave de registro en la ruta "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" que apunta al archivo "Microsoft.AnyKey.lnk". Este archivo es un acceso directo y contiene el siguiente destino:
C:\ProgramData\Microsoft\LogUpdateWindows\Microsoft.AnyKey.exe abnormal c:\programdata\%username%0 cmd /c C:\ProgramData\Microsoft\LogUpdateWindows\LogUpdate.bat
El ejecutable "Microsoft.AnyKey.exe", que también se descargó del archivo comprimido, es un programa legítimo que forma parte de las herramientas de Node.js para Visual Studio y se denomina "Microsoft.NodejsTools.PressAnyKey.exe".
Ejecución
Los archivos "LogUpdate.bat" y "WindowsUpdate.bat" tienen la misma funcionalidad, pero cargan archivos diferentes.

Los archivos "Wiaphoh7um.t" y "kautix2aeX.t" contienen datos ofuscados. Los datos sin procesar y la clave son diferentes para esos archivos, pero los datos resultantes serán los mismos. Tras el proceso de decodificación, la muestra define estos datos como ensamblado de .NET y llama a un método con algunos parámetros.

Después de realizar el volcado de todos los datos del script, podemos observar las siguientes variables:
Las variables $var1, $var2 y $var3 determinan los ensamblados a los que se hace referencia, y cuando se concatenan forman la siguiente cadena:
System.Drawing.dllSystem.Web.Extensions.dllSystem.Windows.Forms.dll
$var4 es diferente para cada archivo y contiene una dirección de servidor C2. A continuación, se muestra una tabla con los argumentos que se utilizan en la llamada a un ensamblado de .NET para cada archivo:

"$fjwZrHB1k2RF" representa un ensamblado de .NET que se carga en la memoria. Después del volcado de los datos, podemos observar el código C#. El guion para llamadas de PowerShell llama a una función del espacio de nombres "Bzxmlpi" y la clase "OyrWkb". Al principio de esta clase, podemos observar algunas cargas adicionales y nombres de variables ilegibles.

De hecho, este archivo es una versión modificada del proyecto de código abierto "ThunderShell". Se realizaron varios cambios en el proyecto original:
- Se han eliminado las funciones de registro de teclas, captura de pantalla y carga de ensamblados de .NET, así como los comandos del servidor que representaban dichas funciones.
- Se han cambiado los nombres de todas las clases, funciones y variables.
- Se han añadido valores predeterminados que se utilizarán si se ejecuta la carga útil sin argumentos

Esta función genera en primer lugar una cadena aleatoria de 16 bytes. Al inicializar la clase Random, la muestra utiliza la fecha, la hora y el ID de proceso actuales como valor de inicialización (o "semilla"). A continuación, obtiene algunas variables de entorno, como COMPUTERNAME, USERDOMAIN y USERNAME. Se dará formato a todos esos datos:

Como resultado, se genera la cadena siguiente:

A continuación, la muestra pasa esta cadena a una función que la enviará al servidor. Una vez en el servidor, la muestra cifrará los datos con un cifrado RC4 y una clave que se pasó como segundo argumento.

Después del proceso de cifrado, añade algunos datos a la solicitud y codifica la cadena cifrada en formato Base64. Todos estos datos se envían posteriormente al servidor.

En esta primera conexión, se ignora la respuesta del servidor. Cuando la muestra entra en un bucle, se conecta de nuevo al servidor, pero ambos argumentos son "null". A continuación, se guarda la respuesta y se compara con los valores guardados. Si se recibe el comando "delay", la muestra tomará un argumento adicional y cambiará el valor, que pasará a la función "sleep". Si se obtiene el comando "exit", se romperá el bucle y se terminará la ejecución. Si obtiene algún dato distinto de "delay" o "exit", se creará un nuevo hilo con una función que tomará los datos obtenidos como argumento. Todas esas acciones se repetirán con un intervalo de 95 segundos entre cada iteración del bucle.

La respuesta que llega del servidor pasa a la función de deserialización de la clase ‘zWxFlnVASjHYb’, que recopila y almacena los siguientes datos: "UUID", "ID" y "Data".

Servidor C2
Aunque el enlace que se presentó en la muestra ya está offline, podemos utilizar el servidor del proyecto original para ver cómo funciona la comunicación. En primer lugar, tenemos que cambiar la configuración del servidor. Dicha configuración contiene varios campos, incluida la dirección IP del servidor, la clave de cifrado, la configuración de la interfaz gráfica de usuario (GUI) y la configuración de HTTP y HTTPS. En segundo lugar, tenemos que cambiar los parámetros "callback-url", "gui-host" y "encryption-key". Tomaremos los parámetros de la clave de cifrado de una muestra de SharpRhino.

El servidor es una aplicación Python y requiere un servidor Redis en ejecución. Tras iniciarse, da como resultado información sobre el servidor.

Esto incluye una dirección de la GUI web. Cuando se abre, el usuario debe iniciar sesión en primer lugar. Aunque no importa qué nombre de usuario introduzcan, la contraseña debe utilizarse a partir del archivo de configuración. Cuando se inicie sesión, se mostrará la sección del panel de control. Contiene información sobre sesiones y registros.

La carga útil se puede incorporar en la GUI web. Debe proporcionarse la dirección IP del servidor, así como el tipo de carga útil.

Tras elegir una sesión, el atacante puede interactuar con ella. Si escribe "help", se mostrarán todos los comandos compatibles que se pueden utilizar en la sesión.

Comunicaciones C2
Estos comandos tienen cadenas predefinidas que se añadirán a los datos que el atacante introduzca como argumentos. Por ejemplo, si utiliza "shell [command]", se añadirá "cmd.exe /c" al principio de la cadena que se envíe. Otro ejemplo es el comando "ps", que enviará el script de PowerShell al cliente:

El comando llega al cliente cifrado con RC4 y codificado en formato Base64. Contiene los parámetros ID y UUID, donde ID es el ID del cliente y UUID es el ID del comando.

Todos estos datos se pasan al nuevo subproceso. La función de este subproceso utiliza módulos de PowerShell para ejecutar los comandos proporcionados.

La muestra obtiene el resultado del comando ejecutado mediante la canalización. A continuación, estos datos se cifrarán y se enviarán de vuelta al servidor.

Conclusión
ThunderShell, un antiguo proyecto de código abierto que se actualizó por última vez hace casi cuatro años, fue utilizado por parte del grupo Hunters International para distribuir malware a las víctimas. Llega como un programa de instalación del software Angry IP Scanner, que descarga y ejecuta scripts de PowerShell maliciosos. A través de las funciones de PowerShell, esos scripts ejecutan ensamblados de .NET codificados, por lo que no es necesario llevar ningún ejecutable compilado adicional: el código malicioso se invoca y se ejecuta en la memoria.
Aunque el código original se modificara, conservó su funcionalidad principal: ejecutar comandos de forma remota en los sistemas objetivo. Este es el peligro de los proyectos de código abierto. Normalmente se desarrollan con fines educativos o para llevar a cabo pruebas de penetración, pero también se utilizan para perpetrar ataques reales.
Detectado por Acronis

