Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
claude-awm — 유니코드 변형 선택자를 주입하여 LLM 텍스트 워터마크를 우회합니다. SynthID 생성기, mean-g 탐지기, 정규화 방어 및 엔트로피 실험을 포함합니다. | Kitploit
도구/GitHubGitHub/aloshdenny/claude-awm
SteganographyPrivacyMachine LearningAI SecurityAdversarial Attack
GitHubaloshdenny/claude-awm

claude-awm

유니코드 변형 선택자를 주입하여 LLM 텍스트 워터마크를 우회합니다. SynthID 생성기, mean-g 탐지기, 정규화 방어 및 엔트로피 실험을 포함합니다.

저장소 보기
1734일 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

claude-awm: 텍스트를 편집해서 SynthID 텍스트 워터마크를 지울 수 있을까?

안녕하세요, Alosh입니다 ✌🏻

네, 하지만 작동하는 공격 계열은 하나뿐이고, 모두가 짐작하는 그 공격은 아닙니다.

유니코드 변형 선택자(variation selectors)(카테고리 Mn, U+FE00U+FE0F 및 U+E0100U+E01EF)는 검출기를 임계값 아래로 몰아넣고 그 상태를 유지합니다. 제가 시도한 다른 모든 보이지 않는 문자 공격은 입력 정규화 한 줄로 완전히 되돌려졌습니다. 변형 선택자는 그렇지 않은데, 이는 의미 있는 코드포인트(이모지 표현, 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 논문)은 키 기반 토너먼트로 토큰 샘플링에 편향을 주는 방식으로 생성 텍스트에 워터마크를 새겼습니다. 신호는 숨겨진 문자가 아니라 어떤 토큰이 선택되었는지에 있습니다. 저는 이것이 찾기 및 바꾸기 도구를 가진 동기 부여된 사람에게 얼마나 취약한지 알고 싶어서, 생성기와 훈련되지 않은 mean-g 검출기를 만들고 공격을 퍼부었습니다.

검출기 임계값은 z = 2.33(오탐률 1%)입니다. 이보다 높으면 워터마크로 검출됩니다. 저는 워터마크가 있는 텍스트를 생성하고, 공격하고, 다시 토큰화한 뒤 점수를 매겼습니다. 모든 결과 테이블에는 roundtrip 대조군(공격하지 않은 워터마크 텍스트)이 있어 해당 행에서 검출기가 실제로 작동한다는 것을 확인할 수 있습니다. 이 연구에서 두 번, 버그로 모든 z가 0으로 붕괴했고 대조군만이 그것을 잡아냈습니다.

공격 범위: 실제로 효과가 있는 것

공격 표면은 유니코드 범주에 따라 깔끔하게 나뉘는데, 그것이 사실상 전부였습니다.

효과 있음(카테고리 Mn, 비간격 결합 부호):

효과 없음(카테고리 Cf, 형식 문자):

Cf 문자는 의미 내용이 없는 순수한 형식 문자이므로, 정규화기가 그것들을 통째로 제거해도 잃을 것이 없습니다. Mn 변형 선택자는 이모지와 CJK 텍스트에서 실제 의미를 지니므로, 무차별적으로 제거하면 정당한 문서가 손상됩니다. 이러한 비대칭성 때문에 한 계열은 방어가 가능하고 다른 계열은 그렇지 않습니다.

현실적 범위: 강한 기준값을 임계값 아래로 밀어내려면 대략 20% 이상의 문자를 건드려야 합니다. 하지만 삽입된 문자는 보이지 않으므로 어떤 편집률에서도 텍스트는 정상적으로 읽힙니다. 시각적으로 동일함이 검증되어 있습니다(src/fidelity_check.py 참조). 네 계열은 아무것도 렌더링하지 않는 문자만 삽입합니다. homoglyph는 솔직한 예외입니다(글꼴에 따라 다르며, 보이지 않음이 보장되지 않습니다).

작동하지 않는 것: 뻔한 방법들

제가 처음에 가졌던 두려움은 지루한 것이었습니다. 엠 대시를 하이픈으로 바꾸고, "and"를 "&"로 바꾸고, markdown을 제거하면 그냥 통하지 않을까, 그러면 워터마크가 보안 연극(security theater)에 불과한 게 아닐까였습니다. 온라인의 많은 사람들이 정확히 그렇게 가정합니다.

그것은 작동하지 않습니다. gpt-oss-20b에서 32k 토큰까지 확장한 전체 표면 편집 래더는 다음과 같습니다:

세 모델(0.8B, 4B, 20B = 294개 셀)에서 정확히 하나의 셀만 임계값을 넘었습니다: 4B에서 가장 짧은 길이일 때 모든 단어의 39%를 삭제한 경우입니다. 그건 공격이 아니라 문서를 분쇄하는 것입니다.

저를 놀라게 한 두 가지가 있습니다:

  • **손상은 편집 횟수가 아니라 편집 기하(geometry)가 결정합니다. 모든 markdown을 제거해도(토큰의 13.6%) 아무 효과가 없었고, 오히려 기준값보다 약간 높게 점수가 나왔습니다. 1.6%의 무작위 공백 삽입은 편집당 25배 더 큰 손상을 입혔습니다. Markdown 마커는 군집을 이루므로 손상 창이 서로 겹치고, 그 사이의 긴 산문 구간은 워터마크 시드를 온전히 재생합니다. 토크나이저를 비동기화시키는 분산 편집은 매번 새로운 창을 때립니다.
  • 길이는 공격자가 아니라 검출기를 돕습니다. z는 sqrt(토큰 수)처럼 자랍니다. "긴 컨텍스트에서 속이기"는 거꾸로입니다. 32k는 공격하기 가장 쉬운 경우가 아니라 가장 어려운 경우입니다.

