2026 年 8 月 20 日,一篇发布在安全研究博客 xusheng.dev 上的逆向分析报告指出,Windows 11 的画图(Paint)和照片(Photos)应用在保存 AI 生成图像时,会把一个由微软服务器下发的 GUID(全局唯一标识符)以隐形水印的形式写进图像像素。这项研究登上 Hacker News 首页后引发讨论,核心争议在于:本地生成的图像,也会携带一个与远程内容审核绑定的唯一标识。

这项分析覆盖了画图应用的完整生成链路。以下按逆向工程的推进顺序拆解这套机制。
画图内置的本地模型
分析从画图应用的安装目录开始。画图现在位于 C:\Program Files\WindowsApps\Microsoft.Paint_11.2605.71.0_x64__8wekyb3d8bbwe\PaintApp\,目录内有四个 .onnxe 扩展名的模型文件:
| 文件 | 大小 | 解密后 ONNX 图 |
|---|---|---|
| seg.onnxe | 23.1 MB | 1,094 节点,输入 input_image |
| inseg_enc.onnxe | 28.0 MB | 1,014 节点,输出 image_embeddings |
| inseg_dec.onnxe | 16.5 MB | 1,133 节点,输出 masks |
| mager.onnxe | 302.4 MB | 15,284 节点,图像/掩码输入 |
.onnxe 是微软对 ONNX 模型做的异或加密。早期版本的 seg.onnxe 用字符串 Microsoft_2023 异或即可还原为标准 ONNX;新版本换了密钥,segapi.dll 内的注册表项 ps_enc_key.1.0.81-main 指向一个 4,096 字节的字母数字串。解密后 onnx.checker.check_model() 全部通过。其中 302 MB 的 mager.onnxe(15,284 节点)即本地 Stable Diffusion 图像生成模型,在配备 NPU 的 Copilot+ PC 上于设备端完成推理。
可见水印背后的第二个 DLL
画图的设置里有一项「AI 生成内容是否包含水印」,提供 Never、Always、Ask every time 三个选项,控制的是右下角那个 Copilot 标志的可见水印。

