Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
claude-awm — Обходит текстовые водяные знаки LLM, внедряя селекторы вариантов Unicode; включает генератор SynthID, детектор mean-g, защиту от нормализации и эксперименты с энтропией. | Kitploit
Инструменты/GitHubGitHub/aloshdenny/claude-awm
СтеганографияКонфиденциальностьМашинное ОбучениеБезопасность ИИСостязательная Атака
GitHubaloshdenny/claude-awm

claude-awm

Обходит текстовые водяные знаки LLM, внедряя селекторы вариантов Unicode; включает генератор SynthID, детектор mean-g, защиту от нормализации и эксперименты с энтропией.

Репозиторий
1734 дней назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

claude-awm: можно ли убрать текстовый водяной знак SynthID, редактируя текст?

Привет, это Alosh ✌🏻

Да, но работает только одно семейство атак, и это не то, которое все предполагают.

Unicode селекторы вариантов начертания (категория Mn, U+FE00 to U+FE0F and U+E0100 to U+E01EF) уводят детектор ниже порога и остаются там. Любая другая атака с невидимыми символами, которую я пробовал, полностью откатывается одной строкой нормализации ввода. Селекторы вариантов — нет, потому что это значимые кодовые точки (презентация эмодзи, варианты CJK), которые NFKC не сворачивает и не должен сворачивать.

Воспроизведено на трёх моделях и двух доменах:

модельдоменбазовое zпосле vs16_30доля правок
gpt-oss-20bпроза45.030.7257%
gpt-oss-20bкод37.240.6858%
Qwen3.8-27Bпроза35.50-0.6757%

Порог — z = 2.33. Все три значения оказываются ниже него и остаются ниже после нормализации (0.09, 0.45 и -0.78 соответственно). Для читателя-человека текст выглядит идентично.

Второй настоящий результат не требует вообще никакой атаки: низкоэнтропийный текст изначально почти не содержит водяного знака. Генерация кода у Qwen3.8-27B даёт чистый базовый уровень z = 4.31, который уже находится вблизи порога без какого-либо воздействия.

что это

Anthropic (а до них Google DeepMind в статье SynthID-Text) наносила водяной знак на генерируемый текст, смещая сэмплирование токенов с помощью турнира с ключом. Сигнал живёт в том, какие токены были выбраны, а не в каком-то скрытом символе. Мне хотелось понять, насколько это уязвимо перед мотивированным человеком с функцией поиска и замены, поэтому я собрал генератор, необученный детектор mean-g и обрушил на него атаки.

Порог детектора — z = 2.33 (1% ложноположительных срабатываний). Выше него = водяной знак обнаружен. Я генерировал текст с водяным знаком, атаковал его, заново токенизировал и оценивал. В каждой таблице результатов есть контроль roundtrip (неатакованный текст с водяным знаком), чтобы видно было, что детектор в этой строке действительно работает. Дважды за время исследования баг обнулял все z, и только контроль позволил это заметить.

охват атаки: что реально работает

Поверхность атаки чётко делится по категориям Unicode, и в этом, как оказалось, вся суть.

Работает (категория Mn, непробельные знаки):

Не работает (категория Cf, символы форматирования):

Символы категории Cf — это чистое форматирование без семантического содержания, поэтому нормализатор может вычистить их целиком и ничего не потерять. Селекторы вариантов Mn несут реальный смысл в тексте с эмодзи и CJK, поэтому их массовое удаление испортило бы легитимные документы. Именно эта асимметрия объясняет, почему одно семейство можно вычищать, а другое нельзя.

Практический охват: чтобы сдвинуть сильный базовый уровень ниже порога, нужно затронуть примерно 20% символов и больше, но вставленные символы невидимы, поэтому текст читается нормально при любой доле правок. Визуальная идентичность подтверждена, см. src/fidelity_check.py. Четыре семейства вставляют только символы, которые не отображаются; гомоглифы — честное исключение (зависит от шрифта, невидимость не гарантирована).

что не работает: очевидные вещи

Моим первоначальным страхом был скучный сценарий: что длинные тире, замена «and» на «&» и удаление разметки просто сработают, и водяной знак окажется театральной защитой. Многие в интернете предполагают именно это.

