
Exploit de um clique para CVE-2026-54121 (Certighost) visando a falsificação de identidade de certificados AD CS. Automatiza a criação de contas de máquina, redirecionamento de tráfego, CA rogue, PKINIT e extração de hash NT para comprometimento do domínio.
Ferramenta de exploração one-click para CVE-2026-54121 (Certighost) — apenas para laboratórios locais/testes autorizados.
Versão nativa para Windows adaptada do PoC upstream (análise @h0j3n / implementação @aniqfakhrul): Redirecionador WinDivert próprio integrado (pydivert), um único comando executa "criar conta → redirecionar → listener rogue → CA chase → certificado de identidade do DC → PKINIT → hash NT da conta de máquina do DC", sem interromper o serviço Server, sem alterar nenhuma configuração do host, restauração imediata ao sair.
| Patch | Descrição |
|---|
--redirect | Redirecionador WinDivert integrado (445 → --lsa-port, filtro de escopo estreito: apenas tráfego do IP do listener), inicia/para com o processo, restaura 445 automaticamente ao sair. Substitui o PortBender oficial (cujo artefato oficial é um DLL refletivo 32 bits específico para CS, incapaz de execução independente) |
--lsa-port | Porta de escuta do rogue LSA/SMB parametrizada (padrão 445; com --redirect o padrão é 8445) |
Guarda os.geteuid | A verificação de root do upstream falha no Windows → guarda hasattr + aviso de porta no Windows |
| Verificação de prontidão parametrizada | port_ok(127.0.0.1, 445) codificado no upstream → args.lsa_port |
| Cabeçalho PEP 723 | uv run certighost.py ... executa diretamente, dependências resolvidas automaticamente (incluindo impacket git-master), zero poluição do ambiente |
--new-computer-name | Nome personalizado para criação de conta (evita assinatura de detecção GHOST*) |
--new-computer-pass | Senha personalizada para criação de conta (deve atender à política de senhas do domínio) |
Polyfill random.randbytes | impacket git-master usa API 3.9+ na importação do smbserver; necessário para Python 3.8, implementado com os.urandom |
| Saída imediata | Após GGWP, flush + os._exit() (elimina o travamento de minutos causado por threads não-daemon do impacket) |
| Códigos de saída semânticos | 0 sucesso / 1 falha |
Gravação de <dc>.hash.txt | Hash NT da conta de máquina do DC gravado em arquivo (apenas uma linha name:lm:nt) |
① Pré-verificação (somente leitura, confirma CA e pré-requisitos de exploração):
uv run check_ca.py -d bingo.com -dc-ip 192.168.16.144 -u zhaolei -p 'pass'
Exibe lista de Enterprise CA, emissão do template Machine e permissões de registro (requer Domain Computers com Enroll).
Verifique também o flag chase na máquina CA: certutil -getreg policy\EditFlags (deve ter
EDITF_ENABLECHASECLIENTDC; confirmado ativo na instalação padrão do Server 2016).
② Exploração one-click (Windows, administrador):
uv run certighost.py -d bingo.com -u zhaolei -p '[email protected]' \
--dc-ip 192.168.16.144 --listener <IP acessível localmente> --redirect \
--new-computer-name MACH$ --new-computer-pass 'Your@Pw123!'
Três artefatos de saída (gravados automaticamente no diretório de execução):
| Arquivo | Conteúdo |
|---|---|
<dc>.pfx | Certificado de identidade do DC (material PKINIT) |
<dc>.ccache | Cache de tickets Kerberos |
<dc>.hash.txt | Hash NT da conta de máquina do DC (apenas linha name:lm:nt) |
③ Limpeza (excluir conta criada):
uv run cleanup_ghost.py -d bingo.com -dc-ip 192.168.16.144 -u administrator -p 'pass' --prefix MACH
| Parâmetro | Descrição |
|---|---|
-d / -u / -p / -H | Domínio / usuário de baixo privilégio / senha / hash NTLM |
--dc-ip | Endereço do DC (obrigatório) |
--listener IP | IP do listener rogue (obrigatório especificar explicitamente com múltiplas NICs) |
--redirect | Núcleo Windows: redirecionamento WinDivert 445 integrado (requer administrador + pydivert) |
--lsa-port N | Porta do rogue LSA (padrão 8445 com --redirect) |
--new-computer-name | Nome personalizado para criação de conta (adiciona $ automaticamente) |
--new-computer-pass | Senha personalizada para criação de conta (mutuamente exclusivo com caminho existing) |
--computer-name/--computer-pass/--computer-hash | Sem MAQ: reutilizar conta de máquina já controlada |
--target-san DC01$ | Especificar alvo de impersonação (padrão: descoberta automática do DC) |
--template | Template de certificado (padrão Machine) |
--ca / --ca-ip | Especificar CA manualmente |
--debug | Rastreamento completo das fases do protocolo |
Phase1 Usuário de baixo privilégio cria conta de máquina (caminho MAQ automático / --new-computer-* personalizado / --computer-* reutiliza existente)
Phase2 [Windows] Redirecionador WinDivert integrado: listener_ip:445 -> :lsa_port
Filtro de escopo estreito (apenas esse IP), pacotes reescritos saem do filtro = sem loop de reinjeção; handle fechado com o processo
Phase3 Servidor rogue: LDAP:389 + LSA/SMB:lsa_port (responde chase cdc/rmd, alimenta dados de identidade do DC)
Phase4 Submete solicitação de certificado como identidade de máquina (template Machine), CA faz callback ao rogue → emite certificado de identidade do DC
Phase5 PKINIT → KDC retorna hash NT da conta de máquina do DC no PAC → extrai e grava em .hash.txt
Phase6 (Posterior) secretsdump DCSync → krbtgt → domínio totalmente comprometido; cleanup_ghost remove conta criada
Uso no Linux inalterado (bind direto root em 445/389, sem --redirect).
A extração de hash na cadeia de ataque usa PKINIT → PAC → hash NT, não DCSync:
Usar secretsdump para DCSync após obter o hash é uma operação de segundo passo, não a fonte do hash.
# PowerShell 7
./build_exe.ps1 # Perfil padrão (Win10 / Server 2016+)
./build_exe.ps1 3.10 # Perfil compatível (Win8.1 / Server 2012 R2+)
./build_exe.ps1 legacy # Perfil legado (Win7 SP1 / Server 2008 R2 x64)
Artefato dist\certighost_x64.exe: 19-27MB (conforme perfil), auto-elevação --uac-admin, zero dependências,
script gera automaticamente checksum SHA256.
Requer CPython 3.8.10 oficial do python.org instalado no seguinte caminho (último build binário oficial que suporta kernel Win7, não depende de APIs UCRT novas):
D:\网安相关\Tools\Python\cpython-3.8.10-x64\
Comando de instalação (silencioso, sem escrever no PATH, sem instalar launcher):
python-3.8.10-amd64.exe /quiet InstallAllUsers=0 TargetDir=D:\网安相关\Tools\Python\cpython-3.8.10-x64 PrependPath=0 Include_launcher=0
Também fixa PyInstaller==5.13.2 (bootloader 6.x não suporta kernel Win7) e cryptography==38.0.4 (wheels Rust passam a exigir Win10+ após 38.x), ambos já consolidados no script.
| Perfil | Sistema real | Cadeia completa | Observações |
|---|---|---|---|
| Padrão | Win11 | ✅ | |
| Compatível 3.10 | Win11 / Win10 / Server 2012 R2 | ✅ ×3 | Inclui WinDivert em hardware real |
| Legado | Win11 / Server 2008 R2 x64 | ✅ ×2 | 3.8.10 oficial + PyInstaller 5.13.2 |
Atenção: PyInstaller+impacket é zona de alto risco para assinaturas de antivírus, avalie antes da implantação.
ciphertext integrity failure: observado uma vez, reexecução resolvecertighost.py Exploit principal (upstream + patches de nativização Windows + PEP 723)
certighost_redirect.py Redirecionador WinDivert 445 próprio (pydivert; autoteste --selftest/--e2e)
check_ca.py Pré-verificação: CA/template/permissões de registro/flag chase (somente leitura)
cleanup_ghost.py Finalização: excluir conta criada
build_exe.ps1 Empacotamento PyInstaller de arquivo único (pwsh7, matriz de três perfis, SHA256 automático)