Daniel StepanicJia Yu Chan

Perdidos en la reubicación: análisis de un nuevo cargador que distribuye CASTLESTEALER

Descubre cómo un cargador nuevo ofuscado evade la detección estática usando .reloc abuso de sección, cinco comprobaciones anti-VM/lenguaje y ofuscación de MBA para entregar malware infostealer a través de Google Ads.

8 min de lecturaAnálisis de malware

Un cargador de Windows previamente no documentado, rastreado como OXLOADER, está entregando el infostealer de CASTLESTEALER mediante anuncios maliciosos de Google, con bajas tasas de detección en motores estáticos y detonaciones sandbox. El cargador emplea varias capas de ofuscación (aplanamiento de flujo de control, predicados opacos, aritmética booleana mixta), stubs de descifrado automodificables y abusa de la sección de .reloc de Windows para estacionar shellcode.

Elastic Security Labs identificó a OXLOADER en una campaña activa dirigida a uno de nuestros clientes; Las exclusiones en la región de la CEI y en el idioma ruso apuntan a un actor de amenaza de habla rusa motivado financieramente. No encontramos ningún reporte público previo sobre esta familia.

Conclusiones clave

  • Elastic Security Labs descubre un nuevo cargador (OXLOADER)
  • OXLOADER observado en campañas que distribuyen CASTLESTEALER mediante anuncios maliciosos de Google
  • La exclusión de la región de la CEI y las comprobaciones de idioma ruso sugieren un actor amenazante de habla rusa y motivado económicamente
  • Bajas tasas de detección en motores estáticos y detonaciones en caja de arena
  • Elastic Defend detiene toda la cadena de ataque empleando capacidades avanzadas de prevención

Cómo el malaut de publicidad entregó OXLOADER a las víctimas

OXLOADER se distribuye mediante anuncios maliciosos de Google que se hacen pasar por Node.js. Las víctimas son redirigidas a través de un dominio intermedio a un script batch alojado en Storj, que descarga y ejecuta OXLOADER.

La infección comenzó cuando el usuario buscó un lts version of node.js e hizo clic en un resultado patrocinado que llevó a node-js[.]prentiva99[.]info, una página de aterrizaje maliciosa diseñada para suplantar a una plataforma legítima de despliegue de Node.js. El actor malicioso operaba una campaña de Google Ads dirigida a víctimas con base en Estados Unidos; el anuncio se mostró por última vez el 23de abril de 2026, y el sitio ya está fuera de línea. El anunciante se registró bajo el nombre verificado ВОЛОДИМИР ТЕРЕЩЕНКО, con sede en Ucrania. No está claro si esto refleja al operador real, una cuenta fachada o una identidad comprada. El 14de mayo de 2026, el anunciante junto con sus campañas publicitarias asociadas fueron eliminados por completo de Google.

Al interactuar, el usuario era redirigido a través de app[.]miloyannopoulos[.]com/download?subid1=download, que respondía con un 302 Found a la URL de la carga útil link[.]storjshare[.]io/raw/jux4e4ky5mruo4jkxsssp42sau4q/ruslan/BATPackageBuilderSetup.bat. Esto entregaba un script batch para Windows, alojado en el legítimo servicio de intercambio de enlaces de Storj , que el actor de la amenaza abusaba para evadir el filtrado de reputación basado en dominios.

El script por lotes muestra una interfaz de asistente de instalación de software falsa, descarga inmediatamente el ejecutable de siguiente etapa desde la URL link.storjshare[.]io/raw/jwwvr4oskkkjsgevt774ta62ehya/ruslan/aBsvwbdas.exe de Storj vía PowerShell y lo lanza con -Verb RunAs para activar un aviso de elevación UAC.

Tras la ejecución del script Batch, Elastic Defend detectó comportamientos maliciosos (la política se configuró solo para detectar), activando múltiples reglas de comportamiento, incluyendo Microsoft Common Language Runtime Loaded from Suspicious Memory, insinuando un . Carga útil basada en NET compatible con CASTLESTEALER.

A continuación se muestra el gráfico de ejecución de la cadena de ataque desde la descarga de la carga útil hasta el despliegue de CASTLESTEALER .

