Log in

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:


Code:
VOID NtUserRandomService( ... )
or
Code:
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)

NtUserAlterWindowStyle
NtUserSetThreadState
NtUserNotifyWinEvent
NtUserModifyUserStartupInfoFlags
NtUserSetThreadLayoutHandles
NtUserNotifyIMEStatus
NtUserSetThreadLayoutHandles
NtUserSetRipFlags (Windows XP only)
NtUserSetDbgTag (Windows XP only)

ETHREAD (partial disclosure)

NtUserRegisterClassExWOW
NtUserGetKeyState
NtUserGetAsyncKeyState
NtUserVkKeyScanEx
NtUserSetWindowWord
NtUserSetClassWord

W32THREAD (full disclosure)

NtGdiEngUnlockSurface
NtGdiPATHOBJ_vEnumStartClipLines
NtGdiEngDeletePath
NtGdiEngDeleteClip
NtGdiFONTOBJ_vGetInfo

Other (unknown?)

NtGdiFlush
NtGdiEngUnlockSurface

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 ("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:

Code:
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:

Code:
--- 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/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/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!





http://j00ru.vexillium.org/?p=762