返回

文章详情

MS Paint 和 Photos 在本地生成的输出中隐形水印带有 GUID

Hacker News2026年8月24日 15:28

逆向工程揭示了 Paint 和 Photos 如何将服务器颁发的 GUID 嵌入到本地生成的 AI 图像的像素中。概述:微软 Paint 支持本地和云图像生成;Paint 和 Photos 还提供本地 AI 模型;两个应用将提示发送到远程服务器进行审核;服务器返回一个 GUID 以及经过审核的提示;该 GUID 作为隐形水印嵌入到本地生成的图像中;单独的可见水印设置无法控制该隐形水印;在 Copilot+ 电脑上,图像生成是本地的,但提示审核仍然是远程的;微软披露 Paint 向 AI 生成的图像添加了 C2PA 元数据;仅限于 C2PA 保存格式的 AI 生成图像保存:PNG、JPEG、GIF 和 .paint。对微软 Paint 的好奇:这项研究的开始源于我对 Paint 的好奇。我最近在探索一些不太被关注的 Windows 功能时取得了一些成功,比如 UCPD、WHESCVC,我早就知道微软在 Paint 应用中添加了一些 AI 功能。我不知道是否有人实际使用 Paint + AI 生成图像,但我想了解图像生成的具体工作原理。在开始之前,我预计它仅仅是调用一个远程 API 来进行图像生成。然而,在我使用 Binary Ninja MCP 和 Codex 进行分析并设置完成后,我很快意识到微软实际上在 Windows 中作为 Copilot 的一部分提供了本地模型。Paint 应用位于以下路径(是的,现在它们都是 Windows 应用):C:\Program Files\WindowsApps\Microsoft.Paint_11.2605.71.0_x64__8wekyb3d8bbwe\PaintApp\; 而且有四个明显的模型文件,扩展名为 .onnxe:seg.onnxe 23.1 MB; inseg_enc.onnxe 28.0 MB; inseg_dec.onnxe 16.5 MB; mager.onnxe 302.4 MB。seg.onnxe 的格式之前已知,即,当其与字符串 Microsoft_2023 进行异或运算时,变成一个正常的 ONNX 文件。然而,其余三个 .onnxe 文件的格式最初看起来不同。结果发现,微软并没有更改算法,只是更改了密钥。segapi.dll 包含一个小的密钥注册表:ps_enc_key.1.0.80-main -> "Microsoft_2023"; ps_enc_key.1.0.81-main -> 一个4096字节的字母数字字符串。解密后,onnx.checker.check_model() 在它们上都能正常工作:模型图 seg.onnx 有 1094 个节点,输入为 input_image,输出为 output;inseg_enc.onnxe 有 1014 个节点,输出为 image_embeddings; inseg_dec.onnxe 有 1133 个节点,输入为 embeddings、points 和 masks;输出为 masks; mager.onnxe 有 15284 个节点,输入为 image/mask;输出为 output。一个可见的水印:在浏览这些文件时,我发现了一个 Watermarker.dll:这对我来说并不十分惊讶,因为在与 Paint 应用交互时,我已经发现它有一个设置,可以将可见水印嵌入到生成的图像中:可见水印只是图像右下角的一个小 Copilot 徽标,这非常正常。然后,突然之间,我决定请 AI 分析这个 DLL,看看它是否也可以嵌入一个隐形水印。这是我作为反向工程师的直觉,因为该文件的大小为 1.67 MB,对于如此简单的功能来说大得不寻常(可以说,可见水印甚至不需要单独的 DLL)。显然,最近 Claude Code 文本水印的公告也促使我考虑这种可能性。一个隐形水印:首先, visible watermark 通过 AddPerceptibleWatermark 添加: CPBDoc::Save(...) | `-- perceptible-watermark save helper(bitmap, WatermarkSetting) | +-- WatermarkSetting::Never | `-- return the original bitmap | +-- WatermarkSetting::AskEveryTime | `-- display Yes / No confirmation popup | +-- No: return the original bitmap | `-- Yes: continue | `-- Always or confirmed Yes +-- Paint::AI::GetPerceptibleWatermarkSvg() `-- Paint::AI::AddPerceptibleWatermark(bitmap, SVG stream) `-- composite the visible Copilot logo;然后还有一个不同的 WmkWriteWatermark 函数: Watermarker.dll ! WmkWriteWatermark ( output_pixels, payload, payload_length, width, height, stride, input_pixels, pixel_format); 追踪调用树,可以看到 WmkWriteWatermark 在局部稳定扩散图像生成后被调用。如果 WmkWriteWatermark 失败,Paint 将整个生成转换为错误,而不是返回没有它的图像: CocreatorViewModel::GenerateImageAsync(...) | `-- Paint::AI::StableDiffusionHelpers::GenerateAsync(..., watermarkId, ...) | `-- Microsoft.ImageCreation.ImageGenerator | `-- NPU 生成的图像结果 | +-- output safety/moderation checks | +-- Paint::AI::AddWatermark(bitmap, watermarkId) | | | `-- Watermarker.dll!WmkWriteWatermark(...) | | | +-- success: return the watermarked bitmap | `-- failure: turn generation into an error | `-- construct successful StableDiffusionResult; 然后自然地要问,传入的有效载荷实际上是什么。很快就很明显,它必须是16个字节的: if (payload_length < 16) return -6; if (payload_length > 16) return -1; ...

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