Тот самый 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)
Сразу видим событие, предупреждающее о запуске файла с двойным расширением.
Далее происходит любопытная вещь. Процесс пытается копировать свой 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.