Analyzing Lu0Bot: A Node.js

akok

Команда форума
Администратор
Ассоциация VN
Сообщения
24,719
Реакции
13,565
В этой статье мы рассмотрим образец вредоносной программы Lu0Bot, который мы обнаружили, отслеживая злонамеренную активность в публичных задачах ANY.RUN.

Нас заинтересовало то, что образец написан на Node.js. Хотя сначала он казался обычным ботом для атак DDOS, на самом деле все оказалось намного сложнее.

1695842075087.png


Вредоносная программа на Node.js интересна тем, что она нацелена на среду выполнения, которая часто используется в современных веб-приложениях. Платформонезависимый характер среды зависит от конкретного кода и библиотек, которые используются, но он часто позволяет большую гибкость. Обычно такая вредоносная программа использует многоуровневые техники обфускации с помощью JavaScript. Она сочетает в себе традиционные характеристики вредоносных программ с веб-технологиями, что делает ее уникальным вызовом для обнаружения и анализа.

Из-за большого объема статьи мы решили разделить ее на две части:

  • Часть 1: основной анализ: В первой части мы изучим архитектуру вредоносной программы и то, что в ней хранится.
  • Часть 2: анализ трафика: Во второй части мы рассмотрим реальный случай, когда образец связывается с сервером C2.

Что такое вредоносная программа Lu0Bot?​


Прежде чем перейти к анализу, давайте кратко рассмотрим Lu0Bot и поговорим о том, что делает его особенно интересным.

Lu0bot впервые появился в феврале 2021 года как второстепенный полезный груз в атаках GCleaner. Теперь он служит ботом, который ждет команд от сервера C2 и отправляет обратно на этот сервер зашифрованную базовую информацию о системе.

Стоит отметить, что уровень активности бота остается относительно низким, в среднем 5-8 новых образцов на Bazaar каждый месяц. На момент написания этой статьи только один новый образец был загружен в августе. Однако возможно, что реальная популярность этой вредоносной программы выше, чем показывает уровень активности, с множеством образцов, лежащих бездействующими и ожидающих команд C2 - хотя это лишь наше предположение.

Несмотря на эту ограниченную активность, Lu0bot интересен тем, что демонстрирует творческий подход к дизайну вредоносных программ - написанный на Node.js его возможности ограничены только тем, что возможно в этом языке программирования.

Хотя мы не смогли найти живой образец, получающий команды - скорее всего из-за неспособности бота найти IP-адрес - публичный образец успешно подключился. В этом случае сервер ответил кодом JavaScript, инициировал новый домен и продолжил обмен зашифрованным кодом. Процесс расшифровки жестко закодирован в боте - но мы подробнее рассмотрим алгоритм расшифровки во второй части нашего анализа.

Статический анализ исходного файла​

Давайте начнем наш разбор Lu0Bot с его статического анализа.

Первое, что мы заметили, это то, что файл использует упаковщик SFX (см. рис. 1) - это самораспаковывающийся архив, который можно открыть с помощью любой утилиты для работы с архивами.
1695842475617.png

Внутри архива был файл BAT и несколько других содержимого (см. скриншот ниже). Давайте разберем, что они делают по очереди:
1695842546852.png


1. BAT - файл​

1695842609572.png

Первая строка содержит комментарий, но его значение остается неясным - он не упоминался позже в нашем анализе.
Далее несколько файлов объединяются в файл EXE, а именно интерпретатор Node с именем fjlpexyjauf.exe.
В третьей строке этот интерпретатор получает файл, содержащий байты и число (в терминах заполнителя, %1%, как видно на скриншоте выше), но реальное число в нашем случае - 3991425476. Это число, вероятно, действует как ключ шифрования для файла байтов.


2. eqnyiodbs.dat​

Этот один файл разделен на разные блоки байтов. Эти блоки позже объединяются, чтобы сформировать интерпретатор Node.
1695842737897.png


3. lknidtnqmg.dat​

Этот файл содержит байты, зашифрованные в Base64. Вероятно, он расшифровывается с помощью числа, предоставленного на входе.

1695842793240.png


4. gyvdcniwvlu.dat​

Это драйвер, который позволяет 32-битным программам на x64 системах преобразовывать коды сканирования клавиш в символы Unicode. Основной процесс полагается на него, скорее всего, чтобы обеспечить функциональность регистрации нажатий клавиш.

