In June 2019, ESET researchers identified a zero-day exploit being used in a highly targeted attack in Eastern Europe.
The exploit abuses a local privilege escalation vulnerability in Microsoft Windows, specifically a NULL pointer dereference in the
win32k.sys component. Once the exploit was discovered and analyzed, it was reported to the Microsoft Security Response Center, who promptly fixed the vulnerability and released a patch.
The vulnerability affects the following Windows versions:
- Windows 7 for 32-bit Systems Service Pack 1
- Windows 7 for x64-based Systems Service Pack 1
- Windows Server 2008 for 32-bit Systems Service Pack 2
- Windows Server 2008 for Itanium-Based Systems Service Pack 2
- Windows Server 2008 for x64-based Systems Service Pack 2
- Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1
- Windows Server 2008 R2 for x64-based Systems Service Pack 1
This blog post focuses on the technical details of the vulnerability and its exploitation. Another post delves into the malware sample and its broader implications.
As with a number of other Microsoft Windows
win32k.sys vulnerabilities disclosed in recent years, this exploit uses popup menu objects. For example, the Sednit group’s local privilege escalation exploit that we analyzed in 2017 used menu objects and techniques very similar to the current exploit.
This exploit creates two windows; one for the first stage and another one for the second stage of the exploitation. For the first window, it creates popup menu objects and appends menu items using the
AppendMenu functions. In addition, the exploit sets up
Then the exploit displays a menu using the
TrackPopupMenu function. At this point the code hooked to
EVENT_SYSTEM_MENUPOPUPSTART gets executed. This code attempts to open as the first available item in the menu, by sending a sequence of
MN_OPENHIERARCHY messages to the menu.
The next step is very important for triggering this vulnerability. The exploit must catch the moment in time when the initial menu is already created, but the sub-menu is only about to be created. For that, the exploit has code that handles the
WM_NCCREATE message in the
WH_CALLWNDPROC hook. When the exploit code detects the system is in this state, it sends
MN_CANCELMENUS (0x1E6) message to the first menu, which cancels that menu. However, its sub-menu is still about to be created.
Now if we check this sub-menu object in kernel mode, we would see that
tagPOPUPMENU‑>ppopupmenuRootequals 0. This state allows the attacker to use that element in this kernel structure as a NULL pointer dereference. The exploit allocates a new page at address 0x0 and this address will be treated as a
tagPOPUPMENUobject (see Figure 1) by the kernel.
Figure 1. The
tagPOPUPMENU kernel structure
At this point, the attackers use the second window. The main exploit goal is to flip the
bServerSideWindowProc bit in the
tagWND structure of the second window. This causes the execution of a
WndProc procedure in kernel mode.
To perform that, the attackers leak the kernel memory address of the
tagWND structure of the second window by calling the non-exported
HMValidateHandle function in the
user32.dll library. Then the exploit crafts a fake
tagPOPUPMENU object at the NULL page and sends a
MN_BUTTONDOWN message to a sub-menu.
After that, the kernel will eventually execute the
Figure 2. Disassembled code of the
This function passes a crafted object at the NULL page to
bServerSideWindowProc bit is set inside the
win32k!HMDestroyUnlockedObject function, which is located a few calls deeper inside
Figure 3. Disassembled code of the
Everything is done! Now the exploit can send a specific message to the second window in order to execute
WndProc in kernel mode.
The exploit only works against older versions of Windows, because since Windows 8 a user process is not allowed to map the NULL page. Microsoft back-ported this mitigation to Windows 7 for x64-based systems.
People who still use Windows 7 for 32-bit systems Service Pack 1 should consider updating to newer operating systems, since extended support of Windows 7 Service Pack 1 ends on January 14th, 2020. Which means that Windows 7 users won’t receive critical security updates. Thus, vulnerabilities like this one will stay unpatched forever.
Indicators of Compromise (IoCs)
|SHA-1 hash||ESET detection name|