Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
claude-awm — Contorna marcas d'água de texto de LLM injetando seletores de variação Unicode; inclui o gerador SynthID, detector mean-g, defesas de normalização e experimentos de entropia. | Kitploit
Ferramentas/GitHubGitHub/aloshdenny/claude-awm
EsteganografiaPrivacidadeAprendizado de MáquinaSegurança de IAAtaque Adversário
GitHubaloshdenny/claude-awm

claude-awm

Contorna marcas d'água de texto de LLM injetando seletores de variação Unicode; inclui o gerador SynthID, detector mean-g, defesas de normalização e experimentos de entropia.

Ver Repositório
173há 4 diasAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

claude-awm: dá para remover uma marca d'água de texto SynthID editando o texto?

Olá, Alosh aqui ✌🏻

Sim, mas apenas uma família de ataque funciona, e não é a que todo mundo assume.

Os seletores de variação do Unicode (categoria Mn, U+FE00 a U+FE0F e U+E0100 a U+E01EF) levam o detector para abaixo do limiar e ficam lá. Qualquer outro ataque de caractere invisível que tentei é totalmente revertido por uma linha de normalização de entrada. Os seletores de variação não, porque são pontos de código significativos (apresentação de emoji, variantes CJK) que o NFKC não colapsa e não deve colapsar.

Replicado em três modelos, dois domínios:

modelodomínioz da linha de baseapós vs16_30taxa de edição
gpt-oss-20bprosa45.030.7257%
gpt-oss-20bcódigo37.240.6858%
Qwen3.8-27Bprosa35.50-0.6757%

O limiar é z = 2.33. Todos os três ficam abaixo dele e permanecem abaixo após a normalização (0.09, 0.45, -0.78, respectivamente). O texto é renderizado de forma idêntica para um leitor humano.

A segunda descoberta real não precisa de ataque nenhum: texto de baixa entropia quase não é marcado para começar. A geração de código do Qwen3.8-27B tem uma linha de base limpa de z = 4.31, já perto do limiar sem que nada seja feito.

o que é isto

A Anthropic (e o Google DeepMind antes dela, no artigo SynthID-Text) marca texto gerado ao enviesar a amostragem de tokens com um torneio chaveado. O sinal vive em quais tokens foram escolhidos, não em qualquer caractere oculto. Eu queria saber o quão frágil isso é para uma pessoa motivada com localizar-e-substituir, então construí o gerador mais um detector mean-g não treinado e joguei ataques nele.

