Daniel StepanicJia Yu Chan

Perdu dans le déplacement : analyse d’un nouveau chargeur distribuant CASTLESTEALER

Découvrez comment un nouveau chargeur obfusqué échappe à la détection statique grâce à .reloc abus de section, cinq vérifications anti-VM/langage et obscurcissement MBA pour diffuser des logiciels malveillants infostealer via Google Ads.

8 minutes de lectureAnalyse des malwares

Un chargeur Windows auparavant non documenté, suivi sous le nom d’OXLOADER, diffuse l’infostealer CASTLESTEALER via des annonces Google malveillantes, avec de faibles taux de détection via des moteurs statiques et des détonations en bac à sable. Le chargeur utilise plusieurs couches d’obfuscation (aplatissement du flux de contrôle, prédicats opaques, arithmétique booléenne mixte), des stubs de déchiffrement auto-modificateurs, et abuse de la section .reloc Windows pour établir le shellcode.

Elastic Security Labs a identifié OXLOADER dans une campagne active ciblant l’un de nos clients ; Les exclusions de la région CEI et des langues russes indiquent un acteur de menace russe motivé financièrement. Nous n’avons trouvé aucun rapport public antérieur sur cette famille.

Principaux points abordés dans cet article

  • Elastic Security Labs découvre un nouveau chargeur (OXLOADER)
  • OXLOADER observé dans des campagnes distribuant CASTLESTEALER via des Google Ads malveillants
  • L’exclusion de la région de la CEI et les contrôles de langue russe suggèrent un acteur de menace russophone et motivé financièrement
  • Faibles taux de détection sur les moteurs statiques et les détonations en bac à sable
  • Elastic Defend arrête toute la chaîne d’attaque grâce à des capacités avancées de prévention

Comment le malvertising a livré OXLOADER aux victimes

OXLOADER est distribué via des Google Ads malveillants se faisant passer pour Node.js. Les victimes sont redirigées via un domaine intermédiaire vers un script batch hébergé sur Storj, qui télécharge et exécute OXLOADER.

L’infection a commencé lorsque l’utilisateur a recherché un lts version of node.js et cliqué sur un résultat sponsorisé menant à node-js[.]prentiva99[.]info, une page d’atterrissage malveillante conçue pour se faire passer pour une plateforme de déploiement Node.js légitime. L’acteur menait une campagne Google Ads ciblant des victimes basées aux États-Unis ; la publicité a été diffusée pour la dernière fois le 23avril 2026, et le site est désormais hors ligne. L’annonceur était enregistré sous le nom vérifié ВОЛОДИМИР ТЕРЕЩЕНКО, basé en Ukraine. Reste incertain si cela reflète l’opérateur réel, un compte de façade ou une identité achetée. Le 14mai 2026, l’annonceur ainsi que ses campagnes publicitaires associées ont été totalement retirés de Google.

Lors de l’interaction, l’utilisateur était redirigé via app[.]miloyannopoulos[.]com/download?subid1=download, qui répondait par un 302 Found à l’URL de la charge utile link[.]storjshare[.]io/raw/jux4e4ky5mruo4jkxsssp42sau4q/ruslan/BATPackageBuilderSetup.bat. Cela a livré un script batch Windows, hébergé sur le service légitime de partage de liens de Storj , que l’acteur malveillant a exploité pour échapper au filtrage de réputation basé sur le domaine.

Le script batch affiche une fausse interface d’assistant d’installation logicielle, télécharge immédiatement l’exécutable de l’étape suivante depuis le link.storjshare[.]io/raw/jwwvr4oskkkjsgevt774ta62ehya/ruslan/aBsvwbdas.exe URL Storj via PowerShell, puis le lance avec -Verb RunAs pour déclencher une invite d’élévation UAC.

Après l’exécution du script Batch, Elastic Defend détecta un comportement malveillant (la politique était réglée sur détection uniquement), déclenchant plusieurs règles comportementales, dont Microsoft Common Language Runtime Loaded from Suspicious Memory, suggérant un . Charge utile basée sur NET compatible avec CASTLESTEALER.

Voici le graphique d’exécution de la chaîne d’attaque, du téléchargement de la charge utile au déploiement CASTLESTEALER .

