Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
claude-awm — Umgeht LLM-Textwasserzeichen durch Einfügen von Unicode-Variationsselektoren; enthält den SynthID-Generator, den mean-g-Detektor, Normalisierungsabwehrmaßnahmen und Entropie-Experimente. | Kitploit
Tools/GitHubGitHub/aloshdenny/claude-awm
SteganografiePrivatsphäreMaschinelles LernenKI-SicherheitAdversarial-Angriff
GitHubaloshdenny/claude-awm

claude-awm

Umgeht LLM-Textwasserzeichen durch Einfügen von Unicode-Variationsselektoren; enthält den SynthID-Generator, den mean-g-Detektor, Normalisierungsabwehrmaßnahmen und Entropie-Experimente.

Repository anzeigen
173vor 2 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

claude-awm: Kann man ein SynthID-Textwasserzeichen durch Bearbeiten des Texts entfernen?

Hallo, Alosh hier ✌🏻

Ja, aber nur eine Angriffsfamilie funktioniert – und es ist nicht die, die alle vermuten.

Unicode-Variationsselektoren (Kategorie Mn, U+FE00 bis U+FE0F und U+E0100 bis U+E01EF) drücken den Detektor unter die Schwelle und bleiben dort. Jeder andere Angriff mit unsichtbaren Zeichen, den ich versucht habe, wird durch eine einzige Zeile Eingabenormalisierung vollständig rückgängig gemacht. Variationsselektoren nicht, weil sie bedeutungstragende Codepoints sind (Emoji-Präsentation, CJK-Varianten), die NFKC weder entfernen wird noch sollte.

Reproduziert auf drei Modellen, zwei Domänen:

ModellDomäneBasis-znach vs16_30Änderungsrate
gpt-oss-20bProsa45.030.7257 %
gpt-oss-20bCode37.240.6858 %
Qwen3.8-27BProsa35.50-0.6757 %

Die Schwelle liegt bei z = 2,33. Alle drei landen darunter und bleiben nach der Normalisierung darunter (0,09, 0,45 bzw. -0,78). Der Text sieht für einen menschlichen Leser identisch aus.

Der zweite echte Befund braucht überhaupt keinen Angriff: Text mit niedriger Entropie ist von vornherein kaum mit Wasserzeichen versehen. Die Codegenerierung von Qwen3.8-27B hat eine saubere Basis von z = 4,31 – ohne dass irgendetwas damit gemacht wurde, liegt sie bereits nahe an der Schwelle.

worum es geht

Anthropic (und zuvor Google DeepMind, das SynthID-Text-Paper) markierte generierten Text, indem sie das Token-Sampling mit einem schlüsselbasierten Turnier verzerrten. Das Signal liegt darin, welche Tokens ausgewählt wurden, nicht in einem versteckten Zeichen. Ich wollte wissen, wie fragil das gegenüber einer motivierten Person mit Suchen-und-Ersetzen ist, also baute ich den Generator plus einen untrainierten Mean-g-Detektor und schleuderte Angriffe darauf.

Die Detektorschwelle liegt bei z = 2,33 (1 % Falschpositivrate). Darüber = Wasserzeichen erkannt. Ich erzeugte wasserzeichenmarkierten Text, griff ihn an, tokenisierte ihn neu und bewertete ihn. Jede Ergebnistabelle enthält eine roundtrip-Kontrolle (nicht angegriffener wasserzeichenmarkierter Text), damit man sieht, dass der Detektor in dieser Zeile tatsächlich funktioniert. Zweimal in dieser Studie ließ ein Bug alle z auf Null zusammenfallen, und nur die Kontrolle hat das aufgedeckt.

Umfang des Angriffs: was tatsächlich funktioniert

Die Angriffsfläche teilt sich sauber nach Unicode-Kategorie auf – und das war die ganze Geschichte.

Funktioniert (Kategorie Mn, nichtabstandbildende Zeichen):

Funktioniert nicht (Kategorie Cf, Formatzeichen):

Cf-Zeichen sind reine Formatierung ohne semantischen Inhalt, daher kann ein Normalisierer sie im Ganzen entfernen, ohne etwas zu verlieren. Mn-Variationsselektoren tragen echte Bedeutung in Emoji- und CJK-Text, daher würde ihr pauschales Entfernen legitime Dokumente beschädigen. Diese Asymmetrie ist der Grund, warum die eine Familie verteidigbar ist und die andere nicht.

