Jump to content
Nytro

An Analysis of MS16-098 / ZDI-16-453

Recommended Posts

Posted

 

An Analysis of MS16-098 / ZDI-16-453

Published On August 25th, 2016 | By Steiner
 

This past patch Tuesday, Microsoft released MS16-098, a patch for multiple vulnerabilities in “Kernel-Mode Drivers”. Within this patch, the vulnerability identified as CVE-2016-3308 andZDI-16-453 was addressed. This post is an analysis of this vulnerability and how it could potentially be leveraged by an attacker in the form of a Local Privilege Escalation (LPE) exploit.

 

MS16-098 xxxInsertMenuItem Diff

 

The vulnerability exists within the function win32k!xxxInsertMenuItem and how it handles reallocations of memory. This function is responsible for adding items to menus that are displayed to users. Menu items that are being added to a menu can be inserted either based on a position or an existing menu items identifier. This difference is explained in the documentation provided by Microsoft for the InsertMenuItem function. Additionally when a new menu is created, it has no storage for it’s menu items. It is not until an initial item is added to the menu that item storage is allocated. On Windows 7 x64, this allocation is done 8 items at a time resulting in the 2nd through the 8th item added to the menu not requiring a reallocation of space.

 

When a 9th, 17th, etc. item is added to the menu, a reallocation is triggered in order to be able to accommodate the additional item. After this occurs, and the memory allocation is successful, win32k!xxxInsertMenuItem callswin32k!MNLookUpItem a second to get the item’s location in the newly allocated space. The vulnerability in question can be triggered when the item returned from the second invocation of win32k!MNLookUpItem does not exist in the same menu as the first. Thewin32k!MNLookUpItem function recursively searches the menu structure, it’s items and the submenus optionally associated with those items. In order to force the second call to return an item from a different menu than the first call a parameter needs to be changed between the two function call. The prototype for this function looks roughly like: PITEM MNLookUpItem(PMENU pMenu, UINT uItem, BOOL fByPosition, PMENU *pMenuOut);. The first three parameters are required, while the 4th parameter is an optional pointer to a location to store the menu object for which the item returned is associated with. Under non-exploit conditions the value of pMenu is written to pMenuOut, the change introduced in this patch checks that this is the case and exits before harm can be done to the system.

 

In order to trigger the desirable code path, an attacker needs to create a menu along with a submenu. The submenu requires a single item with wID set to 1 for reasons outlined later. This submenu is referenced in an item that is added to the top level menu with a specific arbitrary wID. The top level menu is then populated with 7 additional items with additional unique wID values to fill it’s allocated space. To trigger the vulnerability the attacker calls theNtUserThunkedMenuItemInfo function to add a 9th item with the wID specified as the submenu. The first call to win32k!MNLookUpItem in win32k!xxxInsertMenuItemidentifies the submenu item and returns the toplevel menu in which it resides. Before the reallocation takes place, a check on the submenu item’s pItem->hbmpItem field takes place. If this field is set to HBMMENU_SYSTEM, then the value compared with wID is updated to 1. This change is leveraged by the attacker to cause the second call to win32k!MNLookUpItem to identify the submenu’s item (who’s wID was explicitly set to 1) and return the submenu instead of the original top level menu.

 

Under exploitation conditions, the item returned by the second call to win32k!MNLookUpItem  is in a different menu than what was originally assumed. This causes an out-of-bounds read to occur when a subsequent call to memmove uses pointer arithmetic to copy and overwrite a potentially excessively large block of memory. The call to memmove is roughly equivalent tomemmove(&pItem[1], pItem, &pMenu->rgItems[0] + (sizeof(ITEM) * pMenu->cItems - (QWORD)pItem). The pointer arithmetic assumes that the PITEM returned is in the array pointed to by pMenu->rgItems.

 

Reliable exploitation of this vulnerability would require the user to be able to limit the memory passed to memmove to avoid triggering a violation by corrupting memory stored after pItem. Assuming the size of memmove were limited, and pItem were the last item in the array pointed to by pMenu->rgItems, it is feasible that an attacker could leverage the memmove operation to write up to sizeof(win32k!tagITEM) bytes (0x90 on Windows 7 SP1 x64) past the region allocated for the array. An attacker can leverage the HANDLEENTRY structs within the shared region to identify the location in Kernel memory of the win32k!tagMENU struct, however to accurately predict the parameters of the memmove call, the attacker would need to know the value of the rgItems field within this struct.

A proof of concept for this vulnerability which triggers a BSOD on Windows 7 SP1 x64 can be found here.

 

Sursa: https://warroom.securestate.com/an-analysis-of-ms16-098/

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...