After one years without blogging (all my apologies), I’m back. A few days ago I’ve seen the pwnie awards nominations list, there were lot’s of interesting and sophisticated bug exploitation. But one attract my attention “Privilege escalation in CSRSS” discovered by Matthew ‘j00ru’ Jurczyk. If you want to undestand this vulnerability and the way to exploit it, read this excellent post http://j00ru.vexillium.org/?p=893. And if you’re not familiar with CSRSS I advice you to read this article or this one (in french).
So, for writing the PoC we have to follow this steps :
- Spray the shared WIN32K section, by creating a sufficient amount of USER objects. The section is then going to be mapped to every process running in the context of the local desktop, thus we can perform this step at this early point,
- Create N instances of a process, each of which will create a single zombie console and then go idle, (*)
- Kill all N instanes of the processes,
- Create 3N local threads, (**)
- Kill 2N threads (in the order described in the “Second Stage” section),
- Kill the remaining N threads,
- Emulate the win+u key presses, resulting in a new instance of UTILMAN.EXE being created,
- Call SendMessage(HWND_BROADCAST,WM_SYSCOMMAND,0xFFF7,0), triggering the execution of CreateRemoteThread on each of the N freed handles.
* – by creating a zombie console, we also mean replacing the original PropertiesProc address (used in kernel32!AllocConsole) with a custom pointer.
** – the technique is very time-sensitive. If any handle is picked / stored on the free-list between steps 3 and 4, than steps 5 and 6 might not succeed in setting up the expected free-list handle layout.
I wont speak about first step immediately for different reason.
Let’s start with step two “create a single zombie console”, for me it’s the most hard part. We have to code AllocConsole and AllocConsoleInternal (I only scope Windows XP version for the moment). With AllocConsoleInternal we can control the PropRoutine & CtrlRoutine of the console. For conding this function I start googling with “AllocConsoleInternal + PropRoutine + CtrlRoutine” and reach this function definition :
BOOL APIENTRY AllocConsoleInternal( IN LPWSTR lpTitle, IN DWORD dwTitleLength, IN LPWSTR lpDesktop, IN DWORD dwDesktopLength, IN LPWSTR lpCurDir, IN DWORD dwCurDirLength, IN LPWSTR lpAppName, IN DWORD dwAppNameLength, IN LPTHREAD_START_ROUTINE CtrlRoutine, IN LPTHREAD_START_ROUTINE PropRoutine, IN OUT PCONSOLE_INFO pConsoleInfo)
With some call to ntdll!CsrAllocateCaptureBuffer, ntdll!CsrCaptureMessageBuffer for desktop, title and curent dir memory allocation. And then ntdll!CsrClientCallServer with allocConsole request we will reach winsrv!SrvAllocConsole and then spawn a console. For testing we lunch a broken console and kill his process and his parent process, after that we do a “right clic + proprieties/default” on the broken console and then we have a winsrv!InternalCreateCallbackThread executed with free handle! (the killed parent process handle precisely)
Therefore, with all this steps we are able to get CSRSS to call CreateRemoteThread with a system process handle and a controlled start address. Now we need step one “Spray the shared WIN32K section of system process with USER object” and it’s done! For this we have to invoke ultiman (WIN+U) which spawn three new process :
-> ultiman.exe [NT AUTHORITY\\SYSTEM]
+-> ultiman.exe /start [USER]
+–> narrator.exe /UM [USER]
Then we create user object like MessageBox with over long title (32Ko). But ultiman (system) doesn’t share the win32k section with other process at all times. After trying differents unsuccessful methods, I decided contact j00ru who give me the solution. We can inject user object in ultiman (system) if another user (regardless of his privileges) is logged on the machine at the same time. At this moment, I haven’t found explanation of this behaviour. I think it’s something in relation with Desktop/Winstation/Session, if you have some idea tell me.
Source of the poc :
Thanks to j00ru for his help and all shared knowledge on his blog, hitb and so on!