Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
my-CVE-2021-1675 — Detailed analysis and exploit implementation for Windows PrintNightmare (CVE-2021-1675/34527) with RPC-based privilege escalation and remote code execution via malicious printer driver installation. | Kitploit
Tools/GitHubGitHub/hahaleyile/my-cve-2021-1675
Privilege EscalationVulnerability AnalysisExploitationPapers & ResearchLearning & EducationRemote Access ToolBinary Exploitation
GitHubhahaleyile/my-cve-2021-1675

my-CVE-2021-1675

Detailed analysis and exploit implementation for Windows PrintNightmare (CVE-2021-1675/34527) with RPC-based privilege escalation and remote code execution via malicious printer driver installation.

View Repository
3385 years agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

= Print Nightmare Analysis Report :imagesdir: Figures :toc: :icons: font :figure-caption: Figure :xrefstyle: short :pdf-theme: basic-theme.yml

On June 29, 2021, a very severe Windows Print Spooler vulnerability was exposed as a 0-day, with a base score of 8.8, and was published on GitHub (now deleted). This vulnerability is the infamous PrintNightmare: CVE-2021-34527, which is even more dangerous than EternalBlue.

== Vulnerability Basic Information

CVE-2021-34527 affects almost all versions of Windows 7 and Windows Server 2008 and later; see <> for details.

In terms of impact, an attacker can use a standard user credential to remotely execute arbitrary code with administrator privileges. As for exploit difficulty, this vulnerability is very easy to exploit, therefore extremely harmful.

In terms of vulnerability characteristics, CVE-2021-34527 is based on CVE-2021-1675. CVE-2021-1675 is both a local privilege escalation and remote code execution vulnerability, and it has many similarities with CVE-2021-34527.

Before understanding how the vulnerability works, we should have a general understanding of the Windows Print Spooler architecture, which will help us clarify the relationships between the modules involved in the vulnerability.

== CVE-2021-1675 Call Flow

=== Windows Print Spooler Architecture

The spooler architecture can be represented as shown in <<spooler_arch>>:

[[spooler_arch]] .Print Spooler Architecture image::Print Spooler Architecture.png[]

Specifically, the Print Spooler is used to manage print jobs and consists of the following components:

winspool.drv:: The dynamic-link library file provided to users. This file defines the spooler-related Win32 API for user calls. All APIs use remote procedure calls to obtain services.

spoolsv.exe:: spoolsv.exe acts as the server role in the architecture, being the first program to process API calls. This design allows the Print Spooler to handle both local and remote print jobs without differentiation.

spoolsv.dll:: The router program. It forwards print requests received by spoolsv.exe to various print providers and decides which provider will ultimately process the request. Its function is to distinguish whether a print job is remote or local. On a remote machine, it will always assign the job to the local print provider.

localspl.dll:: The local print provider. The main task of the print provider is to handle print job management; most of the APIs are implemented in this module.

Continuing research based on the above theory, for example, when I call the AddPrinterDriverEx function (CVE-2021-1675), the following flow occurs:

=== Function Version Selection

First, this function is actually a macro that selects the Unicode version (W) or ANSI version (A) based on the local compilation environment, as shown in <>:

[[AddPrinterDriverEx]] .AddPrinterDriverEx image::AddPrinterDriverEx.png[]

However, whether it is the wide character or narrow character version, the result is essentially the same because Windows kernel strings use Unicode encoding, so the ANSI version call will eventually be converted to a Unicode version call, as shown in <>:

[[AnsiToUnicode]] .AnsiToUnicode image::AnsiToUnicode.png[]

After the parameters of the ANSI function are all converted to the Unicode version, a function is called (<>):

[[AnsiCallUnicode]] .AnsiCallUnicode image::AnsiCallUnicode.png[]

And that function is actually the Unicode version of AddPrinterDriverEx (<>):