Cargador de malware OXLOADER: análisis técnico

La primera muestra de OXLOADER que analizamos por nuestro equipo se hace pasar por la popular herramienta API Monitor de rohitab.com. Debido a la fuerte presencia de código legítimo y a técnicas de ocultación de código, este cargador puede pasar desapercibido frente a analizadores de archivos estáticos.

Cómo se desempaqueta OXLOADER en tiempo de ejecución

El malware comienza a ejecutar durante la fase de inicialización del CRT, antes de que se ejecute cualquier código de usuario. La función CRT cinit() invoca initterm(), que recorre la tabla inicializadora de C++ (__xc_a__xc_z) llamando a cada entrada. El desarrollador del malware secuestró una de estas entradas, señalando una función que realiza una llamada RegisterClipboardFormatW() antes de saltar directamente al primer stub de descifrado.

El cargador emplea técnicas automodificables con varios stubs de descifrado para desenrollar a sí mismo. A continuación hay un ejemplo de un stub de descifrado que se parchea durante la ejecución, antes de saltar a él.

Una vez que se realizó el parcheo, el cargador descifra una región de 28.233 bytes. Cada byte se descifra con una clave XOR de un solo byte que se actualiza tras cada iteración: el byte de texto plano recién descifrado se agrega a la clave, que luego se emplea para descifrar el siguiente byte. Esta rutina de descifrado similar se ejecuta tres veces en total, cada una en una región diferente.

Técnicas de ofuscación empleadas para evadir la detección estática

OXLOADER rompe la detección automatizada de límites de función en herramientas de análisis binario como IDA Pro empleando técnicas de ofuscación en cuatro capas: aplanamiento de flujo de control (CFF), aritmética mixta de Boolean (MBA), predicados opacos y fragmentación de funciones en regiones de código no contiguas. Las funciones se unen con saltos incondicionales, y algunas regiones se alcanzan mediante saltos indirectos cuyas direcciones objetivo se calculan en tiempo de ejecución mediante aritmética MBA. El resultado es que IDA Pro no puede reconstruir de forma fiable los límites de funciones, lo que requiere correcciones manuales.

El cargador descifra varias cadenas en tiempo de ejecución usando el siguiente algoritmo de descifrado de cadenas:

uint32_t obf_xor_a1_with_a2_plus_33FDA(uint32_t a1, uint32_t a2) { 
return a1 ^ (a2 + 0x33FDA); 
}

Una vez que el código está completamente descomprimido/descifrado, el malware combina esta función de descifrado de cadenas con un algoritmo de hashing de API Adler-32 para resolver dinámicamente sus importaciones.

¿Cómo evade OXLOADER la detección sandbox y VM?

Tras resolver sus APIs, OXLOADER realiza diversas comprobaciones para cerciorar que la máquina se ejecuta en un entorno limpio, evitando la ejecución en entornos sandbox.

CompruébaloMétodoUmbral
EmulaciónWNetAddConnection2W con recurso malformadoEspera ERROR_BAD_NAME (0x43)
Recuento de CPUComprobación del entorno de proceso≥ 3 CPUs
RAMGlobalMemoryStatusEx≥ 3 GB de memoria física
Tasa de refresco de la pantallaConsulta Win32_VideoController WMI≥ 20 Hz
Región geográficaGetUserGeoIDExcluye los GEOIDES CIS

La primera comprobación intenta conectarse a un recurso de red deliberadamente malformado (*72s@1s) usando mpr!WNetAddConnection2W. Esta técnica parece derrotar la emulación/sandboxes que pueden enganchar o devolver una conexión exitosa incondicionalmente. El desarrollador del malware verifica esta llamada accediendo directamente al TEB para recuperar el LastErrorValue. El cargador espera que este código de error sea ERROR_BAD_NAME (0x43), si el código de error es distinto a este valor, el malware toma la rama de fallo y detiene la ejecución.

La segunda comprobación es una prueba anti-sandbox basada en el conteo de procesadores: el cargador requiere que el host tenga al menos 3 CPUs para continuar. Muchos sandboxes y máquinas virtuales de análisis están provisionados con una o dos CPUs para conservar recursos, por lo que este umbral filtra estos entornos de análisis automatizados.

