Windows Kernel Exploitation 101: Exploiting CVE-2014 ... - MWR Labs

Msg => Message, the event that has occurred, this could be that window has .... //The length of the menu item text - in the case 1 for just a single NULL byte.
448KB Sizes 0 Downloads 92 Views
MWR Labs Walkthrough

Windows Kernel Exploitation 101: Exploiting CVE-2014-4113 Sam Brown

1.1 Introduction In this walkthrough I will be walking the reader through going from a publically available description of a relatively simple Windows Kernel vulnerability and creating a functioning exploit for it. If you haven’t used kernel debugging before each of the two following posts provide a quick introduction: +

“An Introduction to Debugging the Windows Kernel with WinDbg” By Jan Mitchell

+

“Intro to Windows kernel exploitation 1/N: Kernel Debugging “ By Sam Brown

The vulnerability we will be focussing on exploiting is CVE-2014-4113 which is caused by a pointer being incorrectly validated before being used, this isn’t quite a NULL pointer dereference vulnerability but since we’ll be exploiting it using the same techniques we can effectively treat it as one. A NULL pointer dereference is pretty self-explanatory as it occurs when a piece of code attempts to deference a variable whose value is NULL/0. The vulnerability occurs within the win32k.sys driver which supports the Kernel-mode Graphics Display Interface which communicates directly with the graphics driver, this provides the kernel mode support for outputting graphical content to the screen. The vulnerability is in the function win32k!xxxHandleMenuMessages when it calls the function xxxMNFindWindowFromPoint which can either return a pointer to a win32k!tagWND structure or an error code which can be -1 or -5. xxxMNFindWindowFromPoint only checks if the error code -1 has been returned and will pass -5 to xxxSendMessage as if it’s a valid pointer which will then call a function it expects the tagWND structure to contain a pointer to. This vulnerability was patched in MS14-058 so I’ll be working on an unpatched version of Windows 7 Service Pack 1 32 bit while using a Window 10 VM to kernel debug it, setting this up is described in the resources referenced above.

1.2 Exploiting NULL pointer dereferences The process of exploiting a NULL pointer dereference vulnerability is straight forward: 1. Map the NULL page in user space. 2. Place a fake data structure in it which will cause our shell code to be executed. 3. Trigger the dereference bug.

On later versions of Windows it is not possible to map a NULL address space which means this class of vulnerability has been fully mitigated but on Windows 7 it is still possible and since it still has a substantial install base I thought this was worth a look.

1.3 Triggering the bug The first step for writing our exploit is to write code which can reliably trigger the vulnerability, this should crash our VM and in the kernel debugger we will be able to see that a NULL/Invalid pointer dereference has occurred. We will try to trigger the bug using the details from the Trendlabs report which gives an outline of the actions needed: 1. Create a window and 2-level popup menu. 2. Hook that window’s wndproc call. 3. Track popup menu on the window and enter hook callback. 4. In the hook callback, it changes wndproc of the menu to another callback. labs.mwrinfosecurity.com

2

5. In menu’s callback, it will destroy the menu and return -5 (PUSH 0xfffffffb; POP EAX) 6. Lead to xxxMNFindWindowFromPoint() on the destroyed menu return -5

Following these steps we start off by creating a window and hooking its wndproc function inside a new Visual Studio project. #include "stdafx.h" #include <Windows.h> /* LRESULT WINAPI DefWindowProc( _In_ HWND

hWnd,

_In_ UINT

Msg,

_In_ WPARAM wParam, _In_ LPARAM lParam ); hWnd => Handle of the Window the event was triggered on Msg => Message, the event that has occurred, this could be that window has moved, has been minimized, clicked on etc wParam, lParam => extra information depending on the msg recieved. */ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { //Just pass any messages to th