Динамический анализ вредоносного ПО Lu0Bot в ANY.RUN​

Статический анализ указывает на значимость файла EXE и файла lknidtnqmg.dat. Следующим шагом будет изучение динамического поведения и попытка либо расшифровать байты, либо найти их расшифрованными в памяти процесса.

Для выполнения динамического анализа мы воспользуемся интерактивной песочницей для вредоносных программ ANY.RUN.
1695843201994.png


Процессы и активность​

Снимок экрана дерева процессов выше отображает дерево процессов во время выполнения образца. Основной процесс инициирует знакомый BAT-файл, который в свою очередь запускает файл EXE. Постановка анализа подтверждает, что это интерпретатор Node.js, который принимает на вход зашифрованный JS-код.

Помимо попыток установления соединений, JS-код извлекает системные данные, используя WMIC. Он специально собирает информацию о процессах и местоположении выполнения, соответствуя тактике T1047.
1695843252129.png

Динамический анализ показал, что интерпретатор копируется в папку запуска. После перезагрузки системы продолжается соединение с доменом (это видно на снимке экрана дерева процессов выше) - обратите внимание на номер процесса 5252 (Тактика T1053.005). Это гарантирует, что бот остается активным после перезагрузки системы.
1695843280802.png


Сеть и трафик​

Уникальной характеристикой этой вредоносной программы является ее подход к соединению с доменом. Доменное имя конструируется из различных частей и собирается в единое целое внутри кода на JavaScript:
1695843372723.png


Выше представлен небольшой обзор трафика Lu0Bot - мы более подробно рассмотрим его во второй части нашего анализа.

Технический анализ вредоносной программы Lu0Bot с использованием дизассемблера и отладчика​

В нашем случае дамп или скрипт одновременно упакован и зашифрован. Для доступа к основному JS-коду нам потребуется:

  • Распаковать SFX-архив.
  • Запустить команду для сбора файла Node.js.
  • Запустить fjlpexyjauf.exe в x32dbg, введя входные данные в командной строке.
  • Дойти до момента начала выполнения JS-кода.
  • Найти код в памяти и сохранить дамп.

Шаги для распаковки и сбора байтов:

Чтобы распаковать архив, мы можем использовать любой стандартный архиватор.
Для сбора байтов мы сосредоточимся на второй строке BAT-скрипта - давайте выполним его.
1695843607079.png


Извлечение дампа​

Давайте запустим файл в отладчике и передадим входные данные в командной строке.
1695843666286.png


Мы ищем место, где начинается выполнение кода на JS, отмеченное вызовом функции uv_run. После этого вызова программа начинает попытки соединения с доменом и висит бесконечно. Давайте перейдем к этой функции и найдем код. Для облегчения этой задачи мы можем использовать синтаксические подсказки и атрибуты переменных, такие как слово ini(), которое является уникальным для синтаксиса JS.

1695843701593.png


1695843714982.png


Как только мы обнаружим расшифрованный код, давайте перейдем в раздел "Memory Map" и сохраним этот раздел. Ваш дамп должен выглядеть примерно так:
1695843757116.png


Анализ JS​

Представленный нам JavaScript-код сильно обфусцирован и нечитаем.
1695843821930.png


Мы можем преобразовать код в читаемую форму, удалив лишние байты и использовав JavaScript-деобфускатор (вот ссылка на удобный скрипт, который вы можете использовать). После преобразования результат должен выглядеть примерно так:


1695843887738.png


Заметьте следующее:

1. Код начинается с массива, содержащего зашифрованные строки.
2. Сразу после этого массива выполняется манипуляция, перемещая конкретные элементы в конец.
3. Далее идет функция, посвященная расшифровке строк массива. Сначала она использует альтернативную форму BASE64 (T1132.002), затем URL-кодирование и декодирование, а затем применяет RC4.

Эта функция вызывается с двумя переменными: первая - это элемент из массива, а вторая - ключ RC4.

Для упрощения задачи разбора этого кода мы написали небольшой скрипт, который автоматически расшифровывает эти строки. Вы можете скачать его с нашего GitHub.

Запуск скрипта дает нам следующий результат до и после расшифровки:
1695844125557.png

1695844136434.png