真正引起研究者注意的是另一个文件:随画图分发的 Watermarker.dll,体积 1.67 MB。给"在图上叠一个 logo"这种功能配一个独立 DLL 且体积达 MB 级,超出了正常需要。逆向分析确认了这个直觉:这个 DLL 负责嵌入一枚肉眼不可见的水印,与上述设置无关。
16 字节 GUID 如何写进像素
可见水印由 AddPerceptibleWatermark 叠加 SVG 完成,流程清晰。另一条独立路径调用 WmkWriteWatermark,发生在本地 Stable Diffusion 生成之后。函数签名要求一个 16 字节的 payload,长度校验写得颇为讲究:短于 16 字节返回 -6,长于 16 字节返回 -5,随后无视长度参数、按硬编码的 16 次循环拷贝。
这个 16 字节 payload 后来被证实是 GUID。WmkWriteWatermark 的包装层构造一条 18 字节(144 比特)的消息:
0x4c || GUID[0..15] || (16 字节 GUID 的求和模 256)编码器的嵌入策略可以概括为:
- 将可用图像尺寸向下取整到 8 的倍数,维护 144 个比特计数器
- 对选中的图像块做量化修改,内含 3×5 矩阵运算和矩阵分解例程,使用 24.0、0.25、0.5、0.2 等常数,属于内容自适应的块域 SVD 风格水印
- 要求 144 个比特中每一比特至少成功放置三次,容量不足时返回 -8
- 要求图像宽高均不小于 192 像素
研究者用一张合成的 512×512 BGRA 图像直接调用该函数验证:262,144 个像素中有 193,376 个(约 73.8%)在嵌入后发生了变化。单像素变化幅度极小,肉眼无从分辨,但信息确实写进了像素。
更关键的细节在调用链上游:如果 WmkWriteWatermark 失败,画图会把整次生成转换为错误,不会把未打水印的图像交给用户。
GUID 来自远程审核
水印 payload 从哪里来?沿调用链回溯,Paint::AI::AddWatermark(Gdiplus::Bitmap&, winrt::guid const&) 的签名暴露了 GUID 类型。继续追到 AIServices.dll,答案明确:在本地模型推理之前,画图会先把提示词发送到微软的审核服务。
POST https://apsaiservices-a0fqcjc6bzbhgdcd.b02.azurefd.net/
v1/paint-cocreator/moderate-prompt
请求: { prompt, style, lastPromptGenerationId }
响应: { revisedPrompt, promptGenerationId,
watermarkId, containsHumanReference }响应中的 watermarkId 就是最终嵌入像素的 GUID。研究者复用画图自身的已认证会话,向该端点发送提示词 "a cobalt blue circle above a tiny orange square",服务器返回 HTTP 200,watermarkId 为 83424621-03cb-40e3-9808-a9fae837156d。换一条包含人物的提示词后,返回的 GUID 不同,且 containsHumanReference 变为 true,说明服务器同时完成了提示词是否涉及人物的分类。
ParseModerateResponse 把两个 ID 字符串解析为 GUID 并拒绝零值。下一次请求还会把上一次的 promptGenerationId 作为 lastPromptGenerationId 回传,使连续请求可以被显式关联。在 Copilot+ PC 上,图像生成在设备端 NPU 完成,但提示词审核始终经由网络。
像素水印与 C2PA 清单是同一套体系
画图保存 AI 生成图像时还会附加 C2PA Content Credentials,由 ProvenanceHelper.dll 和 provenancesdk.dll 处理。本地生成路径的签名流程是:把 PromptGenerationId、生成种子、创造力等级和审核评分连同待签名图像一并 POST 到 /v1/paint-cocreator/image-sign,由服务器返回 C2PA 清单再嵌入文件。
研究者检查了从画图 Image Creator 直接保存的 PNG:紧跟 IHDR 之后是一个 18,979 字节的 caBX 块,包含签名的 C2PA 清单,其中一条断言写道:
{
"c2pa.soft-binding": {
"alg": "com.microsoft.invismark.1",
"blocks": [{
"scope": "the entire image",
"value": "83424621-03cb-40e3-9808-a9fae837156d"
}]
}
}这个 value 与审核服务返回的 watermarkId、写进像素的 GUID 三者一致。C2PA 把这类断言称为软绑定(soft binding):当文件级清单被截图或转码剥离后,仍可通过像素中的水印把内容与原始凭证关联起来。微软的清单还标注生成器为 Microsoft Responsible AI Provenance,AI 系统为 Azure OpenAI ImageGen,动作为 c2pa.watermarked。
为什么需要本地水印实现
画图有两条生成路径,解释了 Watermarker.dll 存在的理由。云端的 Image Creator 由 Azure OpenAI ImageGen 完成,水印和 C2PA 签名都可以在云端打包好后返回成品。Copilot+ PC 上的 Cocreator 不同:Stable Diffusion 推理在本地 NPU 运行,云端无法在返回途中替它打水印,画图只能自己修改像素。这也解释了为什么水印失败会被当作整次生成失败。
一个佐证是保存格式。AI 生成结果直接保存时画图只提供 PNG;应用回画布后可选格式也只有 PNG、JPEG、GIF 和画图私有的 .paint,唯独没有经典的 BMP。这四种格式恰好都能承载 C2PA 清单(PNG 用 caBX 块,JPEG 用 APP11 标记段,GIF 有专用应用扩展),而 C2PA 规范明确指出 BMP 无法内嵌清单数据。格式列表是围绕凭证保全设计的。

照片应用同机制,失败处理更宽松
照片应用(Microsoft.Windows.Photos_2026.11060.2004.0)内含同名 Watermarker.dll,其 Image Creator 和 Restyle Image 两个功能背后同样有本地 Stable Diffusion,同样把 GUID 嵌入像素。两者差别在失败处理:照片应用在水印编码器报错时记录日志 "watermark will not be applied" 后仍返回图像,画图则直接判整次生成失败。
披露边界与合规背景
微软的 Image Creator 支持页面确实披露了远程内容过滤、C2PA 清单的存在,以及会收集用户与设备标识符用于滥用防范。页面未说明的部分是:C2PA 清单里记录着与像素水印关联的 GUID,本地生成路径的水印 GUID 来自远程提示词审核。
时间点上,欧盟 AI 法案第 50 条的透明度义务已于 2026 年 8 月 2 日生效,要求 AI 生成内容携带可检测的机器可读标记。微软的这套双层机制(像素级 InvisMark 水印 + 文件级 C2PA 签名)与该要求方向一致;超出义务要求的部分在于标记携带的是与单次提示词审核绑定、且可跨请求关联的唯一标识。研究者同时指出,修改画图或照片应用可以绕过审核与水印,但这对能力边界没有影响:任何人都可以直接运行 Stable Diffusion,本就无需经过这套机制。
来源:xusheng.dev 逆向分析原文(2026-08-20);微软 Image Creator 支持页;C2PA 规范