Attacker Value
(1 user assessed)
(1 user assessed)
User Interaction
Privileges Required
Attack Vector


Disclosure Date: May 09, 2023
Exploited in the Wild
Add MITRE ATT&CK tactics and techniques that apply to this CVE.


Win32k Elevation of Privilege Vulnerability

Add Assessment

Technical Analysis

Doing a patch diff between a Windows 10 1607 x86 version of win32kfull.sys prior to the patch and after the patch shows that only one function changed: xxxEnableMenuItem.

Looking at the code diff for this with BinDiff shows that two new blocks were added. These appear to be doing some validation of data and then optionally also incrementing a different data element.

After some time getting proper structures defined in Binary Ninja, I was able to come up with the following HLIL graph showing the code for xxxEnableMenuItem before the patch was issued:

And here is the code after the patch was issued:

Of note is the fact that the new edition of the code is checking that pRealMenu exists and then if it does, its incrementing that object’s cObjLock count by one. This extra lock appears to then be undone in a call to pRealMenu = ThreadUnlock1(), which was also added in.

Further analysis is available at which explains how this bug is a UAF, which makes sense given that a check was added into update the lock count appropriately. As explained in that writeup, prior to the patch, the code purely locked the window object pointed to by pMenu->spwndNotify and failed to also lock the menu object nested within the window object, aka the pRealMenu object returned by the call to MenuItemState.

Tracing the call flow backwards we can see that xxxEnableMenuItem() is called by NtUserEnableMenuItem(). According to the writeup, the menu item passed in via the first argument to xxxEnableMenuItem(), aka pMenu, would typically be locked inside of inside of a higher level function such as NtUserEnableMenuItem(). However they raise the question of “okay so you have a menu object you need to lock, but which menu item would need locking?”

So why this question in particular? Surely we are just dealing with one menu object which means one menu itself right? Well as the writeup explains, the object returned by a function such as MenuItemState() may encompass not only the main menu within a window object but also its submenus, and even subsubmenus in some cases.

This is becuase MenuItemState() will call MNLookupItem() which will in turn recursively call itself until it finds the object its looking for, meaning that pMenu may actually point to a nested set of menu objects. This looks like a potential case where assumptions could lead to some incorrect results.

In the exploit they create 4 menus, namely MenuA, MenuB, MenuC and MenuD, with MenuB being a child of MenuA, MenuC being a child of MenuB, and so on. They set the ID of MenuD to be 0xF060, aka SC_CLOSE. As noted at, this is sent when the user presses the close button or otherwise uses some menu control to close the window. They remove the class ID of SC_CLOSE from MenuA. They then release MenuC by deleting all references to it within MenuB, in order to ensure proper memory deallocation.

When xxxRedrawTitle() is called from within xxxEnableMenuItem(), a transfer will be made to a user mode callback via a call to xxxSendMessage(), at which point the exploit removes the reference between MenuC and MenuB, effectively releasing MenuC. At this point the reference to MenuC within xxxEnableMenuItem() will become invalid. Keep in mind in the code MenuC is effectively var_pMenu_spwndNotify
so thats where the relationship comes into play.

Hope that helps!

CVSS V3 Severity and Metrics
Base Score:
7.8 High
Impact Score:
Exploitability Score:
Attack Vector (AV):
Attack Complexity (AC):
Privileges Required (PR):
User Interaction (UI):
Scope (S):
Confidentiality (C):
Integrity (I):
Availability (A):

General Information


  • microsoft


  • windows 10 1507,
  • windows 10 1607,
  • windows server 2008 -,
  • windows server 2008 r2,
  • windows server 2012 -,
  • windows server 2012 r2,
  • windows server 2016 -


The following exploit POCs have not been verified by Rapid7 researchers, but are sourced from: nomi-sec/PoC-in-GitHub.
Additional sources will be added here as they become relevant.
Notes: We will only add the top 3 POCs for a given CVE. POCs added here must have at least 2 GitHub stars.

Additional Info

Technical Analysis