Вредонос FlutterShell: три поколения атак на macOS через злоупотребление Flutter-фреймворком

information security

С декабря 2025 года по март 2026 года злоумышленники из кластера CL-CRI-1089 провели кампанию Operation FlutterBridge, нацеленную на пользователей macOS. Атака использует легитимный фреймворк Flutter для доставки вредоносной нагрузки, маскируясь под обычные приложения - подкаст-плеер, PDF-редактор. Исследователи проанализировали десять бинарных образцов трёх поколений и выявили устойчивые признаки, позволяющие обнаруживать угрозу даже после смены сертификатов, доменов и имён команд.

Описание

Инфраструктура атаки строится на двухкомпонентной модели: небольшой загрузчик Mach-O (около 150 Кбайт) инициализирует среду выполнения Flutter, после чего загружает основную библиотеку-нагрузку (около 10 Мбайт), содержащую Dart-рантайм и логику управления. Вредоносное поведение не зашито в статический образ - команды доставляются с C2-сервера через WebView в виде JavaScript. Без ответа сервера приложение ведёт себя как безобидная программа: открывает интерфейс подкастов или PDF, не проявляя активности. Все исследованные образцы в изолированном запуске не генерировали ни сетевых соединений, ни изменений файлов, ни процессов.

Первый образец (Gen 0/1, декабрь 2025) был подписан сертификатом UBZDAAV97Y, приложение маскировалось под PodcastsLounge. Уже через месяц Apple отозвала сертификат, но злоумышленники заранее получили новый - FW9NHQ8922, выпустив Gen 2 в январе 2026 года под видом PDF-Brain. Третье поколение (март 2026) перешло на самоподписанные сертификаты, отказываясь от нотаризации Apple, что позволило полностью уйти от зависимости от инфраструктуры Apple CA. Промежуток между отзывом и появлением нового поколения составил от 31 до 57 дней.

Как показал анализ бинарных артефактов, все шесть нагрузочных библиотек независимо от поколения и архитектуры (x86_64 или arm64) имеют идентичный экспортированный символьный отпечаток (symhash). Это означает, что злоумышленники переиспользовали одну и ту же базу Flutter-фреймворка, меняя только внутренний код Dart. Данная инвариантность позволяет создать единственное сигнатурное правило, которое сработает на любое будущее поколение, пока не будет заменён сам фреймворк. Кроме того, обнаружена устойчивая опечатка в строке регистрации плагина: plugins.flutter.io/path_providerr (двойная буква r). Она присутствует в первом и третьем поколениях, что даёт дополнительный статический детектор.

Эволюция вредоноса демонстрирует целенаправленное наращивание возможностей и обфускации. Размер нагрузочной библиотеки вырос с 6,75 Мбайт (Gen 1) до 10,04 Мбайт (Gen 2) - прирост почти на 49%, полностью за счёт закрытого Dart-кода. Ни одного нового экспортированного символа добавлено не было. В Gen 3 размер снизился до 8,17 Мбайт благодаря улучшенному tree-shaking, что не означает уменьшения функционала. Количество обфусцированных Dart-символов увеличилось с 92 (Gen 1) до 707 (Gen 3) - на 669%, что подтверждает включение полной обфускации на этапе компиляции. Имена внутренних классов заменены на двух-трёхсимвольные случайные идентификаторы.

Команды моста между JavaScript и нативным кодом переименовывались с каждым поколением: exec_sync → pdf_sync → renderPDF. Последнее название имитирует ожидаемое поведение PDF-приложения. Таким образом, сигнатуры, завязанные на конкретные строки команд, требовали постоянного обновления.

Поведенческий анализ показал, что вредонос использует C2-зависимую модель исполнения. При запуске WKWebView загружает управляемый атакующим сайт, получая скрипты только при наличии живого сервера. В изолированном окружении ни одна из десяти моделей не продемонстрировала вредоносной активности - все 5 сред для Gen 1 и одна для Gen 2 завершились с тайм-аутом по поведению. Это означает, что традиционные песочницы, имитирующие изолированный запуск, неэффективны против данной угрозы.

Зафиксированные техники включают: сбор аппаратного UUID через запуск ioreg дочерним процессом от несистемного приложения, модификацию файла Secure Preferences браузера Chrome для внедрения подставного поискового движка sinterfumesco[.]com, принудительное завершение Chrome с флагами подавления окна восстановления после сбоя, а также установку персистентности через механизм Sparkle - бесшумную замену пакета в кэше и его автоматический запуск.

Злоумышленники использовали три домена C2: atsheisdomestic.org, etoftheappyrince.org и healightejustb.org. В Gen 2 в бинарный файл попали незачищенные отладочные строки, раскрывающие базовый URL и обработку ошибок HTTP 404. Также утечка исходных путей Dart показала, что кодовая база Gen 1 и Gen 2 использует одно и то же внутреннее имя пакета podcasts_lounge, что доказывает прямую преемственность даже при смене внешнего бренда.

Оборонительные рекомендации включают три уровня. Уровень A - поведенческие правила, эффективные независимо от поколения: перезапуск Chrome с флагами подавления и доменом sinterfumesco, запуск ioreg дочерним процессом от несистемного приложения, бесшумная замена пакета Sparkle по характерным путям. Эти сигналы не производятся ни одним легитимным приложением в управляемой среде macOS. Уровень B - статические сигнатуры: правило на инвариантный symhash, правило на строки C2-доменов и правило на опечатку path_providerr. Уровень C фиксирует пробелы: отсутствие сетевого детектирования (домены вращаются), обнаружение самоподписанных приложений с идентификатором io.flutter.flutter.app, а также невозможность перехвата на этапе доставки без телеметрии браузерных кликов.

Кампания Operation FlutterBridge демонстрирует, как злоумышленники эксплуатируют легитимные технологии для маскировки, используя преимущества Flutter-приложений, которые по своей структуре неотличимы от безопасных продуктов. Единственным надёжным способом выявления остаётся endpoint-телеметрия, нацеленная на аномалии в поведении процессов, а не на статические признаки файлов.

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

Domains

  • atsheisdomestic.org
  • etoftheappyrince.org
  • healightejustb.org
  • sinterfumesco.com

SHA256

  • 134517796178a150a1585672be134169d6877082b598d840baa3f37b0222be26
  • 2c5bc9e95e1e9b73e3ba8870a008802899866a2c0e2e10112aefddf7a96af04e
  • 32da1437a2734224406c7e5e8d756f0c0cd58c0c959478571cbfc0cd564d018a
  • 363923500ce942bf1a953e8a4e943fbf1fb1b5ed6e5d247964c345b3ad5bfc34
  • 6c3f61d46d4de26b9cb16808bf17c33ae69f651a4b879e7b5612ff7f548e2a82
  • bf90fb31e6024d7e6616f5acd0e8aa28738a9095a508c1a986e1e974cb9e79a0
  • cc4f048e66c5ab3c0f1d767bb8fc464d082641f4888ea3cd14ea3775077c4bf2
  • f544bfab72d380cc20692d8ec9d31ea666785fe225dccd55beab29a3c0fdfad2
  • fc091ddb4d845280aeb7745cfdb6b7cb0013abc35db9e634f055b8e8fb0b5b1e

YARA

Комментарии: 0