Metasploit Module: Win32k NtGdiResetDC Use After Free Local Privilege Elevation
Type: exploit
Path: modules/exploits/windows/local/cve_2021_40449.rb
Platform: win
Disclosure date: 2021-10-12
References: CVE-2021-40449, URL-https://securelist.com/mysterysnail-attacks-with-windows-zero-day/104509/, URL-https://mp.weixin.qq.com/s/AcFS0Yn9SDuYxFnzbBqhkQ, URL-https://github.com/KaLendsi/CVE-2021-40449-Exploit, URL-https://github.com/ly4k/CallbackHell
Targets: Windows 10 x64 RS1 (build 14393) and RS5 (build 17763)

Description:
A use after free vulnerability exists in the `NtGdiResetDC()` function of Win32k which can be leveraged by
            an attacker to escalate privileges to those of `NT AUTHORITY\SYSTEM`. The flaw exists due to the fact
            that this function calls `hdcOpenDCW()`, which performs a user mode callback. During this callback, attackers
            can call the `NtGdiResetDC()` function again with the same handle as before, which will result in the PDC object
            that is referenced by this handle being freed. The attacker can then replace the memory referenced by the handle
            with their own object, before passing execution back to the original `NtGdiResetDC()` call, which will now use the
            attacker's object without appropriate validation. This can then allow the attacker to manipulate the state of the
            kernel and, together with additional exploitation techniques, gain code execution as NT AUTHORITY\SYSTEM.

            This module has been tested to work on Windows 10 x64 RS1 (build 14393) and RS5 (build 17763), however previous versions
            of Windows 10 will likely also work.

Check method (fingerprinting):
if session.platform != 'windows'
      # Non-Windows systems are definitely not affected.
      return CheckCode::Safe('Target is not a Windows system, so it is not affected by this vulnerability!')
    end

    version = get_version_info
    unless version.build_number.between?(Msf::WindowsVersion::Server2008_SP0, Msf::WindowsVersion::Win10_21H1) ||
           version.build_number == Msf::WindowsVersion::Server2022 ||
           version.build_number == Msf::WindowsVersion::Win11_21H2
      return CheckCode::Safe('Target is not running a vulnerable version of Windows!')
    end

    # Build numbers taken from https://www.qualys.com/research/security-alerts/2021-10-12/microsoft/
    if version.build_number == Msf::WindowsVersion::Win11_21H2 && version.revision_number.between?(0, 257)
      return CheckCode::Appears('Vulnerable Windows 11 build detected!')
    elsif version.build_number == Msf::WindowsVersion::Server2022 && version.revision_number.between?(0, 287)
      return CheckCode::Appears('Vulnerable Windows Server 2022 build detected!')
    elsif version.build_number == Msf::WindowsVersion::Win10_21H2 && version.revision_number.between?(0, 1318)
      return CheckCode::Appears('Vulnerable Windows 10 21H2 build detected!')
    elsif version.build_number == Msf::WindowsVersion::Win10_21H1 && version.revision_number.between?(0, 1287)
      return CheckCode::Appears('Vulnerable Windows 10 21H1 build detected!')
    elsif version.build_number == Msf::WindowsVersion::Win10_20