La siguiente comprobación emplea GlobalMemoryStatusEx() para verificar que el host dispone al menos de 3 GB de memoria física disponible.

Una comprobación adicional emplea WMI para consultar la tasa de refresco de la pantalla del sistema, ejecutando la SELECT CurrentRefreshRate FROM Win32_VideoController de la sentencia WQL y comparando el valor devuelto (en Hertz) con un umbral de 20. Los monitores físicos suelen informar alrededor de 60 Hz o más, mientras que las configuraciones sin interfaz y virtualizadas por defecto suelen informar 0 o 1, y valores inferiores a 20 provocan que el cargador aborte.

Exclusiones geográficas y lingüísticas

Las dos últimas comprobaciones detienen la ejecución si el host está ubicado en un país de la CEI o configurado para el idioma ruso. La primera comprobación en esta categoría emplea GetUserGeoID para recuperar la región geográfica del sistema y compararla con una lista codificada de GEOIDES de países de la CEI.

La segunda comprobación emplea GetUserDefaultUILanguage y coincide con LANGID (0x419 - Russian, Russia), la configuración estándar para una instalación de Windows en ruso.

Etapa de shellcode mediante .reloc sección y archivo OCX

Tras todas las comprobaciones, el malware hace una copia de la DLL del motor DirectUI de Windows (C:\Windows\System32\dui70.dll), almacenándola en una ubicación temporal usando un nombre generado aleatoriamente con la extensión .ocx (PFHemkxVk.ocx). Esta elección de extensión inspiró el apellido OXLOADER.

OXLOADER crea entonces una nueva sección llamada (.xtext) en esta DLL objetivo (PFHemkxVk.ocx).

Esta nueva sección (.xtext) está configurada con protecciones RWX (lectura/escritura/ejecución) en preparación para almacenar y ejecutar la siguiente etapa del código malicioso.

Esta DLL actualizada (PFHemkxVk.ocx) se carga entonces en el proceso de cargador existente mediante LoadLibraryA.

En un ejecutable normal de Windows, la sección .reloc contiene una tabla de bloques de IMAGE_BASE_RELOCATION que el cargador de Windows aplica para parchear direcciones absolutas cuando la imagen se carga en una dirección distinta a su base preferida. En este ejemplo, el desarrollador de malware está usando
la sección .reloc para albergar código malicioso en lugar de las entradas de reubicación base. Esto es una señal de alerta fuerte en el análisis estático: las cadenas de herramientas legítimas no emiten código en la sección .reloc .

Este shellcode de la sección .reloc se copia entonces a la sección recién creada (.xtext) en el archivo OCX, y el cargador llama a este código.

Como se observó anteriormente, hay otro stub de descifrado empleado para desentrañar esta siguiente etapa.

Entrega de infostealer en memoria mediante DonutLoader y ensamblador .NET

Este shellcode de siguiente etapa es una carga útil configurada desde DonutLoader, un generador de shellcode de código abierto empleado para envolver ensamblajes, DLLs y EXE .NET en shellcode independiente de la posición (PIC) para su ejecución en memoria. Durante el desempaquetado, el shellcode descifra la configuración y contexto de ejecución embebido del cargador usando el cifrado de bloques Chaskey-LTS en modo CTR con la clave (6E0A1F8F77F7011561F6F9CA96B71B8F) y IV (956C6128E9362E075F8D006C93616A66).

Tras el descifrado, la carga útil se descomprime mediante aPLib y luego se arranca mediante la función RunPE() de DonutLoader. La carga útil final es un robador de información recién descubierto por Huntress llamado CASTLESTEALER. Esta atribución se basa en la misma clave AES empleada para las comunicaciones C2 encontrada entre marcadores de 0xDEADBEEF en una muestra anterior.

Segunda variante de OXLOADER: mismo cargador, programa disfrazado diferente

Una segunda variante de OXLOADER se hace pasar por un instalador de Node.js en lugar de un API Monitor, pero emplea el mismo mecanismo de cargador.