Der praktische Rahmen: Es müssen grob 20 % oder mehr der Zeichen angefasst werden, um eine starke Basis unter die Schwelle zu drücken, aber die eingefügten Zeichen sind unsichtbar, sodass der Text bei jeder Änderungsrate normal lesbar ist. Es ist visuell identisch verifiziert, siehe src/fidelity_check.py. Vier Familien fügen nur Zeichen ein, die nichts rendern; Homoglyphen sind die ehrliche Ausnahme (schriftartabhängig, nicht garantiert unsichtbar).

was nicht funktioniert: das Offensichtliche

Meine anfängliche Befürchtung war die langweilige: dass Gedankenstriche und die Ersetzung von „and“ durch „&“ sowie das Entfernen von Markdown einfach funktionieren würden und das Wasserzeichen sich als Sicherheitstheater herausstellen würde. Viele Leute online nehmen genau das an.

Es funktioniert nicht. Die gesamte Leiter oberflächlicher Edits auf gpt-oss-20b, bis zu 32k Tokens:

Über drei Modelle (0,8B, 4B, 20B = 294 Zellen) hat genau eine Zelle die Schwelle überschritten: das Löschen von 39 % eines jeden Worts bei der kürzesten Länge auf dem 4B. Das ist kein Angriff, das ist das Schreddern des Dokuments.

Zwei Dinge haben mich überrascht:

  • Die Anzahl der Edits sagt keinen Schaden voraus, die Geometrie der Edits schon. Das Entfernen des gesamten Markdowns (13,6 % der Tokens) bewirkte nichts; es schnitt sogar leicht über der Basis ab. Das Einfügen verstreuter Leerzeichen bei 1,6 % richtete pro Edit 25-mal mehr Schaden an. Markdown-Marker treten gehäuft auf, daher überlappen ihre Korruptionsfenster, und die langen Prosa-Abschnitte dazwischen spielen den Wasserzeichen-Seed unversehrt weiter ab. Verstreute Edits, die den Tokenizer desynchronisieren, treffen jedes Mal frische Fenster.
  • Länge hilft dem Detektor, nicht dem Angreifer. z wächst wie sqrt(tokens). „Täusche es über einen langen Kontext“ ist rückwärts gedacht: 32k ist der am schwersten anzugreifende Fall, nicht der einfachste.

Vollständiger Mechanismus und Tabellen pro Angriff in docs/FINDINGS.md.

Probier die interaktive Version aus → Echte Studien-Stichproben mit einem Vorher/Nachher-Anzeige-Umschalter sowie eine Spielwiese, um die Angriffstransformation auf deinen eigenen Text anzuwenden. Es teilt dir nicht mit, ob beliebig eingefügter Text wirklich ein Wasserzeichen trägt (dafür bräuchte es einen Schlüssel, den wir nicht haben), und genau das sagt es auch; siehe site/ für das Generator-Skript.

der Befund, der keinen Angriff braucht

Das Wasserzeichen reitet auf der Token-für-Token-Unsicherheit des Modells. Wo das Modell beim nächsten Token sicher ist, hat das Turnier keinen Raum, es zu verzerren, also geht kein Signal hinein. Das bedeutet: Die Markierung ist bei Text mit niedriger Entropie schwach, und Code hat niedrige Entropie.

Qwen3.5-4B, Prosa vs. Code, 512-Token-Stichproben, überhaupt kein Angriff:

DomäneEntropiez
Prosa1.19 bits/tok11.1
Code0.55 bits/tok5.0

z-Verhältnis 0,45x, Entropie-Verhältnis 0,46x, sie bewegen sich gemeinsam – der Mechanismus zeigt sich durch. 3 von 8 Code-Stichproben fielen von selbst auf oder unter die Erkennungsschwelle. Die engste (ein nackter Algorithmus, 0,2 Bits/Token) erreichte 1,7, ein Fehlschlag.

Im größeren Maßstab wird es extremer. Basis-z ganz ohne Angriff:

ModellProsaCodeVerhältnis
gpt-oss-20b45.0337.240.83
Qwen3.8-27B35.504.310.12

