MS Paint встраивает в ИИ-изображения невидимый водяной знак с сервера

MS Paint встраивает в ИИ-изображения невидимый водяной знак с сервера

Xusheng Li, автор блога о реверс-инжиниринге xusheng.dev, 20 августа 2026 года публикует разбор того, как в Microsoft Paint устроена генерация изображений с помощью ИИ. С помощью Binary Ninja MCP и ассистента Codex автор анализирует бинарники приложения и обнаруживает, что часть генерации выполняется не в облаке, а локальными моделями: в папке Paint лежат четыре файла с расширением .onnxe, seg.onnxe (23,1 МБ), inseg_enc.onnxe (28,0 МБ), inseg_dec.onnxe (16,5 МБ) и mager.onnxe (302,4 МБ). Один файл расшифровывается уже известным ранее XOR-ключом «Microsoft_2023», для трёх остальных в segapi.dll находится новый ключ, буквенно-цифровая строка длиной 4096 байт; после расшифровки все четыре файла проходят проверку onnx.checker.check_model().

В процессе разбора обнаруживается Watermarker.dll размером 1,67 МБ, подозрительно много для функции, которая, судя по интерфейсу Paint, должна отвечать только за видимый водяной знак (небольшой логотип Copilot в углу картинки, включаемый переключателем «никогда / всегда / спрашивать каждый раз»). Как отмечает автор, отчасти на эту мысль навела недавняя новость о текстовом водяном знаке Claude Code. ИИ-ассистент разбирает DLL и находит в ней вторую, отдельную функцию, WmkWriteWatermark, которая вызывается сразу после локальной генерации через Stable Diffusion и принимает ровно 16 байт полезной нагрузки (при другой длине, ошибка). Если WmkWriteWatermark не срабатывает, Paint не возвращает пользователю немаркированную картинку, а превращает всю генерацию в ошибку.

Эти 16 байт оказываются GUID: в обёртке PaintAIManager.dll параметр называется winrt::guid. Обёртка формирует из него 18-байтное (144-битное) сообщение, байт-префикс 0x4c, сам 16-байтный GUID и контрольная сумма (сумма всех 16 байт GUID по модулю 256), и кодирует его в пикселях: каждый из 144 бит должен быть встроен минимум трижды, изображение должно быть не меньше 192×192 пикселей, а сам алгоритм, судя по константам 24.0, 0.25, 0.5 и 0.2 и операциям с матрицами 3×5, похож на адаптивный блочный SVD-водяной знак. На тестовом изображении 512×512 пикселей после встраивания знака изменились 193 376 из 262 144 пикселей.

Источник самого GUID находится выше по стеку вызовов: перед локальной генерацией AIServices.dll отправляет промпт и стиль на сервер Microsoft, POST-запрос на /v1/paint-cocreator/moderate-prompt (домен apsaiservices-a0fqcjc6bzbhgdcd.b02.azurefd.net). В ответ сервер присылает не только промодерированный текст (revisedPrompt), но и два GUID, promptGenerationId и watermarkId, и флаг containsHumanReference. Xusheng Li проверяет это вживую, переиспользуя авторизованную сессию Paint: на тестовый промпт «кобальтово-синий кружок над маленьким оранжевым квадратом» сервер возвращает watermarkId 83424621-03cb-40e3-9808-a9fae837156d, а на промпт с изображением человека, другую пару GUID и containsHumanReference: true. Именно этот присланный сервером watermarkId и оказывается тем значением, которое затем зашито в пикселях, то есть «локальная» генерация всё равно зависит от сетевого похода к Microsoft.

На этом совпадения не заканчиваются. Paint также подписывает сохранённый файл метаданными C2PA (Content Credentials) через ProvenanceHelper.dll. Изучая реально сохранённый PNG из Image Creator, автор находит сразу после блока IHDR чанк caBX размером 18 979 байт с подписанным манифестом C2PA. Внутри, блок c2pa.soft-binding с алгоритмом com.microsoft.invismark.1 и значением 83424621-03cb-40e3-9808-a9fae837156d, тем же GUID, что и в пикселях. То есть пиксельный водяной знак и файловые метаданные, это две проекции одной и той же серверной записи модерации: даже если манифест вырезать из файла, идентификатор всё равно можно извлечь из самих пикселей (в терминологии C2PA это называется «мягкой привязкой», soft binding).

