Exploit for CVE-2021-40449 - Win32k Elevation of Privilege Vulnerability (LPE)

Overview

CallbackHell

Exploit for CVE-2021-40449 (Win32k - LPE)

Description

CVE-2021-40449 is a use-after-free in Win32k that allows for local privilege escalation.

The vulnerability was found in the wild by Kaspersky.

The discovered exploit was written to support the following Windows products:

  • Microsoft Windows Vista
  • Microsoft Windows 7
  • Microsoft Windows 8
  • Microsoft Windows 8.1
  • Microsoft Windows Server 2008
  • Microsoft Windows Server 2008 R2
  • Microsoft Windows Server 2012
  • Microsoft Windows Server 2012 R2
  • Microsoft Windows 10 (build 14393)
  • Microsoft Windows Server 2016 (build 14393)
  • Microsoft Windows 10 (build 17763)
  • Microsoft Windows Server 2019 (build 17763)

However, this exploit is current only tested on the following versions:

  • Microsoft Windows 10 (build 14393)
  • Microsoft Windows 10 (build 17763)

Technical Writeup

I highly recommend reading Kaspersky's technical writeup before proceeding.

As mentioned in the technical writeup by Kasperky, the vulnerability exists in GreResetDCInternal. If an attacker hooks the user-mode callback DrvEnablePDEV, which is called during hdcOpenDCW, it is possible to destroy the original device context by calling ResetDC, which causes a use-after-free in the kernel when the user-mode callback returns.

The following pseudo-code is made partially from the leaked Windows XP source code and by reverse-engineering the latest (before the patch) GreResetDCInternal from Win32kfull.sys. The irrelevant parts have been removed with [...]. Look for the VULN: comments.

BOOL GreResetDCInternal(
    HDC hdc,
    DEVMODEW *pdmw,
    BOOL *pbBanding,
    DRIVER_INFO_2W *pDriverInfo2,
    PVOID ppUMdhpdev)
{
    // [...]
    HDC hdcNew;

    {
        // Create DCOBJ from HDC
        DCOBJ dco(hdc);

        if (!dco.bValid())
        {
            SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
        }
        else
        {
            // Create DEVOBJ from `dco`
            PDEVOBJ po(dco.hdev());

            // [...]

            // Create the new DC
            // VULN: Can result in a usermode callback that destroys old DC, which
            // invalidates `dco` and `po`
            hdcNew = hdcOpenDCW(L"",
                                pdmw,
                                DCTYPE_DIRECT,
                                po.hSpooler,
                                prton,
                                pDriverInfo2,
                                ppUMdhpdev);

            if (hdcNew)
            {
                po->hSpooler = NULL;

                DCOBJ dcoNew(hdcNew);

                if (!dcoNew.bValid())
                {
                    SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
                }
                else
                {
                    // Transfer any remote fonts

                    dcoNew->pPFFList = dco->pPFFList;
                    dco->pPFFList = NULL;

                    // Transfer any color transform

                    dcoNew->pCXFList = dco->pCXFList;
                    dco->pCXFList = NULL;

                    PDEVOBJ poNew((HDEV)dcoNew.pdc->ppdev());

                    // Let the driver know
                    // VULN: Method is taken from old (possibly destroyed) `po`
                    PFN_DrvResetPDEV rfn = po->ppfn[INDEX_DrvResetPDEV];

                    if (rfn != NULL)
                    {
                        (*rfn)(po->dhpdev, poNew->dhpdev);
                    }

                    // [...]
                }
            }
        }
    }

    // Destroy old DC
    // [...]
}

As can be seen from the pseudo-code, the old device context can be freed in a user-mode callback from the hdcOpenDCW call, and later on, the method DrvResetPDEV is retrieved from the old device context and called with (po->dhpdev, poNew->dhpdev).

To create and hook a device context, one can do the following:

  • Find an available printer with EnumPrinters
  • Load the printer driver into memory with OpenPrinter, GetPrinterDriver and LoadLibraryExA
  • Get the printer driver's user-mode callback table with GetProcAddress and DrvEnableDriver
  • Unprotect the printer driver's user-mode callback table with VirtualProtect
  • Overwrite the printer driver's desired user-mode callback table entries
  • Create a device context for the printer with CreateDC(NULL, printerName, NULL, NULL)

