Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
claude-awm — 通过注入 Unicode 变体选择符来规避 LLM 文本水印;包含 SynthID 生成器、mean-g 检测器、归一化防御和熵实验。 | Kitploit
工具/GitHubGitHub/aloshdenny/claude-awm
隐写术隐私保护机器学习AI 安全对抗性攻击
GitHubaloshdenny/claude-awm

claude-awm

通过注入 Unicode 变体选择符来规避 LLM 文本水印;包含 SynthID 生成器、mean-g 检测器、归一化防御和熵实验。

查看仓库
1734天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

claude-awm:你能通过编辑文本擦除 SynthID 文本水印吗?

你好,我是 Alosh ✌🏻

是的,但只有一种攻击类型有效,而且不是大家以为的那种。

Unicode 变体选择符(类别 Mn,U+FE00 到 U+FE0F 以及 U+E0100 到 U+E01EF)能将检测器拉到阈值以下,并保持在那里。我试过的所有其他不可见字符攻击,都会被一行输入归一化完全还原。变体选择符不会,因为它们是承载意义的码位(emoji 呈现、CJK 异体字),NFKC 不会也不应该将其折叠掉。

已在三个模型、两个领域上复现:

模型领域基线 zvs16_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 论文)通过使用带密钥的锦标赛偏置 token 采样来为生成的文本加水印。信号存在于选择了哪些 token中,而不是任何隐藏字符中。我想知道这种机制对于一个有动机、会用查找和替换的人来说有多脆弱,于是我构建了生成器和一个未经训练的 mean-g 检测器,并对它发起了攻击。

检测器阈值为 z = 2.33(1% 误报率)。高于该值即检测到水印。我生成带水印文本、发起攻击、重新分词并评分。每张结果表都带有一个 roundtrip 对照(未受攻击的带水印文本),以便你看到该行中检测器确实在工作。本研究中有两次 bug 使所有 z 值归零,而只有这个对照能发现它。

攻击范围:哪些攻击真正有效

攻击面按 Unicode 类别清晰划分,事实证明这一点就是关键。

有效(类别 Mn,非间距标记):

无效(类别 Cf,格式字符):

Cf 字符纯粹是格式字符,没有语义内容,因此归一化器可以整体删除它们而不会损失任何信息。Mn 变体选择符在 emoji 和 CJK 文本中承载真实含义,因此一刀切地删除它们会破坏合法文档。这种不对称性正是为什么一类攻击是有防御理由的,而另一类没有。

实际可用范围: 这需要大约 20% 或更多的字符被改动,才能将强基线压到阈值以下;但由于插入的字符不可见,任何编辑率下文本读起来都正常。已验证视觉上完全一致,见 src/fidelity_check.py。四个家族只插入不渲染任何内容的字符;同形字攻击是坦诚的例外(依赖字体,不保证不可见)。

无效的方法:那些显而易见的操作

我最初的担忧很老套:担心把破折号换成连字符、把 "and" 换成 "&"、去掉 markdown 之类的操作就能奏效,那样水印就会沦为安全表演。网上很多人恰恰就是这么假设的。

这些并不奏效。在 gpt-oss-20b 上的整个表面编辑阶梯,直到 32k token:

在三个模型(0.8B、4B、20B = 294 个单元格)中,恰好一个单元格越过了阈值:在 4B 模型上以最短长度删除每个词 39% 的字符。那不算攻击,那是把文档撕碎。

有两件事让我意外:

  • 编辑数量无法预测破坏程度,编辑几何分布才行。 去除所有 markdown(13.6% 的 token)毫无效果;它甚至得分略高于基线。以 1.6% 的比例注入零散空格,每次编辑造成的破坏要高 25 倍。Markdown 标记聚集在一起,因此它们的破坏窗口相互重叠,而它们之间的大段散文会不断完整地重放水印种子。使分词器失步的分散编辑每次都会击中全新的窗口。
  • 长度帮助的是检测器,而不是攻击者。 z 随 sqrt(tokens) 增长。“在长上下文中骗过它”是完全反的,32k 是最难攻击的情况,而不是最容易的。

完整机制和逐攻击表见 docs/FINDINGS.md。

试试交互式版本 → 包含真实研究样本和前后对照显示开关,以及一个可对你自己文本运行攻击变换的游乐场。它不会告诉你任意粘贴的文本是否真的带水印(这需要我们没有的密钥),而且它也明确说明了这一点;生成脚本见 site/。

无需攻击的发现

水印寄生于模型对每个 token 的不确定性。当模型对下一个 token 很有信心时,锦标赛就没有空间去偏置它,因此不会有信号注入。这意味着水印在低熵文本上很弱,而代码就是低熵的。

Qwen3.5-4B,散文与代码,512-token 样本,完全没有攻击:

领域熵z
散文1.19 bits/tok11.1
代码0.55 bits/tok5.0

z 比值为 0.45 倍,熵比值为 0.46 倍,两者同步变化,这正是底层机制在显现。**8 个代码样本中有 3 个自行落到了检测阈值或以下。**最紧凑的那个(一个裸算法,0.2 bits/token)得分为 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 类别字符。能干掉零宽字符、双向控制符以及各种组合。这是最大的收益。
  2. 做 NFKC 折叠。能处理 nbsp 和兼容形式。
  3. 显式去除变体选择符范围。 NFKC 不会替你完成这件事,而这是目前仍然敞开的缺口。
  4. 为同形字维护一份 Unicode confusables 映射(UTS-39)。NFKC 同样不会做这件事。

第 3 步和第 4 步正是朴素的归一化器会遗漏的。

本研究的不足 / 我未能完成的部分

坦白面对这些缺口。

  • 27B 的代码数据作为攻击结果没有信息量。 未受攻击的基线已经是 z = 4.31,因此你无法展示一种攻击能击败一个本就近乎失明的检测器。我保留了这些行,但已作标记;有意义的信号是基线,而不是攻击差值。
  • 27B 的代码结果究竟是熵还是模型风格所致,尚无定论。 它需要像 4B 那样进行逐 token 熵测量,而我没有对该模型运行这样的测量。
  • GLM-5.2 没有产出任何数据。 我租了一个 8xA100 pod,连续遇到五次基础设施故障(已废弃的下载命令、torch/torchvision ABI 损坏、模型加载进主机内存而不是 GPU),烧掉了约 25 美元,其中 19 美元花在一个空转的 pod 上——因为我信任了一个从未开始的下载,最终只能一无所获地终止它。Kimi-K3 从未尝试;大约 1.5TB 的体积即使量化后也需要 20+ 块 A100。前沿规模的问题仍未解决。
  • Qwen3.8-27B 的三个社区量化检查点均加载失败(FP8 需要我们没有的 torch dtype;两个 AWQ/compressed-tensors 重新打包版存在打包不匹配)。改为在 H100 上以 bf16 运行。如果你要复现,跳过那些重新打包的版本。
  • 检测器是未经训练的 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 使用 HF 的 GPU 处理器(在词表大的模型上快得多;在 H100 上,这决定了 GPU 利用率是 0% 还是 46%)。

水印需要完整的下一个 token 分布,因此它通过 transformers 运行(CUDA 原生 MXFP4,或 MPS/CPU)。Ollama 和 llama.cpp 做不到这一点,它们不会在生成过程中暴露 logits。在 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
去除所有 markdown13.6%27.2103.3
美式英语转英式英语 + 缩写1.3%~28~100
删除每个词 40% 的字符38%4.925.4