Архитектура объясняет, зачем вообще понадобился локальный водяной знак. У Paint два разных пути генерации: облачный Image Creator на Azure OpenAI ImageGen может сразу вернуть готовую картинку с уже наложенным знаком и подписью; а Cocreator на Copilot+ PC генерирует изображение локально на NPU, но модерация промпта и последующая онлайн-подпись данных о происхождении (provenance) всё равно идут через сеть, так что «локально» не значит «офлайн» ни в одном из двух случаев. Это же объясняет и ограничение на форматы сохранения: экспортировать ИИ-картинку из Paint можно только в PNG, JPEG, GIF или собственном формате .paint, все они умеют хранить манифест C2PA; классический BMP, который этого не умеет, для таких файлов недоступен.

Тот же Watermarker.dll находится и в приложении Microsoft Photos (версия 2026.11060.2004.0), там он используется в функциях Image Creator и Restyle Image по такой же схеме. Разница в одном: если функция встраивания знака возвращает ошибку, Photos лишь пишет её в лог и, судя по коду, всё равно отдаёт пользователю изображение, тогда как Paint в такой ситуации проваливает всю генерацию целиком.

Публичная страница поддержки Image Creator у Microsoft раскрывает часть картины: там сказано, что компания «применяет фильтрацию контента, чтобы предотвратить генерацию изображений», и что сгенерированные изображения «будут содержать манифест C2PA, помогающий пользователям определить, что это изображение создано ИИ». Но, как отмечает Xusheng Li, объяснения тому, что именно скрывается в этом манифесте GUID, привязанный к конкретному запросу модерации, и что тот же идентификатор незаметно встроен в сами пиксели, найти не удалось.

Несколько вопросов в материале сознательно остаются открытыми. Если облачный эндпоинт генерации можно каким-то образом заставить вернуть картинку до того, как к ней применены водяной знак и подпись C2PA, было бы это уязвимостью, недосмотром или заложенным поведением, Xusheng Li не берётся судить, не зная замысла Microsoft. Материал также осторожно связывает находку со статьёй 50 Закона ЕС об ИИ, которая вступила в силу 2 августа 2026 года и требует заметной машиночитаемой метки на ИИ-контенте (но не привязанного к промпту GUID), называя эту связь лишь возможной, не подтверждённой. Технически изменить Paint или Photos так, чтобы обойти и модерацию, и водяной знак, судя по всему, возможно, но, как отмечает автор, ничего принципиально нового это не даёт: Stable Diffusion и так можно запустить напрямую, в обход обоих механизмов. Сколько именно Microsoft хранит промпты, GUID и связь между ними на своих серверах, в статье не указано. По словам Xusheng Li, это первое известное автору исследование, которое задокументировало именно невидимую маркировку Paint и Photos, сами по себе видимые ИИ-водяные знаки (у Microsoft 365, Bing Image Creator) и невидимые (SynthID у Google, скрытый знак Bing) не новы.

Ключевые факты

  • Прежде чем сгенерировать изображение локально, Paint и Photos отправляют промпт на сервер модерации Microsoft; в ответ сервер присылает не только одобренный текст, но и уникальный GUID (watermarkId).
  • Этот GUID отдельная DLL, Watermarker.dll (1,67 МБ), незаметно кодирует в пикселях готового изображения; это отдельный механизм от видимого логотипа Copilot, у которого свой переключатель «никогда / всегда / спрашивать каждый раз».
  • Тот же самый GUID Microsoft повторно записывает в подписанные метаданные C2PA файла, поле c2pa.soft-binding с алгоритмом com.microsoft.invismark.1, так что пиксельный знак и файловые метаданные привязаны к одной и той же записи модерации.
  • Paint требует успешной вставки водяного знака как условия генерации: при сбое Watermarker.dll всё создание изображения завершается ошибкой; Photos в такой ситуации, судя по коду, лишь пишет ошибку в лог и всё равно отдаёт изображение.
  • Публичная страница поддержки Microsoft упоминает фильтрацию промптов и метаданные C2PA в общих словах, но не объясняет, что за ними стоит GUID, привязанный к конкретному запросу модерации и вшитый прямо в пиксели.

Почему это важно

