Introduction
In February 2021, the corporate Dbappsecurity found a pattern within the wild that exploited a zero-day vulnerability on Home windows 10 x64.
The vulnerability, CVE-2021-1732, is a win32k window object kind confusion resulting in an OOB (out-of-bounds) write which can be utilized to create arbitrary reminiscence learn and write capabilities throughout the Home windows kernel (native Elevation of Privilege (EoP)). Reminiscence exploitation typically requires a learn, write, and execute primitive to bypass trendy exploit mitigations akin to DEP, ASLR and CFG on hardened working techniques akin to Home windows 10. A knowledge-only assault requires solely a learn and write primitive because it doesn’t search to execute malicious code in reminiscence, however slightly manipulates knowledge buildings utilized by the working system to its benefit (i.e., to attain elevated privileges).
Kernel exploits are normally essentially the most subtle assault as they work together instantly with the Home windows kernel. When such assaults are profitable, they’re crucial as a result of they supply excessive privileges to the attacker, which can be utilized to extend the affect of the general exploit chain. On this case the exploit is a Native Privilege Escalation (LPE) that targets 64-bit Home windows 10 model 1909. The unique pattern found was compiled in Might 2020 and reported to Microsoft in December 2020. Whereas looking for further findings we went by means of a public exploit printed in March of 2021 by a researcher. Having this code publicly out there could elevate the potential for added menace attackers. Whereas now we have not discovered clear proof demonstrating malicious use of the proof-of-concept (POC), we did uncover some variants being examined and uploaded to VirusTotal.
On this weblog publish, McAfee Superior Risk Analysis (ATR) carried out a deep dive into the evaluation of the vulnerability, to determine the primitives for detection and safety. The exploit is novel in its use of a brand new win32k arbitrary kernel reminiscence learn primitive utilizing the GetMenuBarInfo API, which to one of the best of our data had not been beforehand recognized publicly.
CVE-2021-1732 Deep Dive
Exploitation of CVE-2021-1732 might be divided into six phases with the top aim of escalating a course of’ privileges to System. The next diagram reveals the phases.

Earlier than we dive into the small print, we should give some background to win32k exploitation primitives that are used within the exploitation of CVE-2021-1732.
Win32K Background
Win32k is a Graphical (GUI) element of the Microsoft Home windows Subsystem, most of which exists within the kernel for efficiency causes. It’s used for graphical print of the Home windows OS desktop. Nonetheless, because of the win32k structure, the kernel element of win32k nonetheless wants to have the ability to make calls to person mode by means of user-mode callback capabilities to facilitate window creation and administration.
Kernel user-mode callbacks have been nicely researched way back to 2008 and 2010, with a really complete evaluation in 2011 by Mandt. A win32k kernel perform akin to xxxCreateWindowEx will make a callback perform akin to xxxClientAllocWindowClassExtraBytes by means of the person course of PEB KernelCallbackTable.
When the user-mode callback has accomplished, NtCallbackReturn executes and passes the anticipated return parameter again to the kernel. As a result of stateless nature of those callbacks, many vulnerabilities have been found associated to the locking mechanisms on the objects resulting in use-after-free (UAF) exploitation.
Win32k has been one of the exploited parts within the Home windows kernel accounting for 63% of vulnerabilities from 2010 to 2018, resulting from its giant assault floor of syscalls relative to ntdll syscalls. Win32k vulnerabilities are typically become data-only assaults utilizing a learn/write kernel primitive through the use of a desktop object referred to as a tagWND knowledge construction.
There are two features to data-only assaults:
- Discovering a vulnerability.
- Leveraging present or new learn/write primitives utilizing particular OS APIs on object fields akin to tagWND.cbWndExtra.
The tagWND knowledge construction has two fields which make it a first-rate goal for studying/writing inside kernel reminiscence; tagWND.cbWndExtra and tagWND.ExtraBytes. When a window is created utilizing CreateWindowEx, it’s potential to request further bytes of reminiscence instantly after the tagWND object in reminiscence by means of the cbWndExtra subject within the WNDCLASSEXA construction when registering the window class.
The variety of further bytes is managed by the cbWndExtra subject, and the allotted further reminiscence handle is positioned on the ExtraBytes subject. The learn/write primitive is created as follows:
- Uncover a vulnerability akin to a UAF, which can assist you to write to a tagWND object in reminiscence referred to as WND0.
- Allocate one other tagWND object referred to as WND1 close to the beforehand corrupted WND0 in reminiscence.
- Overwrite WND0.cbWndExtra to a big worth akin to 0xFFFFFFF.
- Name an API akin to SetWindowLongPtr on WND0 which can write OOB to fields inside WND1.
Win32k kernel user-mode callbacks have been exploited many occasions by leveraging tagWND learn/write capabilities throughout the Home windows kernel for escalation of privileges akin to CVE-2014-4113, CVE-2015-0057, MS15-061, CVE-2016-7255 and CVE-2019-0808.
Win32k Exploit Primitives
A number of primitives have been noticed within the CVE-2021-1732 exploit utilized by the attackers; moreover, it’s value mentioning that a few of them are new and never beforehand seen within the wild.
Previous to Home windows RS4 it was trivial to leak tagWND kernel addresses utilizing a number of methods, akin to calling HMValidateHandle to repeat tagWND objects from the kernel to person desktop heap. The newest model of Home windows 10 has been hardened towards such trivial methods.
Nonetheless, utilizing the spmenu kernel handle leak method and relative tagWND desktop heap offsets, as soon as a vulnerability is found to overwrite a tagWND.cbWndExtra subject, it’s potential to attain kernel learn/write capabilities with out leaking the precise tagWND kernel addresses. The spmenu method on this exploit was used right here and right here, however we aren’t conscious of the GetMenuBarInfo API ever getting used earlier than in a win32k exploit.
The next diagram reveals the primitives utilized in CVE-2021-1732.

