This article will analyze win32k
the CVE-2015-2546 vulnerability in the Windows operating system kernel module window manager subsystem. Similar to the CVE-2017-0263 vulnerability analyzed in the previous article, this vulnerability is also a post-release reuse of the pop-up menu tagPOPUPMENU
object ( UAF) vulnerability. The environment analyzed is a virtual machine in the Windows 7 x86 SP1 basic environment.
Article link: xiaodaozhi.com/exploit/122…
0x0 Preface
This article analyzes the CVE-2015-2546 UAF (use-after-free) vulnerability that occurs in the menu management component of the window manager (User) subsystem. During the kernel function xxxMNMouseMove
call xxxSendMessage
to send a message to the target menu window object MN_SELECTITEM
, the execution flow has the possibility of a user callback; after the function call that sends the message returns, the function does not reacquire the address of xxxMNMouseMove
the pop-up menu object associated with the target menu window object , but tagPOPUPMENU
Directly use the pop-up menu object address MN_SELECTITEM
stored in the register before sending the message , pass the object address as a parameter to the function call, and access the target pop-up menu object in the function.ebx
xxxMNHideNextHierarchy
If the user process has previously constructed a menu window object with special associations and properties through the exploit technique, and set a specific hook handler, then during the call to send a message to the xxxSendMessage
target menu window object MN_SELECTITEM
, the execution flow returns to the user context, and the exploit in the user process The code will have enough ability to trigger the destruction of the target menu window object, thereby directly releasing the pop-up menu object associated with the menu window object in the kernel; when the execution flow returns to the kernel context, the memory pointed to by the address stored in the register has been released, ebx
and The function xxxMNHideNextHierarchy
lacks necessary verification before passing the address as a parameter to the function , which will lead to a UAF vulnerability.
After triggering the destruction of the target menu window object, the exploit code in the user process uses clever memory layout to cause the system to reallocate a memory area of the same size to occupy the memory block of the previously released pop-up menu object, forge a new pop-up menu object and construct Relevant member fields, forge a new submenu window object and associated message processing function in the user process address space, and store the address of the window object in the reassigned pop-up menu object member field spwndNextPopup
. The function in the kernel will send a message to the submenu window object pointed to by the member xxxMNHideNextHierarchy
field of the target pop-up menu object , which will cause the execution flow to directly enter the forged message processing function defined in the user process address space in the kernel context, in the execution function Kernel exploit code to achieve the purpose of kernel exploitation and privilege escalation.spwndNextPopup
MN_SELECTITEM
0x1 principle
The CVE-2015-2546 vulnerability occurs in a kernel function win32k!xxxMNMouseMove
. During the execution of this function, after calling the function to send a ( ) message xxxSendMessage
to the target menu window object , if the function returns a value of , the system will verify the validity of the memory address of the target pop-up menu object stored in the register. Just call the function and pass the address into the function's parameter.0x1F0
MN_SETTIMERTOOPENHIERARCHY
0
ebx
tagPOPUPMENU
xxxMNHideNextHierarchy
popupMenu
.text:00139530pushedi ; lParam
.text:00139531pushedi ; wParam
.text:00139532push1F0h; message
.text:00139537pushesi ; pwnd
.text:00139538call_xxxSendMessage@16 ; xxxSendMessage(x,x,x,x)
.text:0013953Dtesteax, eax
.text:0013953Fjnz short loc_139583
.text:00139541pushebx ; popupMenu
.text:00139542call_xxxMNHideNextHierarchy@4 ; xxxMNHideNextHierarchy(x)
.text:00139547jmp short loc_139583
Vulnerable target code snippet
Comparing with the patch, it is found that the patch adds a comparison judgment between the pointer of the target window object extension area pointing to the associated pop-up menu object and the value stored in the register between the statements of calling the function to xxxSendMessage
send a message and calling MN_SETTIMERTOOPENHIERARCHY
the function . If they are not equal, the function will be skipped. call.xxxMNHideNextHierarchy
ebx
xxxMNHideNextHierarchy
.text:BF93EC2Epushedi ; lParam
.text:BF93EC2Fpushedi ; wParam
.text:BF93EC30push1F0h; message
.text:BF93EC35pushesi ; pwnd
.text:BF93EC36call_xxxSendMessage@16 ; xxxSendMessage(x,x,x,x)
.text:BF93EC3Btesteax, eax
.text:BF93EC3Djnz short loc_BF93EC8C
.text:BF93EC3Fmov eax, [ebp+pwnd]
.text:BF93EC42cmp [eax+0B0h], ebx
.text:BF93EC48jnz short loc_BF93EC8C
.text:BF93EC4Apushebx
.text:BF93EC4Bcall_xxxMNHideNextHierarchy@4 ; xxxMNHideNextHierarchy(x)
.text:BF93EC50jmp short loc_BF93EC8C
Target code snippet fixed by patch
In the Windows kernel, the menu object is displayed on the screen through tagWND
a special type #32768
( ) menu window object of the window object. The pointer MENUCLASS
to the associated pop-up menu object is stored in the extended area at the end of the menu window object .tagPOPUPMENU
When a function xxxSendMessage
sends MN_SETTIMERTOOPENHIERARCHY
a message, the system ultimately xxxMenuWindowProc
receives and calls a function in function MNSetTimerToOpenHierarchy
to process the message and return the function's return value to the caller.
When the execution flow returns to the function xxxMNMouseMove
, the system determines the return value. If the return value is , 0
the function is called xxxMNHideNextHierarchy
to close tagPOPUPMENU
the pop-up submenu of the target pop-up menu object.
Since before calling function xxxMNHideNextHierarchy
, xxxMNMouseMove
there is also a statement in function that calls xxxSendMessage
function to send MN_SETTIMERTOOPENHIERARCHY
message, this may cause the execution flow to be called back to the user process. Therefore, during this period, the attacker can trigger logic in the user process to cause tagPOPUPMENU
the memory of the target pop-up menu object to be released or reallocated, which will cause the target parameter popupMenu
to point to uncontrollable data in the memory area. If the attack code deliberately constructs the data in the memory block reallocated in the original location, then when xxxMNHideNextHierarchy
sending a message to the submenu window object in the function, the execution flow of the kernel context may directly enter the exploit code function located in the user process address space. middle.
0x2 Tracking
In win32k
the kernel module, there are two calls to function from other functions xxxMNMouseMove
:
- xxxHandleMenuMessages(x,x,x)+2E9
- xxxMenuWindowProc(x,x,x,x)+D1C
One of them is when the function xxxHandleMenuMessages
handles WM_MOUSEMOVE
the or WM_NCMOUSEMOVE
message, and the other is when the function xxxMenuWindowProc
handles MN_MOUSEMOVE
the message.
Use WinDBG to xxxMNMouseMove
set a breakpoint on the function and pop up the right-click menu in the virtual machine desktop area. Observe the paths through which the system will call the function under natural conditions. It is found that the resulting call stack is basically as follows:
# ChildEBP RetAddr
00 98af4a90 94779066 win32k!xxxMNMouseMove
01 98af4aec 94778c1f win32k!xxxHandleMenuMessages+0x2ed
02 98af4b38 9477f8f1 win32k!xxxMNLoop+0x2c6
03 98af4ba0 9477f9dc win32k!xxxTrackPopupMenuEx+0x5cd
04 98af4c14 83e501ea win32k!NtUserTrackPopupMenuEx+0xc3
05 98af4c14 76e170b4 nt!KiFastCallEntry+0x12a
Natural condition call stack of function xxxMNMouseMove
xxxMNMouseMove
Function xxxMNMouseMove
used to process the message that the mouse moves to the specified coordinate point. At xxxMNMouseMove
the beginning of the function, the function determines whether the pop-up menu object passed in through the parameter tagPOPUPMENU
is the current root pop-up menu object, and determines tagMENUSTATE
whether the incoming mouse coordinates have indeed changed compared with the coordinates previously stored in the current menu state structure. If If the conditions are not met, return directly. Next, the function calls xxxMNFindWindowFromPoint
the function and passes in the target pop-up menu object pointer and the new coordinates as parameters to find the menu window object displayed on the screen where the coordinate point is located. When the return value is the address of the real menu window object, the function uses the window object as the target window object and the menu item number where the mouse coordinates are located as the parameter. It sends a () message to the target window object to perform the operation of selecting the menu item wParam
and receives The return value of the function serves as the feedback flag variable.0x1E5
MN_SELECTITEM
Before calling the statement xxxSendMessage
to send the message, the function determines the value of the previously returned feedback flag variable to ensure that the menu item pointed to by the pointer is associated with another pop-up menu ( ) as a submenu and is not in a disabled state ( ).MN_SETTIMERTOOPENHIERARCHY
xxxMNMouseMove
MF_POPUP
MFS_GRAYED
.text:00139517xor edi, edi
.text:00139519pushedi ; lParam
.text:0013951Apush[ebp+cmdItem] ; wParam
.text:0013951Dpush1E5h; message
.text:00139522pushesi ; pwnd
.text:00139523call_xxxSendMessage@16 ; xxxSendMessage(x,x,x,x)
.text:00139528testal, 10h ; MF_POPUP
.text:0013952Ajzshort loc_139583
.text:0013952Ctestal, 3 ; MFS_GRAYED
.text:0013952Ejnz short loc_139583
Function xxxMNMouseMove determines the value of the flag variable fed back by selecting the menu item
Next, the function sets the timer for opening the pop-up submenu by calling the function to xxxSendMessage
send a message to the target menu window object . MN_SETTIMERTOOPENHIERARCHY
If the function returns a value of , 0
indicating that the pop-up submenu operation failed, the function is called xxxMNHideNextHierarchy
to close the pop-up menu belonging to the current target pop-up menu object.
popupNext = popupMenu->spwndNextPopup;if ( popupNext ){[...]popupNext = popupMenu->spwndNextPopup;if ( popupNext != popupMenu->spwndActivePopup )xxxSendMessage(popupNext, 0x1E4, 0, 0); // MN_CLOSEHIERARCHYxxxSendMessage(popupMenu->spwndNextPopup, 0x1E5, 0xFFFFFFFF, 0); // MN_SELECTITEM[...]}
Code snippet of function xxxMNHideNextHierarchy
Function Determines whether the menu window object pointed to by xxxMNHideNextHierarchy
the member field of the target pop-up menu object is the same as the member field pointed to. The member field points to the menu window object of the submenu directly associated with the current pop-up menu object; and the member field is used to store the menu window object of the currently active menu (that is, the menu where the current mouse or keyboard focus is). If they are not the same, then the function returns the submenu window pointed to by the member fieldspwndNextPopup
spwndActivePopup
spwndNextPopup
spwndActivePopup
spwndNextPopup