Это не работает. Вся лестница поверхностных правок на gpt-oss-20b вплоть до 32k токенов:

На трёх моделях (0.8B, 4B, 20B = 294 ячейки) ровно одна ячейка пересекла порог: удаление 39% каждого слова при самой короткой длине на модели 4B. Это не атака, это уничтожение документа.

Меня удивили две вещи:

  • Количество правок не предсказывает ущерб; его предсказывает геометрия правок. Удаление всей разметки (13.6% токенов) не дало ничего; оно даже показало результат немного выше базового. Вставка случайных пробелов на 1.6% нанесла в 25 раз больше урона в пересчёте на одну правку. Маркеры разметки группируются, поэтому их окна искажения перекрываются, а длинные прозаические участки между ними продолжают без изменений воспроизводить зерно водяного знака. Разрозненные правки, рассинхронизирующие токенизатор, каждый раз попадают в свежие окна.
  • Длина помогает детектору, а не атакующему. z растёт как sqrt(токенов). «Обмануть его на длинном контексте» — это наоборот: 32k — самый сложный случай для атаки, а не самый лёгкий.

Полный механизм и таблицы по каждой атаке — в docs/FINDINGS.md.

Попробуйте интерактивную версию → Реальные образцы из исследования с переключателем «до/после», плюс песочница, в которой можно применить атакующее преобразование к своему тексту. Она не скажет вам, действительно ли произвольный вставленный текст содержит водяной знак (для этого нужен ключ, которого у нас нет), и прямо об этом говорит; см. site/ — там скрипт генератора.

результат, который не требует атаки

Водяной знак держится на неуверенности модели по каждому токену. Там, где модель уверена в следующем токене, у турнира нет возможности сместить выбор, поэтому сигнал не попадает в текст. Это значит, что знак слаб на низкоэнтропийном тексте, а код как раз низкоэнтропиен.

Qwen3.5-4B, проза против кода, выборки по 512 токенов, без какой-либо атаки:

доменэнтропияz
проза1.19 бит/ток11.1
код0.55 бит/ток5.0

Отношение z — 0.45x, отношение энтропии — 0.46x, они движутся вместе, и в этом проявляется сам механизм. 3 из 8 образцов кода сами по себе опустились до порога обнаружения или ниже него. Самый низкоэнтропийный из них (голый алгоритм, 0.2 бит/токен) набрал 1.7 — мимо.

В масштабе это становится ещё более выраженным. Базовый уровень z вообще без атак:

модельпрозакодотношение
gpt-oss-20b45.0337.240.83
Qwen3.8-27B35.504.310.12

Кодовый вывод Qwen3.8-27B настолько шаблонен, что чистый, неатакованный водяной знак оказывается на уровне z = 4.31, едва выше порога 2.33. Противник не нужен.

Это говорит о том, что единый порог уверенности для всех доменов небезопасен, а короткие фрагменты кода почти нельзя пометить водяным знаком. Это обобщается на JSON, конфиги, структурированное извлечение и шаблонный код.

защитный вывод

Если вы внедряете один из таких детекторов, нормализация входа закрывает бо́льшую часть пути, но не весь:

  1. Удаляйте символы категории Cf. Это убивает zero-width, bidi и их комбинации. Самый большой выигрыш.
  2. Применяйте свёртку NFKC. Обрабатывает nbsp и формы совместимости.
  3. Явно удаляйте диапазоны селекторов вариантов начертания. NFKC этого за вас не сделает, и именно здесь сейчас открыт зазор.
  4. Держите карту конфьюзаблов Unicode (UTS-39) для гомоглифов. NFKC этого тоже не сделает.

Именно шаги 3 и 4 пропускает наивный нормализатор.

что здесь не так / до чего я не дошёл