Current Home windows OS Mitigations
Nice work has been finished to harden the safety of win32k towards EoP assaults with new and improved mitigations by the Microsoft OSR staff, Mandt, Google Venture Zero, Schenk and Dabah. These mitigations embody:
- Kind isolation (all identical kind objects tagWND getting used).
- Win32k filtering (restricted to Edge browser and never course of extensive however since this analysis there have been many enhancements on win32k API filtering capabilities such because the addition of _stub_UserSetWindowLong and _stub_UserSetWindowLongPtr _stub_UserGetMenuBarInfo in win32k.sys).
- Fragmenting kernel desktop heap and elimination of kernel addresses within the person desktop heap (can use relative offsets inside person and desktop heaps described later within the weblog).
- Elimination of knowledge kind symbols from win32k drivers (obfuscation slightly than mitigation).
Within the context of a malicious course of exploiting CVE-2021-1732, the above mitigations present no safety. Nonetheless, it doesn’t affect Google Chrome because it disallows win32k calls (Home windows 8 and better), or Microsoft Edge because it applies win32k filtering on the related APIs.
Triggering the Vulnerability and Patch Evaluation
When a window is created utilizing CreateWindowEx API, a tagWND object is created by the Home windows working system. This window, as defined above, might be created with a parameter to allocate further reminiscence utilizing cbWndExtra.
In the course of the home windows creation course of (CreateWindowEx API) a callback named xxxClientAllocWindowClassExtraBytes is triggered to allocate house within the person mode desktop heap for the tagWND.ExtraBytes (offset 0x128) per the tagWND.cbWndExtra (offset 0xc8) worth measurement (see determine 3 and 4 under for WND1).


The situation of this reminiscence is saved as a person mode reminiscence pointer to the desktop heap and positioned at tagWND.ExtraBytes. It’s then potential to transform the traditional window to a console window utilizing NtUserConsoleControl which can convert that person mode pointer at tagWND.ExtraBytes to an offset worth which factors into the kernel desktop heap (see determine 5 under for WND0). It’s this modification in worth at tagWND.ExtraBytes (window kind confusion) that may be exploited for an OOB write throughout the xxxClientAllocWindowClassExtraBytes callback window.


Per determine 6 above the next steps are required to set off the vulnerability:
- Get a pointer to the HMValidateHandle inline perform inside user32.dll.
- Hook xxxClientAllocWindowClassExtraBytes throughout the PEB KernelCallBack desk.
- Create a number of home windows (we are going to simply use the primary two WND0 and WND1 created), utilizing the CreateWindowEx API, in order that two home windows are created in shut reminiscence proximity.
- Name HMValidateHandle on WND0 and WND1 which can copy their objects from the kernel desktop heap to person desktop heap. At tagWND+0x8 an offset is saved into the desktop heap; this offset is similar for the person and kernel desktop heaps. The exploit makes use of these offset values to calculate the relative distance between WND0 and WND1 within the kernel desktop heap which is required later for studying and writing OOB. Per desk 1 under, through the use of these offsets there is no such thing as a requirement to leak the precise WND0 and WND1 kernel addresses since learn and writes might be finished relative to the offsets (person and kernel desktop heaps have the identical offsets).

