Большой хабросалют всем! С вами на связи я, Ксения Наумова, и мой коллега Антон Белоусов. Мы работаем в компании Positive Technologies, в отделе обнаружения вредоносного ПО. Я занимаюсь анализом и детектированием вредоносного ПО в сети, другими словами исследую вредоносный сетевой трафик, а также совершенствую инструменты для его анализа и ищу новые подходы к обнаружению сетевых угроз. А Антон — вирусный аналитик, он занимается исследованием вредоносов, разбирает на части образцы вирусов, чтобы придумать, как лучше их детектировать или как найти похожие друг на друга.
В декабре 2023 года, в ходе постоянного отслеживания новых угроз ИБ, изучая в PT Sandbox и других песочницах вредоносные образцы и генерируемый ими трафик, мы обнаружили подозрительное сетевое взаимодействие, с которого наше дальнейшее исследование и началось. Надо сказать, обратили мы внимание на это еще и благодаря внезапно увеличившемуся количеству похожих семплов. Сами злоумышленники, видимо призрачно надеясь на убедительность, назвали в коде свой троян удаленного действия SafeRAT, с именованием которого мы, конечно, не согласны, но довольно спойлеров! Ниже мы постарались детально описать вредонос, который ранее исследователям не встречался, чтобы показать его НЕбезопасность.
Загрузчик
Каждый загрузчик представляет собой довольно простой бинарный файл формата PE (EXE) с единственной функцией. Загрузчик распространяется по почте в письмах с расширением .bat
. Оказавшись на компьютере жертвы, загрузчик с помощью функций библиотеки WinHTTP обращается к зашитому внутри него удаленному серверу (C2) за получением дополнительной полезной нагрузки следующего этапа.
Предполагаем, что код загрузки взят из примера MSDN, поскольку в некоторых семплах используется User-Agent:WinHTTP Example/1.0
.
Загрузчики незначительно различаются между собой, однако их функции идентичны. Ознакомиться подробнее с хешами можно в блоке «Индикаторы компрометации. Загрузчики».
Шеллкод
64-битный шеллкод отдается C2 в ответ на GET-запрос /payload.bin
в открытом виде.
Значение User-Agent не всегда такое, как на скриншоте выше. Например, мы встречали такие User‑Agent, как Chromium
, Google
, souhu
, sougou
, File Downloader
, baidu
, cpp-httplib/0.14.3
, ShellcodeDownloader
, python-requests/2.25.1
, Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
.
Далее исполнение стартует с 0-го байта.
Шеллкод получает свой адрес с помощью простого выражения.
В конце шеллкода указаны адрес C2 и порт, как выделено на скриншоте выше. Они хранятся в следующем виде:
struct C2 {
uint32_t port;
char addr[256];
};
После этого шеллкод получает адреса API-функций с помощью кастомного алгоритма хеширования их имен:
def hash_exp(name, poly):
result = poly
for i in range(len(name)):
result = (result * 0x21) & 0xFFFFFFFFFFFFFFFF
v = struct.unpack_from('<b', name, i)[0]
i += 1
result += v
return result
В процессе исследования мы столкнулись с двумя последовательными шеллкодами, имеющими как похожие функции, так и различия.
Шеллкод № 1 (payload.bin)
В этом шеллкоде параметр poly равен 0x85967AEFDADF5658
. Он находит следующие функции из ntdll:
LdrLoadDll (0xD33201CB07BB2036)
RtlInitUnicodeString (0x4E80BBE9CCE6585C)
NtAllocateVirtualMemory (0xD1A4739FEC736F3F)
Шеллкод загружает библиотеку ws2_32.dll
, а также получает адрес ее функции для создания сокета (TCP) и запроса шеллкода следующего этапа. Для этого отправляет следующий пакет на тот адрес C2, который зашит в конце шеллкода.
Первый DWORD — это длина пакета, далее следует захардкоженная строка efaSnigoL
(перевернутая строка LoginSafe
).
В ответ на этот пакет приходит шеллкод второго этапа, которому передается управление. Также шеллкод № 1 передает шеллкоду № 2 адрес C2.
Шеллкод № 2
Второй шеллкод вначале также получает адреса API-функции из ntdll по тому же хеш-алгоритму, что и первый, только в этом случае используется следующее значение poly: 0x8596741254585658
.
Назначение шеллкода — загрузка PE-модуля, который располагается после самого шеллкода.
После загрузки модуля шеллкод находит в таблице экспорта функцию Online и передает ей управление.
Основной модуль
Модуль является x64 DLL с единственным экспортом — Online
. Дата и время компиляции (из заголовка) — 05.11.2023 03:00:19. Имя библиотеки в таблице экспорта — online.dll
.
Online
Вначале создается событие Global\safeRat
— именно по нему мы и дали впоследствии название вредоносу.
После этого модуль избавляется от перехватов библиотечных функций, которые могли быть установлены антивирусом или XDR-системой.
Суть метода состоит в том, что бинарный файл с помощью CreateFileMappingA
отображает в памяти файл библиотеки из системной директории, затем устанавливает на секцию TEXT загруженного в процесс модуля права RWX и перезаписывает секцию в модуле содержимым отображенного файла — чтобы содержание модуля соответствовало файлу. После этого возвращаются ранее установленные права на секцию.
Среди других функций Online
:
установка обработчика исключений верхнего уровня, единственная задача которого состоит в том, чтобы перезапустить процесс в случае необрабатываемого исключения;
поиск адреса функции
NtTraceEvent
и патчинг первого байта этой функции на0xC3
(ret), чтобы от вредоносного процесса не регистрировались ETW-события для EDR-системы и других средств защиты;поиск и сохранение номера syscall NtQueryInformationProcess для дальнейшего использования;
создание путей для файлов wallet.safe и clip.safe в директории
C:\ProgramData
(файлclip.safe
— для сохранения содержимого буфера обмена, а файлwallet.safe
— для результатов работы кейлоггера);считывание из реестра сохраненного адреса C2 (в дальнейшем семпл может запросить у текущего сервера новый адрес и сохранить его в реестре, но вначале это значение отсутствует);
хранение адреса C2 и других значений по пути
HKCU\Software\<computer_name>
(если имя компьютера получить не удалось, то вместо него используется строкаUnKnow
).
Упомянутое выше новое значение сервера хранится в параметре Mov
, закодированное base64 и зашифрованное побайтным XOR (0x46
).
Основные функции семпла выполняются в отдельном потоке, который создается из функции Online
. В начале этого потока создается объект класса CClientSocket
, который отвечает за сетевое взаимодействие.
Стоит отметить, что в этом объекте есть несколько вложенных объектов класса CBuffer
, который предоставляет динамический буфер для хранения отправляемых и принимаемых данных. Далее объект клиента подключается к серверу по TCP. Прием и обработка входящих пакетов выполняются в отдельном потоке. Следующим этапом становится создание объекта класса CKernelManager
, который наследуется от класса CManager
и служит своего рода оркестратором для рабочих потоков и плагинов, получаемых от C2. В конструкторе CKernelManager создается отдельный поток, отвечающий за работу кейлоггера. Причем получение данных с клавиатуры выполняется через интерфейс IDirectInput8A
и устройство SysKeyboard
.
После этого семпл собирает начальную информацию о системе для отправки на сервер. В нее входят:
IP-адрес зараженного устройства,
имя компьютера,
имя пользователя,
PID вредоносного процесса,
список установленных антивирусов,
статус пользователя (является ли он администратором),
разность тиков процессора:
GetTickCount64 − GetTickCount64()
(вероятно, для проверки работы в ВМ),локальное время.
Результат можно представить в виде следующей структуры:
#pragma pack(push, 1)
struct system_info
{
char sz;
char host_ip_addr[130];
char reg_remark_or_comp_name[50];
char username[51];
uint32_t curr_pid;
char gap_EC[64];
char AVs[128];
char reg_cfg_Group_val;
char gap_1AD[63];
char is_admin;
char module_filename[255];
char reg_cfg_Run_val[3];
char gap_2EF[5];
uint32_t ticks_diff;
SYSTEMTIME localtime;
};
#pragma pack(pop)
Данные о системе отправляются на сервер. Для этого они сжимаются Zlib и шифруются RC4. Для шифрования генерируется случайный ключ с помощью rand % 511
. Либо задается как 123
. Далее это число форматируется в виде строки и используется для RC4.
Структуру пакета клиента можно представить следующим образом:
struct packet
{
uint32_t key;
uint32_t packet_size;
uint32_t payload_size;
uint8_t payload[payload_size];
};
Стоит отметить, что указывается длина разжатого пейлоада в переменной payload_size
. От C2 приходит пакет аналогичной структуры, за исключением того, что поля key
и packet_size
поменяны местами, то есть размер пакета содержится в нулевом DWORD, а ключ — в первом. В трафике это выглядит следующим образом:
Расшифрованную сессию можно посмотреть в «Кибершефе».
После расшифровки и распаковки пакета от сервера семпл проверяет нулевой байт, в котором содержится идентификатор команды (в данном случае 0e
). Обработку команд выполняет объект CKernelManager
. В ответ клиент посылает серверу отстук в виде той же самой команды.
Идентификатор команды | Описание |
0 | Разлогинивает текущего пользователя Windows |
2 | Устанавливает флаг завершения работы |
3 | Сохраняет в реестре новое значение параметра |
4 | Сохраняет в реестре новое значение параметра |
6–12, 14–17, 19–21, 25, 32–34 | Запускает плагин (номер команды — идентификатор плагина) |
13 | Вызывает BSOD с помощью |
18 | Запускает поток клиппера (стилер буфера обмена) |
22 | Обновляет C2 |
23 | Запускает кейлоггер |
24 | Запускает поток клиппера (стилер буфера обмена) |
26–31 | Получает и запускает новый модуль |
35 | Сохраняет в реестре новое значение параметра |
36–42 | В зависимости от номера команды стилер похищает данные: |
Заключение
Исходя из оригинального имени в сервисе VirusTotal и некоторых целей SafeRAT (Sogou, 360 Secure Browser, QQBrowser), предполагаем, что вредонос рассчитан на китайскоговорящих пользователей.
Судя по именам классов (CKernelManager
, CClientSocket
) и общей архитектуре кода, можно сделать вывод, что SafeRAT — это очередная поделка, основанная на утекших исходниках Gh0st, только с урезанной функциональностью.
Вердикты наших продуктов
PT Sandbox:
tool_win_ZZ_SafeRAT__Backdoor__Loader
tool_win_ZZ_SafeRAT__Backdoor__MainModule
tool_mem_ZZ_SafeRAT__Backdoor__MainModule
tool_win_ZZ_SafeRAT__Backdoor__Shellcode
tool_mem_ZZ_SafeRAT__Backdoor__Shellcode
Trojan-Downloader.Win32.SafeRAT.a
PT Network Attack Discovery:
REMOTE [PTsecurity] SafeRAT 10010258
REMOTE [PTsecurity] SafeRAT 10010259
REMOTE [PTsecurity] SafeRAT 10010260
Индикаторы компрометации
Загрузчики:
0bc5545cf48254aff60e1757e45f7020a64ee9eda2e6db9352e9107811309f8e
1720528e27ba5ceaa207de277155ddf1880f1d3d3dacd5ee61f54c908712d63c
1c84b5fe2ae149b94c3da5bb0a925a03121b40c425bad018e39e1bf22667d597
63943b876cad63a0024e908f8c412a63aec181b6765cfa0365bbdee90943694f
6d09ee4e5800516fb1f4afb65de6fccb0861757a2b366157c401826e7fbe6b55
6dbce4cd9e1c3c024c43424699ee3510ad7453a48d8c966f995995de23b7333f
acee04a9da6a6fc6e78bddd8285d9d7a0e8bbd9da73171b87a3e04917fbbab5d
aef9cfcabb5f39bcb66ee081d42e30461abcc55601f5f3236abbc5435911a2e4
b1c19d93439f8f773910e386bb108f95050b6188e48a2607fb38e9083b974262
b60280482ec39af421c349c480163e466d300334f748ea9d479203258198baf6
Шеллкоды:
215a4fefc44e9cf8e3b2e320e09cca29f1cda0eac8b99844d72ef36c14939803
5d8981b146880cbee147a07f9905de2c1fb75e965386b7c3d12a4a2ccee0da85
Основной модуль:
979f17cad701227065fd405eeaeb1e00a917ae605c1616d4de92ba6da86407bc
Сетевые индикаторы:
103.216.152.150:280
103.216.152.150:3300
104.218.234.78:280
104.218.234.78:8000
154.213.17.136:8000
154.213.17.147:280
154.23.182.133:280
154.23.182.133:8000
154.23.182.24:280
154.23.187.249:280
154.23.187.249:8000
154.55.128.137:280
154.55.128.137:8000
156.245.19.172:280
202.95.14.203:8000
202.95.14.223:280
27.124.4.221:8000
27.124.4.228:280
27.124.4.229:280
27.124.44.10:280
27.124.44.3:8000
43.135.39.104:280
43.135.39.104:8000
43.243.73.220:280
43.243.73.220:8000
45.195.204.101:280
45.195.204.36:280
45.195.204.76:8000
45.248.11.63:280
45.248.11.63:8000
45.249.93.80:280
45.249.93.80:8000