Chargeur de malwares OXLOADER : analyse technique

Le premier échantillon d’OXLOADER que notre équipe a analysé se fait passer pour l’outil populaire, API Monitor de rohitab.com. Grâce à la forte présence de code légitime et de techniques de dissimulation de code, ce chargeur peut passer inaperçu face aux analyseurs de fichiers statiques.

Comment OXLOADER se décompose à l’exécution

Le malware commence à s’exécuter pendant la phase d’initialisation du CRT, avant que tout code utilisateur ne soit exécuté. La fonction CRT cinit() invoque initterm(), qui parcourt la table d’initialisation C++ (__xc_a__xc_z) appelant chaque entrée. Le développeur du malware a détourné l’une de ces entrées, pointant vers une fonction qui passe un appel RegisterClipboardFormatW() avant de passer directement au premier stub de déchiffrement.

Le chargeur utilise des techniques auto-modifiables avec plusieurs stubs de déchiffrement pour se dérouler lui-même. Voici un exemple d’un stub de déchiffrement patché pendant l’exécution, avant de passer dessus.

Après le patching, le chargeur déchiffre une région de 28 233 octets. Chaque octet est déchiffré avec une clé XOR d’un seul octet qui se met à jour après chaque itération : l’octet de texte clair juste déchiffré est ajouté à la clé, qui sert ensuite à déchiffrer le octet suivant. Cette routine de déchiffrement similaire s’exécute trois fois au total, chacune sur une région différente.

Techniques d’obfuscation utilisées pour éviter la détection statique

OXLOADER casse la détection automatisée des frontières de fonction dans des outils d’analyse binaire tels que IDA Pro en utilisant quatre techniques d’obfuscation en couches : aplatissement en flux de contrôle (CFF), arithmétique booléenne mixte (MBA), prédicats opaques et fragmentation de fonctions à travers des régions de code non contiguës. Les fonctions sont assemblées par des sauts inconditionnels, et certaines régions sont atteintes par des sauts indirects dont les adresses cibles sont calculées à l’exécution via l’arithmétique MBA. Le résultat est qu’IDA Pro ne peut pas reconstruire de manière fiable les limites de fonction, nécessitant des corrections manuelles.

Le chargeur déchiffre diverses chaînes à l’exécution en utilisant l’algorithme de déchiffrement suivant :

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

Une fois le code complètement décompressé/déchiffré, le malware combine cette fonction de déchiffrement de chaînes avec un algorithme de hachage API Adler-32 pour résoudre dynamiquement ses importations.

Comment OXLOADER évite-t-il la détection du bac à sable et des machines virtuelles ?

Après avoir résolu ses API, OXLOADER effectue diverses vérifications pour s’assurer que la machine s’exécute dans un environnement propre, évitant ainsi l’exécution dans des environnements bac à sable.

C'est par iciMéthodeSeuil
ÉmulationWNetAddConnection2W avec ressource malforméeS’attend à ERROR_BAD_NAME (0x43)
Nombre de processeursVérification de l’environnement de procédé≥ 3 CPU
RAMGlobalMemoryStatusEx≥ 3 Go de mémoire physique
Taux de rafraîchissement d’affichageRequête WMI Win32_VideoController≥ 20 Hz
Région géographiqueGetUserGeoIDExclut les GEOÏDES CIS

La première vérification tente de se connecter à une ressource réseau délibérément déformée (*72s@1s) en utilisant mpr!WNetAddConnection2W. Cette technique semble contrer l’émulation/bacs à sable qui peuvent accrocher ou rétablir une connexion réussie sans condition. Le développeur du malware vérifie cet appel en accédant directement au TEB pour récupérer le LastErrorValue. Le chargeur s’attend à ce que ce code d’erreur soit ERROR_BAD_NAME (0x43); si le code d’erreur est autre que cette valeur, le malware prend la branche de défaillance et arrête l’exécution.

La seconde vérification est un test anti-bac à sable basé sur le nombre de processeurs : le chargeur exige que l’hôte ait au moins 3 processeurs pour continuer. De nombreux bacs à sable et machines virtuelles d’analyse sont équipés d’un ou deux CPU pour économiser des ressources, ce qui filtre donc ces environnements d’analyse automatisés.