Die Codeausgabe von Qwen3.8-27B ist so stark vorlagenbasiert, dass das saubere, nicht angegriffene Wasserzeichen bei z = 4,31 sitzt, kaum über der 2,33-Schwelle. Kein Angreifer nötig.

Das bedeutet: Eine einzige Konfidenzschwelle über alle Domänen hinweg ist unsicher, und kurze Codeschnipsel sind nahezu unmarkierbar. Das gilt auch für JSON, Konfiguration, strukturierte Extraktion und Boilerplate.

Fazit für die Verteidigung

Wenn du einen solchen Detektor auslieferst, bringt dich die Normalisierung der Eingabe einen großen Teil des Weges, aber nicht den gesamten:

  1. Entferne Zeichen der Kategorie Cf. Tötet Zero-Width, Bidi und die Kombos. Das ist der große Gewinn.
  2. NFKC-Faltung. Behandelt nbsp- und Kompatibilitätsformen.
  3. Entferne die Variationsselektor-Bereiche explizit. NFKC wird das nicht für dich tun, und das ist die Lücke, die derzeit offen ist.
  4. Halte eine Unicode-Confusables-Karte (UTS-39) für Homoglyphen bereit. NFKC macht das auch nicht.

Die Schritte 3 und 4 sind die, die ein naiver Normalisierer übersieht.

was daran falsch ist / wozu ich nicht gekommen bin

Ehrlich sein über die Lücken.

  • Die 27B-Codezahlen sind als Angriffsergebnis uninformativ. Die nicht angegriffene Basis liegt dort bei z = 4,31, also lässt sich kein Angriff demonstrieren, der einen ohnehin fast blinden Detektor schlägt. Ich habe diese Zeilen behalten, aber markiert; das aussagekräftige Signal ist die Basis, nicht die Angriffs-Deltas.
  • Ob das 27B-Codeergebnis auf Entropie oder Modellstil zurückgeht, ist ungeklärt. Es bräuchte eine Token-für-Token-Entropiemessung wie bei der 4B, die ich für dieses Modell nicht durchgeführt habe.
  • GLM-5.2 hat keinerlei Daten produziert. Ich mietete einen 8xA100-Pod und kassierte fünf Infrastrukturfehler in Folge (veralteter Download-Befehl, ABI-Brüche bei torch/torchvision, Modell, das in den Host-RAM statt in die GPUs geladen wurde), verbrauchte etwa 25 $, davon 19 $ für einen Pod, der leerlief, weil ich einem Download vertraute, der nie begonnen hatte, und beendete ihn ohne Ergebnisse. Kimi-K3 habe ich nie versucht; bei etwa 1,5 TB braucht es selbst quantisiert 20+ A100. Die Frage im Frontier-Maßstab ist offen.
  • Drei Community-quantisierte Checkpoints von Qwen3.8-27B ließen sich nicht laden (FP8 wollte einen torch-dtype, den wir nicht haben, zwei AWQ/compressed-tensors-Neuverpackungen mit Packungsfehlern). Habe es stattdessen auf einer H100 mit bf16 ausgeführt. Wenn du das reproduzierst, überspringe die Neuverpackungen.
  • Der Detektor ist der untrainierte Mean-g-Scorer, nicht der trainierte Bayessche aus dem Paper. Der Bayessche Detektor wäre vermutlich empfindlicher, also sind diese z-Werte eine Untergrenze, aber ich habe es nicht gemessen.
  • Mein Anspruch an die Homoglyphen-Treue ist „typischer Leser“, nicht bewiesen. Das kyrillische а ist Kategorie Ll, seine Unsichtbarkeit ist also eine Schrifteigenschaft, keine Unicode-Garantie.
  • n ist klein, 2 Dokumente pro Zelle für die Leitern, 8 Stichproben pro Domäne für die Entropie. Genug für die Effektgrößen hier (sie sind groß), nicht genug für enge Fehlerbalken pro Angriff.
  • Ich liefere kein abgestimmtes Umgehungsrezept, und das ist beabsichtigt. Jeder Angriff wird hier zusammen mit dem Normalisierungsergebnis berichtet, das ihn besiegt oder nicht. Es ging darum zu messen, wo die Grenze verläuft, nicht darum, einen Bypass zu verpacken.

Aufbau

