Уязвимый Exchange нередко становится лакомым кусочком для атакующих. Пока уязвимость не будет устранена, все больше и больше злоумышленников будут пытаться атаковать его. На одном из таких серверов среди целого зоопарка известного ВПО нам удалось найти новый модульный бэкдор ShadowRelay. Он позволяет загружать разные по функциональности плагины. А его устройство говорит о высокой подготовке атакующих.
Обзор инцидента
Весной 2025 года мы выявили, что инфраструктура одной из организаций госсектора с высокой вероятностью была скомпрометирована азиатской группировкой Erudite Mogwai (aka Space Pirates). После чего связались с отделом информационной безопасности этой компании и предложили помощь в расследовании.
В результате исследования было обнаружено несколько зараженных систем пользователей, где мы среди прочего нашли вредоносное ПО Shadowpad Light (aka Deed RAT), а источником их заражения оказался почтовый сервер Exchange, который оказался скомпрометированным еще летом 2024 года с помощью эксплуатации цепочки уязвимостей ProxyShell (CVE-2021-34473, CVE-2021-34523, CVE-2021-31207). Да, данная уязвимость из 2021-го все еще является актуальной.
Но как этот уязвимый почтовый сервер оставался незамеченным так долго? Все просто, ведь его установили и опубликовали тем же летом 2024 года, и уже спустя несколько недель сервер был обнаружен сразу множеством хакерских группировок. Так при исследовании системы были обнаружены различные файлы вредоносного ПО:
- Оригинальный ShadowPad (азиатские группы)
- Shadowpad Light (Erudite Mogwai)
- Donnect (Obstinate Mogwai)
- Mythic Agent (GOFFEE)
Также кроме инструментов данных групп мы обнаружили и индикаторы компрометации, и тактики, которые соответствовали профилям атакующих.
Помимо уже известных инструментов атакующих, при исследовании системы мы нашли новый образец модульного вредоносного ПО, который был размещен в системе в период предполагаемой активности Obstinate Mogwai. Это вредоносное ПО позволяет атакующим скрытно подгружать плагины, которые реализуют необходимую в конкретной атаке функциональность. Также бэкдор может поддерживать связь с другими имплантами, которые, например, не имеют подключения к интернету. Сам бэкдор не содержит полезной нагрузки для шпионажа или удаленного управления, но позволяет ее загрузить. Нам еще не удалось найти плагины для данного ВПО, поэтому сценарий атакующих и их цели не ясны до конца.
Техническое описание
Запуск
При запуске вредонос пытается установить себя в качестве сервиса. Если это не выходит, все равно запускает функцию main_routine.
Бэкдор также пытается обнаружить дебаггеры и песочницу. Он имеет простейшие проверки обратной разработки. Вредоносная нагрузка запускается, только если в параметрах передается специальное значение из конфига. В случае провала проверок запускается функция самоликвидации.
Для самоудаления у бэкдора имеется специальная функция suicide, которая удаляет закрепления и файлы. Для удаления файлов создается bat-файл, который через некоторое время удаляет нужный файл.
Конфигурация
В конфигурации определяются параметры сетевого соединения. Задается рабочий режим «клиент/сервер», данные С2, способ шифрования и опции работы:
- antidebug — включает проверки инструментов обратной разработки,
- portreuse — включает функцию переиспользования открытых портов,
- targetprocess — активирует инъекцию бекдора в указанный процесс,
- envparam — параметр для запуска (обход песочницы),
- srvi — управляющий сервер,
- mode — режим «клиент/сервер»,
- lsp — порт для подключений в случае сервера,
- srvp — порт управляющего сервера,
- transip — Source IP, используемый в правиле для переиспользования портов,
- reconnintv — ожидание перед подключением.
Конфигурация зашифрована шифром Цезаря со сдвигом -1 по ASCII.
Всего нам встретилось три семпла бэкдора. Самая последняя конфигурация извлечена из серверной версии бэкдора, она содержит новый параметр beattimeout и сконфигурирована для работы на локальном хосте.
|
MD5 |
7d3f5ac6ec93f6e03409b5cd6bd3b817 |
|
SHA1 |
7a8ffcbec06f8252aa84b8787a44df9ce074e72c |
|
SHA256 |
504d27aa26256fff8083cb7563d8bb0123516f1120f8c609ba57d91acf349416 |
|
File name |
comms.exe |
|
File type |
PE32+ executable for MS Windows 6.00 (GUI), x86-64, 8 sections |
|
File size |
1.84 MB (1926144 bytes) |
|
MD5 |
0bd08e75f20e0e664c219d744d28f57b |
|
SHA1 |
8cc7bcaf9d436a12f300638c3cbc77d4e9585008 |
|
SHA256 |
0968de8d650848e2c3e381593e47e4216cfecd45e377264fab976ba214b38fec |
|
File name |
publicrundll64.exe |
|
File type |
PE32+ executable for MS Windows 6.00 (GUI), x86-64, 7 sections |
|
File size |
1.84 MB (1932800 bytes) |
|
MD5 |
5cbeb83ae2cebc318fffbadc29ceacdb |
|
SHA1 |
2358fd681988f67f35049d6d653b7df3a2c37ccb |
|
SHA256 |
541628370c4d4f64468021bd83414efa9ee1634554acf29055c6c1dfa601a5e5 |
|
File name |
C:\Windows\jx71a1wa.exe |
|
File type |
PE32+ executable (console) x86-64, for MS Windows |
|
File size |
2.27 MB (2383360 bytes) |
// 504d27aa26256fff8083cb7563d8bb0123516f1120f8c609ba57d91acf349416
{
"mode": "client",
"proto": "tcp",
"svri": "94.131.2.59",
"svrp": 443,
"reconnintv": 515, // задержка подключения
"enctype": "aes",
"aeskey": "]zf,.Hso'!x3|ezz/hzHzxa(P=x.bB.r",
"rsapubkey": "not set",
"rsaprikey": "not set",
"antidebug": 1,
"autodelete": 0, // (не используется) автоудаление
"autostart": 0, // (не используется) автостарт
"portreuse": 0,
"envpara": "2110cc46a55a4bcff3cb",
"targetprocess": "",
"usehttp": 0
}
// 0968de8d650848e2c3e381593e47e4216cfecd45e377264fab976ba214b38fec
{
"mode": "client",
"proto": "tcp",
"svri": "5.34.176.39",
"svrp": 443,
"reconnintv": 500,
"enctype": "aes",
"aeskey": "]zf,.Hso'!x3|ezz/hzHzxa(P=x.bB.r",
"rsapubkey": "not set",
"rsaprikey": "not set",
"antidebug": 1,
"autodelete": 0,
"autostart": 0,
"portreuse": 0,
"envpara": "e8779a07ccefbacfe2b2",
"targetprocess": "",
"usehttp": 0
}
// 541628370c4d4f64468021bd83414efa9ee1634554acf29055c6c1dfa601a5e5
{
"mode": "server",
"proto": "tcp",
"lsp": "10002",
"svri": "127.0.0.1",
"svrp": "8085",
"reconnintv": 1,
"enctype": "aes",
"aeskey": "bcudisbofds42bio",
"rsapubkey": "...",
"rsaprikey": "...",
"beattimeout": 10,
"antidebug": 1,
"autostart": 0,
"portreuse": 0,
"transip": "127.0.0.1",
"reuseport": "80",
"envpara": "726919c0fbbac9038741"
}
Инъекция пакетов и инъекция в процессы
Имплант имеет множество функций сокрытия себя в системе. Одной из таких является инъекция себя в другие процессы. В клиентской версии ВПО имеет специальный параметр targetprocess, который определяет имя процесса, в который будет инжектирован бэкдор. В случае успеха этого внедрения основной процесс завершается.
В дополнение к этому у бэкдора есть функциональность переиспользования портов. Для этого нужен драйвер WinDivert, а для активации этой функции используется параметр portreuse. Мы пока не встретили бэкдор с активированной функцией переиспользования портов. Используя уже открытые и разрешенные порты, вредоносное ПО может скрывать свое сетевое взаимодействие с управляющими серверами (C2). Такая техника может применяться и для обхода межсетевого экрана, когда запрещенные порты блокируются. Для фильтрации пакетов ShadowRelay использует следующее правило (порты обозначены именами, как на рисунке):
(outbound and tcp.DstPort == reuseport_0 and ip.SrcAddr == transip)
(inbound and tcp.DstPort == reuseport_0 and ip.SrcAddr == transip)
(loopback and tcp.DstPort == 65534)
(outbound and tcp.SrcPort == reuseport_1)
В коде указывается порт 65534, который, видимо, используется как порт для отправки пакетов в ответ. ВПО получает пакеты на reuseport_0 на определенный внешний адрес transip, пакет копируется и направляется на reuseport_1 на loopback. А ответ пересылается обратно.
Структура пакетов
Сигнатура пакетов: S&j0$
ShadowRelay имеет оригинальную структуру пакетов. Тип шифрования устанавливается в конфигурации, а для сжатия используется модифицированная zlib.
В заголовке передается:
- operation_code — код операции,
- crypted_msg_size — длина зашифрованного сжатого сообщения,
- initial_msg_size — изначальная длина сообщения,
- total_size — общая длина, равная 42*frame_count+buff_size+63,
- frame_count — количество фреймов,
- argument — передаваемый аргумент в plugin_task (возможно, номер команды/операции по аналогии).
Заголовок
|
Значение |
Размер (байт) |
|---|---|
|
operation_code |
2 |
|
crypted_msg_size |
10 |
|
initial_msg_size |
10 |
|
total_size = 42*frame_count+buff_size+63 |
10 |
|
frame_count |
8 |
|
argument |
8 |
|
crc |
10 |
Фрейм
|
Значение |
Размер (байт) |
|---|---|
|
frame_count |
8 |
|
frame_num |
8 |
|
delta_sent |
8 |
|
argument |
8 |
|
crc |
10 |
Многопоточное общение
В бэкдоре есть кастомный класс потока, а также несколько потоков, которые взаимодействуют с друг другом через специальные контексты. Они запускают основную логику работы импланта.
Видно, что авторы потрудились над многопоточностью и создали собственный класс потока со встроенными семафорами и атомарными счетчиками.
Контексты
Существует три контекста, которые работают как очереди. В контексте есть очередь, mutex и несколько event, которые обозначают разные этапы работы с очередью. В очередь передается пара «код операции / сообщение» и пара «длина сообщения / аргумент для plugin_task».
Функции
hello_connect
Пытается установить соединение с сервером и получить информацию для передачи через Context2 в функцию load_plugin. Парсит заголовок пакета, извлекает оттуда код команды и саму команду.
В конфигурации сервера начинает прослушивать порт, указанный в конфигурации.
В заголовках пакета передается тип команды. Для некоторых кодов и команд предусмотрены отдельные сценарии:
|
Код |
Команда |
Описание |
|---|---|---|
|
13 |
uninstall |
Деинсталляция |
|
5 |
число (double) |
Завершить сеанс, подключиться через время, которое определяется задержкой |
|
_ |
_ |
Передается в контекст 2 |
send_message
Получает сообщения из контекста 1 и передает на управляющий сервер. В случае если сообщение является строкой success и содержит код операции 6, выходит из цикла и добавляет в контекст 3 пустую структуру и ожидает 5 секунд.
В серверной версии убрали взаимодействие с третьим контекстом.
load_plugin
Получает команды из hello_connect. Тоже имеет несколько команд с особыми сценариями. Способна подгружать исполняемые PE-плагины.
|
Код |
Команда |
Описание |
Ответ |
|---|---|---|---|
|
16 |
uninstall |
Деинсталляция плагина |
fail/success |
|
16 |
_ |
Получает в качестве информации плагин (pedll) и грузит его в память. Ищет и запускает функцию plugin_init |
fail/success |
|
15 |
_ |
Шифрует входящие данные AES и записывает их в файл INLICIT |
Success/Fail create file |
|
_ |
_ |
Код используется для вычисления офсета, а команда передается в плагин с командой plugin_task |
_ |
|
Код |
Команда |
Описание |
Ответ |
|---|---|---|---|
|
15 |
uninstall |
Деинсталляция плагина |
fail/success |
|
15 |
_ |
Получает в качестве информации плагин (pedll) и грузит его в память (или заменят старый плагин на новый). Ищет и запускает функцию plugin_init |
fail/success |
|
_ |
_ |
Код используется для вычисления офсета, а команда передается в плагин с командой plugin_task |
_ |
В бэкдоре есть информация о трех командах, которые обязательно имеются в плагине. Сами плагины обнаружить не удалось. Плагин обязательно содержит три команды:
- plugin_init — инициализация,
- plugin_task — основная логика,
- plugin_deinit — деинициализация.
Такая модульная система позволяет не компрометировать функциональность плагинов и избегать обнаружения управляющей логики.
send_pc_info
Функция send_pc_info собирает и отправляет информацию о компьютере. Проверяет наличие отладчиков и других средств анализа. Если они присутствуют, завершает программу. В серверной версии разработчики изменили подход. Раньше она посылала информацию напрямую, по теперь использует для этого контекст. При соединении бэкдоры обмениваются системной информацией друг с другом каждые несколько секунд.
01192.168.116.118*| |*00:0В:28:59:5A:9D*| |*DESKTOP-4HВВJ5H*| |*admin*| |*user*||*C:\Users\admin\Downloads\541628370c4d4f64468021bd83414efa9ee1634554acf29055c6c1dfa601a5e5*| |*726919c0fbbac9038741
Детектирование сетевой активности
Как мы уже говорили, данный бэкдор может в теории соединяться с другими зараженными машинами. Это позволяет ему поддерживать связь с серверами и АРМ в сегментах без прямого доступа к интернету.
При соединении два бэкдора общаются между собой, пересылая информацию о хосте. Но логика управления, видимо, реализуется подгружаемыми плагинами. Устройство бэкдора позволяет контролировать хосты, которые не подключены напрямую к интернету, образуя сеть из серверов и клиентов.
Для детектирования общения между имплантами подойдет простое правило snort. Оно детектирует сигнатуру пакета, используемого бэкдором ShadowRelay, и следующий за ним информационный пакет.
alert tcp any any -> any any (
sid: 1; rev:1;
msg:"MALWARE ShadowRelay Backdoor";
classtype:trojan-activity;
content:"|53 26 6A 30 24 30 31 30 30 30 30 30 30|";
startswith;
reference:md5,0bd08e75f20e0e664c219d744d28f57b;
metadata:place,perimeter;
metadata:malware,ShadowRelay;
metadata:MITRE,T1071;
)
Заключение
Уязвимый сервер помог выявить новую кампанию атак совершенно неизвестным до это вредоносом. Хотя бэкдор был загружен в атакованную инфраструктуру в то же самое время, когда там присутствовала группировка Obstinate Mogwai, у нас пока нет достаточных свидетельств, что ShadowRelay является частью арсенала именно этой группы. Кроме того, иные инструменты (такие, как ShadowPad) и артефакты присутствия других группировок существенно расширяют «круг подозреваемых».
С большей уверенностью можно судить о мотивах операторов, скрывающихся за ShadowRelay. Данный бэкдор имеет средства сокрытия своей сетевой активности через инъекцию сетевых пакетов, имплант способен скрытно шпионить в защищенных сегментах сети организации, общаясь через сеть зараженных машин. Чтобы избежать детектирования своего процесса, он способен внедряться в другие процессы. А использование плагинов для подгрузки дополнительной логики позволяют укрывать полезную нагрузку от внимания аналитиков вредоносного ПО. Все это указывает на относительно высокий уровень подготовки атакующих, а также на то, что их основная цель — длительное скрытное присутствие в атакованной инфраструктуре и шпионаж. Такое поведение характерно прежде всего для прогосударственных шпионских APT-группировок.
IOC
Files
MD5
0bd08e75f20e0e664c219d744d28f57b
7d3f5ac6ec93f6e03409b5cd6bd3b817
5cbeb83ae2cebc318fffbadc29ceacdb
SHA1
2358fd681988f67f35049d6d653b7df3a2c37ccb
7a8ffcbec06f8252aa84b8787a44df9ce074e72c
8cc7bcaf9d436a12f300638c3cbc77d4e9585008
SHA256
504d27aa26256fff8083cb7563d8bb0123516f1120f8c609ba57d91acf349416
0968de8d650848e2c3e381593e47e4216cfecd45e377264fab976ba214b38fec
541628370c4d4f64468021bd83414efa9ee1634554acf29055c6c1dfa601a5e5
IP
94.131.2[.]59
5.34.176[.]39

















