La vérification suivante utilise GlobalMemoryStatusEx() pour vérifier que l’hôte dispose d’au moins 3 Go de mémoire physique disponible.

Une vérification supplémentaire utilise WMI pour interroger la fréquence de rafraîchissement de l’affichage système, exécuter la SELECT CurrentRefreshRate FROM Win32_VideoController de l’instruction WQL et comparer la valeur retournée (en Hertz) avec un seuil de 20. Les moniteurs physiques indiquent généralement autour de 60 Hz ou plus, tandis que les configurations headless et virtualisées par défaut indiquent généralement 0 ou 1, et des valeurs inférieures à 20 provoquent l’annulation du chargeur.

Exclusions géographiques et linguistiques

Les deux derniers contrôles arrêtent l’exécution si l’hôte est situé dans un pays de la CEI ou configuré pour la langue russe. La première vérification dans cette catégorie utilise GetUserGeoID pour récupérer la région géographique du système et la comparer à une liste codée en dur des GEOÏDES des pays de la CEI.

La seconde vérification utilise GetUserDefaultUILanguage et correspond à LANGID (0x419 - Russian, Russia), la configuration standard pour une installation Windows en langue russe.

Staging par shellcode via .reloc section et fichier OCX

Après toutes les vérifications, le malware effectue une copie du DLL Windows DirectUI Engine (C:\Windows\System32\dui70.dll), le stockant dans un emplacement temporaire à l’aide d’un nom généré aléatoirement avec l’extension .ocx (PFHemkxVk.ocx). Ce choix d’extension a inspiré le nom de famille OXLOADER.

OXLOADER crée alors une nouvelle section nommée (.xtext) dans cette DLL cible (PFHemkxVk.ocx).

Cette nouvelle section (.xtext) est configurée avec des protections RWX (lecture/écriture/exécution) en préparation du stockage et de l’exécution de l’étape suivante du code malveillant.

Cette DLL mise à jour (PFHemkxVk.ocx) est ensuite chargée dans le processus de chargement existant via LoadLibraryA.

Dans un exécutable Windows classique, la section .reloc contient un tableau de blocs de IMAGE_BASE_RELOCATION que le chargeur Windows applique pour corriger les adresses absolues lorsque l’image est chargée à une adresse autre que sa base préférée. Dans cet exemple, le développeur du malware utilise
la section .reloc pour loger du code malveillant au lieu des entrées de relocalisation de base. C’est un signal d’alarme fort pour l’analyse statique : les chaînes d’outils légitimes n’émettent pas de code dans la section .reloc .

Ce shellcode de la section .reloc est ensuite copié dans la nouvelle section (.xtext) du fichier OCX, et le chargeur appelle alors ce code.

Comme observé précédemment, un autre stub de déchiffrement est utilisé pour décomposer cette étape suivante.

Livraison infostealer en mémoire via DonutLoader et assembleur .NET

Ce shellcode de l’étape suivante est une charge utile configurée à partir de DonutLoader, un générateur de shellcode open source utilisé pour envelopper les assemblies, DLL et EXE .NET dans un shellcode indépendant de la position (PIC) pour une exécution en mémoire. Lors du décompressage, le shellcode déchiffre la configuration intégrée et le contexte d’exécution du chargeur en utilisant le chiffrement de blocs Chaskey-LTS en mode CTR avec la clé (6E0A1F8F77F7011561F6F9CA96B71B8F) et IV (956C6128E9362E075F8D006C93616A66).

Après le déchiffrement, la charge utile est décompressée via aPLib puis démarrée via la fonction RunPE() de DonutLoader. La dernière charge utile est un voleur d’information récemment découvert par Huntress appelé CASTLESTEALER. Cette attribution est basée sur la même clé AES utilisée pour les communications C2 que celle trouvée entre 0xDEADBEEF marqueurs dans un échantillon précédent.

Deuxième variante d’OXLOADER : même chargeur, programme masqué différent

Une seconde variante d’OXLOADER se fait passer pour un installateur Node.js plutôt qu’un moniteur API, mais utilise le même mécanisme de chargeur.

