SOC Prime Bias: Середній

08 May 2026 18:33

NWHStealer Поширюється через середовище виконання Bun JavaScript

Author Photo
SOC Prime Team linkedin icon Стежити
NWHStealer Поширюється через середовище виконання Bun JavaScript
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Резюме

У статті пояснюється, як зловмисники використовують середовище виконання Bun JavaScript для доставки крадія інформації на основі Rust під назвою NWHStealer. Шкідливі ZIP-архіви містять основний інсталяційний файл, який запускає завантажувач JavaScript у пакеті Bun разом із вторинним завантажувачем під назвою dw.exe. Компонент JavaScript виконує перевірки антивіртуальних систем, зв’язується з інфраструктурою командування та управління, розшифровує додаткове навантаження і використовує вбудовані API Windows для впровадження крадіжа в пам’ять. Щоб зменшити підозру, кампанія приховує шкідливі файли за легітимними платформами зберігання, такими як GitHub, MediaFire та SourceForge.

Розслідування

Дослідники виявили, що Bun використовувався для упаковки шкідливого JavaScript всередині .bun секції завантажувача. Два скрипти, sysreq.js and memload.js, обробляли перевірки середовища та зв’язок з інфраструктурою атакуючих. Завантажувач отримував конфігураційні дані та зашифровані навантаження з доменів, таких як silent-harvester.cc, розшифровував їх з допомогою AES-256-CBC та впроваджував через виклики Win32 API. Кінцеве навантаження було NWHStealer, який викрадає облікові дані, дані браузера та інформацію про криптовалютні гаманці, і може також запускати додаткову майнінгову активність.

Запобігання

Користувачам слід уникати завантаження виконуваних файлів з ненадійних сайтів і перевіряти підписи інсталяторів перед виконанням. Команди безпеки повинні моніторити незвичну активність середовища виконання Bun, запити PowerShell CIM, що використовуються для перевірок віртуалізації, та підозрілі виклики API, такі як VirtualAlloc and LoadLibraryA. Організації також повинні блокувати відомі шкідливі домени та запроваджувати політику виконання з мінімальними привілеями, щоб обмежити зловживання.

Реагування

Якщо ця активність виявлена, ізолюйте уражену кінцеву точку, зберіть зображення пам’яті та диска, і шукайте Installer.exe, dw.exe, та підозрілі .bun сегменти. Блокуйте виявлені командно-контрольні домени та URL-адреси на межі мережі. Розгорніть виявлення на кінцевих точках для спостережуваних PowerShell команд і шаблонів Win32 API. Змініть пошкоджені облікові дані та моніторте уражені системи на ознаки несанкціонованого майнінгу криптовалюти.

graph TB %% Визначення класів classDef technique fill:#ffcc99 classDef action fill:#99ccff %% Вузли node_initial_access[“<b>Початковий доступ</b><br/><b>T1036.008 Маскування: тип файлу</b>: шкідливий ZIP, замаскований під безпечний файл.<br/><b>T1204.002 Виконання користувачем: шкідливий файл</b>: користувач запускає завантажений файл.”] class node_initial_access technique node_obfuscated_loader[“<b>Обфускований завантажувач</b><br/><b>T1027.016 Вставка сміттєвого коду</b>: додавання нерелевантного JavaScript для приховування логіки.<br/><b>T1027.008 Видалення частин payload</b>: видалення неважливого коду для ускладнення аналізу.”] class node_obfuscated_loader technique node_discovery[“<b>Розвідка</b><br/><b>T1082 Отримання системної інформації</b>: збір даних про ОС, апаратне та програмне забезпечення.<br/><b>T1016 Розвідка мережевої конфігурації</b>: IP-адреси, мережеві адаптери та маршрутизація.”] class node_discovery technique node_credential_access[“<b>Доступ до облікових даних</b><br/><b>T1555.003 Дані браузерів</b>: викрадення збережених паролів та автозаповнення.<br/><b>T1550.004 Використання альтернативних даних автентифікації</b>: викрадення сесійних cookie.”] class node_credential_access technique node_c2[“<b>C2</b>: отримання AES-ключа розшифрування та зашифрованого payload з віддаленого сервера.”] class node_c2 action node_execution[“<b>Виконання</b><br/><b>T1620 Рефлективне завантаження коду</b>: виконання в пам’яті без запису на диск.<br/><b>T1055.009 Ін’єкція в процес</b>: вставка коду у запущений процес.”] class node_execution technique node_persistence[“<b>Постійність</b><br/><b>T1053 Заплановане завдання</b>: створення задачі для регулярного запуску.”] class node_persistence technique %% Зв’язки node_initial_access –>|призводить до| node_obfuscated_loader node_obfuscated_loader –>|призводить до| node_discovery node_discovery –>|призводить до| node_credential_access node_credential_access –>|призводить до| node_c2 node_c2 –>|призводить до| node_execution node_execution –>|призводить до| node_persistence

Потік атаки

Експлуатаційне тренування

Передумова: перевірка телеметрії та базового стану повинна бути успішною.