전체 메커니즘과 공격별 테이블은 docs/FINDINGS.md에 있습니다.

대화형 버전 사용해 보기 → 실제 연구 샘플에 before/after 표시 토글이 있고, 자신의 텍스트에 공격 변형을 적용해 볼 수 있는 플레이그라운드도 있습니다. 임의로 붙여넣은 텍스트가 정말로 워터마크인지 여부는 알려주지 않으며(그러려면 우리가 갖고 있지 않은 키가 필요합니다), 그 점도 명시되어 있습니다. 생성 스크립트는 site/를 보십시오.

공격이 필요 없는 발견

워터마크는 모델의 토큰별 불확실성에 실려 있습니다. 모델이 다음 토큰에 대해 확신하는 곳에서는 토너먼트가 그것을 편향시킬 여지가 없으므로 신호가 들어가지 않습니다. 즉, 워터마크는 낮은 엔트로피 텍스트에서 약하고, 코드는 엔트로피가 낮습니다.

Qwen3.5-4B, 산문 vs 코드, 512토큰 샘플, 아무 공격도 없음:

도메인엔트로피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 문자를 제거하십시오. 제로 폭 문자, bidi, 그리고 콤보 공격을 무력화합니다. 이것이 가장 큰 이득입니다.
  2. NFKC 폴드를 적용하십시오. nbsp와 호환성 형태를 처리합니다.
  3. 변형 선택자 범위를 명시적으로 제거하십시오. NFKC가 대신 해주지 않으며, 이것이 현재 열려 있는 갭입니다.
  4. homoglyph를 위해 Unicode confusables 맵(UTS-39)을 유지하십시오. NFKC는 그것도 해주지 않습니다.

3번과 4번이 순진한 정규화기가 놓치는 부분입니다.

이 연구의 문제점 / 내가 하지 못한 것

빠진 부분에 대해 솔직히 말하자면.

  • 27B 코드 수치는 공격 결과로서 정보를 주지 못합니다. 거기의 공격받지 않은 기준값이 z = 4.31이므로, 이미 거의 맹목적인 검출기를 이기는 공격을 입증할 수 없습니다. 저는 그 행들을 유지하되 라벨을 붙였습니다. 의미 있는 신호는 공격 델타가 아니라 기준값입니다.
  • 27B 코드 결과가 엔트로피 때문인지 모델 스타일 때문인지는 미해결입니다. 4B에서 했던 것 같은 토큰별 엔트로피 측정이 필요한데, 그 모델에서는 실행하지 않았습니다.
  • GLM-5.2는 데이터를 전혀 생성하지 못했습니다. 8xA100 팟을 대여했는데 인프라 실패를 연달아 다섯 번 겪었습니다(폐기된 다운로드 명령어, torch/torchvision ABI 호환성 깨짐, 모델이 GPU가 아닌 호스트 RAM으로 로드됨). 약 $25를 날렸는데, 그중 $19는 시작조차 하지 않은 다운로드를 믿고 유휴 상태로 둔 팟에 쓴 것입니다. 아무것도 얻지 못한 채 종료했습니다. Kimi-K3는 시도조차 하지 않았습니다. 약 1.5TB라서 양자화해도 A100이 20개 이상 필요합니다. 프런티어 규모의 질문은 여전히 열려 있습니다.
  • Qwen3.8-27B의 커뮤니티 양자화 체크포인트 3개는 로드에 실패했습니다(FP8은 우리가 갖고 있지 않은 torch dtype을 요구했고, AWQ/compressed-tensors 리패키지 2개는 패킹 불일치가 있었습니다). 대신 H100에서 bf16으로 실행했습니다. 재현한다면 리패키지 버전은 건너뛰십시오.
  • 검출기는 논문의 훈련된 베이지안 검출기가 아니라, 훈련되지 않은 mean-g 스코어러입니다. 베이지안 검출기는 아마 더 민감할 것이므로 이 z 값들은 하한선이지만, 저는 그것을 측정하지 않았습니다.
  • 제 homoglyph 충실도 주장은 "일반적인 독자" 기준이지 증명된 것이 아닙니다. 키릴 문자 а는 카테고리 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%의 차이였습니다).

워터마킹에는 전체 다음 토큰 분포가 필요하므로 transformers(CUDA 네이티브 MXFP4, 또는 MPS/CPU)를 통해 실행됩니다. Ollama와 llama.cpp는 생성 중간에 logits을 노출하지 않기 때문에 그렇게 할 수 없습니다. Apple Silicon에서는 src/synthid_mlx.py가 MLX 생성과 워터마크 계산을 연결하며, HF 레퍼런스와 비트 단위로 동일함을 검증했습니다.


꿈, 아마도

(이 모든 것을 시작한 밈. 결국 필요한 건 찾아바꾸기가 아니라 변형 선택자였다.)


참고: 저는 구현과 네 대의 머신(Mac, 제 4090, 대여한 3090, H100)에서 실험을 다시 실행하는 데 Claude Code를 많이 사용했습니다. 실험 설계, 시도해보고 싶었던 공격, 프레이밍 결정은 모두 제 것입니다. Claude는 모든 공격을 그에 대응하는 방어와 함께 측정하라고 주장했고, 그래서 stego 테이블에는 raw 열만 있는 것이 아니라 raw 열과 normalized 열이 함께 있습니다. 그것이 "보이지 않는 문자가 워터마크를 깨뜨린다"는 말을, 정규화기를 살아남는 것은 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
모든 markdown 제거13.6%27.2103.3
AmE → BrE + 약어화1.3%~28~100
모든 단어의 40% 삭제38%4.925.4