
Educational proof-of-concept for PrintNightmare (CVE-2021-1675/34527) with simulated non-functional payload, attack flow analysis, MITRE mapping, detection guidance, and remediation steps.
Type: Proof of Concept — Simulated (Non-Functional) CVE: CVE-2021-1675 + CVE-2021-34527 CVSS: 7.8 (LPE) / 8.8 (RCE) Alias: PrintNightmare Patched: Junho/Julho 2021 — KB5004945 Adicionado ao CISA KEV: Julho 2021
⚠️ O payload deste PoC é explicitamente fictício e não-malicioso — apenas 4 bytes de cabeçalho DCE/RPC seguidos do nome da função em ASCII. Não executa código, não instala driver, não eleva privilégios. Uso exclusivo para fins de aprendizado e desenvolvimento de detecções.
Developed by: HKK$ cat ./vulnerability_summary.txtCVE-2021-1675, conhecido como PrintNightmare, é uma vulnerabilidade crítica de Remote Code Execution e Local Privilege Escalation no serviço Windows Print Spooler. A falha permite que atacantes executem código arbitrário com privilégios SYSTEM explorando a função RpcAddPrinterDriverEx(), usada para instalação remota de drivers de impressora sem validação adequada de controle de acesso.
Originalmente classificada como LPE (CVSS 7.8) e patchada no Patch Tuesday de junho de 2021, a Microsoft reclassificou a vulnerabilidade como RCE (CVSS 8.8) em 21 de junho. Para evitar confusão, o vetor RCE recebeu um novo identificador, CVE-2021-34527 — ambos são comumente chamados de PrintNightmare.
$ cat ./timeline.txtJun 08, 2021 Microsoft publica patch inicial no Patch Tuesday — CVE-2021-1675 (LPE, CVSS 7.8)
Jun 21, 2021 Microsoft reclassifica como RCE (CVSS 8.8)
Jun 29, 2021 Pesquisadores publicam PoC acidentalmente — acreditando ser a mesma vuln já patchada
Jul 01, 2021 CVE-2021-34527 atribuído para o vetor RCE — distinto do LPE original
Jul 02, 2021 Microsoft lança patch emergencial out-of-band: KB5004945
Jul 2021 CISA adiciona ao Known Exploited Vulnerabilities Catalog
Exploração ativa por grupos de ransomware (Vice Society, Magniber, etc.)
$ cat ./architecture.txt┌──────────────────────────────────────────────────────────────────────────┐
│ PRINTNIGHTMARE — ATTACK FLOW │
│ │
│ ATACANTE (usuário autenticado) WINDOWS PRINT SPOOLER │
│ (spoolsv.exe) │
│ 1. Autenticar com qualquer ┌────────────────────────────┐ │
│ conta de domínio válida │ Roda como SYSTEM │ │
│ │ │ Ativo por padrão em todos │ │
│ 2. Conectar via RPC ao │ os Windows, incluindo DCs │ │
│ named pipe \pipe\spoolss └──────────────┬─────────────┘ │
│ │ │ │
│ 3. Chamar RpcAddPrinterDriverEx() │ │
│ com path para DLL maliciosa ──────────────────────►│ │
│ (UNC: \\attacker\share\evil.dll) │ │
│ ┌────────────▼────────────┐ │
│ │ Print Spooler carrega │ │
│ │ o driver (DLL) como │ │
│ │ SYSTEM sem verificar │ │
│ │ origem ou integridade │ │
│ └────────────┬────────────┘ │
│ │ │
│ ◄── RCE / LPE como SYSTEM ───────────────────────────┘ │
│ New admin user, reverse shell, │
│ ransomware deployment, etc. │
│ │
│ ───────────────────────────────────────────────────────────────────── │
│ ESTE POC: apenas TCP connect + 25 bytes → sem RPC real → sem exploit │
└──────────────────────────────────────────────────────────────────────────┘
$ cat ./design_decisions.mdfake_rpc_payload = b"\x05\x00\x0b\x03RpcAddPrinterDriverEx"
Este payload tem 25 bytes e demonstra dois conceitos simultaneamente:
Bytes 0-3: Cabeçalho DCE/RPC legítimo
Bytes 4-24: Nome da função em ASCII
RpcAddPrinterDriverEx — o nome da função vulnerável, em texto plano.
Por que esse payload não funciona como exploit real?
Um BIND RPC legítimo exigiria, após o header de 4 bytes:
- max_xmit_frag (2 bytes)
- max_recv_frag (2 bytes)
- assoc_group_id (4 bytes)
- num_ctx_items (1 byte)
- context_elem[] → Interface UUID do MS-RPRN:
{12345678-1234-ABCD-EF00-0123456789AB}
- transfer_syntaxes → NDR UUID
Sem essa estrutura, o Windows rejeita o pacote imediatamente. O payload é, efetivamente, apenas uma asserção de conectividade — "consigo alcançar a porta 445 com esse payload fictício?".
sock.connect((target_ip, 445))
Por que 445 e não 135 (RPC Endpoint Mapper)?
O PrintNightmare usa o SMB named pipe \pipe\spoolss como transporte — não o RPC direto. O fluxo real é:
1. TCP connect → porta 445 (SMB)
2. SMB negotiate + session setup (autenticação NTLM/Kerberos)
3. Tree connect → IPC$
4. Named pipe open → \pipe\spoolss
5. DCE/RPC BIND → interface MS-RPRN
6. RpcAddPrinterDriverEx() call com NDR marshaling
O PoC simula apenas o passo 1 — a conexão TCP inicial — sem implementar os passos 2-6.
sock.settimeout(5): timeout de 5 segundos previne que o PoC fique bloqueado em hosts que não respondem. Útil para scanning rápido de disponibilidade da porta.
A causa raiz em ambos é a mesma: a função RpcAddPrinterDriverEx() falha em validar a origem dos arquivos de driver, não impõe restrições de privilégio adequadas para instalação de drivers, e não verifica a autenticidade ou integridade das DLLs sendo carregadas.
$ cat ./mitre_mapping.ymltactic: Initial Access / Lateral Movement
- T1210 # Exploitation of Remote Services
# RPC call via \pipe\spoolss para host remoto
# Requer credencial de domínio válida
tactic: Privilege Escalation
- T1068 # Exploitation for Privilege Escalation
# usuário comum → SYSTEM via Print Spooler
# CVE-2021-1675 (LPE): processo local eleva para SYSTEM
tactic: Execution
- T1569.002 # System Services: Service Execution
# DLL maliciosa carregada pelo spoolsv.exe como SYSTEM
# Equivalente a execução de código via serviço do Windows
- T1055 # Process Injection
# DLL injetada no contexto do processo spoolsv.exe (SYSTEM)
tactic: Persistence
- T1547.012 # Boot or Logon Autostart: Print Processors
# Driver registrado persiste entre reinicializações
# Armazenado em: HKLM\SYSTEM\CurrentControlSet\Control\Print\
tactic: Defense Evasion
- T1036.005 # Masquerading: Match Legitimate Name or Location
# DLL maliciosa nomeada como driver legítimo (ex: Canon_XP.dll)
$ cat ./detection_opportunities.md# Event ID 808 — Print Spooler falhou ao carregar DLL suspeita
# Fonte: Microsoft-Windows-PrintService/Admin
Condição:
EventID: 808
Log: Microsoft-Windows-PrintService/Admin
Level: Error
Description CONTAINS: "failed to load a plug-in module"
Evidência real (observed in-the-wild):
"The print spooler failed to load a plug-in module
C:\Windows\system32\spool\DRIVERS\x64\3\svch0st.dll"
# Typosquatting de svchost.dll → DLL maliciosa
# Event ID 316 — Driver instalado via RpcAddPrinterDriverEx
# Fonte: Microsoft-Windows-PrintService/Admin
Condição:
EventID: 316
Log: Microsoft-Windows-PrintService/Admin
Message CONTAINS: "RpcAddPrinterDriverEx"
OR
Message CONTAINS: "\\\\*\\*" # UNC path → DLL remota
# Processo filho suspeito do Print Spooler
EventID: 1 (Process Creation)
Condição:
ParentImage: C:\Windows\System32\spoolsv.exe
Image: cmd.exe OU powershell.exe OU wscript.exe OU mshta.exe
Severidade: CRÍTICA — spoolsv não deve spawnar shells
# DLL carregada de path não-padrão
EventID: 7 (Image Loaded)
Condição:
Image: C:\Windows\System32\spoolsv.exe
ImageLoaded NOT STARTS WITH:
- C:\Windows\System32\spool\DRIVERS\
- C:\Windows\System32\
- C:\Windows\SysWOW64\
Severidade: ALTA
Para detecção em nível de rede, monitorar named pipes SMB: presença de \pipe\spoolss combinada com as operações RpcEnumPrinterDrivers ou RpcAddPrinterDriverEx são indicadores diretos de exploração do PrintNightmare.
# Regra Zeek / Suricata conceitual:
alert smb any any -> $SERVERS 445 (
msg:"PrintNightmare RpcAddPrinterDriverEx via SMB";
content:"|5c 70 69 70 65 5c 73 70 6f 6f 6c 73 73|"; # \pipe\spoolss
content:"RpcAddPrinterDriverEx";
sid:2021001675;
)
$ cat ./remediation.mdOPÇÃO 1 — Desabilitar Print Spooler (se impressão não for necessária)
PowerShell:
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
OPÇÃO 2 — Bloquear impressão remota via Group Policy
Computer Configuration → Administrative Templates → Printers
→ "Allow Print Spooler to accept client connections": DISABLED
Isso desabilita apenas o vetor remoto, mantendo impressão local
OPÇÃO 3 — Aplicar patches (obrigatório independente das opções acima)
KB5004945 → patch out-of-band Julho 2021
+ Patches cumulativos subsequentes
VERIFICAÇÃO PÓS-PATCH — Registry ainda pode deixar vulnerável:
REG QUERY "HKLM\Software\Policies\Microsoft\Windows NT\Printers\PointAndPrint"
Se NoWarningNoElevationOnInstall=1 OU UpdatePromptSettings=0 → AINDA VULNERÁVEL
Corrigir: definir ambos os valores para 0 ou remover as chaves
PRIORIDADE ESPECIAL: Domain Controllers
DCs rodam Print Spooler por padrão
Comprometer um DC via PrintNightmare = comprometimento completo do domínio AD
$ cat ./usage.sh# Instalar dependência (socket é stdlib)
python --version # Python 3.x, sem pip necessário
# Editar o IP alvo no script (somente em lab autorizado)
# simulate_printnightmare_attack("192.168.1.xxx")
python poc_cve_2021_1675.py
# Output esperado se porta 445 acessível:
[+] Payload enviado para 192.168.1.117
# Output esperado se porta fechada/filtrada:
[-] Erro ao conectar: [Errno 111] Connection refused
# ou
[-] Erro ao conectar: timed out
O que esse output indica: apenas que a porta 445 está acessível. Não confirma vulnerabilidade — para isso, seria necessário um RPC BIND real + verificação da versão do patch.
$ cat ./poc_vs_real_exploit.mdComparação explícita entre o PoC simulado e um exploit real.
$ cat ./lessons_learned.txt[+] Print Spooler ativo em DCs por padrão é o cenário mais crítico — SYSTEM em DC = game over
[+] SMB named pipes como transporte RPC são um vetor subestimado em defesas perimeter-focused
[+] DCE/RPC é protocolo complexo — entender a estrutura de bind/call ajuda a criar assinaturas
[+] CVE publicada ≠ patch aplicado — semanas após o patch, a maioria dos ambientes ainda era vulnerável
[+] PointAndPrint registry keys podem reintroduzir a vuln mesmo após o patch — controle pós-patch crítico
[-] Este PoC apenas verifica conectividade TCP — não valida se o sistema está patchado de fato
[-] Socket puro sem SMB não consegue negociar autenticação — limitação fundamental da abordagem
[-] settimeout(5) pode gerar falso negativo em redes lentas — considerar timeout parametrizável
[→] Melhorias: usar impacket para RPC real, verificar banner SMB para fingerprint de versão do OS,
testar KB aplicado via registry query remota
CVE Research · PrintNightmare · Patched July 2021 · CISA KEV · Simulated payload only
| Byte | Valor | Significado |
|---|
\x05 | 5 | Versão do protocolo DCE/RPC (versão 5 — padrão Windows) |
\x00 | 0 | Minor version 0 |
\x0b | 11 | PDU Type: BIND — primeiro passo da negociação RPC |
\x03 | 3 | Flags: `PFC_FIRST_FRAG(0x01) |
| Aspecto | CVE-2021-1675 | CVE-2021-34527 |
|---|
| Vetor | Local (LPE) | Remoto (RCE) |
| CVSS | 7.8 | 8.8 |
| Autenticação | Conta local | Conta de domínio autenticada |
| Patch | Junho 2021 (Patch Tuesday) | Julho 2021 (out-of-band KB5004945) |
| Função vulnerável | RpcAddPrinterDriverEx | RpcAddPrinterDriverEx |
| Cenário | Escalação local | RCE remoto via SMB named pipe |
| Componente | Este PoC | Exploit Real |
|---|
| Conexão | TCP socket porta 445 | SMB session + Tree connect IPC$ |
| Autenticação | Nenhuma | NTLM ou Kerberos (conta de domínio) |
| Named pipe | Não implementado | \pipe\spoolss |
| RPC BIND | Falso (4 bytes + ASCII) | DCE/RPC BIND com UUID MS-RPRN |
| Função chamada | Não chamada | RpcAddPrinterDriverEx() via NDR |
| DLL path | Não enviado | UNC: \\attacker\share\evil.dll |
| Resultado | Print em console | RCE como SYSTEM / LPE |
| Detecção | Quase nula | EventID 808, 316, Sysmon 1/7 |