We should now have a device context for a printer with hooked user-mode callbacks.

We're interested in only one hook, namely DrvEnablePDEV. This hook is interesting in two aspects: triggering the UAF and controlling the arguments, as described earlier. To trigger the UAF vulnerability, we will call ResetDC inside of the hook, which will destroy the old device context. When we return from the hook, we will still be inside the first GreResetDCInternal, which will shortly after get and call the function pointer for DrvResetPDEV from our old and destroyed device context with the two arguments that got returned from DrvEnablePDEV; the old and the new DHPDEV.

If your process is running with a medium integrity level, KASLR should not be an issue with the help of EnumDeviceDrivers and NtQuerySystemInformation.

Kaspersky mentions that the original exploit used GDI palette objects and a single kernel function call to achieve arbitrary memory read/write. This exploit uses a technique to allocate a BitMapHeader on the big pool and RtlSetAllBits to enable all privileges on our current process token. The BitMapHeader will point to our current process token's _SEP_TOKEN_PRIVILEGES. By calling RtlSetAllBits(BitMapHeader), it's possible to enable all privileges for our current process token with a single kernel function call. From here, one can abuse the new privileges to get SYSTEM. This exploit uses SeDebugPrivilege to inject shellcode into the winlogon.exe process.

PoC

./poc.png

References

You might also like...
Local Privilege Escalation Edition for CVE-2021-1675
Local Privilege Escalation Edition for CVE-2021-1675