[[GetUnicodeProcAddress]] .GetUnicodeProcAddress image::GetUnicodeProcAddress.png[]

=== API Function Sends RPC Request to Spooler Server

After entering the Unicode version of the function, it first selects the function parameter type based on the value of Level:

image::pDriverInfo.png[]

In this vulnerability, we set Level to 2, meaning the type of parameter pDriverInfo is the DRIVER_INFO_2 structure. Then Windows processes the function parameters, and after processing, continues to handle the API through a remote procedure call:

image::set arguments.png[]

image::NdrClientCall3.png[]

=== MSRPC Mechanism

Microsoft's remote procedure call mechanism is built on the DCE standard. In simple terms, a remote procedure call runs a process on a remote system; these processes are predefined by the programmer or the system.

The specific approach of RPC is to serialize the function to be called remotely, transmit it over the network to the remote system, where it is deserialized and executed. In Microsoft's architecture, TCP/IP and SMB are commonly chosen protocols to transport RPC calls.

To use MSRPC, you must first define the IDL interface description of the function to be called, then use the MIDL tool to generate the corresponding serialization stubs for the client and server. For some Win32 APIs, the server stub is already defined, so we only need to generate and use the client stub.

MSRPC uses UUIDs to identify a protocol type. For example, MS-RPRN is used to describe the remote print protocol; all functions related to remote printing are part of this protocol. MSRPC uses UUID 12345678-1234-ABCD-EF00-0123456789AB to identify this protocol (<<rprn_uuid>>):

[[rprn_uuid]] .MS-RPRN UUID image::spoolss uuid.png[]

Then, on this connection, you can use an operation number to identify a specific function within the protocol for remote invocation. For example, AddPrinterDriverEx identifies itself with 89 (<<addPrinterDriverEx_opnum>>):

[[addPrinterDriverEx_opnum]] .AddPrinterDriverEx Opnum image::AddPrinterDriverEx Opnum.png[]

When using MSRPC, two points are worth noting:

[IMPORTANT]

  • TCP/IP connections use dynamic ports, which must be obtained through the endpoint mapper listening on port 135.

"As you can see in your output, the scripts are trying to connect to port 135 (endpoint mapper) in order to get the TCP/IP port where the DCOM endpoint is listening (that is a dynamic port)." -- SecureAuthCorp/impacket issue #412

  • Additionally, some RPC functions require authentication to call, so this vulnerability requires a standard user account. ====

=== spoolsv.exe Processes API Requests

[[call_flow]] .RpcAddPrinterDriverEx Call Flow image::Function Calls.png[]

From <<call_flow>>, we can see that spoolsv.exe calls these functions, and from internal analysis, this module does not perform much besides initialization. Finally, this module calls the function pointed to by pLocalProvidor, which is the LocalAddPrinterDriverEx function in the localspl.dll module. As a local print provider, localspl is indeed the module that implements API functionality.

=== Local Print Provider Function Implementation Logic

[[LocalAddPrinterDriverEx]] .LocalAddPrinterDriverEx image::LocalAddPrinterDriverEx.png[]

First, <> shows that this module verifies whether the spooler is running properly, then jumps to the SplAddPrinterDriverEx function.

[[SplAddPrinterDriverEx]] .SplAddPrinterDriverEx image::SplAddPrinterDriverEx.png[]

The <> function is an important location for determining whether the AddPrinterDriverEx function can be executed successfully. The first half can be ignored because WPP is a logging-related technology; we skip it for now.

In the second half, Microsoft defines a variable v12, a flag that determines whether the function continues execution or exits directly.

[[bittest]] .bittest dwFileCopyFlags image::bittest in spl.png[]

From <>, we can see there are two conditions for continuing execution: either v12 is 0 (meaning bittest succeeds) or Validate succeeds. Validate is a permission check that cannot be easily bypassed. One API inside is OpenProcessToken, which means it needs to elevate privileges in the following process; this cannot be done without being an administrator.

Download Tool