⏱️ Lectura: 12 min

Cada imagen que generás con la inteligencia artificial local de Microsoft Paint lleva escondido un identificador único de 16 bytes que nunca autorizaste y que no podés desactivar.

📑 En este artículo
  1. TL;DR
  2. Qué pasó
  3. Contexto e historia
  4. Cómo funciona la marca de agua invisible
  5. Cómo comprobarlo vos mismo
  6. Impacto y privacidad
  7. Qué sigue
  8. Preguntas frecuentes
    1. ¿Qué es un GUID y por qué Paint lo usa como marca de agua?
    2. ¿Puedo desactivar la marca de agua invisible de Paint?
    3. ¿Esto afecta también a la app Fotos de Windows?
    4. ¿Qué formatos de archivo preservan la marca C2PA?
    5. ¿La generación de imágenes de Paint es realmente local?
    6. ¿Cómo puedo comprobar si una imagen tiene metadata C2PA?
  9. Referencias
    1. 📚 Artículos relacionados

Un ingeniero inverso que firma como Xusheng Li documentó cómo Paint y la app Fotos de Windows convierten ese GUID en una marca de agua invisible incrustada directamente en los píxeles de cada imagen, incluso cuando la generación ocurre por completo en el dispositivo, sin tocar la nube.

TL;DR

  • Microsoft Paint genera imágenes con IA en la nube y también localmente, usando modelos ONNX propios.
  • Antes de generar, Paint envía el prompt a un servidor remoto de Microsoft para moderación.
  • El servidor devuelve, junto al prompt moderado, un GUID que identifica la solicitud.
  • Paint incrusta ese GUID como marca de agua invisible en los píxeles vía WmkWriteWatermark en Watermarker.dll.
  • La marca invisible es independiente del logo visible de Copilot: apagar uno no apaga el otro.
  • El payload debe medir exactamente 16 bytes; si la escritura falla, Paint convierte toda la generación en un error.
  • En las Copilot+ PC la inferencia corre en el NPU local, pero la moderación del prompt sigue viajando a un servidor.
  • Microsoft ya declara que Paint agrega metadata C2PA y solo permite guardar en PNG, JPEG, GIF o el formato .paint.

Qué pasó

La investigación arrancó como curiosidad personal. Xusheng Li venía de auditar funciones poco documentadas de Windows, como UCPD y WHESCVC, y quería entender cómo Paint genera imágenes con IA. Esperaba encontrar una simple llamada a una API en la nube. En cambio, conectó Binary Ninja MCP a un agente de código (Codex) y descubrió que Microsoft empaqueta modelos de IA completos dentro de la propia app, en la carpeta C:\Program Files\WindowsApps\Microsoft.Paint_11.2605.71.0_x64__8wekyb3d8bbwe\PaintApp\.

Ahí aparecen cuatro archivos con extensión .onnxe: seg.onnxe (23,1 MB), inseg_enc.onnxe (28,0 MB), inseg_dec.onnxe (16,5 MB) y mager.onnxe (302,4 MB), según detalla la investigación original. El formato ya era parcialmente conocido: aplicando un XOR con la cadena «Microsoft_2023» contra el archivo, el resultado es un modelo ONNX válido que pasa la verificación estándar del formato.

Mientras rastreaba las llamadas de Paint, Li encontró Watermarker.dll, un archivo de 1,67 MB. Ya sabía que Paint tiene una opción para agregar un logo de Copilot visible en la esquina de la imagen generada, así que el tamaño le llamó la atención: esa función, por sí sola, no justifica un binario tan grande. El detonante final fue el anuncio de Claude Code sobre marcas de agua en texto, que lo llevó a preguntarse si Paint hacía algo parecido pero oculto en los píxeles.

Carpeta de Microsoft Paint con los modelos ONNX cifrados y Watermarker.dll
Watermarker.dll pesa 1,67 MB: demasiado para solo un logo visible. Foto de Alexandre Debiève en Unsplash

Contexto e historia

El hallazgo del formato .onnxe no era enteramente nuevo: la comunidad ya sabía que se resolvía con un XOR simple contra la clave «Microsoft_2023». Lo que Li aportó fue encontrar el resto de la lógica: segapi.dll guarda un pequeño registro de claves donde la versión 1.0.80-main usa esa cadena literal, pero la versión 1.0.81-main ya rota a una clave alfanumérica de 4.096 bytes. El algoritmo de cifrado nunca cambió, solo la clave, lo que sugiere que Microsoft trata esto como ofuscación liviana y no como protección criptográfica real.