Расшифрованные строки показывают, что части доменов жестко закодированы в образце. Затем вы найдете раздел кода, ответственный за сборку домена:
1695844190566.png



Отладка кода на JavaScript.​

Для отладки мы будем использовать Node.js вместе с параметром --inspect-brk (node.exe --inspect-brk обфусцированный дамп без мусорных байтов). Давайте установим точку останова на ключевое слово "var" и наблюдать за выводом, генерируемым каждой строкой:

Первая функция, ginf, занимается сбором информации. Она выводит массив с 15 элементами, все из которых представляют собой детали о системе.
1695844283983.png

1695844295621.png


Функция hwco получает на вход массив из 15 элементов, который формируется функцией ginf. Выходными данными является хвостовая часть домена, до точки. Анализ показывает, что этот вывод на самом деле является хешем собранных данных о системе.
1695844351856.png

1695844372799.png


Далее из массива acc извлекаются элементы, такие как порт, номер и сегмент домена, следующий за точкой, и присваиваются переменным.
1695844437850.png


Переменной acc добавляются значения 3, rns (которое генерируется случайным образом), и bt, который представляет текущее время.
1695844498641.png

1695844505958.png


Затем к сегменту домена перед точкой добавляется переменная, содержащая случайное число. Следующая строка обрабатывает выбор домена после точки: если выполняются определенные условия, то выбирается альтернативный домен, если он доступен.

1695844541905.png


Собирается полный домен, и все необходимые элементы упаковываются в JSON-объект:
Код:
{“gttk”,”59c58bb5327116933080087040012a04a641e14b536350088dba00221232f.hsh.juz09.cfd”,18223,”59c58bb5″,”331c90″,1693308008704,null,[“win32″,”ia32″,32,”10.0.19044″,6386.265,3220688896,1396203520,4,”Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz”,3094,”PC”,”admin”,”C:\\Users\\admin\\Desktop\\node-v20.5.0-win-x86″,”C:\\Users\\admin\\AppData\\Local\\Temp”,”20.5.0″],”0012a04a641e14b536350088dba00221232f”}

Итак, давайте подведем итоги
НачалоЧислоСлучайное числоВремяHashesОкончание домена
59c58bb5327116933080087040012a04a641e14b536350088dba00221232fhsh.juz09.cfd

Последняя функция на экране использует шифрование aes-128-cbc. Выходные данные представляют собой массив из 435 элементов, состоящий из 1 байта, затем 16 байт IV, затем 2 байта, и, наконец, зашифрованных данных (Тактика T1573).
1695844805197.png

Мы также обнаружили ключ: becfe83392d83ef8c743ea00711a25c8, который соответствует всем активным задачам, выявленным нашей командой.

После выполнения вредоносное ПО продолжает попытки найти адрес для передачи данных. Когда трафик успешно достигает сервера, происходит обмен данными, включая отправку JS-кода со стороны сервера C2. Больше информации об этом мы предоставим во второй части нашего анализа.

Правила SIGMA​

Код:
title: Lu0Bot detect
 status: experimental
 description: Detects Lu0Bot activity
 author: ANY.RUN
 date: 2023/09/26
 tags:
     - Lu0Bot
 detection:
     parent_process:
         ParentImage|endswith: '\cmd.exe'
         CommandLine|re: '\/d \/c [A-z0-9]+\.bat \d+$'
     child_process:
         OriginalFileName: 'node.exe'
         CommandLine|re: '\.dat \d+$'
     condition: parent_process and child_process

Правила YARA​


Код:
rule Lu0Bot_detection {
    meta:
   
      description = "Detection of Lu0Bot"
      date = "2023-09-26"
      family = "Lu0Bot"
     
strings:

 

        $start_code = /var \_0x[a-f0-9]{4,6}/
        $altBase64 = "'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='" ascii
        $domain = "var acc=" ascii
        $end_code = "}ini();" ascii
        $func = “ginf” ascii

 

    condition:

 

       all of them and #start_code >= 50
}

Написание правил Suricata для Lu0Bot​

Для эффективных сетевых правил Suricata ключевым является содержание (content). DNS-запросы играют большую роль во всех запросах сетевого протокола. Как упоминалось ранее, в случае вредоносной программы Lu0Bot в DNS-запросах нет стабильного содержания - в основном случайные байты или хеши. Однако есть небольшая часть имени домена, которая включает в себя временную метку в формате Unix. Мы будем использовать это для сетевого обнаружения.

