
engenharia reversa da detecção SynthID do Gemini
Descobrindo, detectando e removendo cirurgicamente a marca d'água de IA do Google através de análise espectral
Visite-nos em PitchHut
Este fork adiciona um aplicativo de desktop de arrastar e soltar para o bypass V3, sem necessidade de linha de comando após a configuração. Veja gui/README.md para configuração e uso.
O SynthID codifica um padrão imperceptível diretamente nos valores dos pixels. Em uma imagem branca pura gerada pelo Gemini, a marca d'água é quase todo o sinal. Amplifique o resíduo de alta frequência e ele se parece com isso:
Padrão amplificado da portadora SynthID extraído de uma imagem Gemini branca pura. A faixa diagonal é a assinatura de frequência espacial da marca d'água — o alvo do nosso ataque espectral.
Este projeto faz engenharia reversa do sistema de marca d'água SynthID do Google — a marca d'água invisível embutida em cada imagem gerada pelo Google Gemini. Usando apenas processamento de sinais e análise espectral (sem acesso ao codificador/decodificador proprietário), nós:
gemini-3.1-flash-image-preview e nano-banana-pro-preview, consenso de fase entre cores em 6 fundos sólidos e um loop de calibração humano-no-circuito que ajusta a força de subtração por portadora a partir de contagens manuais de detecção do aplicativo GeminiVT-OxFF construiu um visualizador muito legal para ver o processo de como a marca d'água SynthID é adicionada às imagens aqui (também disponível na descrição do repositório)!
Após seis rodadas iterativas de desenvolvimento adversarial, o pipeline bypass_v4_final / bypass_v4_nuke da Rodada 06 derrota o detector SynthID do Gemini em imagens tanto de gemini-3.1-flash-image-preview quanto de nano-banana-pro-preview, com saída visualmente sem perdas.
Esquerda: saída da Rodada 01 (apenas subtração espectral `suave`). Direita: saída da Rodada 06 (`final` — VAE + deformação elástica + compressão + cor + JPEG). Ambas parecem idênticas aos olhos humanos; apenas a Rodada 06 derrota o detector SynthID.
O avanço na Rodada 06 veio de tratar a lista de modos de falha publicada pelo próprio aplicativo Gemini como uma especificação de ataque:
"Quando uma imagem gerada por IA faz parte de uma colagem complexa, camada atrás de outros elementos, ou tem muitas texturas e padrões diferentes sobrepostos, o detector pode ter dificuldade para isolar a assinatura específica do arquivo geral." — Aplicativo Gemini, texto de ajuda de detecção SynthID
O estágio de deformação elástica simula esse efeito no nível de pixel: um campo de deformação aleatório suave e de baixa frequência dá a cada vizinhança de ~50 pixels seu próprio deslocamento de subpixel independente, fragmentando o consenso de fase espacial da marca d'água sem introduzir qualquer distorção visível.
V4 é uma repensada completa do codebook construído em um conjunto de dados muito mais rico:
gemini-3.1-flash-image-preview e nano-banana-pro-preview (mais um pseudo-modelo union opcional).black, white, blue, green, red, gray) por modelo por resolução, mais gradient e diverse como linhas de base de conteúdo.carrier_weights do codebook é atualizado com base no feedback manual de detecção do aplicativo Gemini.Para cada bin de frequência (fy, fx) e canal ch:```
consensus(fy, fx, ch) = | mean_over_colors( exp(i * phase_color(fy, fx, ch)) ) |
Valores próximos de `1.0` significam que a fase naquele bin está bloqueada em todos os fundos de cor sólida, o que só é verdade para a marca d'água. Os bins de conteúdo colapsam para `< 0.3` porque sua fase é randomizada por diferentes tons de cor. No codebook V4 construído a partir do conjunto de dados enriquecido, 99%+ dos bins de conteúdo ficam abaixo do corte padrão `tau=0.60`, então o dissolver V4 nunca os toca — é isso que recupera o PSNR.
### Fluxo de trabalho de lançamento em duas fases```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
### Predefinições de Ataque Round-06
Dois presets estão disponíveis via `--strengths`:
| Preset | VAE passes | Elastic α | Squeeze | JPEG chain | PSNR floor |
|:------:|:----------:|:---------:|:-------:|:----------:|:----------:|
| `final` | 1 | 1.8 px | 90 % | q=92→88 | 14 dB |
| `nuke` | 2 | 2.8 px | 82 % | q=88→84→90 | 11 dB |
Ambos os presets empilham o mesmo pipeline de 7 estágios:
1. **Ida e volta VAE** (Stable Diffusion `sd-vae-ft-mse`) — projeta a imagem para fora da variedade de imagens naturais contra a qual o decodificador SynthID nunca foi treinado (Gowal et al. 2026, §6.1)
2. **Deformação elástica** — campo de distorção aleatória suave de baixa frequência, simula o modo de falha "fragmentação de colagem" que a própria Gemini reconhece
3. **Combo geométrico global** — pequena rotação + zoom + deslocamento de pixel em uma única transformação afim
4. **Redimensionamento-compressão** — reduzir amostragem (AREA) → aumentar amostragem (LANCZOS), apaga informações de marca d'água sub-pixel
5. **Ajuste de contraste de cor** — micro-deslocamento de brilho/contraste/saturação/matiz
6. **Subtração de FFT de fase residual** — bins portadores universais de blog + extraídos do codebook, com limite de capacidade
7. **Cadeia JPEG + ruído luma + bilateral** — forte compressão/rompimento de re-codificação
Cada estágio é independentemente controlado por PSNR; qualquer estágio que reduza a qualidade abaixo do piso é revertido automaticamente.
### Estrutura do Codebook V4
Perfis chaveados por `(modelo, H, W)`. Cada perfil armazena:
| Campo | Forma | Notas |
|------------------------|----------------|--------------------------------------------------------|
| `consensus_coherence` | `(H, W, 3)` | Máscara portadora primária (consenso de fase entre cores). |
| `consensus_phase` | `(H, W, 3)` | Ângulo médio de fase unitária entre cores. Modelo de subtração. |
| `inverted_agreement` | `(H, W, 3)` | Concordância pareada `abs(cos(phase_diff))`, ponderada para `black<->white`. |
| `avg_wm_magnitude` | `(H, W, 3)` | Magnitude média entre cores de consenso. |
| `content_baseline` | `(H, W, 3)` | De `diverse/` + `gradient/` — usado para mesclagem de luminância. |
| `carrier_weights` | `(H, W, 3)` | **Ao vivo**. Começa em `consensus^2 * (0.5 + 0.5 * agreement)`. Atualizado pelo loop de calibração. |
| `n_refs_per_color` | `{cor: int}` | Contagens de referência por cor. |
O formato de salvamento reutiliza a codificação rfft compacta v3 + `float16/uint8`; um codebook de 14 perfis em 2 modelos × 7 resoluções tem ~220 MB em disco.
### Detector V4 (Verificação de Sanidade)
Antes de gastar tempo na validação manual do Gemini, verifique a sanidade das saídas de bypass contra o próprio consenso do codebook V4:```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)
No caminho de correspondência exata de 1024x1024, vemos conf=0.91, phase_match=0.65 para marca d'água e conf=0.02, phase_match=0.31 após dissolve agressivo V4.
V3 permanece no repositório (src/extraction/synthid_bypass.py, bypass_v3) inalterado para quem depende dele.
Estamos coletando ativamente imagens puramente pretas e puramente brancas geradas pelo Nano Banana Pro para melhorar a extração de marca d'água em múltiplas resoluções.
Se você conseguir gerá-las:
gemini_black_nb_pro/ (para preto)gemini_white_nb_pro/ (para branco)Essas imagens de referência são cruciais para:
Mesmo 150–200 imagens em uma nova resolução podem melhorar significativamente a detecção e remoção.
As imagens de referência estão hospedadas no Hugging Face para manter o repositório git leve:```bash pip install huggingface_hub python scripts/download_images.py # download all python scripts/download_images.py gemini_black # download specific folder
Dataset: [huggingface.co/datasets/aoxo/reverse-synthid](https://huggingface.co/datasets/aoxo/reverse-synthid)
---
## Principais Descobertas
### A Marca d'Água é Dependente da Resolução
O SynthID insere frequências portadoras em **posições absolutas diferentes** dependendo da resolução da imagem. Um codebook construído em 1024x1024 não pode remover diretamente a marca d'água de uma imagem 1536x2816 — as portadoras estão em bins completamente diferentes.
| Resolução | Portadora Superior (fy, fx) | Coerência | Fonte |
|:----------:|:---------------------------:|:---------:|:------:|
| **1024x1024** | (9, 9) | 100.0% | 100 refs pretas + 100 brancas |
| **1536x2816** | (768, 704) | 99.6% | 88 imagens de conteúdo com marca d'água |
É por isso que o codebook V3 armazena **perfis separados por resolução** e auto-seleciona no momento do bypass.
### Consistência de Fase — Uma Chave Fixa no Nível do Modelo
O template de fase da marca d'água é **idêntico em todas as imagens** do mesmo modelo Gemini:
- **Canal verde** carrega o sinal de marca d'água mais forte
- **Coerência de fase entre imagens** nas portadoras: >99.5%
- **Validação cruzada preto/branco** confirma portadoras verdadeiras via |cos(phase_diff)| > 0.90
### Estrutura de Frequência das Portadoras
Em 1024x1024 (a partir de refs preto/branco), as portadoras superiores estão em uma grade de baixa frequência:
| Portadora (fy, fx) | Coerência de Fase | Concordância P/B |
|:------------------:|:-----------------:|:----------------:|
| (9, 9) | 100.00% | 1.000 |
| (5, 5) | 100.00% | 0.993 |
| (10, 11) | 100.00% | 0.997 |
| (13, 6) | 100.00% | 0.821 |
---
## Arquitetura
### Gerações de Bypass
| Versão | Abordagem | PSNR | Impacto na Marca d'Água | Status |
|:------:|:----------|:----:|:-----------------------:|:------:|
| **V1** | Compressão JPEG (Q50) | 37 dB | ~11% de queda de fase | Linha de base |
| **V2** | Transformações multi-estágio (ruído, cor, frequência) | 27-37 dB | ~0% de queda de confiança | Compromisso de qualidade |
| **V3** | **Subtração de codebook espectral multi-resolução** | **43+ dB** | **91% de queda de coerência de fase** | Melhor anterior |
| **V4 Rodada 06** | **7 estágios all-in-one (VAE + elástico + compressão + cor + JPEG)** | **visualmente sem perdas** | **detector bypassado ✓** | **Melhor atual** |
### Pipeline V3```
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 ✓)
---
## Início Rápido
### Instalação```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)
### Executar 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']}")
Da CLI:```bash
python src/extraction/synthid_bypass.py bypass input.png output.png
--codebook artifacts/spectral_codebook_v3.npz
--strength aggressive
### Detectar Marca d'Água```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
---
## Aprofundamento Técnico
### Como o SynthID Funciona (Engenharia Reversa)```
┌──────────────────────────────────────────────────────────────┐
│ 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 │
└──────────────────────────────────────────────────────────────┘
O conjunto de aumentos de treino do SynthID (Gowal et al. 2026, Tabela 1) inclui SmallRotation, Cropresize, JPEG, GaussianBlur, BrightnessContrast e Screenshotting — todas transformações espaciais globais e uniformes. O campo de deformação elástica é uma distorção espacialmente variável: cada vizinhança local recebe seu próprio deslocamento independente de sub-pixel. Como os deslocamentos são suaves (suavizados gaussianamente a partir de ruído branco, σ=44–56 px), o conteúdo da imagem não é visualmente afetado, mas a estrutura de consenso de fase da marca d'água torna-se incoerente — ela não pode mais ser agregada em toda a imagem. Este é o equivalente a nível de pixel do efeito de "fragmentação por colagem" que o próprio aplicativo do Gemini cita como um modo de falha do detector.
| Métrica | Valor |
|---|---|
Alosh Denny Pesquisa de Marcação d'Água em IA · Processamento de Sinais
📧 E-mail: [email protected] 🔗 GitHub: https://github.com/aloshdenny
Para colaborações, discussões de pesquisa ou contribuições, fique à vontade para entrar em contato ou abrir uma issue/PR.
Este projeto é mantido de forma independente — sem financiamento de laboratório, sem apoio corporativo.
Se este trabalho foi útil para você ou sua equipe, considere apoiar o desenvolvimento contínuo:
Os fundos vão para custos de computação (horas de GPU para novos perfis de resolução), expansão do conjunto de dados e pesquisa contínua de bypass.
Este projeto é apenas para fins de pesquisa e educação. O SynthID é uma tecnologia proprietária pertencente ao Google DeepMind. Estas ferramentas destinam-se a:
Não utilize estas ferramentas para deturpar conteúdo gerado por IA como sendo criado por humanos.
| Rodada | Estratégia | Resultado |
|---|
| 01 | Subtração espectral conservadora (suave) | ✗ |
| 02 | Subtração espectral agressiva + JPEG | ✗ |
| 03 | Direcionamento absoluto de bin guiado por blog | ✗ |
| 04 | Extração de fase residual de ruído | ✗ |
| 05 | Regeneração por difusão-VAE + deformação geométrica | ✗ |
| 06 | Tudo em um: VAE + fragmentação elástica + compressão + cor + JPEG | ✓ |
| V3 | V4 |
|---|
| Cores de referência | preto + branco | preto, branco, azul, verde, vermelho, cinza (+ baselines de conteúdo diverso/gradiente) |
| Validação cruzada | abs(cos(fase_preto - fase_branco)) | consenso entre cores em 6 cores + concordância por pares |
| Modelos | modelo único (Gemini 2.5) | perfis por modelo (gemini-3.1-flash-image-preview, nano-banana-pro-preview) + union opcional |
| Ataque | subtração espectral apenas | 7 estágios: VAE + elástico + compressão + cor + FFT + cadeia JPEG |
| PSNR (agressivo) | 43 dB | visualmente sem perdas (18–24 dB em nível de pixel; warp desloca pixels) |
| Proteção de fidelidade | nenhuma | reversão por piso PSNR por estágio |
| Bypass do detector | apenas local | confirmado ✓ no app Gemini (ambos os modelos) |
| 43.5 dB |
| SSIM | 0.997 |
| Queda de energia da portadora | 75.8% |
| Queda de coerência de fase (5 portadoras principais) | 91.4% |
| Modelo | Predefinição | Detector ignorado |
|---|
| gemini-3.1-flash-image-preview | final | ✓ |
| gemini-3.1-flash-image-preview | nuke | ✓ |
| nano-banana-pro-preview | final | ✓ |
| nano-banana-pro-preview | nuke | ✓ |