View Full Version : Subtle information disclosure in WIN32K.SYS syscall return values

j00ru vx tech blog
May 22nd, 2011, 11:59
While performing some random research related to the WIN32K.SYS driver syscalls a few months ago, I stumbled on an interesting finding – when examining the full 32-bit (or in the case of the original research – 64) return values, some of the services seemed to return unusual numbers, for example 0xfffffa8000ea0000. After investigating the subject for a while, it turned out that a part of the WIN32K syscall interface indeed does not always return a value of the native CPU size (as opposed to the core NT kernel). Instead, some of the graphical services seem to be explicitly declared as:

VOID NtUserRandomService( ... )
USHORT NtUserRandomService( ... )

Funny enough to find such types of quirks in the Windows kernel, eh? A list of the flawed syscall names is as follows:

ETHREAD (full disclosure)

NtUserSetRipFlags (Windows XP only)
NtUserSetDbgTag (Windows XP only)

ETHREAD (partial disclosure)


W32THREAD (full disclosure)


Other (unknown?)


The above list was created based on the Windows 7 64-bit graphical system call table, although I do not guarantee it is by any means complete (system calls might have been added, removed, or altered since then). As can be seen, a user-mode application is primarily able to read the addresses of two, internal kernel-mode structures (assigned to the currently executed thread, thus no serious information disclosure is going on, here). These are:

ETHREAD – the very standard NT kernel structure, assigned to every single thread running in the system,
W32THREAD – an internal, and pretty much unexplored structure, allocated on demand (i.e. when the thread calls a win32k service for the first time). For more details, you’re advised to take a look at the Mysteries of win32k & GDI ("http://www.woodmann.com/forum/archive/index.php/t-10295.htmlc") post on the Woodmann RCE Forums ("http://woodmann.com/forum/").
In order to confirm the story a little, let’s take a look at the exemplary NtUserGetKeyState system call epilogue:

mov**** [ecx+48h], edx
mov**** eax, [eax+70h]
mov**** [ecx+4Ch], eax
call*** _LeaveCrit@0*** ; LeaveCrit()
mov**** ax, di
pop**** edi
pop**** esi
pop**** ebp
retn*** 4
Clearly, the code doesn’t care about the upper 16 bits of the return value (leading to a partial disclosure) – that’s also the case for the rest of the aforementioned routines. A complete log from a Windows 7 64-bit instance of a Proof of Concept code follows:

--- 64bit Kernel-address disclosure:
[+] [ETHREAD] NtUserAlterWindowStyle********* : 0xfffffa8000ea80b0
[+] [ETHREAD] NtUserSetThreadState*********** : 0xfffffa8000ea80b0
[+] [ETHREAD] NtUserNotifyWinEvent*********** : 0xfffffa8000ea80b0
[+] [ETHREAD] NtUserModifyUserStartupInfoFlags: 0xfffffa8000ea80b0
[+] [ETHREAD] NtUserSetThreadLayoutHandles*** : 0xfffffa8000ea80b0
[+] [ETHREAD] NtUserNotifyIMEStatus********** : 0xfffffa8000ea80b0
[+] [ETHREAD] NtUserSetThreadLayoutHandles*** : 0xfffffa8000ea80b0
[+] [W32THREAD] NtGdiEngUnlockSurface******** : 0xfffff900c216f010
[+] [W32THREAD] NtGdiPATHOBJ_vEnumStartClipLines: 0xfffff900c216f010
[+] [W32THREAD] NtGdiEngDeletePath*********** : 0xfffff900c216f010
[+] [W32THREAD] NtGdiEngDeleteClip*********** : 0xfffff900c216f010
[+] [W32THREAD] NtGdiFONTOBJ_vGetInfo******** : 0xfffff900c216f010

--- 48bit Kernel-address disclosure (the AX value is uncontrolled):
[+] [ETHREAD] NtUserRegisterClassExWOW******* : 0xfffffa8000ea0000
[+] [ETHREAD] NtUserGetKeyState************** : 0xfffffa8000ea0000
[+] [ETHREAD] NtUserGetAsyncKeyState********* : 0xfffffa8000ea0000
[+] [ETHREAD] NtUserVkKeyScanEx************** : 0xfffffa8000ea0332
[+] [ETHREAD] NtUserSetWindowWord************ : 0xfffffa8000ea0000
[+] [ETHREAD] NtUserSetClassWord************* : 0xfffffa8000ea0000
Since the disclosed addresses do not pose a direct threat to the system security, the MSRC team did not consider the issue worth fixing. Well, although I do agree that it’s a minor issue, it is still amusing for me to find such peculiarities in the main Windows graphical kernel module http://j00ru.vexillium.org/wp-includes/images/smilies/icon_wink.gif No source code this time, although I do encourage you to fire your IDA and verify the findings by yourself (Windows WIN32K.SYS System Call Table ("http://j00ru.vexillium.org/win32k_syscalls/") might come in handy).

Take care!

PS. It seems that I wasn’t the only one coming across this matter – Tavis Ormandy has apparently tweeted ("http://twitter.com/#!/taviso/status/16853682570") about it a year ago, as well http://j00ru.vexillium.org/wp-includes/images/smilies/icon_wink.gif Nice one.

PS2. I received the first, valid submission for Pimp CrackMe – a reversing challenge by Gynvael ("http://gynvael.coldwind.pl/") and me (see: link ("http://j00ru.vexillium.org/?p=747")). Well done!