Local Privilege Escalation Edition of CVE-2021-1675/CVE-2021-34527 Local Privilege Escalation implementation of the CVE-2021-1675/CVE-2021-34527 (a.k.

CVE-2021-24084 Windows Local Privilege Escalation Left officially unpatched since 2020. Hence, its still a zero day

WindowsMDM-LPE-0Day Works best on Windows 11 CVE-2021-24084 Windows Local Privilege Escalation Left officially unpatched since 2020. Hence, its still

CVE-2021-4034: Local Privilege Escalation in polkit's pkexec proof of concept
CVE-2021-4034: Local Privilege Escalation in polkit's pkexec proof of concept

CVE-2021-4034 Proof of Concept Qualys researches found a pretty cool local privilege escalation vulnerability in Polkit's pkexec: writeup, tweet. This

CVE-2021-4034 Add Root User - Pkexec Local Privilege Escalation

CVE-2021-4034 CVE-2021-4034 Add Root User - Pkexec Local Privilege Escalation 根据CVE-2021-4034进行了加强,执行Exploit将会默认添加用户名rooter,密码[email protected],并且rooter用户将具

Exploit for the pwnkit vulnerability from the Qualys team

CVE-2021-4034 Exploit for the pwnkit vulnerability from the Qualys team. This exploit assumes that gcc is present on the target machine. $ id uid=1001

Exploit to SYSTEM for CVE-2021-21551
Exploit to SYSTEM for CVE-2021-21551

CVE-2021-21551 Exploit to SYSTEM for CVE-2021-21551 SpoolPrinter Privesc using SeImpersonatePrivileges was made thanks to

a reliable C based exploit for CVE-2021-3560.

CVE-2021-3560 a reliable C based exploit for CVE-2021-3560. Summary: Yestreday i stumbled upon this blog post by Kevin Backhouse (discovered this vuln

Exploit for CVE-2021-30807

Write up is here: https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html Exploit for CVE-2021-30807. If you really want to build a jai

Gex is an iOS 14.7 jailbreak using CVE-2021-30807 IOMFB exploit

Gex is an iOS 14.7 jailbreak using CVE-2021-30807 IOMFB exploit rest of this readme is from jsherman212's exploit repo and probably stuff that is abou

Comments
  • Failed to allocate remote memory Windows 2019 17763

    Failed to allocate remote memory Windows 2019 17763

    Hi, I saw your project the other day and I decided to give it a try against a Windows Server 2019 (Build 17763) that I have set up. Every time I ran the exploit I got a [-] Failed to allocate remote memory[-] Failed to write to remote memory error and I was wondering was is it that makes it not work.

    The problem arises here: LPVOID buffer = VirtualAllocEx(proc, NULL, sizeof(payload), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    because the buffer is left blank therefore I get the error each time, but what could cause the allocation to fail?

    I'm trying to debug the problem, but I don't seem to be able to reach its solution.

    Any hints? Thanks so much.

    opened by MikosMotta 0
  • Exploit does not elevate privileges on Windows build 19042.746

    Exploit does not elevate privileges on Windows build 19042.746

    Hi,

    thank you for your work!

    The exploit does not elevate privileges on Windows build 19042.746 I tried to inject into explorer.exe for the last step and that does work for spawning the cmd, also all the steps before the injection do work. Injecting into winlogon.exe did not work as the privileges are not sufficient I guess. But once the cmd got spawned it has the context of the executing user and not system.

    What could be done to debug this or add functionality for Windows build 19042.746 ?

    Many thanks

    opened by 0xShkk 2
Owner
Oliver Lyak
Security Researcher
Oliver Lyak
My exploit for CVE-2021-40449, a Windows LPE via a UAF in win32kfull!GreResetDCInternal.

CVE-2021-40449 My exploit for CVE-2021-40449, a Windows LPE via a UAF in win32kfull!GreResetDCInternal. short wu along with the UAF vulnerabilty other

hakivvi 31 Oct 19, 2022
win32k LPE bypass CVE-2021-1732

CVE-2022-21882 win32k LPE bypass CVE-2021-1732 Test only tested on windows 20h2 19042.1415 tested on windows 21H1 (not working) Download https://raw.g

null 6 Apr 12, 2022
Exploit for CVE-2021-40449

CVE-2021-40449 More info here: https://kristal-g.github.io/2021/11/05/CVE-2021-40449_POC.html Compiling I did a bit of a hack with the MinHook library

null 48 Nov 9, 2022
PoC for PwnKit: Local Privilege Escalation Vulnerability in polkit’s pkexec (CVE-2021-4034)

CVE-2021-4034 PoC for PwnKit: Local Privilege Escalation Vulnerability in polkit’s pkexec (CVE-2021-4034) https://seclists.org/oss-sec/2022/q1/80 http

Andris Raugulis 924 Nov 21, 2022
CVE-2021-4034 One day for the polkit privilege escalation exploit

CVE-2021-4034 One day for the polkit privilege escalation exploit Just execute make, ./cve-2021-4034 and enjoy your root shell. The original advisory

Davide Berardi 1.7k Nov 26, 2022
Self-contained exploit for CVE-2021-4034 - Pkexec Local Privilege Escalation

PwnKit Self-contained exploit for CVE-2021-4034 - Pkexec Local Privilege Escalation Usage Should work out of the box on Linux distributions based on U

Oliver Lyak 679 Nov 25, 2022
This repository contains an exploit of CVE-2021-4034, a local privilege escalation in pkexec

pwnkit (CVE-2021-4034) Privilege Escalation exploit sample This repository contains an exploit of CVE-2021-4034, a local privilege escalation in pkexe

Peter Gottesman 28 Nov 6, 2022
An exploit for CVE-2021-4034 aka Pwnkit: Local Privilege Escalation in polkit's pkexec

CVE-2021-4034 Exploit Usage $ git clone https://github.com/whokilleddb/CVE-2021-4034 $ cd CVE-2021-4034 $ make [!] CVE-2021-4034 Exploit By whokilledd

whokilleddb 3 Jun 30, 2022
PoC for CVE-2021-28476 a guest-to-host "Hyper-V Remote Code Execution Vulnerability" in vmswitch.sys.

CVE-2021-28476: a guest-to-host "Microsoft Hyper-V Remote Code Execution Vulnerability" in vmswitch.sys. This is a proof of concept for CVE-2021-28476

Axel Souchet 208 Nov 26, 2022