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.
Exploitation
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 CreatePopupMenu
and AppendMenu
functions. In addition, the exploit sets up WH_CALLWNDPROC
and EVENT_SYSTEM_MENUPOPUPSTART
hooks.
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_SELECTITEM
, MN_SELECTFIRSTVALIDITEM
and 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 win32k!xxxMNOpenHierarchy
function.
Figure 2. Disassembled code of the win32k!xxxMNOpenHierarchy
function
This function passes a crafted object at the NULL page to win32k!HMAssignmentLock
. The bServerSideWindowProc
bit is set inside the win32k!HMDestroyUnlockedObject
function, which is located a few calls deeper inside win32k!HMAssignmentLock
.
Figure 3. Disassembled code of the win32k!HMDestroyUnlockedObject
function
Everything is done! Now the exploit can send a specific message to the second window in order to execute WndProc
in kernel mode.
Conclusion
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 |
---|---|
CBC93A9DD769DEE98FFE1F43A4F5CADAF568E321 | Win32/Exploit.CVE-2019-1132.A |
Source: Welivesecurity