5. WND0 is then transformed to a console window by calling NtUserConsoleControl which converts WND0.ExtraBytes from a person desktop heap pointer to an offset throughout the kernel desktop heap. That is wanted later in order that WND0 can write OOB to WND1.
6. Create malicious window WND_Malicious utilizing the CreateWindowEx API
-
- In the course of the window creation the callback xxxClientAllocWindowClassExtraBytes API is executed to request person mode to allocate reminiscence for WND_Malicious.cbWndExtra and cross the person desktop heap pointer again to the kernel perform win32kfull!xxxCreateWindowEx.
- xxxClientAllocWindowClassExtraBytes has now been hooked and we do the next earlier than returning to win32kfull!xxxCreateWindowEx:
- Name NtUserConsoleControl to transform WND_Malicious to a console window so changing its WND_Malicious.cbWndExtra from a person desktop heap pointer to an offset throughout the kernel desktop heap.
- Lastly name NtCallbackReturn which completes the callback and returns a single worth to xxxClientAllocWindowClassExtraBytes. As an alternative of passing the person desktop heap pointer as anticipated by xxxClientAllocWindowClassExtraBytes again to the kernel we cross the worth at WND0+0x08 which is the kernel desktop heap offset to WND0 per determine 7 under. Now anytime we name SetWindowLongW on WND_Malicious we will probably be writing to WND0.

Patch Evaluation
The vulnerability lies in the truth that win32kfull!xxxCreateWindowEx doesn’t test whether or not the window kind has modified between the time it initiates the xxxClientAllocWindowClassExtraBytes and will get the response from NtCallbackReturn.
After we name NtUserConsoleControl with WND_Malicious within the hook above, xxxConsoleControl checks if tagWND+0xE8 flag has been set to 0x800 to point a console window per determine under. As WND_Malicious was created as a traditional window, xxxConsoleControl allocates reminiscence at an offset throughout the kernel desktop heap after which frees the person desktop heap pointer present at WND_Malicious.ExtraBytes (0ffset 0x128). It then locations the offset to this new allocation within the kernel heap at WND_Malicious.ExtraBytes (0ffset 0x128) and units the tagWND+0xE8 flag to 0x800 to point it’s a console window.
After coming back from the callback once we issued NtCallbackReturn above, xxxCreateWindowEx doesn’t test that the window kind has modified and locations the WND0+0x08 at WND_Malicious.ExtraBytes per determine 9 under. The RedirectFieldpExtraBytes checks the WND_Malicious.ExtraBytes initialized worth however it’s too late as WND0+0x08 has already been written to WND_Malicious.ExtraBytes (offset 0x128).

The patched win32kfull.sys has up to date xxxCreateWindowEx to now test the ExtraBytes initialized worth earlier than writing the returned worth from person mode to tagWND. ExtraBytes (offset 0x128) per determine 10 under.

Determine 11 under reveals that tagWND. ExtraBytes is initialized to zero inside xxxCreateWindowEx throughout regular window creation.

Determine 12 under reveals that tagWND. ExtraBytes is initialized to the brand new offset worth within the kernel desktop heap inside xxxConsoleControl throughout console window creation. RedirectFieldpExtraBytes merely checks this initialized worth to find out if the window kind has modified. As well as, Microsoft have additionally added telemetry for detecting modifications to the window kind flag within the patched model.

tagWND OOB Write
The vulnerability throughout the xxxCreateWindowEx API allowed the WND_Malicious.ExtraBytes subject be to set to a price of WND0 offset throughout the kernel desktop heap. Now any time SetWindowLongW known as on WND_Malicious it is going to write to WND0. By supplying an offset of 0xc8, the perform will overwrite the WND0.cbWndExtra subject to a big worth of 0XFFFFFFF per figures 13 and 14 under.
This implies it could actually write past its tagWND construction and ExtraBytes in kernel reminiscence to fields inside WND1. As well as, WND0.ExtraBytes can also be overwritten with the offset to itself so calls to SetWindowLongPtrA on WND0 will write to an offset in kernel desktop heap relative to the beginning of WND0.