Le 13mai 2026, nous avons découvert que le point de terminaison du redirecteur répondait app.miloyannopoulos[.]com/download par l’un des deux champs d’en-tête de Location , choisis au hasard :

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

Le script d’installation Batch (BATPackageBulderSetup.bat, avec une faute de frappe pour « Builder ») est resté en grande partie identique. La seule différence était que le lien de la charge utile Storj pointait désormais vers un autre binaire nommé node-v24.15.0-x64-86.exe.

La charge utile tente de se faire passer pour un code CMake bénin tout en conservant « nœud » dans le nom du fichier, probablement pour préserver le thème de leurre. Nous pensons que l’échantillon précédent « API Monitor » était probablement une erreur de distribution de l’opérateur.

Lors de l’exécution, nous avons remarqué le même schéma : des sauts indirects utilisés pour l’auto-déchiffrement en mémoire, suivis du chargement de mpr.dll et d’un appel à WNetAddConnection2W. Nous avons confirmé qu’il s’agit du mécanisme de chargement identique évoqué précédemment, et cet échantillon charge également CASTLESTEALER.

Voici un extrait où l’auto-déchiffrement a lieu. Les chaînes de chaînes liées à la CMake factice semblent être transmises comme arguments à un appel de fonction, qui patche un petit stub de déchiffrement en mémoire immédiatement après le site d’appel. L’exécution passe ensuite au stub pour déchiffrer les instructions suivantes, et ce processus se répète 2 fois jusqu’à ce que le corps principal du malware soit déchiffré.

Conclusion : pourquoi les défenseurs devraient suivre OXLOADER

OXLOADER en est à une phase opérationnelle précoce, mais l’ingénierie qui le sous-tend suggère que cette famille mérite d’être surveillée. L’obfuscation du code, les mesures anti-VM, le code à l’apparence bénigne utilisé pour masquer ses binaires, et les techniques de staging uniques reflètent des choix d’ingénierie délibérés pour échapper à l’analyse. Cet investissement porte ses fruits, entraînant de faibles taux de détection sur les moteurs statiques et les détonations, offrant à OXLOADER une fenêtre pour fonctionner avant d’être traqué.

REF8372 à MITRE ATT&CK

Elastic utilise le cadre MITRE ATT& CK pour documenter les tactiques, techniques et procédures communes que les menaces utilisent contre les réseaux d'entreprise.

Tactiques

Les tactiques représentent le pourquoi d'une technique ou d'une sous-technique. Il s'agit de l'objectif tactique de l'adversaire : la raison pour laquelle il effectue une action.

Techniques

Les techniques représentent la manière dont un adversaire atteint un objectif tactique en effectuant une action.

Assainissement REF8372

La prévention

YARA

Elastic Security a créé des règles YARA pour identifier cette activité.

Observations

Les observables suivants ont été examinés dans le cadre de cette recherche.

ObservableTypeNomRéférence
node-js\[.\]prentiva99\[.\]infonom de domainePage d’accueil de malvertisation
app\[.\]miloyannopoulos\[.\]comnom de domaineRedirecteur de malvertisation
fdfc7831e5c24cfa80152860dfe8c056ba079f7df1393bf6bb7b18ed974eda37SHA-256BATPackageBuilderSetup.batTéléchargeur et lanceur OXLOADER
de4f51649ec1a33071854aefe93ffb3fc225e19f802d8dd914676dd5dfef2615SHA-256BATPackageBulderSetup.batTéléchargeur et lanceur OXLOADER
9a9939dff297997732aaade9b243d695632cbd64033c5fbcb9de3d09b7e6c28dSHA-256apimonitor-x64.exeOXLOADER
c85f2765a6c3c3f3907c17e57df12f8f68826f74bff3bbfd272af50666d065feSHA-256node-v24.15.0-x64-86.exeOXLOADER
4ec9d9d4d10ad78fc6d7bda7cb17d52984878ccd2dd4302fd1cef152313b9741SHA-256VOLEUR DE CHÂTEAU
39019279686c820c3af5684012a0085a7e2109f612c9fab886dd0577ace5b5c6SHA-256VOLEUR DE CHÂTEAU
89.124.95\[.\]161ipv4CASTLESTEALER C2
89.124.115\[.\]82ipv4CASTLESTEALER C2

Partager cet article