Честно о пробелах.

  • Цифры по коду на 27B малоинформативны как результат атаки. Неатакованный базовый уровень там — z = 4.31, поэтому нельзя продемонстрировать атаку, которая побеждает детектор, уже почти слепой. Я сохранил эти строки, но пометил их; значимый сигнал — это базовый уровень, а не дельты атак.
  • Остаётся невыясненным, является ли результат по коду на 27B следствием энтропии или стиля модели. Для этого нужно было бы измерить энтропию по токенам, как это было сделано для 4B, но я не запускал это для той модели.
  • GLM-5.2 не дал ни одного результата. Я арендовал под с 8xA100 и последовательно наткнулся на пять отказов инфраструктуры (устаревшая команда загрузки, поломки ABI torch/torchvision, загрузка модели в оперативную память хоста вместо GPU), сжёг около $25, включая $19 за под, который простаивал, потому что я доверился загрузке, так и не начавшейся, и завершил его ни с чем. Kimi-K3 я даже не пробовал: при ~1.5TB даже в квантованном виде ему нужно 20+ A100. Вопрос о моделях frontier-масштаба остаётся открытым.
  • Три квантованных чекпоинта Qwen3.8-27B от сообщества не загрузились (FP8 требовал torch dtype, которого у нас нет; две пересборки AWQ/compressed-tensors с несовпадением упаковки). Вместо этого я запустил её в bf16 на H100. Если будете воспроизводить, пропускайте пересборки.
  • Детектор — это необученный скоринг mean-g, а не обученный байесовский из статьи. Байесовский детектор, скорее всего, был бы чувствительнее, так что эти значения z — нижняя граница, но я её не измерял.
  • Моё утверждение о невидимости гомоглифов — «типичный читатель», а не доказанный факт. Кириллическая а относится к категории Ll, поэтому её невидимость — свойство шрифта, а не гарантия Unicode.
  • n небольшое: 2 документа на ячейку для лестниц атак и 8 образцов на домен для энтропии. Этого достаточно для наблюдаемых эффектов (они велики), но недостаточно для узких планок погрешности по каждой атаке.
  • Я не даю доведённый до ума рецепт обхода, и это осознанное решение. Каждая атака здесь описана вместе с результатом нормализации, которая либо побеждает её, либо нет. Целью было измерить, где проходит граница возможного, а не упаковать готовый обход.

структура проекта

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

запуск

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 принимает значения prose, code или mixed. FAST_WM=1 использует numpy-мост для нанесения водяного знака (быстрее на моделях с небольшим словарём и мощным CPU), FAST_WM=0 использует GPU-процессор от HF (намного быстрее на моделях с большим словарём; на H100 это была разница между 0% и 46% загрузки GPU).

Для нанесения водяного знака нужно полное распределение следующего токена, поэтому используется transformers (CUDA native MXFP4 или MPS/CPU). Ollama и llama.cpp так не могут: они не отдают логиты в процессе генерации. На Apple Silicon src/synthid_mlx.py интегрирует генерацию MLX в математику водяного знака; проверено, что результат побитово идентичен эталону HF.


мечта, как утверждается

(тот самый мем, с которого всё началось. оказалось, нужны селекторы вариантов начертания, а не «найти и заменить».)


Примечание: я активно использовал Claude Code для реализации и повторного запуска экспериментов на четырёх машинах (Mac, моя собственная 4090, арендованная 3090 и H100). Дизайн эксперимента, атаки, которые я хотел проверить, и решения по подаче материала — мои. Claude настоял на том, чтобы каждую атаку измерять против её собственной защиты, поэтому в таблицах стего-атак есть сырая и нормализованная колонка, а не только сырая; именно это превратило «невидимые символы ломают защиту» в настоящий вывод: нормализатор переживают только символы категории Mn.

Скачать инструмент
атакачто делаетдоля правокпереживает нормализацию?
vs16_30селектор вариантов начертания после ~30% символов57%да
vs16селектор вариантов начертания после ~10% символов23%да (z 3.46)
vs_suppселекторы дополнительной плоскости (U+E0100+)24%да (z 3.40)
homoglyphкириллическая а вместо латинской a (категория Ll)9%да, но эффект слабый
атакасырое zнормализованное zвердикт
zwsp_30-0.0935.68полностью откатывается
combo0.9235.68полностью откатывается
bidi24.3735.68полностью откатывается
nbsp41.0446.51едва сдвигает
атакадоля правокz @ 1kz @ 32k
roundtrip (контроль)0%25.7104.3
длинное тире на дефис~0%26.4113.7
удалить всю разметку13.6%27.2103.3
амер. англ. на брит. англ. + аббревиатуры1.3%~28~100
удалить 40% каждого слова38%4.925.4