O limiar do detector é z = 2.33 (taxa de falsos positivos de 1%). Acima disso = marca d'água detectada. Eu gerei texto com marca d'água, ataquei-o, re-tokenizei e pontuei. Toda tabela de resultados traz um controle roundtrip (texto com marca d'água não atacado) para você ver que o detector está realmente funcionando naquela linha. Duas vezes neste estudo, um bug fez todos os z colapsarem para zero, e o controle foi a única coisa que o pegou.

escopo do ataque: o que realmente funciona

A superfície de ataque se divide claramente por categoria Unicode, o que acabou sendo toda a história.

Funciona (categoria Mn, marcas sem espaçamento):

Não funciona (categoria Cf, caracteres de formato):

Caracteres Cf são formatação pura, sem conteúdo semântico, então um normalizador pode removê-los por completo sem perder nada. Seletores de variação Mn carregam significado real em texto de emoji e CJK, então removê-los de forma indiscriminada corromperia documentos legítimos. Essa assimetria é o motivo pelo qual uma família é defensável e a outra não.

O escopo prático: isso precisa que aproximadamente 20% ou mais dos caracteres sejam tocados para empurrar uma linha de base forte para baixo do limiar, mas os caracteres inseridos são invisíveis, então o texto é lido normalmente em qualquer taxa de edição. Está verificado como visualmente idêntico; veja src/fidelity_check.py. Quatro famílias inserem apenas caracteres que não renderizam nada; os homóglifos são a exceção honesta (dependem da fonte, não são garantidamente invisíveis).

o que não funciona: as coisas óbvias

Meu medo inicial era o óbvio: que travessões e "and" virando "&" e remover markdown simplesmente funcionassem, e a marca d'água acabasse sendo teatro de segurança. Muita gente online assume exatamente isso.

Não funciona. Toda a escada de edições superficiais no gpt-oss-20b, até 32k tokens:

Em três modelos (0.8B, 4B, 20B = 294 células), exatamente uma célula cruzou o limiar: apagar 39% de cada palavra no menor comprimento no 4B. Isso não é um ataque, é triturar o documento.

Duas coisas me surpreenderam:

  • A quantidade de edições não prevê o dano; a geometria das edições prevê. Remover todo o markdown (13.6% dos tokens) não fez nada; chegou até a pontuar ligeiramente acima da linha de base. Injetar espaços perdidos a 1.6% causou 25x mais dano por edição. Os marcadores de markdown se agrupam, então as janelas de corrupção deles se sobrepõem e os longos trechos de prosa entre eles continuam reproduzindo a semente da marca d'água intacta. Edições espalhadas que dessincronizam o tokenizador atingem janelas novas a cada vez.
  • O comprimento ajuda o detector, não o atacante. z cresce como sqrt(tokens). "Enganá-lo em um contexto longo" é ao contrário; 32k é o caso mais difícil de atacar, não o mais fácil.

Mecanismo completo e tabelas por ataque em docs/FINDINGS.md.

Experimente a versão interativa → Amostras reais do estudo com um botão de revelar antes/depois, além de um playground para rodar a transformação do ataque no seu próprio texto. Ele não vai dizer se um texto colado arbitrário está realmente marcado (isso exige uma chave que não temos), e ele mesmo avisa; veja site/ para o script do gerador.

a descoberta que não precisa de ataque

A marca d'água se apoia na incerteza por token do modelo. Onde o modelo está confiante sobre o próximo token, o torneio não tem espaço para enviesá-lo, então nenhum sinal entra. Isso significa que a marca é fraca em texto de baixa entropia, e código é de baixa entropia.

Qwen3.5-4B, prosa vs código, amostras de 512 tokens, sem ataque algum:

domínioentropiaz
prosa1.19 bits/tok11.1
código0.55 bits/tok5.0

A razão de z 0.45x, a razão de entropia 0.46x; eles se movem juntos, o que é o mecanismo transparecendo. 3 de 8 amostras de código caíram para o limiar de detecção ou abaixo dele sozinhas. A mais apertada (um algoritmo puro, 0.2 bits/token) pontuou 1.7, um erro.

Fica mais extremo em escala. Linha de base z sem ataque algum:

modeloprosacódigorazão
gpt-oss-20b45.0337.240.83
Qwen3.8-27B35.504.310.12

A saída de código do Qwen3.8-27B é tão modelizada que a marca d'água limpa, não atacada, fica em z = 4.31, pouco acima do limiar de 2.33. Nenhum adversário é necessário.

Isso diz: um único limiar de confiança entre domínios é inseguro, e trechos curtos de código estão perto de ser impossíveis de marcar. Generaliza para JSON, config, extração estruturada, boilerplate.

lição para a defesa

Se você disponibiliza um desses detectores, normalizar a entrada te leva quase até lá, mas não todo o caminho:

  1. Remova os caracteres da categoria Cf. Elimina zero-width, bidi e as combinações. Essa é a grande vitória.
  2. Aplique NFKC. Cuida de nbsp e formas de compatibilidade.
  3. Remova explicitamente os intervalos de seletores de variação. NFKC não fará isso por você, e essa é a lacuna atualmente aberta.
  4. Mantenha um mapa de confusáveis Unicode (UTS-39) para homóglifos. NFKC também não faz isso.

Os passos 3 e 4 são os que um normalizador ingênuo deixa passar.

o que há de errado nisso / o que eu não consegui fazer

Sendo honesto sobre as lacunas.

  • Os números de código do 27B são pouco informativos como resultado de ataque. A linha de base não atacada ali é z = 4.31, então não dá para demonstrar um ataque vencendo um detector que já está quase cego. Mantive essas linhas, mas as rotulei; o sinal significativo é a linha de base, não os deltas do ataque.
  • Se o resultado de código do 27B é entropia ou estilo do modelo, isso está em aberto. Precisa de uma medição de entropia por token como a que o 4B teve, que não rodei para aquele modelo.
  • GLM-5.2 produziu zero dados. Aluguei um pod 8xA100 e encontrei cinco falhas de infraestrutura seguidas (comando de download obsoleto, quebras de ABI torch/torchvision, o modelo carregando na RAM do host em vez das GPUs), gastei ~$25, incluindo $19 num pod que ficou ocioso porque confiei num download que nunca começou, e o encerrei sem nada. Kimi-K3 nunca foi tentado; com ~1.5TB, mesmo quantizado, precisa de 20+ A100s. A questão em escala de fronteira está em aberto.
  • Três checkpoints quantizados da comunidade do Qwen3.8-27B falharam ao carregar (FP8 exigindo um dtype do torch que não temos, dois repacks AWQ/compressed-tensors com incompatibilidades de empacotamento). Rodei em bf16 num H100 em vez disso. Se você for reproduzir, pule os repacks.
  • O detector é o scorer mean-g não treinado, não o Bayesiano treinado do artigo. O detector Bayesiano provavelmente seria mais sensível, então esses valores de z são um piso, mas não o medi.
  • Minha afirmação de fidelidade dos homóglifos é "leitor típico", não comprovada. O а cirílico é da categoria Ll, então sua invisibilidade é uma propriedade da fonte, não uma garantia do Unicode.
  • n é pequeno: 2 documentos por célula nas escadas, 8 amostras por domínio para entropia. Suficiente para os tamanhos de efeito aqui (são grandes), não suficiente para barras de erro apertadas por ataque.
  • Não forneço uma receita de evasão ajustada, e isso é deliberado. Cada ataque aqui é relatado junto com o resultado da normalização que o derrota ou não. O objetivo era medir onde está a fronteira, não empacotar um bypass.

estrutura

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

como executar

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 aceita prose, code ou mixed. FAST_WM=1 usa uma ponte de marca d'água numpy (mais rápida em modelos de vocabulário pequeno com uma CPU forte), FAST_WM=0 usa o processador de GPU da HF (muito mais rápido em modelos de vocabulário grande; num H100 essa foi a diferença entre 0% e 46% de utilização da GPU).

A marca d'água precisa da distribuição completa do próximo token, então ela roda por transformers (CUDA nativo MXFP4, ou MPS/CPU). Ollama e llama.cpp não conseguem fazer isso; eles não expõem logits no meio da geração. No Apple Silicon, src/synthid_mlx.py faz a ponte da geração MLX para a matemática da marca d'água; é validado como bit idêntico à referência HF.


o sonho, supostamente

(o meme que começou tudo. no fim das contas, você precisa de seletores de variação, não de localizar-e-substituir.)


Nota: usei o Claude Code intensamente para a implementação e para reexecutar experimentos em quatro máquinas (um Mac, minha própria 4090, uma 3090 alugada e um H100). O desenho do experimento, os ataques que eu queria tentar e as decisões de enquadramento são meus. O Claude insistiu em medir cada ataque contra a sua própria defesa, e é por isso que as tabelas de esteganografia têm uma coluna bruta e uma normalizada, em vez de só a bruta; foi isso que transformou "caracteres invisíveis quebram isso" na descoberta real, que é que apenas os da categoria Mn sobrevivem a um normalizador.

Baixar ferramenta
ataqueo que faztaxa de ediçãosobrevive à normalização?
vs16_30seletor de variação após ~30% dos caracteres57%sim
vs16seletor de variação após ~10% dos caracteres23%sim (z 3.46)
vs_suppseletores de plano suplementar (U+E0100+)24%sim (z 3.40)
homoglyphcirílico а no lugar do latino a (categoria Ll)9%sim, mas efeito fraco
ataquez brutoz normalizadoveredito
zwsp_30-0.0935.68totalmente revertido
combo0.9235.68totalmente revertido
bidi24.3735.68totalmente revertido
nbsp41.0446.51quase não o move
ataquetaxa de ediçãoz @ 1kz @ 32k
roundtrip (controle)0%25.7104.3
travessão para hífen~0%26.4113.7
remover todo o markdown13.6%27.2103.3
inglês americano para britânico + abreviações1.3%~28~100
apagar 40% de cada palavra38%4.925.4