MS Paint and Photos inivisibly watermark even locally generated output with GUID

MS Paint and Photos inivisibly watermark even locally generated output with GUID

Reverse engineering reveals how Paint and Photos embed a server-issued GUID into the pixels of locally generated AI images. This research started with my curiosity about Paint. I recently had some success looking into less-explored Windows features like UCPD , WHESCVC , and I have long known that Microsoft added a bunch of AI features into the Paint app. I do not know if anyone actually uses Paint + AI to generate images, but I wanted to see how exactly the image generation works. Before I started, I expected that it simply called a remote API to do the image generation. However, after I set up Binary Ninja MCP with Codex and started the analysis, I soon realized that Microsoft actually shipped local models in Windows as part of Copilot. The Paint App is sitting in the following path (yes, they are all Windows Apps now): seg.onnxe 23.1 MB inseg_enc.onnxe 28.0 MB inseg_dec.onnxe 16.5 MB mager.onnxe 302.4 MB The format of seg.onnxe was previously known , i.e., when it is XORed with the string Microsoft_2023 , it becomes a normal ONNX file.

However, the format of the other three .onnxe files initially looked different. It turned out that Microsoft had not changed the algorithm, only the key. segapi.dll contains a small key registry: ps_enc_key.1.0.80-main -> "Microsoft_2023" ps_enc_key.1.0.81-main -> a 4,096-byte alphanumeric string After decryption, onnx.checker.check_model() works on all of them: While walking through these files, I found a Watermarker.dll : This is not super surprising to me, because while I interacted with the Paint app, I already discovered that it has a setting to embed a visible watermark to the image that it produces: The visible watermark is just a small Copilot logo at the bottom right of the image, which is totally normal. Then, out of nowhere, I decided to ask AI to analyze the DLL and see if it could also be embedding an invisible watermark. This is part of my intuition as a reverse engineer, because the file is 1.67 MB in size, which is unusually large for such trivial functionality (arguably, the visible watermark does not even require a separate DLL). Apparently, the recent Claude Code text-watermark announcement also played a role in prompting me to think about this possibility. To begin with, the visible watermark is added by Add Perceptible Watermark : CPBDoc::Save(...) | `-- perceptible-watermark save helper(bitmap, Watermark Setting) | +-- Watermark Setting::Never | `-- return the original bitmap | +-- Watermark Setting::Ask Every Time | `-- show the Yes / No confirmation popup | +-- No: return the original bitmap | `-- Yes: continue | `-- Always or confirmed Yes +-- Paint::AI::Get Perceptible Watermark Svg() `-- Paint::AI::Add Perceptible Watermark(bitmap, SVG stream) `-- composite the visible Copilot logo Then there is also a different Wmk Write Watermark function: Watermarker.dll !

Wmk Write Watermark ( output_pixels, payload, payload_length, width, height, stride, input_pixels, pixel_format); Tracing the call tree, we can see Wmk Write Watermark is called after a local Stable Diffusion image generation. And if Wmk Write Watermark fails, Paint converts the entire generation into an error rather than returning the image without it: Cocreator View Model::Generate Image Async(...) | `-- Paint::AI::Stable Diffusion Helpers::Generate Async(..., watermark Id, ...) | `-- Microsoft. Image Creation. Image Generator | `-- NPU-generated image result | +-- output safety/moderation checks | +-- Paint::AI::Add Watermark(bitmap, watermark Id) | | | `-- Watermarker.dll! Wmk Write Watermark(...) | | | +-- success: return the watermarked bitmap | `-- failure: turn generation into an error | `-- construct successful Stable Diffusion Result Then it is natural to ask what the incoming payload actually is. It quickly becomes apparent that it must be 16 bytes: if (payload_length 16 ) return - 5 ; It is funny to me that the code is using two different error codes when the payload is too short or too long.

Sources cited: ๐Ÿ“ฐ Hacker News โ†—

โšก Effects Interpreter

๐ŸŒWorld Economy

  • โ–ถInvestors abroad often reprice their bets when this kind of news lands.
  • โ–ถThe ripples can spread across borders, nudging growth forecasts here and there.

๐Ÿ™๏ธLocal Economy

  • โ–ถLocal suppliers who import goods could pass on any change in costs.
  • โ–ถPrices at your local shops could feel a gentle, indirect squeeze from this.

๐ŸฆRates & Banks

  • โ–ถYour loan or mortgage rate is more likely to drift than to lurch here.
  • โ–ถBanks tend to wait and see before nudging the rates they offer.

โค๏ธHealth

  • โ–ถDay-to-day stress can creep up if this starts touching familiar routines.
  • โ–ถCommunity wellbeing might dip a little while people wait for clarity.

๐Ÿ’ทWealth

  • โ–ถLong-term savers usually ride out these small bumps just fine.
  • โ–ถAny hit to your money is more likely a ripple than a wave.

๐Ÿ Housing

  • โ–ถMortgage deals could edge around if lenders read the wider mood.
  • โ–ถBuyers and renters may notice only a gentle drift, if anything at all.
Share: ๐• Twitter Facebook LinkedIn WhatsApp

Editorial note: This analysis was produced by the News Effects Interpreter, an AI editorial tool that cross-references 1 independent news sources and contextualises events in terms of their real-world impact on ordinary people. Original reporting is linked above. News Effects does not alter the facts of source reports.