SLEEPWALKER маскируется под модуль ESET Management Agent и просыпается только от одного пакета
Независимый исследователь малвари Доминик Райхель (это имя указано в метаданных YARA-правила в конце поста; в основном тексте статьи он пишет от первого лица без подписи) выложил 24 августа 2026 года на своём блоге r136a1.dev разбор нового бэкдора под именем SLEEPWALKER. Толчком стала потеря доступа к VirusTotal Intelligence в начале года: вместо охоты за новыми образцами Райхель разобрал старые находки, накопившиеся с прошлого года, и наткнулся на файл, который на первый взгляд не выделялся ничем особенным. SLEEPWALKER оказался пассивным бэкдором. Он не открывает слушающий порт, не хранит внутри готовой полезной нагрузки и попросту ничего не делает, пока по сети не придёт один конкретно заданный пакет.
Проанализированный образец, 64-битная DLL для Windows размером 59 904 байта, собранная 10 июня 2024 года. Она выдаёт себя за системную библиотеку dpapi.dll: несёт скопированные у ESET данные версии (CompanyName, ESET, ProductName, ESET Management Agent) и экспортирует те же семь функций, что и настоящая dpapi.dll. Цель, подгрузиться вместо неё в процесс ERAAgent.exe, исполняемый файл ESET Management Agent, компонента ESET PROTECT и ESET PROTECT On-Prem, с помощью техники DLL side-loading. Проверка при этом на удивление простая: бэкдор смотрит только на имя процесса, а не на подпись файла или путь к нему, теоретически он заработает в любом процессе с именем ERAAgent.exe. При первом обращении к любой из семи экспортированных функций резолвер пытается подгрузить несуществующую в Windows dpapisvc.dll, и если это не получается, убивает весь хост-процесс целиком. Автор сам называет реализацию неидеальной: к перехватчику команд ведут два независимых пути, через загрузку DLL и через тот самый первый вызов DPAPI-функции, и ни один не проверяет, отработал ли уже другой путь, так что в теории оба могут запуститься параллельно.
У бэкдора нет ни одного захардкоженного сервера, домена или IP-адреса: вместо обычного маячка на управляющий сервер он переводит сетевую карту в неразборчивый режим и слушает сразу до восьми интерфейсов, пропуская loopback-интерфейс. Каждый пакет проходит проверку в шесть шагов: не короче 48 байт; из двух последних 16-битных значений через XOR, а затем ещё раз XOR с константой 0xAAAA получается «длина-кандидат»; эта длина должна попадать в допустимый диапазон; байтовая пара на позиции (длина пакета минус длина-кандидат) должна равняться не XOR, а именно сумме тех же двух значений; блок, на который указывает длина-кандидат, обязан пройти свою проверку CRC-32, и только тогда данные расшифровываются AES-256-CCM с проверкой тега подлинности. Не прошёл хоть один шаг, пакет молча выбрасывается без ответа, так что у бэкдора нет ни открытого порта, ни заметной сигнатуры сканирования. После удачного срабатывания SLEEPWALKER ждёт не меньше трёх секунд, прежде чем принять следующий пакет, в основном чтобы не сработать на один и тот же пакет дважды. Второй, скрытый канал доставки того же триггера, через DNS-запросы: команда кодируется Base32 поверх AES-256-CCM и разбивается по меткам домена, а подлинность метки подтверждает контрольная сумма CRC-8. В проанализированном образце этот канал не включён, встроенная стартовая команда запускает только «сырой» пакетный слушатель, но Райхель сам собрал и проверил работающий DNS-триггер, чтобы показать, что механизм рабочий.
Как только пакет проходит все шесть проверок, расшифрованные байты, это не текстовая команда, а программа на собственном языке SLEEPWALKER из 23 инструкций: каждая начинается с байта-опкода, а поля переменной длины (текст, блоки данных, вложенные программы) несут перед собой счётчик байт. Язык поддерживает базовое управление (EXIT останавливает сразу все запущенные программы и сам слушатель, а не только текущий поток), таймеры и планировщик, включая CRON_SCHEDULE, где вложенная программа хранится между запусками в виде, замаскированном простым XOR, и расшифровывается только на момент исполнения, отправку данных по TCP, UDP, ICMP и именованным каналам SMB (в том числе с логином и паролем для перемещения по сети), приём входящих задач и отдельно, сборку и запуск программ: поэтапную запись во временный буфер на 128 КБ с проверкой уже собранных байт по SHA-256, распаковку сжатых данных и запуск шеллкода прямо в памяти, где страница переводится из «доступна для записи» в «доступна для исполнения» непосредственно перед вызовом. Сетевых транспортов в сумме шесть: TCP, UDP, ICMP, именованные каналы SMB, приём «сырых» пакетов в неразборчивом режиме (им же ловится сам триггер) и отдельно, канал VMware VMCI для связи между гостевой машиной и хостом, который вообще не выходит на физический сетевой адаптер и поэтому не виден ни одному перехвату трафика.
Чтобы именованные каналы принимали подключения без авторизации, SLEEPWALKER включает параметр EveryoneIncludesAnonymous и добавляет запись в NullSessionPipes, а свои каналы создаёт с правами для Everyone и Anonymous Logon. Откатить эти изменения бэкдор пытается, но небрежно: он запоминает, что запись в NullSessionPipes добавил именно он, а не то, существовала ли она до заражения, поэтому очистка иногда стирает чужую легитимную запись. Привилегии при этом SLEEPWALKER не повышает вообще: обе правки реестра и так требуют прав локального администратора, которые уже есть у процесса ERAAgent.exe, а единственный механизм закрепления, оставаться в той же папке, чтобы агент ESET подгружал поддельный dpapi.dll заново при каждом своём перезапуске.
В самом файле нашлась только одна реально записанная и зашифрованная команда, слушать все интерфейсы бесконечно в ожидании триггера. Всё остальное, что описано в посте, это возможности языка, а не то, что кто-то реально отправил на заражённую машину. Райхель прямо пишет, что не нашёл более ранних публикаций про этот бэкдор, детект антивирусами на момент публикации оставался низким, а атрибутировать находку он не может: похожего кода он раньше не встречал. Он не знает, кто стал жертвой, как файл попал на машину, и не может даже подтвердить, что образец где-то сработал по-настоящему. В приложении к посту, YARA-правило, каждая строка которого проверена на самом образце, и PowerShell-скрипт, который только читает систему, ничего не меняет и возвращает код 0, 1 или 2 в зависимости от того, ничего ли не нашлось, требует ли реестр ручной проверки или хеш совпал точно (SHA-256 образца: d347170752a28e2b8c4b8b9f3cab2e3a6541ba11682c94498d26eb9002779d60). Отдельно Райхель выложил набор инструментов для работы с байткодом, веб-конструктор и декодер команд, CLI-декодер и honeypot, имитирующий все каналы приёма SLEEPWALKER без реального исполнения чего-либо, и сам образец в архиве с паролем для тех, кто хочет проверить разбор самостоятельно.
Отдельный раздел поста, про то, как автор использовал ИИ при разборе. Первый проход по SLEEPWALKER и другим образцам из своих старых находок он сделал вручную, а детальный анализ и проверку доверил моделям: в сравнении участвовали Claude Opus 5 и GPT-5.6-Sol, а на Opus 4.8 и Sonnet 5 Райхель переключался, когда защитные ограничения останавливали Opus 5 в середине работы. Kimi K3 он хотел добавить, но пока не получил доступ, а Fable исключил, потому что в его тестах фильтры этой модели блокировали даже общие вопросы с потенциально двойным назначением. На самом SLEEPWALKER результаты у Claude и GPT-5.6-Sol получились в целом близкими, где-то точнее оказывался один, где-то другой, явного лидера автор не называет. Разошлись они заметно один раз: на паре опкодов SNIFF_MAGIC_PACKET (0x87) и SNIFF_MAGIC_PACKET_DNS (0x88) три отдельные попытки подряд Claude называл функционально одинаковыми, а GPT с первой попытки правильно указал, что 0x88 дополнительно включает DNS-триггер. На более широком наборе образцов разница вышла резче: недельная квота GPT подошла для долгих сессий реверс-инжиниринга лучше, чем часовой лимит Claude, и ни один тест на GPT не прерывался отказом по безопасности, хотя автор не участвует в программе Trusted Access for Cyber. С Claude вышло наоборот: рано или поздно отказ случался в каждом прогоне анализа малвари на Opus или Sonnet, несмотря на то что Райхеля приняли в Cyber Verification Program, отдельную программу Anthropic именно для такой работы. Свою позицию он формулирует прямо: Anthropic стоило бы жёстче отбирать участников подобных программ, но зато меньше ограничивать тех, кого уже одобрили, в легитимном реверс-инжиниринге. Итоговая оценка у него сдержанная: ИИ ощутимо ускоряет анализ малвари и помогает оформлять находки в читаемый текст, но результат всё равно приходится сверять с кодом вручную.
Ключевые факты
- SLEEPWALKER, пассивный бэкдор без управляющего сервера и встроенной полезной нагрузки: слушает до восьми сетевых интерфейсов и включается только от одного пакета, который проходит шестишаговую проверку длины и контрольных сумм (CRC-32) перед расшифровкой AES-256-CCM.
- Файл, 64-битная DLL на 59 904 байта, собранная 10 июня 2024 года; она выдаёт себя за библиотеку dpapi.dll с данными версии ESET Management Agent и подгружается в процесс ERAAgent.exe вместо неё техникой DLL side-loading, проверяя при этом только имя процесса.
- После срабатывания триггера SLEEPWALKER исполняет программу на собственном байткод-языке из 23 инструкций: планировщик, поэтапная сборка с проверкой по SHA-256, запуск шеллкода прямо в памяти и шесть сетевых транспортов, включая именованные каналы SMB и скрытый канал VMware VMCI, не выходящий на физическую сеть.
- В самом файле нашлась только одна зашифрованная команда, слушать вечно; альтернативный скрытый канал триггера через DNS (Base32 поверх AES-256-CCM, контрольная сумма CRC-8) реализован, но не включён, автор сам собрал и проверил рабочий пример.
- Сравнивая Claude Opus 5 и GPT-5.6-Sol как ассистентов в разборе малвари, автор пишет: ни один тест на GPT не прервался отказом по безопасности, а в Claude отказ в итоге случался в каждом прогоне анализа, хотя автора приняли в Cyber Verification Program от Anthropic.
Почему это важно
SLEEPWALKER показывает, насколько незаметным может быть бэкдор, если отказаться от привычной связки «слушающий порт плюс сервер управления». Файл неделями сидит в памяти процесса ESET Management Agent и не делает вообще ничего, пока по сети не придёт один конкретный пакет, обычный мониторинг исходящих соединений и обращений к вредоносным доменам здесь попросту не с чем сопоставлять. К этому добавляется собственный байткод-язык команд: даже восстановив ключ шифрования, аналитик получает не читаемую команду, а набор опкодов, смысл которых нужно реверсить отдельно. По оценке автора, сочетание пассивного триггера, редкого канала VMware VMCI и side-loading в доверенный процесс ESET больше похоже на прицельную, хорошо подготовленную операцию, чем на массовую рассылку, хотя именно «сырой» вариант триггера требует, чтобы у оператора уже был доступ к сети жертвы или к соседней с ней машине. Заодно пост даёт редкий количественный срез того, как реальный исследователь использует Claude и GPT-5.6-Sol в задаче двойного назначения, и вывод у него не в пользу Claude.
Кому это важно
В первую очередь, специалистам по безопасности в организациях, где развёрнут ESET PROTECT или ESET PROTECT On-Prem: SLEEPWALKER садится ровно в процесс ERAAgent.exe, который такие компании и так держат в списке доверенных. Дальше, реверс-инженерам, которым интересен сам дизайн: собственный командный язык, поэтапная сборка программы в памяти с проверкой по SHA-256, скрытый канал через VMware VMCI. И отдельно, тем, кто следит, как исследователи безопасности используют большие языковые модели в работе двойного назначения: у автора есть доступ к Cyber Verification Program от Anthropic, но именно на Claude он не смог довести до конца ни один длинный анализ малвари без отказа, тогда как GPT-5.6-Sol не прервал ни разу.
Как это применить
У поста готовый набор индикаторов: SHA-256 файла d347170752a28e2b8c4b8b9f3cab2e3a6541ba11682c94498d26eb9002779d60, лишний dpapi.dll рядом с ERAAgent.exe, несуществующий в Windows dpapisvc.dll там же, включённый EveryoneIncludesAnonymous и посторонняя запись в NullSessionPipes. Для проверки Райхель выложил в приложении YARA-правило и PowerShell-скрипт, который только читает систему: он возвращает 0, если ничего не найдено, 1, если нужна ручная проверка реестра или файла, и 2, при точном совпадении хеша. Отдельно опубликован набор инструментов для анализа самого байткода, веб-конструктор с декодером команд, CLI-декодер и honeypot, который изображает все каналы приёма SLEEPWALKER, ничего не исполняя, а также сам образец в защищённом паролем архиве для тех, кто хочет проверить находку самостоятельно.
Можно ли доверять
Технически разбор выглядит основательно: под каждый опкод есть таблица параметров и пример, разобранный по байтам, ключ шифрования и nonce приведены буквально, а YARA-правило и скрипт автор проверял на самом образце, а не только в теории. Но у анализа есть чёткая граница, и Райхель её не прячет: в файле нашлась только одна реальная команда, «слушать вечно», всё остальное, планировщик, шесть транспортов, DNS-триггер, это возможности языка, ничем не подтверждённые в реальном использовании. Жертва, страна, отрасль, способ первого проникновения и принадлежность к какой-либо группировке неизвестны; автор прямо пишет, что не может даже подтвердить, что образец где-то реально сработал. К разделу про ИИ тоже стоит отнестись как к личному опыту одного исследователя на одном наборе образцов, а не как к бенчмарку: сам он говорит, что на SLEEPWALKER Claude и GPT-5.6-Sol показали близкий результат, и выделяет только один конкретный промах Claude на опкодах 0x87/0x88, на фоне картины отказов, которая относится уже к более широкому набору образцов, а не к одному этому файлу. Сам Райхель также не исключает, что перед ним ранняя версия и где-то уже существуют более новые, доработанные сборки.
Риски и подводные камни
Сам бэкдор не поднимает привилегий, обе правки реестра и так требуют прав локального администратора, которые процесс ERAAgent.exe уже имеет, но он ослабляет хост: включает анонимный доступ по SMB и открывает свои именованные каналы для Everyone и Anonymous Logon. Откат этих изменений в коде есть, но сделан небрежно: он помнит, что запись в NullSessionPipes добавил именно он, а не то, была ли она там до заражения, так что очистка может случайно удалить чужую легитимную запись. DNS-канал триггера в этом образце выключен, но реализован полностью: включи его, и пакет для «пробуждения» бэкдора сможет пройти через файрвол и NAT, которые остановили бы «сырой» вариант. И отдельно стоит взвесить предложение автора к Anthropic: смягчить ограничения для одобренных исследователей Cyber Verification Program он подаёт как способ не срывать долгие сессии, но по сути это просьба меньше контролировать именно ту часть работы с ИИ, где двойное назначение выражено сильнее всего, разбор боевого вредоносного кода.
«На мой взгляд, Anthropic стоит жёстче проверять кандидатов в такие программы, как Cyber Verification Program, и взамен меньше ограничивать уже одобренных исследователей, когда они занимаются легитимным реверс-инжинирингом.»
— Доминик Райхель, автор разбора SLEEPWALKER на r136a1.dev