История показывает разрыв между обещанием «локальной» генерации и тем, как она устроена на самом деле. Даже когда картинка технически рисуется на устройстве (NPU в составе Copilot+ PC), сам процесс всё равно требует сетевого похода к серверу Microsoft, за проверкой промпта и за GUID, которым потом помечается результат. Причём этот знак не декоративный: 144-битное сообщение встраивается избыточно (каждый бит, минимум трижды) и дублируется в подписанных метаданных файла, то есть переживает обычное сохранение и остаётся связанным с конкретной серверной записью модерации даже после экспорта. Это пример более широкого архитектурного паттерна, «гибридного» ИИ-продукта, где локальный компонент не отменяет сетевую зависимость и отчётность перед сервером вендора, который стоит иметь в виду и за пределами Paint, особенно на фоне растущих регуляторных требований к маркировке ИИ-контента.

Кому это важно

Владельцам Windows и особенно Copilot+ PC, которые пользуются генерацией изображений в Paint (Cocreator, Image Creator) и Photos (Image Creator, Restyle Image); всем, кто относится к «локальной» генерации как к операции без выхода в сеть и без следа на стороне вендора; специалистам по приватности и безопасности, как конкретный кейс того, как маркировка ИИ-контента реализована технически «под капотом» у крупного производителя; регуляторам и юристам, формулирующим требования к маркировке ИИ-контента (например, статью 50 Закона ЕС об ИИ), материал показывает, что заметная «метка» на практике может оказаться куда информативнее и персонализированнее, чем просто факт «это сделал ИИ».

Как это применить

Практический вывод для пользователя: переключатель видимого водяного знака в Paint («никогда / всегда / спрашивать каждый раз») не отключает второй, невидимый слой, тот встраивается безусловно при каждой успешной локальной генерации. Убрать привязку штатными средствами тоже не получится: приложение не даёт сохранить ИИ-картинку в формате без поддержки C2PA (классический BMP недоступен для таких файлов), только в PNG, JPEG, GIF или .paint. Для тех, кто занимается похожим реверс-инжинирингом, статья показывает рабочую методику: связка Binary Ninja MCP с ИИ-ассистентом для трассировки вызовов в закрытых DLL, плюс проверка гипотезы прямым запросом к боевому эндпоинту через авторизованную сессию самого приложения и разбор PNG-чанков реально сохранённого файла.

Можно ли доверять

Материал, не пресс-релиз и не догадка, а прямой разбор бинарников: названы конкретные DLL и функции (Watermarker.dll, WmkWriteWatermark, ParseModerateResponse), приведена структура полезной нагрузки на уровне байт. Ключевой вывод, что GUID из ответа сервера модерации оказывается тем же значением, что и в пикселях, и в C2PA-метаданных, подтверждён не только статическим анализом, но и живым запросом к серверу Microsoft с реальным ответом, а также разбором PNG-чанков файла, действительно сохранённого из Paint. При этом материал сам аккуратно разделяет факты и предположения: поведение Photos при сбое водяного знака описано с оговоркой «судя по всему», связь с Законом ЕС об ИИ названа лишь возможной, а вопрос, можно ли считать обходимость водяного знака багом, недосмотром или уязвимостью, оставлен открытым, без знания намерений Microsoft ответить на него нельзя. Профессиональная принадлежность автора и возможные связи с Microsoft в тексте не раскрыты; подтверждения или реакции от самой Microsoft материал не приводит.

Риски и подводные камни

Главный риск для пользователя, иллюзия приватности: «локальная» генерация в Paint и Photos всё равно требует аккаунта Microsoft и сети, а итоговая картинка несёт постоянный идентификатор, связанный на сервере с конкретным промптом; при этом неизвестно, сколько времени Microsoft хранит сами промпты, GUID и связь между ними, материал этот срок не называет. Отдельный риск отмечает сам автор: если облачный путь генерации можно заставить вернуть картинку до применения водяного знака и подписи C2PA, например, обратившись к эндпоинту напрямую, можно получить изображение вовсе без обеих меток; является ли это осознанным решением Microsoft, недосмотром или уязвимостью, снаружи определить нельзя. Технически возможно изменить сам клиент Paint или Photos так, чтобы обойти и модерацию, и водяной знак, но это не даёт ничего нового: Stable Diffusion и так можно запустить напрямую в обход обоих механизмов. Наконец, предполагаемая связь истории со вступившей в силу 2 августа 2026 года статьёй 50 Закона ЕС об ИИ, лишь гипотеза, а не подтверждённый факт: сама статья требует заметной машиночитаемой метки на ИИ-контенте, но не привязанного к промпту GUID.

«Сгенерированные изображения будут содержать манифест C2PA, помогающий пользователям определить, что это изображение создано ИИ.»

— Microsoft, страница поддержки Image Creator