
微软画图'隐形水印'逆向实录:你以为本地生成的 AI 图片,像素里藏着一个服务器下发的 GUID
安全研究员逆向 Windows 自带画图和照片应用发现:即使图片在本地 NPU 生成,你的提示词也会发到微软服务器审核,返回的 GUID 会作为隐形水印嵌入图片像素。附完整检测原理和隐私含义。
原文来源:Microsoft Paint and Photos Embed Server-Issued GUIDs as Invisible Watermarks — 安全研究员 Xusheng 逆向微软画图和照片应用,揭示本地 AI 图片生成中的远程审核与隐形水印机制。
这篇文章在 Hacker News 上拿到了 800+ 分,原因很简单:它回答了一个很多人隐隐担心的问题——Windows 自带的 AI 图片生成,到底是不是"本地"的? 答案比想象中复杂:生成可以是本地的,但你的提示词会先发到微软服务器,服务器返回的 GUID 会被嵌入到生成图片的像素里,作为隐形水印。
作者 Xusheng 是研究 Windows 内部机制的老手,之前逆向过 UCPD 和 WHESCVC。这次他把目光投向画图(Paint)应用里新增的 AI 功能,一开始他以为图片生成走的是远程 API,用 Binary Ninja MCP 配合 Codex 分析后才发现:微软把模型直接打包进了 Windows。
第一步:找到藏在系统里的模型文件
在 WindowsApps 目录下的 Paint 应用文件夹里,作者找到了四个 .onnxe 扩展名的模型文件:
seg.onnx e 23.1 MB
inseg_enc.onnx e 28.0 MB
inseg_dec.onnx e 16.5 MB
mager.onnx e 302.4 MB
seg.onnxe 的格式此前有人研究过:把文件内容和字符串 Microsoft_2023 做 XOR 就能还原成普通 ONNX 文件。但另外三个文件的格式看着不一样——结果发现算法没变,只是换了密钥。segapi.dll 里有个小密钥表:ps_enc_key.1.0.80-main 对应 "Microsoft_2023",而 ps_enc_key.1.0.81-main 是一串 4096 字节的字母数字字符串。解密之后,onnx.checker.check_model() 全部通过。
—— 广告 ——
第二步:一个异常巨大的 Watermarker.dll
分析过程中作者注意到一个 Watermarker.dll。这不算意外——画图应用里本来就有一个"可见水印"设置(Never / Always / Ask every time 三档),往图片右下角盖一个小 Copilot 标志。但奇怪的是这个 DLL 有 1.67MB,"对这么个微不足道的功能来说大得不正常"。
加上最近 Claude Code 发布了文本水印功能,作者的逆向直觉被勾起来了:会不会还有一层隐形水印?
第三步:隐形水印的编码机制
顺着调用链追下去,WmkWriteWatermark 的 payload 被限制为恰好 16 字节(短了返回 -6,长了返回 -5),函数还忽略传入的长度参数、用硬编码的循环边界复制 16 字节。再往上层看,包装函数的签名直接写着 winrt::guid const& watermarkId——16 字节 payload 就是一个 GUID。
水印编码器的工作方式大致是:
- 构造 18 字节消息:
0x4c || GUID[0..15] || (16 字节求和 mod 256),即 144 位 - 把图片可用尺寸向下取整到 8 的倍数,维护 144 个计数器,每位至少放置 3 次
- 在选中的图像块上做小幅量化修改,涉及 3×5 矩阵运算和矩阵分解,常量包括 24.0、0.25、0.5、0.2——典型的内容自适应、SVD 风格的隐形水印
作者不是水印专家,但结论很明确:这就是隐形水印。他用 AI 帮忙写代码直接调用这个函数做验证,在一张合成的 512×512 BGRA 图片上,262,144 个像素里有 193,376 个被改动。
第四步:GUID 从哪来?一个远程审核端点
继续往回追调用链,发现 GUID 来自一次网络请求。在跑本地图像模型之前,AIServices.dll 会把提示词和风格发送到:
https://apsaiservices-a0fqcjc6bzbhgdcd.b02.azurefd.net/
v1/paint-cocreator/moderate-prompt
服务器返回的内容包括修订后的提示词(revisedPrompt)、一个 promptGenerationId,以及watermarkId——这个 watermarkId 就是后面嵌入像素的 GUID。
也就是说,所谓"本地生成"的真实数据流是:提示词 → 微软审核服务器 → 返回修订提示词 + 水印 GUID → NPU 本地跑 Stable Diffusion → Watermarker.dll 把 GUID 嵌进像素。
失败处理也很有意思:在画图应用里,如果 WmkWriteWatermark 失败,整次生成直接报错,绝不允许返回一张没有水印的图片。而照片(Photos)应用的处理相反——水印失败只记一条日志"watermark will not be applied",图片照常返回。
保存格式的限制:为什么 BMP 消失了
从 Image Creator 面板直接保存 AI 生成结果时,画图只给一个格式:PNG。应用到画布之后,可选格式也只剩 PNG、JPEG、GIF 和画图自有的 .paint 格式——经典画图格式 BMP 赫然缺席。
原因和 C2PA 有关:PNG 用 caBX chunk 存 manifest,JPEG 用 APP11 标记段,GIF 有自己的 C2PA 表示,.paint 是微软自家格式随便存。而 C2PA 规范明确点名 BMP 是无法内嵌 manifest 的经典格式。如果允许直接导出 BMP,文件级的 C2PA 凭据就没了。
云路径 vs 本地路径
文章对比了两条生成路径:
Image Creator(云端):整条链路都在微软云上——内容过滤、Azure OpenAI ImageGen 生成、隐形水印、C2PA 打包全部在云端完成,画图只负责接收成品。
Cocreator(Copilot+ PC 本地):微软官方说 NPU 本地生成,但安全检查走 Azure 在线服务。所以这个功能同时需要微软账号和联网,即使 Stable Diffusion 推理确实在设备上跑。这大概就是为什么画图需要一套本地水印实现——云生成器可以在返回前打上水印,本地生成器不行,只能自己改像素。
一个值得注意的安全问题
作者指出:如果远端图像生成端点可以被诱导在打水印和打包 C2PA 之前返回原始图片,或者存在跳过这些环节的内部选项,就可能拿到一张既无隐形水印也无 C2PA 的云生成图片。这算不算问题,取决于微软的设计意图——可能是允许的行为(底层服务可以返回原始生成,水印只是画图这层的职责),可能是产品 bug,也可能是一个安全漏洞。在不知道信任边界的前提下,三种可能都还摆着。
微软披露了什么,没披露什么
微软在 Image Creator 支持页面上确实披露了部分事实:图片会"包含 C2PA manifest 帮助用户识别 AI 生成图片"、Image Creator 使用 Azure 在线服务、会收集用户和设备标识符以及提示词用于滥用防护。
但它没有说明:C2PA manifest 里包含一个指向隐形像素水印的 GUID,也没有说明本地生成路径的水印 GUID 来自远程提示词审核。把功能叫"Content Credentials(内容凭据)"不算错,但对 Windows 用户来说,这个和提示词绑定的标识符并不明显。
对你的实际意义
抛开技术细节,这篇文章值得记住三件事:
- "本地生成"不等于"本地处理"。Copilot+ PC 上 AI 图片的生成确实在本地 NPU 完成,但提示词每次都会过一遍微软的审核服务器,需要微软账号和联网。隐私敏感场景(比如商业机密的视觉素材)要意识到这一点。
- 你保存的 AI 图片自带追踪标识。GUID 与提示词审核请求绑定,加上 C2PA 元数据,一张图片从生成源头就是可追溯的。
- 格式限制是刻意的。只允许保存 PNG/JPEG/GIF 不是产品疏忽,是为了保住 C2PA 凭据。想用 BMP 导出 AI 图片?这条路被设计掉了。
对开发者来说,这篇还有一个额外价值:它演示了一套完整的 Windows 应用逆向方法论——从文件系统里找模型 → 识别加密格式 → 解密验证 → 追 DLL 调用链 → 定位网络端点,每一步都有工具和思路可循。
© 2026 四月
原文链接:https://www.aprilzz.com/tutorials/ms-paint-invisible-guid-watermark
相关文章
把可执行文件改成 SQLite 数据库:用 SQL 查询 ELF 的一切,程序照常运行
SELF 格式用 SQLite 数据库替代 ELF 作为可执行文件:file 命令显示它是 SQLite 数据库,./hello 照样输出 Hello world,而 ldd、nm、readelf、strip 全部退化成一条 SQL 查询。附完整原理和实操命令。
在 Mac 上搭建本地编程 Agent:llama.cpp + Gemma 4 + MTP 投机解码完整指南
断网也能用的编程 Agent:用 llama.cpp 在 Mac 上跑 Gemma 4 26B,配合 MTP 投机解码把生成速度从 58 提到 72 token/s,再接上支持图片输入的 Pi 终端 Agent。
用自托管 Umami 给 iOS App 加分析——轻量、隐私友好的方案
独立开发者如何用自托管的 Umami 分析服务给自己的 iOS App 加使用统计,避免使用 Google Analytics 等重量级 SDK。含完整集成代码。