El 13de mayo de 2026, descubrimos que el extremo del redirector app.miloyannopoulos[.]com/download respondía con uno de dos campos de cabecera de Location , elegidos al azar:

  • https://link.storjshare[.]io/raw/jv5uebuqwzfpmtahj34q753ptykq/node/BATPackageBulderSetup.bat
  • https://link.storjshare[.]io/raw/jvsmdybqmvwep2oawbobp6ub7aza/node/node-v24.15.0-x64-86.exe

El script de instalación por lotes (BATPackageBulderSetup.bat, con un error tipográfico para "Builder") se mantuvo mayormente idéntico. La única diferencia era que el enlace de carga útil Storj ahora apuntaba a un binario diferente llamado node-v24.15.0-x64-86.exe.

La carga útil intenta hacer pasar por código CMake benigno manteniendo "nodo" en el nombre del archivo, probablemente para mantener intacto el tema señuelo. Creemos que la muestra anterior de "API Monitor" probablemente fue un error de distribución del operador.

Al ejecutarlo, observamos el mismo patrón: saltos indirectos usados para la autodescifración en memoria, seguidos de la carga de mpr.dll y una llamada a WNetAddConnection2W. Confirmamos que es el mismo mecanismo de cargador mencionado anteriormente, y esta muestra también carga CASTLESTEALER.

A continuación se muestra un fragmento donde ocurre la autodescifración. Las cadenas ficticias relacionadas con CMake parecen pasar como argumentos a una llamada a una función, que parchea un pequeño stub de descifrado en la memoria inmediatamente luego del sitio de llamada. La ejecución salta entonces al stub para descifrar las instrucciones siguientes, y este proceso se repite 2 veces más hasta que el cuerpo principal del malware es descifrado.

Conclusión: por qué los defensores deberían seguir OXLOADER

OXLOADER está en una fase operativa temprana, pero la ingeniería detrás sugiere que esta familia merece la pena seguir. La ofuscación de código, las medidas anti-VM, el código de aspecto benigno empleado para disimular sus binarios y las técnicas únicas de staging reflejan decisiones de ingeniería deliberadas para evadir el análisis. Esa inversión está dando frutos, resultando en bajas tasas de detección en motores estáticos y detonaciones, dando a OXLOADER una ventana para operar antes de que sea perseguido.

REF8372 a través de MITRE ATT&CK

Elastic usa el marco MITRE ATT&CK para documentar tácticas, técnicas y procedimientos comunes que las amenazas emplean contra las redes empresariales.

Táctica

La táctica representa el porqué de una técnica o subtécnica. Es el objetivo táctico del adversario: la razón para realizar una acción.

Técnicas

Las técnicas representan cómo un adversario logra un objetivo táctico mediante la realización de una acción.

Remediación REF8372

Prevención

YARA

Elastic Security creó reglas YARA para identificar esta actividad.

Observaciones

En esta investigación se discutieron los siguientes observables.

ObservableTipoNombreReferencia
node-js\[.\]prentiva99\[.\]infonombre-de-dominioPágina de inicio de malvertido
app\[.\]miloyannopoulos\[.\]comnombre-de-dominioMalvertising Redirector
fdfc7831e5c24cfa80152860dfe8c056ba079f7df1393bf6bb7b18ed974eda37SHA-256BATPackageBuilderSetup.batDescargador y pícher de OXLOADER
de4f51649ec1a33071854aefe93ffb3fc225e19f802d8dd914676dd5dfef2615SHA-256BATPackageBulderSetup.batDescargador y pícher de OXLOADER
9a9939dff297997732aaade9b243d695632cbd64033c5fbcb9de3d09b7e6c28dSHA-256apimonitor-x64.exeOXLOADER
c85f2765a6c3c3f3907c17e57df12f8f68826f74bff3bbfd272af50666d065feSHA-256node-v24.15.0-x64-86.exeOXLOADER
4ec9d9d4d10ad78fc6d7bda7cb17d52984878ccd2dd4302fd1cef152313b9741SHA-256LADRÓN DE CASTILLOS
39019279686c820c3af5684012a0085a7e2109f612c9fab886dd0577ace5b5c6SHA-256LADRÓN DE CASTILLOS
89.124.95\[.\]161ipv4CASTLESTEALER C2
89.124.115\[.\]82ipv4CASTLESTEALER C2