Чтобы захватить три байта этой временной метки в правиле, мы ограничили активный период действия правила. Мы выделили пять периодов, связанных с начальными байтами 169, 170, 171, 172 и 173 в метке времени. Это дало нам пять правил, нацеленных на активность вредоносной программы в конкретных временных окнах.
GMT activity end dateTimestampRule Message
Nov 14 2023 22:13:20<1700000000BOTNET [ANY.RUN] Lu0bot
DNS Query M1
Mar 09 2024 15:59:59<1709999999BOTNET [ANY.RUN] Lu0bot
DNS Query M2
Jul 03 2024 09:46:39<1719999999BOTNET [ANY.RUN] Lu0bot
DNS Query M3
Oct 27 2024 03:33:19<1729999999BOTNET [ANY.RUN] Lu0bot
DNS Query M4
Feb 19 2025 21:19:59<1739999999BOTNET [ANY.RUN] Lu0bot
DNS Query M5

В реальных сценариях некоторые DNS-запросы Lu0Bot вообще не содержат хешей и заканчиваются только временной меткой. Из-за этого регулярное выражение должно учитывать как хешированные, так и не хешированные версии запросов.

Ниже приведено регулярное выражение, которое является частью сетевого правила BOTNET [ANY.RUN] Lu0bot DNS Query M1. Оно отражает переменные, полученные в ходе нашего анализа, и настроено на временные метки, начинающиеся с числа 169. Обратите внимание, что это правило будет действовать до ноября 2023 года, когда временная метка перейдет к началу с числа 170.

1695845350959.png


1695845365682.png


Network rule textDescription
alert dns any any -> any any
(msg: "BOTNET [ANY.RUN] Lu0bot DNS Query M1";
flow: to_server;
Indicates the protocol, the direction of data transfer and the message if the rule is triggered.
dns.query;Targets an inspected buffer containing a DNS query
content: "169"; offset:12; depth:3;Content check for the M1 rule range
pcre:"/^(?:[a-f0-9]{8}\d\d{3}169\d{10})(?:[0-9a-z]{36})?\./";Regular expression describing the structure of a DNS request
threshold:
classtype: trojan-activity;
reference:
metadata: malware_family Lu0bot
sid: 8000603; rev: 2;
The rule's service fields provide essential information: they describe the malware family, set the trigger threshold, and offer a list of links for further reading on this threat.

Обнаружение Lu0bot в ANY.RUN.​

Мы уже реализовали обнаружение Lu0bot в ANY.RUN — наш сервис может автоматически расшифровывать строки, и домены C2 теперь видны в нашем сервисе. Эти задачи показывают обнаружение Lu0bot в ANY.RUN:

Итоги

В данной статье мы рассмотрели вредоносную программу Lu0bot, включающую NODE JS и исполняемый код на JavaScript. На основе нашего анализа мы пришли к следующим ключевым выводам:

1. Весь код вредоносной программы обфусцирован. Основное внимание уделяется сбору базовой информации и ожиданию команд от сервера C2.

2. Функциональность вредоносной программы ограничивается только тем, что может делать ее код на JavaScript.

3. Структура домена вредоносной программы уникальна.

4. Для строк используются собственные методы шифрования.

Учитывая эти факторы, Lu0bot может представлять существенный риск, если его кампания масштабируется, и сервер начнет активно отвечать. Уникальная реализация с использованием NODE JS делает его очень интересным объектом для анализа.

Если сервер станет оперативным, вредоносная программа может иметь потенциал для:

  • Записи нажатий клавиш.
  • Кражи личной информации.
  • Почти полного контроля над компьютером жертвы.
  • Действия как бота для DDoS-атак.
  • Осуществления незаконных действий с использованием компрометированной системы.

Если вас заинтересовала эта статья, обязательно прочтите также наш технический разбор XWorm, а также подробный анализ нового образца LaplasClipper. И, конечно же, мы подробно рассмотрим структуру трафика Lu0bot в гораздо большей детализации в предстоящей части 2 нашего анализа - следите за обновлениями.

 
Последнее редактирование:
Назад
Сверху Снизу