
Technical analysis and proof-of-concept exploit for CVE-2021-1732, a Windows kernel privilege escalation vulnerability in win32kfull, demonstrating exploitation via tagWND manipulation.
win32kfull!NtUserCreateWindowEx function due to a desynchronization between kernel callback user-mode memory allocation and the setting of the tagWND->flag attribute. This allows an attacker to forge the tagWND->offset value, causing an out-of-bounds memory access.win32kfull.sys calls NtUserCreateWindowEx to create a window, it checks tagWND->cbWndExtra (the number of extra allocated memory bytes for the window instance). If this value is non-zero, it calls the function win32kfull!xxxClientAllocWindowClassExtraBytes to callback to user mode user32.dll!__xxxClientAllocWindowClassExtraBytes to allocate space. After allocation, the address is returned to the kernel layer using NtCallbackReturn, which fixes the stack, and then continues execution. However, when the tagWND->flag value contains the 0x800 attribute, the saved value becomes an offset.user32.dll!_xxxClientAllocWindowClassExtraBytes function, call NtUserConsoleControl to modify the tagWND->flag to include the 0x800 attribute, and then use NtCallbackReturn to return a custom value to the kernel's tagWND->offset.win32kfull!NtUserCreateWindowEx.win32kfull.sys calls NtUserCreateWindowEx to create a window, it checks tagWND->cbWndExtra (the number of extra allocated memory bytes for the window instance). If this value is non-zero, it calls the function win32kfull!xxxClientAllocWindowClassExtraBytes to callback to user mode user32.dll!__xxxClientAllocWindowClassExtraBytes to create memory. After allocation, the address is returned to the kernel layer using NtCallbackReturn, which fixes the stack, and then continues execution. However, when the tagWND->flag value contains the 0x800 attribute, the value is accessed via an offset.NtUserConsoleControl to modify the flag to include the 0x800 attribute.17763:[[gpKernelHandleTable] + 0x18 * ((hwnd->cx * [gSharedInfo+0x10]) >> 5)]
It is mentioned that calling NtUserConsoleControl will reset the tagWND->offset and tagWND->flag values to include the 0x800 attribute. When the flag contains the 0x800 attribute, the offset addressing is used. The purpose of calling NtUserConsoleControl here is to modify the tagWND->flag value to include the 0x800 attribute, and then call the NtCallbackReturn function to return a specified value to re-modify the tagWND->offset, because win32kfull!xxxClientAllocWindowClassExtraBytes puts the return value into tagWND->offset.
+0x058 KernelCallbackTable : 0x00007ffb0e9d1070 Void
00007ffb0e9d1448`