Kernel Tackle Leak
Now that the WND0.cbWndExtra subject has been set to a really giant worth (0xFFFFFFF), anytime SetWindowLongPtrA known as on WND0 it is going to write into the adjoining WND1 in kernel reminiscence per determine 15 under. By writing to particular fields in WND1 we are able to create a kernel handle reminiscence leak as follows:
- Write a price of 0x400000000000000 to WND1 fashion subject to briefly change it to a toddler window per figures 15 and 16 under.
- Calling SetWindowLongPtrA API on WND0 with a price of -12 (GWLP_ID) now permits the spmenu subject (kind tagMENU) of WND1 to be overwritten with a pretend spmenu knowledge construction since now we have modified it to be a toddler window per determine 15 and 17 under.
- Per SetWindowLongPtrA API documentation, the return worth will give us the unique worth on the offset overwritten, i.e., the spmenu knowledge construction pointer which is a kernel reminiscence handle. So, we now have leaked a pointer to a spmenu (kind tagMENU) knowledge construction in kernel reminiscence and changed the pointer in WND1.spmenu with a pretend spmenu knowledge construction inside person desktop heap per determine 17 under.



Kernel Arbitrary Learn
Utilizing the spmenu knowledge construction kernel pointer leaked beforehand we are able to use the structure of this knowledge construction and the GetMenuBarInfo API logic to show it into an arbitrary kernel reminiscence learn per figures 18,19 and 20 under.



As you may see from the xxxGetMenuBarInfo perform in figures 21 and 22 under, by putting our leaked kernel handle on the proper location in our pretend spmenu knowledge construction we are able to create an arbitrary kernel reminiscence learn when calling GetMenuBarInfo.


Kernel Arbitrary Write
An arbitrary kernel write primitive might be simply achieved now by writing our vacation spot handle to WND1.ExtraBytes subject by calling SetWindowLongPtrA on WND0 which can write OOB to WND1 relative to the offset we specify per determine 23 under
On this case the offset is 0x128 which is ExtraBytes. Then merely calling SetWindowLongPtrA on WND1 will write a specified worth on the handle positioned within the WND1.ExtraBytes subject. The arbitrary write is achieved as a result of WND1 is a traditional window (has not been transformed to a console window like WND0 and WND_Malicious) and so will write to no matter handle we place in WND1.ExtraBytes.

Knowledge Solely Assault
The arbitrary kernel learn and write primitives might be mixed to carry out a data-only assault to overwrite a malicious course of EPROCESS token with that of PID 4 which is System for an escalation of privilege (EoP).
The unique spmenu kernel handle leaked beforehand has a pointer to WND1 at offset 0x50 per figures 24 and 25 under. Via a number of arbitrary reads utilizing the GetMenuBarInfo on our pretend spmenu knowledge construction with this WND1 kernel handle we are able to ultimately learn the PID 4 System EPROCESS token.


By putting the vacation spot handle (malicious course of EPROCESS token) at WND1.ExtraBytes then the next name to SetWindowLongPtrA will write the worth (PID 4 – System EPROCESS token) to that handle per figures 26 and 27 under.


The exploit then restores overwritten knowledge construction values as soon as the EoP is full to forestall a BSOD (Blue Display screen of Demise).
Conclusion
On this report, we undertook a deep evaluation of CVE-2021-1732 which is a Native Privilege Escalation on Home windows 10. Home windows kernel data-only assaults are troublesome to defend towards, as as soon as a vulnerability is found they use official and trusted code by means of particular APIs to control knowledge buildings in kernel reminiscence.
The win32k element has been hardened by means of nice work by Microsoft towards learn/write primitives, however there are nonetheless alternatives for exploitation resulting from its giant assault floor (syscalls and callbacks) and lack of win32k filtering on a process-wide foundation. It might even be nice to see a system extensive win32k filtering coverage functionality inside Home windows 10.
Patching is all the time one of the best answer for vulnerabilities, however a powerful protection technique akin to menace looking can also be required the place patching is probably not potential, and to detect variants of vulnerabilities/exploits being utilized by campaigns.