Специалисты по кибербезопасности из Splunk и Netomize представили противоречивые данные о новом образце вредоносного ПО, распространяемом вместе с рекламным приложением CloverPlus. Splunk в своей публикации от 17 апреля 2026 года идентифицировал его как вариант известного семейства Gh0stRat (класс программ для удалённого управления заражённой системой). Однако аналитики Netomize категорически не согласны с такой классификацией, указывая на принципиальные различия в архитектуре, протоколах связи и функциональности. Вместо этого они предложили собственное название - Shulfar, образованное от обратного написания экспортной функции DLL "RAFlush".
Описание
Этот случай примечателен не только спором о родстве с Gh0stRat, но и оригинальной реализацией сетевой коммуникации. Вредонос использует два канала: стандартный HTTP для, вероятно, периодических запросов и собственный протокол поверх TCP с нетривиальным шифрованием. Основное внимание исследователи уделили именно второму каналу, который представляет наибольший интерес для анализа.
Вредонос представляет собой 32-битную DLL, написанную на C. Он упакован, что усложняет статический анализ. Однако ключевые особенности поведения удалось восстановить по дампу памяти и сетевым пакетам. В частности, Shulfar подключается к серверу управления (107.163.56[.]251) на порт 6658 по протоколу TCP. Перед отправкой данные шифруются простым, но эффективным алгоритмом: для каждого байта выполняется операция XOR с ключом (0x64), после чего к результату прибавляется то же значение ключа. Таким образом, для расшифровки достаточно из каждого байта вычесть 0x64 и снова применить XOR с тем же ключом.
Структура пакета фиксирована - 296 байт. В неё входят имя процессора (при неудаче устанавливается "Find CPU Error"), объём физической памяти в мегабайтах, версия операционной системы, уникальный идентификатор "10151338", данные из файла "C:\qylxnhy\lang.ini" (если он существует и содержит ссылку http:// без слова search) либо жёстко заданный адрес сервера "http://107.163.56[.]250:18963/main.php", а также идентификатор языка системы по умолчанию. Последние четыре байта - константа 0xFFFFFFFF. Примечательно, что если данные из файла превышают 128 байт, они перезаписывают остальную часть пакета, что может приводить к повреждению структуры.
Ответ сервера, напротив, не шифруется и не сжимается. Вредонос ожидает команду фиксированного размера - ровно 188 байт. Это типичный подход для ботнетов: минималистичный протокол снижает нагрузку на канал управления и усложняет сигнатурное обнаружение.
Исследователи Netomize опубликовали детальный анализ образца и прилагающийся pcap-файл. Они также продемонстрировали, как модуль YARA в их продукте PacketSmith способен выявлять зашифрованный трафик даже без знания конкретного ключа - за счёт перебора всех возможных значений от 1 до 254. Эта техника позволяет детектировать аномалии, не полагаясь на статическую сигнатуру.
С практической точки зрения появление Shulfar - очередное напоминание о том, что даже простая криптография может быть эффективной, если она применяется в сочетании с нестандартным форматом пакета. Для центров мониторинга информационной безопасности (SOC) это означает необходимость внедрения поведенческих анализаторов трафика, способных распознавать аномалии на уровне транспортных протоколов, а не только заголовков прикладного уровня.
Однако главная ценность данного инцидента - в методологическом споре вокруг классификации. Если Splunk опирался на отдельные сигнатуры, которые могли быть унаследованы от Gh0stRat, то Netomize продемонстрировал, что кодовая база, механика шифрования и даже способ распространения (через рекламное ПО) принципиально отличаются. Ошибки в таксономии вредоносного ПО нередко приводят к неверной оценке угрозы: специалисты могут применять неэффективные контрмеры, полагаясь на старые данные.
Пользователям и корпоративным заказчикам стоит обратить внимание на то, что Shulfar нацелен на сбор системной информации и, вероятно, может выполнять команды с сервера. Вектор распространения через подмену рекламного контента (malvertising) или бандлы с бесплатными приложениями остаётся одним из самых распространённых. Поэтому установка приложений только из официальных источников и отключение ненужных расширений браузера остаются базовыми, но действенными мерами защиты.
В целом, появление Shulfar - не революция, а эволюция угроз. Он не использует сложных техник обхода антивирусов или изощрённых уязвимостей. Его сила в простоте и нестандартности протокола, что делает его обнаружение традиционными средствами затруднительным. Ожидается, что в ближайшее время появятся универсальные правила для систем предотвращения вторжений (IPS) и эвристические анализаторы, нацеленные на подобные шифрованные каналы связи. А пока специалистам по безопасности рекомендуется проверить логи сетевого трафика на предмет соединений с адресами 107.163.56[.]250 и 107.163.56[.]251 на порты 6658 TCP и 18963 TCP (HTTP).
Индикаторы компрометации
IPv4
- 107.163.56.250
- 107.163.56.251
IPv4 Port Combinations
- 107.163.56.251:6658
URLs
- http://107.163.56.250:18963/main.php
MD5
- 20e7a8b973ac2b43c95ddb77308266c9
SHA1
- e46e6ea272ae628d15bfb7b71ff40e3950fd2e85
SHA256
- ec6ef50587a847d4a655e9bfc5c1aee4078005c0774a3e6fa23949cc4d8fbad3
YARA
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | rule shulfar_malware_encrypted_tcp_packet { meta: description = "Detecting Shulfar malware encrypted checkin TCP packet" filter = "Frames (frames:)" sha1 = "e46e6ea272ae628d15bfb7b71ff40e3950fd2e85" reference = "https://www.splunk.com/en_us/blog/security/detecting-ghost-rat-cloverplus-adware-loader-analysis.html" author = "Netomize" date = "04/24/2026" condition: tcp.is_set and math.in_range(port.src, 1024, 65535) // ephemeral ports and tcp.data.size == 296 and for any key in (0..255) : ( for any pos in (tcp.data.offset + 64..tcp.data.offset + 96) : ( ( // check for ' ' (0x20) (((uint8(pos) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x20 and // check for 'M' (0x4D) (((uint8(pos + 1) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x4d and // check for 'B' (0x42) (((uint8(pos + 2) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x42 and // check for null byte (0x00) (((uint8(pos + 3) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x00 ) ) and for any pos in (tcp.data.offset + 96..tcp.data.offset + 128) : ( ( // check for 'W' (0x57) (((uint8(pos) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x57 and // check for 'i' (0x69) (((uint8(pos + 1) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x69 and // check for 'n' (0x6e) (((uint8(pos + 2) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x6e and // check for ' ' byte (0x20) (((uint8(pos + 3) - ((key % 254) + 1)) & 0xff) ^ ((key % 254) + 1)) == 0x20 ) ) ) } |