root@kitploit:~
src/synthid_robustness.py   generator + attack ladder + mean-g detector + normalizer
src/code_vs_prose.py        the entropy experiment (with per-token entropy tap)
src/fidelity_check.py       proves the stego attacks are visually identical
src/synthid_mlx.py          watermarking bridge for Apple Silicon (MLX), validated vs HF
src/prompts_code.py         prose / code / mixed prompt sets
src/build_report_data.py    assembles results/ into the tables in FINDINGS.md
results/                    the JSON this is all computed from
docs/FINDINGS.md            every table, the defense hierarchy, the bugs I caught

Ausführen

root@kitploit:~
python -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
root@kitploit:~
# generate watermarked docs + run the full attack ladder on a model
MODEL=Qwen/Qwen3.5-4B LENGTHS=1024,2048,4096,8192 N_DOCS=2 \
  DOCS=docs_4b.json OUT=res_4b.json python src/synthid_robustness.py

# the entropy experiment (code vs prose)
python src/code_vs_prose.py --model Qwen/Qwen3.5-4B --out res_cvp_4b.json

# the variation-selector / stego attacks, scored raw AND post-normalization
ATTACK_SET=desync DEFENSE=1 PROMPT_SET=prose MODEL=Qwen/Qwen3.5-4B \
  DOCS=docs_4b.json OUT=res_defense.json python src/synthid_robustness.py

PROMPT_SET akzeptiert prose, code oder mixed. FAST_WM=1 verwendet eine numpy-Wasserzeichen-Brücke (schneller bei Modellen mit kleinem Vokabular und starker CPU), FAST_WM=0 verwendet den GPU-Prozessor von HF (viel schneller bei Modellen mit großem Vokabular; auf einer H100 war das der Unterschied zwischen 0 % und 46 % GPU-Auslastung).

Wasserzeichenmarkierung benötigt die vollständige Next-Token-Verteilung, also läuft sie über transformers (CUDA nativ MXFP4 oder MPS/CPU). Ollama und llama.cpp können das nicht; sie legen während der Generierung keine Logits offen. Auf Apple Silicon überbrückt src/synthid_mlx.py die MLX-Generierung in die Wasserzeichen-Mathematik; es ist als bit-identisch zur HF-Referenz validiert.


der Traum, angeblich

(das Meme, mit dem alles anfing. Es stellt sich heraus, dass man Variationsselektoren braucht, kein Suchen-und-Ersetzen.)


Hinweis: Ich habe Claude Code intensiv für die Implementierung genutzt und um Experimente auf vier Maschinen erneut auszuführen (ein Mac, meine eigene 4090, eine gemietete 3090 und eine H100). Das Versuchsdesign, die Angriffe, die ich ausprobieren wollte, und die Entscheidungen zur Rahmung stammen von mir. Claude bestand darauf, jeden Angriff gegen seine eigene Verteidigung zu messen – deshalb haben die Stego-Tabellen eine rohe und eine normalisierte Spalte statt nur der rohen; genau das hat aus „unsichtbare Zeichen brechen es“ den eigentlichen Befund gemacht, nämlich dass nur die aus der Kategorie Mn einen Normalisierer überleben.

Tool herunterladen
Angriffwas er tutÄnderungsrateübersteht Normalisierung?
vs16_30Variationsselektor nach ~30 % der Zeichen57 %ja
vs16Variationsselektor nach ~10 % der Zeichen23 %ja (z 3,46)
vs_suppSelektoren aus der Supplementary-Plane (U+E0100+)24 %ja (z 3,40)
homoglyphkyrillisches а für lateinisches a (Kategorie Ll)9 %ja, aber schwache Wirkung
Angriffroh znormalisiertes zErgebnis
zwsp_30-0.0935.68vollständig rückgängig gemacht
combo0.9235.68vollständig rückgängig gemacht
bidi24.3735.68vollständig rückgängig gemacht
nbsp41.0446.51bewegt es kaum
AngriffÄnderungsratez @ 1kz @ 32k
roundtrip (Kontrolle)0 %25.7104.3
Gedankenstrich zu Bindestrich~0 %26.4113.7
gesamtes Markdown entfernen13.6 %27.2103.3
AmE zu BrE + Abkürzungen1.3 %~28~100
40 % jedes Worts löschen38 %4.925.4