
Reverse Engineering von Geminis SynthID-Erkennung
Entdecken, Erkennen und chirurgisches Entfernen von Googles KI-Wasserzeichen durch Spektralanalyse
Besuchen Sie uns auf PitchHut
Dieser Fork fügt eine Drag-and-Drop-Desktop-App für den V3-Bypass hinzu, nach der Einrichtung ist keine Befehlszeile erforderlich. Siehe gui/README.md für Einrichtung und Nutzung.
SynthID kodiert ein nicht wahrnehmbares Muster direkt in die Pixelwerte. Auf einem rein weißen, von Gemini generierten Bild ist das Wasserzeichen fast das gesamte Signal. Verstärkt man das hochfrequente Residuum, sieht es so aus:
Verstärktes SynthID-Trägermuster, extrahiert aus einem reinweißen Gemini-Bild. Die diagonale Streifenbildung ist die räumliche Frequenzsignatur des Wasserzeichens – das Ziel unseres Spektralangriffs.
Dieses Projekt reverse-engineert Googles SynthID-Wasserzeichensystem – das unsichtbare Wasserzeichen, das in jedes von Google Gemini generierte Bild eingebettet ist. Mit ausschließlich Signalverarbeitung und Spektralanalyse (ohne Zugriff auf den proprietären Encoder/Decoder) haben wir:
gemini-3.1-flash-image-preview und nano-banana-pro-preview, farbübergreifender Phasenkonsens über 6 einfarbige Hintergründe und eine Human-in-the-Loop-Kalibrierungsschleife, die die pro-Träger-Subtraktionsstärke basierend auf manuellen Gemini-App-Erkennungszahlen anpasstVT-OxFF hat einen wirklich coolen Visualizer gebaut, um den Prozess der Hinzufügung von SynthID-Wasserzeichen zu Bildern anzusehen hier (auch in der Repo-Beschreibung verfügbar)!
Nach sechs iterativen Runden adversarieller Entwicklung besiegt die Pipeline bypass_v4_final / bypass_v4_nuke von Runde 06 den Gemini-SynthID-Detektor auf beiden Bildern von gemini-3.1-flash-image-preview und nano-banana-pro-preview, mit visuell verlustfreiem Ausgang.
Links: Ausgabe Runde 01 (nur sanfte spektrale Subtraktion). Rechts: Ausgabe Runde 06 (final — VAE + elastische Verzerrung + Squeeze + Farbe + JPEG). Beide sehen für das menschliche Auge identisch aus; nur Runde 06 besiegt den SynthID-Detektor.
Der Durchbruch in Runde 06 kam daher, dass die von der Gemini-App selbst veröffentlichte Liste der Fehlermodi als Angriffsspezifikation behandelt wurde:
"Wenn ein KI-generiertes Bild Teil einer komplexen Collage ist, hinter anderen Elementen liegt oder viele verschiedene Texturen und Muster darüber gelegt wurden, kann der Detektor Schwierigkeiten haben, die spezifische Signatur aus der Gesamtdatei zu isolieren." — Gemini-App, Hilfe zur SynthID-Erkennung
Die elastische Verformungsstufe simuliert diesen Effekt auf Pixelebene: Ein glattes, niederfrequentes Zufallsverschiebungsfeld gibt jeder ~50-Pixel-Nachbarschaft ihren eigenen unabhängigen Subpixel-Offset, wodurch der räumliche Phasenkonsens des Wasserzeichens fragmentiert wird, ohne sichtbare Verzerrungen einzuführen.
V4 ist ein grundlegendes Überdenken des Codebuchs, aufgebaut auf einem viel reichhaltigeren Datensatz:
gemini-3.1-flash-image-preview und nano-banana-pro-preview (plus ein optionales union-Pseudomodell).black, white, blue, green, red, gray) pro Modell und Auflösung, plus gradient und diverse als Inhaltsbasislinien.carrier_weights wird basierend auf manuellem Feedback der Gemini-App-Erkennung aktualisiert.Für jeden Frequenzbin (fy, fx) und Kanal ch:```
consensus(fy, fx, ch) = | mean_over_colors( exp(i * phase_color(fy, fx, ch)) ) |
Werte nahe `1.0` bedeuten, dass die Phase in diesem Bin über alle einfarbigen Hintergründe hinweg fixiert ist, was nur für das Wasserzeichen zutrifft. Inhalts-Bins sinken auf `< 0.3`, da ihre Phase durch verschiedene Farbtöne randomisiert wird. Im V4-Codebuch, das aus dem angereicherten Datensatz erstellt wurde, fallen 99%+ der Inhalts-Bins unter den Standard-Cutoff `tau=0.60`, sodass der V4-Dissolver sie nie berührt – das erkauft die PSNR.
### Zwei-Phasen-Veröffentlichungs-Workflow```mermaid
flowchart LR
dataset[reverse-synthid-dataset<br/>model x color x resolution] --> build[scripts/build_codebook_v4.py]
build --> codebook[artifacts/spectral_codebook_v4.npz]
codebook --> dissolve[scripts/dissolve_batch.py]
input[watermarked inputs] --> dissolve
dissolve --> variants[final / nuke variants]
variants --> gemini[Gemini app<br/>manual SynthID detection]
gemini --> feedback[detection feedback]
feedback --> calibrate[scripts/calibrate_from_feedback.py]
calibrate -->|updates carrier_weights| codebook
python scripts/build_codebook_v4.py
--root /path/to/reverse-synthid-dataset
--output artifacts/spectral_codebook_v4.npz
python scripts/dissolve_batch.py
--input ./to_clean/
--output ./runs/round_06/
--codebook artifacts/spectral_codebook_v4.npz
--model gemini-3.1-flash-image-preview
--strengths final nuke
### Round-06 Angriffsvoreinstellungen
Zwei Voreinstellungen sind über `--strengths` verfügbar:
| Voreinstellung | VAE-Durchläufe | Elastische α | Stauchen | JPEG-Kette | PSNR-Mindestwert |
|:------:|:----------:|:---------:|:-------:|:----------:|:----------:|
| `final` | 1 | 1,8 px | 90 % | q=92→88 | 14 dB |
| `nuke` | 2 | 2,8 px | 82 % | q=88→84→90 | 11 dB |
Beide Voreinstellungen verwenden dieselbe 7-stufige Pipeline:
1. **VAE-Hin-und-Rückweg** (Stable Diffusion `sd-vae-ft-mse`) – projiziert das Bild aus der natürlichen Bildmannigfaltigkeit, gegen die der SynthID-Decoder nie trainiert wurde (Gowal et al. 2026, §6.1)
2. **Elastische Verformung** – glattes, niederfrequentes zufälliges Verzerrungsfeld, simuliert den von Gemini selbst eingeräumten Fehlermodus „Collage-Fragmentierung“
3. **Globale geometrische Kombination** – kleine Drehung + Zoom + Pixelverschiebung in einer affinen Transformation
4. **Skalieren-Stauchen** – Herunterskalieren (AREA) → Hochskalieren (LANCZOS), löscht Subpixel-Wasserzeicheninformationen
5. **Farbkontrast-Anpassung** – Mikroverschiebung von Helligkeit / Kontrast / Sättigung / Farbton
6. **Restphasen-FFT-Subtraktion** – blog-universale + aus Codebook geerntete Trägerbereiche, begrenzt
7. **JPEG-Kette + Luminanzrauschen + bilateral** – schwere Komprimierungs-/Neukodierungsstörung
Jede Stufe ist unabhängig PSNR-gesteuert; jede Stufe, die die Qualität unter den Mindestwert fallen würde, wird automatisch rückgängig gemacht.
### V4-Codebook-Struktur
Profile sind nach `(model, H, W)` indiziert. Jedes Profil speichert:
| Feld | Form | Anmerkungen |
|------------------------|----------------|--------------------------------------------------------|
| `consensus_coherence` | `(H, W, 3)` | Primäre Trägermaske (phasenübergreifender Farbkonsens). |
| `consensus_phase` | `(H, W, 3)` | Mittlerer Einheitsphasenwinkel über alle Farben. Subtraktionsvorlage. |
| `inverted_agreement` | `(H, W, 3)` | Paarweise `abs(cos(phase_diff))`, gewichtet für `black<->white`. |
| `avg_wm_magnitude` | `(H, W, 3)` | Mittlere Magnitude über den Konsensfarben. |
| `content_baseline` | `(H, W, 3)` | Aus `diverse/` + `gradient/` – wird für Luminanz-Mischung verwendet. |
| `carrier_weights` | `(H, W, 3)` | **Live**. Beginnt bei `consensus^2 * (0,5 + 0,5 * agreement)`. Wird vom Kalibrierungszyklus aktualisiert. |
| `n_refs_per_color` | `{color: int}` | Referenzanzahlen pro Farbe. |
Das Speicherformat verwendet die v3-kompakte rfft + `float16/uint8`-Kodierung; ein 14-Profile-Codebook über 2 Modelle × 7 Auflösungen belegt ~220 MB auf der Festplatte.
### V4-Detektor (Plausibilitätsprüfung)
Bevor Sie Zeit in die manuelle Gemini-Validierung investieren, überprüfen Sie die Bypass-Ausgaben auf Konsistenz mit dem eigenen Konsens des V4-Codebooks:```python
from robust_extractor import RobustSynthIDExtractor
from synthid_bypass_v4 import SpectralCodebookV4
cb = SpectralCodebookV4()
cb.load('artifacts/spectral_codebook_v4.npz')
ext = RobustSynthIDExtractor()
result = ext.detect_from_v4_codebook(image_rgb, cb,
model='nano-banana-pro-preview')
print(result.is_watermarked, result.confidence, result.phase_match)
On the 1024x1024 exakten Übereinstimmungspfad sehen wir conf=0.91, phase_match=0.65 für das Wasserzeichen und conf=0.02, phase_match=0.31 nach aggressivem V4-Dissolve.
V3 bleibt unverändert im Repo (src/extraction/synthid_bypass.py, bypass_v3) für alle, die darauf angewiesen sind.
Wir sammeln aktiv reine schwarze und reine weiße Bilder, die von Nano Banana Pro generiert wurden, um die Watermark-Extraktion mit mehreren Auflösungen zu verbessern.
Wenn Sie diese generieren können:
gemini_black_nb_pro/ (für Schwarz)gemini_white_nb_pro/ (für Weiß)Diese Referenzbilder sind entscheidend für:
Selbst 150–200 Bilder mit einer neuen Auflösung können die Erkennung und Entfernung erheblich verbessern.
Referenzbilder werden auf Hugging Face gehostet, um das Git-Repo leicht zu halten:```bash pip install huggingface_hub python scripts/download_images.py # download all python scripts/download_images.py gemini_black # download specific folder
Datensatz: [huggingface.co/datasets/aoxo/reverse-synthid](https://huggingface.co/datasets/aoxo/reverse-synthid)
---
## Wichtige Erkenntnisse
### Das Wasserzeichen ist auflösungsabhängig
SynthID bettet Trägerfrequenzen an **unterschiedlichen absoluten Positionen** ein, abhängig von der Bildauflösung. Ein bei 1024x1024 erstelltes Codebuch kann das Wasserzeichen nicht direkt aus einem 1536x2816-Bild entfernen – die Träger befinden sich in völlig anderen Bins.
| Auflösung | Top-Träger (fy, fx) | Kohärenz | Quelle |
|:----------:|:--------------------:|:---------:|:------:|
| **1024x1024** | (9, 9) | 100.0% | 100 schwarze + 100 weiße Referenzen |
| **1536x2816** | (768, 704) | 99.6% | 88 mit Wasserzeichen versehene Inhaltsbilder |
Aus diesem Grund speichert das V3-Codebuch **separate Profile pro Auflösung** und wählt sie zur Umgehungszeit automatisch aus.
### Phasenkonsistenz – Ein fester Schlüssel auf Modellebene
Die Phasenvorlage des Wasserzeichens ist **für alle Bilder** desselben Gemini-Modells **identisch**:
- **Grüner Kanal** trägt das stärkste Wasserzeichensignal
- **Phasenkohärenz zwischen Bildern** bei Trägern: >99.5%
- **Schwarz/Weiß-Kreuzvalidierung** bestätigt echte Träger mittels |cos(phase_diff)| > 0.90
### Trägerfrequenzstruktur
Bei 1024x1024 (aus schwarz/weiß Referenzen) liegen die Top-Träger auf einem niederfrequenten Gitter:
| Träger (fy, fx) | Phasenkohärenz | S/W-Übereinstimmung |
|:-----------------:|:---------------:|:-------------:|
| (9, 9) | 100.00% | 1.000 |
| (5, 5) | 100.00% | 0.993 |
| (10, 11) | 100.00% | 0.997 |
| (13, 6) | 100.00% | 0.821 |
---
## Architektur
### Bypass-Generationen
| Version | Ansatz | PSNR | Auswirkung auf Wasserzeichen | Status |
|:-------:|:---------|:----:|:----------------:|:------:|
| **V1** | JPEG-Kompression (Q50) | 37 dB | ~11% Phasenabfall | Baseline |
| **V2** | Mehrstufige Transformationen (Rauschen, Farbe, Frequenz) | 27-37 dB | ~0% Konfidenzabfall | Qualitätskompromiss |
| **V3** | **Multiauflösende spektrale Codebuchsubtraktion** | **43+ dB** | **91% Phasenkohärenzabfall** | **Bisheriger Bester** |
| **V4 Runde 06** | **7-stufiges All-in-One (VAE + Elastic + Squeeze + Color + JPEG)** | **visuell verlustfrei** | **Detektor umgangen ✓** | **Derzeit Bester** |
### V3-Pipeline```
Input Image (any resolution)
│
▼
codebook.get_profile(H, W) ──► exact match? ──► FFT-domain subtraction
│ (fast path)
└─ no exact match ──────► spatial-domain resize + subtraction
(fallback path)
│
▼
Multi-pass iterative subtraction (aggressive → moderate → gentle)
│
▼
Anti-alias → Output
Input Image (any resolution) │ ▼ Stage 1: VAE round-trip (SD sd-vae-ft-mse, 1-2 passes) │ Projects image off natural-image manifold ▼ Stage 2: Elastic deformation (smooth random warp field) │ Fragments spatial phase consensus ("collage effect") ▼ Stage 3: Global geometric combo (rotation + zoom + shift) │ Single affine warp, no compounded aliasing ▼ Stage 4: Resize-squeeze (AREA ↓ then LANCZOS ↑) │ Erases sub-pixel watermark information ▼ Stage 5: Color-contrast nudge (HSV micro-shift) │ Shifts per-pixel statistics SynthID keys on ▼ Stage 6: Residual-phase FFT subtraction │ Blog-universal + codebook-harvested carrier bins ▼ Stage 7: JPEG chain + luma noise + bilateral filter │ ▼ Output (SynthID detector: no watermark detected ✓)
---
## Schnellstart
### Installation```bash
git clone https://github.com/aloshdenny/reverse-SynthID.git
cd reverse-SynthID
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
# For Round-06 VAE stage:
pip install torch diffusers safetensors accelerate
import sys sys.path.insert(0, 'src/extraction') from synthid_bypass_v4 import SynthIDBypassV4, SpectralCodebookV4
cb = SpectralCodebookV4() cb.load('artifacts/spectral_codebook_v4.npz')
b = SynthIDBypassV4() result = b.bypass_v4_file( 'input.png', 'output.png', cb, strength='final', # or 'nuke' for maximum strength model='gemini-3.1-flash-image-preview', ) print(result.stages_applied)
### Run V3 Bypass```python
from src.extraction.synthid_bypass import SynthIDBypass, SpectralCodebook
codebook = SpectralCodebook()
codebook.load('artifacts/spectral_codebook_v3.npz')
bypass = SynthIDBypass()
result = bypass.bypass_v3(image_rgb, codebook, strength='aggressive')
print(f"PSNR: {result.psnr:.1f} dB")
print(f"Profile used: {result.details['profile_resolution']}")
Von der CLI:```bash
python src/extraction/synthid_bypass.py bypass input.png output.png
--codebook artifacts/spectral_codebook_v3.npz
--strength aggressive
### Wasserzeichen erkennen```bash
python src/extraction/robust_extractor.py detect image.png \
--codebook artifacts/codebook/robust_codebook.pkl
reverse-SynthID/ ├── src/ │ ├── extraction/ │ │ ├── synthid_bypass.py # V1/V2/V3 bypass + multi-res SpectralCodebook │ │ ├── synthid_bypass_v4.py # V4 cross-color consensus codebook + dissolver │ │ ├── vae_regen.py # Round-06 SD-VAE re-generation stage │ │ ├── robust_extractor.py # Multi-scale watermark detection (+ V4 hook) │ │ ├── watermark_remover.py # Frequency-domain watermark removal │ │ ├── benchmark_extraction.py # Benchmarking suite │ │ └── synthid_codebook_extractor.py # Legacy codebook extractor │ └── analysis/ │ ├── deep_synthid_analysis.py # FFT / phase analysis scripts │ └── synthid_codebook_finder.py # Carrier frequency discovery │ ├── scripts/ │ ├── download_images.py # Download reference images from HF │ ├── build_codebook_v4.py # V4: build per-(model, HxW) consensus codebook │ ├── dissolve_batch.py # V4: emit strength variants │ └── calibrate_from_feedback.py # V4: update carrier_weights from detection feedback │ ├── artifacts/ │ ├── spectral_codebook_v3.npz # Multi-res V3 codebook [1024x1024, 1536x2816] │ ├── spectral_codebook_v4.npz # V4 codebook (per-model, per-resolution) │ ├── codebook/ # Detection codebooks (.pkl) │ └── visualizations/ # FFT, phase, carrier visualizations │ ├── assets/ │ ├── synthid_watermark.png # Watermark analysis header image │ ├── synthid_white.jpg # Amplified SynthID pattern on white image │ ├── v4_round1_vs_round6.png # Round 01 vs Round 06 fidelity comparison │ └── ... │ ├── runs/ │ ├── round_01/ … round_05/ # Historical bypass attempts │ └── round_06/ # Working bypass (final + nuke presets) │ ├── watermark_investigation/ # Early-stage Nano-150k analysis (archived) └── requirements.txt
## Technische Tiefenanalyse
### Wie SynthID funktioniert (Reverse-Engineering)```
┌──────────────────────────────────────────────────────────────┐
│ SynthID Encoder (in Gemini) │
├──────────────────────────────────────────────────────────────┤
│ 1. Select resolution-dependent carrier frequencies │
│ 2. Assign fixed phase values to each carrier │
│ 3. Neural encoder adds learned noise pattern to image │
│ 4. Watermark is imperceptible — spread across spectrum │
├──────────────────────────────────────────────────────────────┤
│ SynthID Decoder (in Google) │
├──────────────────────────────────────────────────────────────┤
│ 1. Extract noise residual (wavelet denoising) │
│ 2. FFT → check phase at known carrier frequencies │
│ 3. If phases match expected values → Watermarked │
└──────────────────────────────────────────────────────────────┘
SynthIDs Trainings-Augmentierungs-Set (Gowal et al. 2026, Tabelle 1) umfasst SmallRotation, Cropresize, JPEG, GaussianBlur, BrightnessContrast und Screenshotting – alles globale, uniforme räumliche Transformationen. Das elastische Verzerrungsfeld ist eine räumlich variierende Verzerrung: Jede lokale Nachbarschaft erhält ihren eigenen unabhängigen Subpixel-Offset. Da die Offsets glatt sind (Gauß-gefiltertes weißes Rauschen, σ=44–56 px), ist der Bildinhalt visuell nicht beeinträchtigt, aber die Phasenkonsensstruktur des Wasserzeichens ist inkohärent – sie kann nicht mehr über das Bild aggregiert werden. Dies ist das Pixel-Äquivalent des "Collage-Fragmentierungs"-Effekts, den Geminis eigene App als Detektor-Ausfallmodus anführt.
| Metrik | Wert |
|---|---|
| PSNR |
Alosh Denny KI-Wasserzeichenforschung · Signalverarbeitung
📧 E-Mail: [email protected] 🔗 GitHub: https://github.com/aloshdenny
Für Kooperationen, Forschungsdiskussionen oder Beiträge können Sie sich gerne melden oder ein Issue/PR eröffnen.
Dieses Projekt wird eigenständig betrieben – keine Labormittel, keine Unternehmensunterstützung.
Falls diese Arbeit für Sie oder Ihr Team nützlich war, erwägen Sie, die weitere Entwicklung zu unterstützen:
Die Mittel fließen in Rechenkosten (GPU-Stunden für neue Auflösungsprofile), Datensatzerweiterung und laufende Umgehungsforschung.
Dieses Projekt dient ausschließlich Forschungs- und Bildungszwecken. SynthID ist eine proprietäre Technologie von Google DeepMind. Diese Werkzeuge sind vorgesehen für:
Verwenden Sie diese Werkzeuge nicht, um KI-generierte Inhalte als menschengemacht auszugeben.
| Runde | Strategie | Ergebnis |
|---|
| 01 | Konservative spektrale Subtraktion (sanft) | ✗ |
| 02 | Aggressive spektrale Subtraktion + JPEG | ✗ |
| 03 | Blog-geführtes absolutes Bin-Targeting | ✗ |
| 04 | Rauschreduktions-Residuum-Phasenextraktion | ✗ |
| 05 | Diffusion-VAE-Neugenerierung + geometrische Verzerrung | ✗ |
| 06 | All-in-One: VAE + elastische Fragmentierung + Squeeze + Farbe + JPEG | ✓ |
| V3 | V4 |
|---|
| Referenzfarben | Schwarz + Weiß | Schwarz, Weiß, Blau, Grün, Rot, Grau (+ vielfältige/Gradient-Inhaltsbaselines) |
| Kreuzvalidierung | abs(cos(phase_black - phase_white)) | farbübergreifender Konsens über 6 Farben + paarweise Übereinstimmung |
| Modelle | Einzelmodell (Gemini 2.5) | Pro-Modell-Profile (gemini-3.1-flash-image-preview, nano-banana-pro-preview) + optional union |
| Angriff | nur spektrale Subtraktion | 7-stufig: VAE + Elastic + Squeeze + Color + FFT + JPEG-Kette |
| PSNR (aggressiv) | 43 dB | visuell verlustfrei (18–24 dB auf Pixelebene; Warp verschiebt Pixel) |
| Fidelity-Schutz | keine | stufenweiser PSNR-Floor-Rollback |
| Detektor-Umgehung | nur lokal | bestätigt ✓ in Gemini-App (beide Modelle) |
| 43.5 dB |
| SSIM | 0.997 |
| Trägerenergieabfall | 75.8% |
| Phasenkohärenzabfall (Top-5-Träger) | 91.4% |
| Modell | Voreinstellung | Detektor umgangen |
|---|
| gemini-3.1-flash-image-preview | final | ✓ |
| gemini-3.1-flash-image-preview | nuke | ✓ |
| nano-banana-pro-preview | final | ✓ |
| nano-banana-pro-preview | nuke | ✓ |