Підстава: цей розділ детально описує точну реалізацію техніки супротивника (TTP), розробленої для запуску правила виявлення. Команди та наративи МАЮТЬ чітко відображати ідентифіковані TTP та націлені на генерування точної телеметрії, очікуваної логікою виявлення. Абстрактні або не пов’язані приклади призведуть до помилкової діагностики.

  • Наратив атаки та команди:

    1. Початковий доступ: Атакуючий доставляє шкідливий файл JavaScript (loader.js) на систему жертви і виконує його за допомогою bun середовища виконання (bun loader.js).
    2. Процедура самоін’єкції: Код JavaScript викликає вбудовані Win32 API через помічник PowerShell, який використовує Add‑Type для визначення підписів P/Invoke для VirtualAlloc, VirtualProtect, та LoadLibraryA.
    3. Розподіл пам’яті: VirtualAlloc резервує область RWX оптимізовану під вбудований шеллкод.
    4. Ін’єкція шеллкоду: Скрипт PowerShell копіює декодований з base64 шеллкод у виділену пам’ять за допомогою Marshal.Copy.
    5. Зміна дозволів: VirtualProtect перемикає захист сторінки на PAGE_EXECUTE_READ.
    6. Виконання навантаження: LoadLibraryA викликається на шкідливій DLL, яка знаходиться лише в пам’яті (заголовок DLL записується в виділену область, потім адреса передається до LoadLibraryA).
    7. Без нового потоку: Атакуючий навмисно уникає виклику CreateThread; DllMain DLL виконується в контексті поточного процесу, задовольняючи правило виключення.
  • Сценарій тестування регресії:

    # -------------------------------------------------
    # Завантажувач NWHStealer JavaScript – Демонстрація самоін’єкції
    # -------------------------------------------------
    # Цей сценарій ім’ює поведінку реального завантажувача NWHStealer.
    # Він навмисно викликає VirtualAlloc, VirtualProtect, і LoadLibraryA
    # без виклику CreateThread.
    
    # 1. Визначити підписи Win32 API
    $sig = @"
    using System;
    using System.Runtime.InteropServices;
    public class Win32 {
        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
        [DllImport("kernel32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
        public static extern IntPtr LoadLibraryA(string lpFileName);
    }
    "@
    Add-Type $sig
    
    # 2. Виділити виконувану пам'ять (RWX)
    $size = 0x1000
    $MEM_COMMIT = 0x1000
    $PAGE_EXECUTE_READWRITE = 0x40
    $mem = [Win32]::VirtualAlloc([IntPtr]::Zero, $size, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
    if ($mem -eq [IntPtr]::Zero) { throw "VirtualAlloc failed" }
    
    # 3. Приклад шеллкоду (MessageBox) – закодований у base64 для читабельності
    $b64 = "AQAAANAAAABAAEAAAABAAAAAgAAAAEAAABWAAAAAQAAAAIAAAD/////AQAAAAAAAAA="
    $shellcode = [Convert]::FromBase64String($b64)
    
    # 4. Копіювання шеллкоду у виділену область
    [System.Runtime.InteropServices.Marshal]::Copy($shellcode, 0, $mem, $shellcode.Length)
    
    # 5. Зміна захисту на EXECUTE_READ
    $oldProtect = 0
    $PAGE_EXECUTE_READ = 0x20
    $ok = [Win32]::VirtualProtect($mem, $size, $PAGE_EXECUTE_READ, [ref]$oldProtect)
    if (-not $ok) { throw "VirtualProtect failed" }
    
    # 6. Завантаження "DLL" з пам’яті (тут ми просто викликаємо LoadLibraryA на kernel32 як заповнювач)
    # У реальному завантажувачі це буде користувацька DLL, записана у $mem.
    $hLib = [Win32]::LoadLibraryA("kernel32.dll")
    if ($hLib -eq [IntPtr]::Zero) { throw "LoadLibraryA failed" }
    
    Write-Host "Кроки самоін’єкції завершені – процес повинен бути позначений правилом виявлення."
    # -------------------------------------------------
  • Команди очищення:

    # Завершити процес PowerShell, який виконав ін’єкцію
    Stop-Process -Id $PID -Force
    
    # (Необов'язково) Якщо користувацька DLL була записана на диск для тестування, видаліть її
    Remove-Item -Path "$env:TEMPmalicious.dll" -ErrorAction SilentlyContinue

Поствиконувальна верифікація

  1. Підтвердити генерацію сповіщення: Запустіть наступний KQL запит, щоб перевірити, чи спрацювало правило:

     // Правило виявлення: VirtualAlloc/VirtualProtect/LoadLibraryA без CreateThread
     Sysmon
     | where EventID == 1
     | where CallTrace contains "VirtualAlloc" or CallTrace contains "VirtualProtect" or CallTrace contains "LoadLibraryA"
     | where not(CallTrace contains "CreateThread")
     | project TimeGenerated, Process, CallTrace, EventID
  2. Перевірити відсутність хибнопозитивних результатів: Пере-запустіть безпечну команду Notepad і переконайтеся, що запит повертає нуль результатів для цього запуску.


Кінець звіту