Фальшивые NuGet-пакеты под видом .NET-библиотек несут infostealer

Исследователи Socket обнаружили 5 вредоносных NuGet-пакетов, замаскированных под китайские .NET-библиотеки, с рабочим кодом и infostealer.

2026-05-07 GIGATAP Team #security
#supply-chain#nuget#.net

Что обнаружил Socket (и что подтверждено)#

Команда Threat Research Team компании Socket сообщает, что выявила пять вредоносных пакетов NuGet, опубликованных с одного аккаунта. Эти пакеты маскируются под китайские .NET UI- и infrastructure-библиотеки и описываются как «функциональные» библиотеки, которые успешно компилируются, одновременно доставляя payload для кражи информации.

Socket отмечает, что подход оператора не сводится к простому «опечаточному клону популярного публичного пакета» во всех случаях. Вместо этого некоторые package ID, похоже, были специально придуманы так, чтобы напоминать private- или внутренне распространяемые библиотеки, используемые в китайских корпоративных средах. Из-за этого такие имена выглядят вполне «нормально» для разработчиков, работающих внутри этих экосистем.

Один из package name, который выделяет Socket, — DantUI; он описывается как анаграмма из одного символа от AntdUI, WinForms component library под лицензией MIT, поддерживаемой на Gitee. По словам Socket, анализ diff исходников (например, по файлу DantUI/Svg/Transforms/SvgTransform.cs) указывает на технику repackaging: вредоносный пакет основан на декомпилированной копии легитимной библиотеки, а затем обернут в protection/packing, который позволяет скрытому payload вести себя незаметно.

Socket сообщает, что суммарно все версии этих пяти пакетов набрали около 65 000 загрузок. Компания также заявляет, что на момент публикации все пять пакетов все еще были доступны в NuGet и что она отправила запросы на удаление команде безопасности NuGet Gallery.

Как пакеты пытаются выглядеть легитимно#

Ключевая деталь в материале Socket заключается в том, что эти пакеты — не «пустые оболочки». Они содержат рабочий .NET-код в ожидаемых namespace и шаблонах (включая, по описанию Socket, service/infrastructure-паттерны, характерные для внутренних enterprise-библиотек). Это важно по двум причинам:

Во-первых, рабочий код снижает подозрения. Потребитель получает библиотеку, которая ведет себя как обычная dependency: сборка проходит, API существуют, ничего явно не ломается.

Во-вторых, рабочий код делает атаку более устойчивой. Если dependency действительно используется в проекте, ее с большей вероятностью будут повторно восстанавливать, собирать и загружать в разных средах: на рабочих станциях разработчиков, CI/CD runner и build-серверах.

Socket также указывает на поведение при публикации как на часть «маски легитимности». Сообщается, что аккаунт владеет ровно этими пятью package ID и никакими другими, без каких-либо безвредных «прикрывающих» пакетов и без истории, предшествующей этой кампании.

Еще важнее то, что Socket описывает большую version history: всего 224 версии на пять package ID, из которых 219 были unlisted. Unlisted-пакеты NuGet все равно можно установить, если знать точные ID и версию. Иными словами, такие пакеты можно скрыть от случайного обнаружения, при этом они останутся пригодными для использования в средах, где на них уже есть ссылки, особенно если version pinned.

Уклонение через ротацию версий (почему hashes вас не спасут)#

Socket описывает workflow «активного уклонения»: для каждого пакета в листинге в каждый момент времени оставляется только одна версия, а при начале анализа версии ротируются.

Сообщаемая последовательность проста:

  • Определенная версия публикуется в листинге и устанавливается.
  • Как только защитники начинают анализировать и блокировать эту версию (часто по hash), оператор публикует новую версию и снимает с листинга уже проанализированную.
  • Байты DLL меняются от версии к версии, поэтому file-hash IOC очень быстро устаревают.

Socket приводит пример: версия 2.1.55 была опубликована 2026-04-14, после чего произошла ротация к 2.1.56 и 2.1.57, когда анализ уже начался. Также отмечается, что этот паттерн прослеживается и в более широкой истории unlisted-версий, что Socket интерпретирует как признак того, что оператор крутит этот цикл ротации уже несколько месяцев.

Socket также отмечает сигнал, указывающий на «release pipeline»: пять версий были опубликованы последовательно в коротком временном окне и в порядке, учитывающем dependency graph (core-пакеты раньше зависимых). По описанию, время и порядок больше похожи на scripted publishing, чем на ручные, разрозненные загрузки.

Практический вывод: если ваша защита в основном опирается на blocklist известных вредоносных package hash или на проверку одной pinned «безопасной» версии, эта кампания специально рассчитана на то, чтобы обгонять такие меры.

Payload и путь выполнения (по описанию)#

Socket связывает поведение payload с infostealer, защищенным .NET Reactor и встроенным в repackaged-библиотеки. Reactor часто используется как protector/obfuscator; здесь, по словам Socket, он применяется для расшифровки и восстановления method body во время выполнения, а также для сокрытия вредоносной логики от статического анализа.

Socket описывает этап, на котором зашифрованный IL расшифровывается во время JIT. По этому описанию, защищенная assembly:

  • использует .NET module initializer, чтобы код запускался автоматически при загрузке assembly (до запуска логики приложения);
  • выполняет anti-tamper integrity checks с использованием встроенного RSA public key;
  • выделяет память с правами на выполнение (например, через VirtualAlloc(PAGE_EXECUTE_READWRITE));
  • расшифровывает зашифрованный payload blob и устанавливает hook, который получает контроль над