El contexto más amplio es la carrera por marcar contenido generado por IA. La Coalition for Content Provenance and Authenticity (C2PA), impulsada por Adobe, Microsoft, Intel y otras compañías, define un estándar de metadata para declarar el origen de una imagen. Microsoft ya reconoce públicamente que Paint agrega metadata C2PA a las imágenes generadas con IA, y por eso limita el guardado de esas imágenes a los formatos que preservan esa metadata: PNG, JPEG, GIF y el formato nativo .paint. Lo que no está documentado públicamente, según la investigación, es la segunda capa: el GUID incrustado píxel a píxel.

Cómo funciona la marca de agua invisible

El camino completo, desde que apretás «generar» hasta que la imagen queda guardada en disco, pasa por varias capas de la app antes de llegar al archivo final:

flowchart TD
A["CocreatorViewModel::GenerateImageAsync"] --> B["StableDiffusionHelpers::GenerateAsync"]
B --> C["ImageGenerator en el NPU local"]
C --> D["Chequeos de seguridad y moderación"]
D --> E["Paint::AI::AddWatermark"]
E --> F["Watermarker.dll: WmkWriteWatermark"]
F -->|"éxito"| G["Imagen final con GUID incrustado"]
F -->|"fallo"| H["La generación se convierte en error"]

CocreatorViewModel::GenerateImageAsync llama a Paint::AI::StableDiffusionHelpers::GenerateAsync, que a su vez invoca a Microsoft.ImageCreation.ImageGenerator. Ahí ocurre la inferencia: en equipos con NPU, el modelo corre localmente usando los archivos .onnxe descritos arriba. El resultado pasa por un chequeo de seguridad y moderación antes de llegar a Paint::AI::AddWatermark, que finalmente llama a WmkWriteWatermark dentro de Watermarker.dll.

Reproducir el desciframiento del formato .onnxe más antiguo es sencillo con un script corto:

with open("seg.onnxe", "rb") as f:
    data = f.read()

key = b"Microsoft_2023"
decrypted = bytes(b ^ key[i % len(key)] for i, b in enumerate(data))

with open("seg.onnx", "wb") as f:
    f.write(decrypted)

Este script reproduce el algoritmo mínimo que usa segapi.dll para la clave de la versión 1.0.80-main: un XOR byte a byte contra la cadena «Microsoft_2023». El resultado es un archivo .onnx estándar.

La parte más reveladora es la firma de la función que escribe la marca invisible, según el análisis binario del código original:

int WmkWriteWatermark(
    uint8_t* output_pixels,
    const uint8_t* payload,
    size_t payload_length,
    int width,
    int height,
    int stride,
    const uint8_t* input_pixels,
    int pixel_format) {

    if (payload_length < 16) return -6;
    if (payload_length > 16) return -5;

    std::vector<uint8_t> message;
    for (size_t i = 0; i < 16; i++) {
        message.push_back(payload[i]);
    }
    // el GUID de 16 bytes se codifica a partir de aqui, pixel a pixel
}

La función exige un payload de exactamente 16 bytes, el tamaño de un GUID, y usa dos códigos de error distintos según sobre o falte contenido. Curiosamente, el bucle que copia el payload ignora el parámetro payload_length y usa un límite fijo de 16 iteraciones de todos modos.

Firma de la función WmkWriteWatermark que exige un payload de 16 bytes
El payload debe medir exactamente 16 bytes: el tamaño de un GUID. Foto de Yogesh Phuyal en Unsplash

Marca de agua Qué contiene ¿Se puede desactivar? Dónde vive en el código
Visible (perceptible) Logo de Copilot superpuesto en la esquina Sí, con el ajuste «Nunca» en WatermarkSetting AddPerceptibleWatermark
Invisible GUID de 16 bytes emitido por el servidor de moderación No hay ajuste que la desactive WmkWriteWatermark en Watermarker.dll

Modelo Tamaño Nodos Función
seg.onnxe 23,1 MB 1.094 Segmentación de imagen
inseg_enc.onnxe 28,0 MB 1.014 Codificador, genera image_embeddings
inseg_dec.onnxe 16,5 MB 1.133 Decodificador de máscaras
mager.onnxe 302,4 MB 15.284 Modelo principal de generación de imagen

⚠️ Ojo: apagar el logo visible de Copilot en la configuración de Paint no apaga la marca de agua invisible. Son dos funciones distintas, controladas por código distinto, y solo una tiene interruptor en la interfaz.

Cómo comprobarlo vos mismo

En Windows podés ubicar los modelos cifrados de Paint con PowerShell:

Get-ChildItem "C:\Program Files\WindowsApps\Microsoft.Paint_*\PaintApp\" -Recurse -Filter *.onnxe

Ese comando lista los cuatro archivos .onnxe descritos arriba. Con el script de Python de la sección anterior podés descifrar seg.onnxe y validar el resultado contra onnx.checker.check_model() de la librería oficial de ONNX.

Para revisar la metadata C2PA de una imagen que generaste con Paint, usá exiftool en cualquier sistema operativo:

# Windows (PowerShell)
.\exiftool.exe .\imagen-generada.png

# macOS (Homebrew)
brew install exiftool
exiftool imagen-generada.png

# Linux (apt)
sudo apt install libimage-exiftool-perl
exiftool imagen-generada.png

Si la imagen tiene metadata C2PA vas a ver un bloque JUMBF o referencias a «C2PA» en la salida. Ojo con el límite de este método: exiftool lee metadata declarada en el contenedor del archivo, no el GUID de 16 bytes que, según la investigación de Li, vive codificado en los propios píxeles y no en un chunk de metadata legible con herramientas estándar.

Impacto y privacidad

La implicancia más directa es que «generación local» no es sinónimo de «sin red». El prompt siempre viaja a un servidor de moderación de Microsoft antes de que el NPU dibuje un solo píxel, y ese servidor es quien emite el GUID que termina incrustado en la imagen. Para un usuario que elige explícitamente el modelo local pensando en privacidad, esa dependencia de red no suele estar documentada con la misma claridad que el ajuste del logo visible.

Queda una pregunta sin responder por ahora: no está confirmado públicamente si Microsoft correlaciona ese GUID, del lado del servidor, con la cuenta o sesión que lo solicitó. La investigación original documenta cómo se genera y se escribe la marca, pero no llega a probar qué hace Microsoft con esa correlación una vez emitida. Es una limitación real del análisis, no un hecho confirmado, y vale aclararlo antes de sacar conclusiones más fuertes.

💭 Clave: en las Copilot+ PC la inferencia de imagen corre en el NPU sin salir del equipo, pero la moderación del prompt sigue siendo un viaje de ida y vuelta a un servidor de Microsoft. «Local» describe dónde corre el modelo, no dónde termina el prompt.

Qué sigue

Es esperable que investigadores de privacidad y medios especializados repliquen este análisis sobre la app Fotos de Windows, que según la propia investigación comparte la misma infraestructura de marcado. También es probable que Microsoft termine publicando documentación más explícita sobre el GUID invisible, dado que ya reconoce el uso de metadata C2PA en Paint. El patrón de fondo es más amplio que un solo producto: entre el SynthID de Google y los anuncios de marcas de agua en texto de Claude Code, la industria se mueve hacia marcadores de procedencia invisibles que el usuario no controla desde un menú de configuración, aunque sí pueda controlar los visibles.

📖 Resumen en Telegram: Ver resumen

Probalo vos: corré el comando de PowerShell de la sección anterior sobre tu propia instalación de Paint y confirmá si tus archivos .onnxe ya usan la clave rotada de 4.096 bytes.

Preguntas frecuentes

¿Qué es un GUID y por qué Paint lo usa como marca de agua?

Un GUID (identificador único global) es una cadena de 16 bytes que un sistema genera para identificar algo sin ambigüedad. En este caso, el servidor de moderación de Microsoft emite un GUID por cada solicitud de generación de imagen, y Paint lo incrusta en los píxeles de la imagen resultante como marca de agua invisible.

¿Puedo desactivar la marca de agua invisible de Paint?

No hay un ajuste visible para eso. El único control que existe en la interfaz es el del logo de Copilot visible, que es una función de código distinta (AddPerceptibleWatermark) a la que escribe el GUID invisible (WmkWriteWatermark).

¿Esto afecta también a la app Fotos de Windows?

Sí. La investigación de Xusheng Li señala que Fotos comparte esta lógica de moderación remota y marca de agua con Paint, aunque el foco técnico del análisis binario se centró en Paint.

¿Qué formatos de archivo preservan la marca C2PA?

Paint limita el guardado de imágenes generadas con IA a PNG, JPEG, GIF y su formato nativo .paint, precisamente porque son los formatos que pueden conservar la metadata C2PA declarada.

¿La generación de imágenes de Paint es realmente local?

La inferencia del modelo sí puede correr en el NPU local en una Copilot+ PC. Pero el prompt siempre se envía primero a un servidor remoto de Microsoft para moderación, y ese mismo servidor es el que emite el GUID que termina incrustado en la imagen.

¿Cómo puedo comprobar si una imagen tiene metadata C2PA?

Con exiftool, ejecutando exiftool imagen-generada.png desde Windows, macOS o Linux, vas a ver un bloque de metadata C2PA o JUMBF si la imagen lo incluye. El GUID incrustado en los píxeles, en cambio, no aparece con esta herramienta.

Referencias

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Imagen destacada: Foto de Shubham Dhage en Unsplash

Categorías: Noticias Tech

Javier Alarcón

Ingeniero de infraestructura especializado en redes, sistemas Linux, Kubernetes y arquitecturas cloud. Cubre hardware, networking, observabilidad y prácticas de ingeniería para equipos de producción.

0 Comentarios

Deja un comentario

Marcador de posición del avatar

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.