Archive for the ‘Articles and Presentations’ Category

Closing “Heaven’s Gate”

Wednesday, December 30th, 2015

Brief Overview of WoW64

“Heaven’s Gate” refers to a technique first popularized by the infamous “Roy G. Biv” of 29a fame, and later re-published in Valhalla #1. Cited and improved in various new forms, and even seen in the wild used by the Vawtrak banking malware, it centers around the fact that on a 64-bit Windows OS, seeing as how all kernel-mode components always execute in 64-bit mode, the address space, core OS structures (EPROCESS, PEB, etc…), and code segments for processes are all initially setup for 64-bit “long mode” execution, regardless of the process actually being hosted by a 32-bit executable binary.

In fact, on 64-bit Windows, the first piece of code to execute in *any* process, is always the 64-bit NTDLL, which takes care of initializing the process in user-mode (as a 64-bit process!). It’s only later that the Windows-on-Windows (WoW64) interface takes over, loads a 32-bit NTDLL, and execution begins in 32-bit mode through a far jump to a compatibility code segment. The 64-bit world is never entered again, except whenever the 32-bit code attempts to issue a system call. The 32-bit NTDLL that was loaded, instead of containing the expected SYSENTER instruction, actually contains a series of instructions to jump back into 64-bit mode, so that the system call can be issued with the SYSCALL instruction, and so that parameters can be sent using the x64 ABI, sign-extending as needed.

This process is accurately described in many sources, including in the Windows Internals books, so if you’re interested in reading more, you can do so, but I’ll spare additional details here.

Enter Heaven’s Gate

Heaven’s Gate, then, refers to subverting the fact that a 64-bit NTDLL exists (and a 64-bit heap, PEB and TEB), and manually jumping into the long-mode code segment without having to issue a system call and being subjected to the code flow that WoW64 will attempt to enforce. In other words, it gives one the ability to create “naked” 64-bit code, which will be able to run covertly, including issuing system calls, without the majority of products able to intercept and/or introspect its execution:

  • Microsoft’s EMET, as well as a myriad of similar tools and sandboxes, only hook/protect the 32-bit NTDLL for WoW64 processes, under the assumption that the 64-bit NTDLL can’t be reached in any other way. The mitigations can therefore be bypassed using Heaven’s Gate. The same technique has been used by the Phenom malware to bypass AV solutions.
  • When debugging a 32-bit application with a 64-bit debugger (such as WinDBG), you will initially see the 64-bit state (heap, stack, NTDLL, TEB, etc…). Since this state is uninteresting, as it only contains the WoW64 system call layer, manual commands and extensions must be used to investigate the 32-bit state instead — and so in order to avoid this, even Microsoft often recommends using the 32-bit WinDBG instead, which will provide a much more seamless debugging experience and show the 32-bit state of the process. Other 3rd party debuggers, which are 32-bit only, will also behave the same way. The problem, therefore, is that by using Heaven’s Gate, there IS now interesting 64-bit state, that these debuggers will miss.
  • Many emulation/detonation engines will, upon seeing a 32-bit executable, emulate it using x86 instructions. They will either ignore or be unable to handle x64 instructions, as they never expect them to run. In fact, this was recently shown by a blog post over at Hexacorn. Heaven’s Gate allows such x64 instructions to run, rendering the x86 code into “dummy” code for misdirection purposes.

Memory Restrictions

These and other “benefits” make Heaven’s Gate a tool of choice for malicious code.  However, there always existed an interesting limitation in 32-bit applications running under WoW64: even when executing in 64-bit long-mode, addresses above the 4 GB could never be allocated (in fact, addresses above 2 GB could normally never be used for compatibility purposes, unless the image was linked with /LARGEADDRESSAWARE — the switch was originally designed to support /3GB x86 server environments, but outgrew its original intent to allow full 4 GB addresses under WoW64, a fact leveraged by many 32-bit games and browsers even today).

Using a kernel debugger and the !vad command, it’s simple to see why, such as on this Windows 7 system, where I’ve typed the command before the process has any chance of executing even a single instruction — not even NTDLL has loaded here, folks. This is an interesting view of what are the “earliest” memory structures you can find in a WoW64 process (at least on Windows 7).

vad

Note that a giant VAD at the end, highlighted in teal, occupies the entire 64-bit portion of the address space. Let’s see what !vad has to say about it:

vadblock

Seeing as how it’s configured as a “NoChange” and “OneSecured” VAD, it cannot be freed or modified in any way. This is further confirmed by the commit charge of -1.

On Windows 8 and later, however, the output changes, as you can see below. Note that I’ve re-used the same colors as in the Windows 7 output for clarity (and the uncolored VADs correspond to the CFG entries).

vad81

The 64-bit NTDLL is actually loaded in 64-bit address space now! And we have not one, but two teal-colored VADs, which surround it, re-creating the “no man’s land” just as on Windows 7 and earlier. This change was briefly mentioned, I believe, by Matt Miller (of skape fame) at one of Microsoft’s BlackHat presentations: it made it a bit harder to guess the location of the 64-bit NTDLL by simply adding a fixed size to the 32-bit NTDLL. In my screenshot, since this is a CFG-enabled process, the VADs don’t exactly envelop NTDLL — rather they surround the native CFG bitmap + NTDLL, but the point remains.

This change in NTDLL load behavior also had the likely intended side effect of making hooks in 64-bit NTDLL extremely hard, or outright impossible. You see, without consuming an enormous amount of space, it’s simply not possible to overwrite an x64 instruction with a call or jmp to an absolute 64-bit address efficiently. Instead, hooking engines will allocate a “trampoline” that is within the 32-bit address range of the hooked function, and use a much smaller 5 byte 32-bit relative jump, which happens to fit nicely in the “hotpatch aware” region that Microsoft binaries have (or anyone linking with /hotpadmin). The trampoline then uses the full 64-bit absolute jump instruction.

As you’ve figured out by now, if the trampoline needs to be within 2GB, but there are two large VADs blocking off all 64-bit addresses around NTDLL, this hooking technique is dead in the water. Other, more complex and error-prone techniques must (and can) be used instead.

Nevertheless, nothing stops Heaven’s Gate on Windows 8. There some minor WoW64 changes which one must adapt to, and accessing or hooking 64-bit NTDLL becomes harder.

Control Flow Guard and WoW64

In Windows 10, a new exploit mitigation is introduced called Control Flow Guard, or CFG. It too, has been rather well described in multiple sources, so I won’t go into details inside of this post. The important piece to remember about CFG is that all relative function calls are now subject to an additional compiler-generated check, which is implemented by NTDLL: only valid function prologues (within 8 bytes of alignment) can be the target of such a call. Valid function prologues, in turn, are marked by a bit being set in a very large bitmap (bit array) structure, which describes the entire user-mode address space (all 128TB of it!). I previously posted on some interesting changes this required in the memory manager, as this bit array obviously becomes quite large (2 TB, in fact).

What’s not been documented too clearly in most research is that on 64-bit systems, there are in fact not one, but two CFG bitmaps: one for 32-bit code, and one for 64-bit code. The addresses of both of these bitmaps is stored in the per-process working set structure (called MMWSL). This structure is pointed to by the MMSUPPORT structure inside of EPROCESS (i..e.: PsGetCurrentProcess()->Vm.VmWorkingSetList), but a unique thing about it, is that it’s stored in a region of memory called “hyperspace”, which is at a fixed address… much like the per-process page table entry array. On recent 64-bit systems, this hard-coded address is 0xFFFFF58010804000, a fact I pointed out in a previous blog post addressing the 64-bit address space of Windows 8.1 and later.

As one can see in the symbols that WinDBG can dump, the MMWSL structure contains a field:

+0x1f8 UserVaInfo       : _MI_USER_VA_INFO

And inside of MI_USER_VA_INFO, we can find an array:

+0x0c8 CfgBitMap : [2] _MI_CFG_BITMAP_INFO

Whose two entries correspond to the following enumeration:

0:000> dt _MI_CFG_BITMAP_TYPE
 CfgBitMapNative = 0n0
 CfgBitMapWow64 = 0n1
 CfgBitMapMax = 0n2

Clearly, thus, a 64-bit Windows 10 kernel contains not one, but two CFG bitmaps. And indeed, the 32-bit NTDLL will utilize the address of the WoW64 bitmap, while the 64-bit NTDLL will utilize the Native bitmap. But why use two separate bitmaps? What separates a WoW64 bitmap from a native bitmap? One would imagine that 64-bit code is marked as executable in the native bitmap, and 32-bit code is marked as executable in the WoW64 bitmap… but that’s not quite the full story.

At verification time, indeed, it is the version of NTDLL that is being used, which determines which bitmap will be looked at. But how does the OS populate the bits?

In CFG-aware versions of Windows, the CFG bitmap is touched through two paths: MiCommitVadCfgBits, and MiCfgMarkValidEntries. These, in turn, correspond to either intrinsic CFG modifications (side-effects of allocating, protecting and/or mapping executable memory), or explicit CFG modifications (effect of calling SetValidCallTargets). Both of these paths will eventually call MiSelectCfgBitMap, whose pseudo-code is shown below.

cfg

As is quite clear from the code, any private memory allocations below the 64-bit boundary will be marked only in the 32-bit bitmap, while the opposite applies to the 64-bit bitmap. In fact, this is the result of an optimization: instead of having two 2TB bit arrays for each processor execution mode, a single 2TB array is used for 64-bit native code, while a single 32MB array is used for 32-bit native code, greatly reducing address space consumption.

Closing the Gate

Basing the decision of which CFG bitmap to populate on the virtual address of the executable allocation creates an obvious dichotomy: 64-bit code, if running in a 32-bit address range, will instantly trip up CFG, because the NTDLL library that is active in that environment is the 64-bit version, which will check the 64-bit bitmap, which will not have any bits set in the 0-4 GB range. Similarly, any 32-bit code must be running below the 4 GB boundary, else the 32-bit NTDLL’s CFG validation routine will trip up, as the 32-bit bitmap isn’t even large enough to account for addresses above 4 GB.

A naive solution is therefore proposed: simply allocate 64-bit code above the 4GB range, and the problem goes away. There is, of course, a problem with this approach: the NoChange VADs which block the entire > 4 GB region of memory and mark it unusable, leaving only 64-bit NTDLL as the only valid allocation in that address range.

In Windows 10, these two factors combined result in the inability to execute any useful 64-bit code in a 32-application/WoW64 process, because the two restrictions combine, creating an impossible condition. You may be tempted to dismiss the reality by stating that all the 64-bit malicious code has to do is not to have been compiled with CFG. In this case, the compiler should not be emitting calls to the validation routine. However, this misses a critical point: it’s not the process’ own executable code/shellcode which are necessarily performing the 64-bit CFG checks — it’s the 64-bit NTDLL itself, or any other additional 64-bit DLLs you may have injected through the initial 64-bit shellcode, into your own process.

Even worse, even if no other 64-bit DLLs are imported, some core system functionality, implemented by NTDLL, also validates the CFG bitmap: Exceptions, User-Mode Callbacks, and APCs. Any usage of these system mechanisms, because they always initially execute in 64-bit mode, will cause a CFG violation if the target is not in the bitmap — which it cannot possibly be. The same goes for higher level functionality like using the Thread Pool, or any other callback-based mechanism owned by NTDLL in 64-bit mode. For example, because kernel-mode injects user-mode APCs through the 64-bit NTDLL, the user-mode APC routine cannot possibly be a custom, non-DLL function: it would’ve been impossible to allocate it > 4 GB, and the APC dispatcher will validate the CFG bits for any address < 4 GB, and be unable to find it.

Perhaps the best example of these unexpected side-effects is to analyze what Heaven’s Gate-using malware often does to gain some usefulness in the hidden 64-bit context: it will lookup LdrLoadDll inside of NTDLL.DLL and attempt to load additional 64-bit DLLs, such as kernel32.dll. With some coercing (as some of the articles I linked to at the beginning showed), this can be made to work. The problem, in a CFG-aware NTDLL.DLL, is that LdrpCallInitRoutines will perform a CFG bitmap check before calling the DllMain of this DLL. As the DLL will be loaded in 32-bit address space, the WoW64 CFG bitmap will be marked, and not the Native CFG bitmap — causing the 64-bit NTDLL to believe that DllMain is not a valid relative call target, and crash the process.

Suffice it to say, although it still is possible to have a very simple 64-bit piece of code, even possibly performing some system calls, execute in the hidden 64-bit world of a WoW64 process/32-bit application, any attempts to load additional DLLs, use APCs, handle exceptions or user-mode callbacks in 64-bit mode will result in the process crashing, as a CFG violation will be tripped. For most intents and purposes, therefore, CFG has a potentially unintended side-effect: it closes down Heaven’s Gate.

Reopening the gate is left as an exercise to the reader ;-)

Final Note

Astute readers may have noticed the following discrepancies, especially if following along on their own systems:

  • Windows 8.1 Update 3 does have support for CFG
  • We saw three, not two VADs, on my Windows 8.1 Update 3 screenshot
  • This post mentions how Windows 10 closes Heaven’s Gate, but not Windows 8.1 Update 3

The key is in  dumping the MI_USER_VA_INFO structure on such a system:

+0x060 CfgBitMap : [3] _MI_CFG_BITMAP_INFO

Three entries? Let’s take a look:

0:000> dt _MI_CFG_BITMAP_TYPE
 CfgBitMapNative = 0n0
 CfgBitMapWow64 = 0n1
 CfgBitMapWow64NativeLow = 0n2
 CfgBitMapMax = 0n3

This explains the three, not two VADs in my dump: in the original CFG implementation on Windows 8.1, 64-bit code could live in the 32-bit address range, as the Native bitmap had a “Wow64Low” portion. In Windows 10, this is now gone (saving 32MB of address space) — Native code is only aware of the 64-bit address ranges.

Co-Authoring Windows Internals 5th Edition

Tuesday, August 19th, 2008

I’ve been a bit slow updating the blog, and so today, I want to take the time to explain what’s been keeping me busy by shareing some exciting news. As this post’s title suggests, I am indeed co-authoring Windows Internals 5th Edition, the latest update to Mark Russinovich and David Solomon‘s Windows Internals 4th Edition book.

The book will mark a return to the previous format of the series — unlike the last edition which covered all supported Windows NT operating systems (2000, XP, 2003), this edition will only cover the Vista and Server 2008 operating systems. This is a great change, because it means less time is explaining minute differences between the 4 different algorithms used in a lookup in each version, and more time is spent talking about what really matters — the behavior and design decisions of the OS.

I’m happy to say this new edition will have a least 250 pages of new information, not only updating various chapters with new Vista/Server 2008 changes, but also adding entirely new sections which previous editions had never touched on, such as the user mode loader in Ntdll.dll, the user mode debugging framework, and the hypervisor. It isn’t only the internals information that will benefit from the update; as a matter of fact, all references to tools, resources and books have also been updated, including up-to-date information on the latest Sysinternals tools, as well as exciting, helpful new experiments that demonstrate the behaviors explained in the text. For those of you who have read Mark’s TechNet Magazine “Inside Vista Kernel Changes” series and its Server 2008 counterpart (for those who haven’t, I strongly suggest you do!), you’ll be glad to know that the book includes all that information and expands on it as well.

The book work is still ongoing, but planned to end soon, after which it should go to print in October and be on shelves in January 2009. My book work is about to reach its one-year anniversary, and I must say that working with Mark and David has been a pleasurable learning experience, as well as a great chance to continue my reverse engineering work and hone my skills. What made ReactOS fun was being able to share my discoveries with the world as code — the book work has allowed me to share that information as text, part of the best internals book available, to a much wider audience. I’m thankful for that, and I can’t wait for everyone to have a chance to read it!

Look for the book hitting your nearest bookstore just after New Year’s. As a sneak peak, here’s a high-quality copy of the book’s cover while you wait.

Book Cover

Black Hat 2008 Wrap-up

Thursday, August 7th, 2008

This year I had the chance to present some security-related findings that I had made earlier during the year inside Win32k.sys, the Windows GUI Subsystem and Window Manager. I presented a total of four bugs, all local Denial of Service (DoS) attacks. Two of these attacks could be done on any system up to Vista SP0 (one up to Server 2008) from any account, while the other two were NULL-pointer dereferences that required administrative access to exploit (however, since they are NULL-pointer dereferences, the risk for user->kernel elevation exists in one of them).

Because the first two attacks (from any guest account) relied on highly internal behavior of the Windows NT Kernel (used in all of Microsoft’s modern operating systems today), I thought it was interesting to talk a bit about the internals themselves, and then present the actual bug, as well as some developer guidance on how to avoid hitting this bug.

I’d like to thank everyone who came to see the talk, and I really appreciated the questions and comments I received. I’ve also finally found out why Win32k functions are called “xxx” and “yyy”. Now I just need to find out about “zzz”. I’ll probably share this information in a later post, when I can talk more about Win32k internals.

As promised, you’ll find below a link to the slides. As for proof of concept code, it’s currently sitting on my home machine, so it’ll take another week. On the other hand, the slides make three of the bugs very clear in pseudo-code. I’ll re-iterate them at the bottom of the post.

One final matter — it seems I have been unable to make the bh08@alex-ionescu.com email work due to issues with my host. For the moment, please use another e-mail to contact me, such as my Google Mail account. My email address is the first letter of my first name (Alex) followed by my entire last name (Ionescu).

Slides here: Keynote and PDF.

Bug 1:
1) Handle = OpenProcess(Csrss)
2) CreateRemoteThread(Handle, …, NtUserGetThreadState, 15, …)

Bug 2:
1) Handle = CreateWindowStation(…)
2) SetHandleInformation(Handle, ProtectFromClose)
3) CloseWindowStation(Handle)

Bug 3:
1) Handle = CreateWindowStation(…)
2) Loop all handles in the process with the NtQuerySystemInformation API, or, just blindly loop every handle from 4 to 16 million and mark it as protected, or, use Process Explorer to see what the current Window Station handle is, and hard-code that for this run. The point is to find the handle to the current window station. Usually this will be a low number, typically under 0x50.
3) SetHandleInformation(CurrentWinstaHandle, ProtectFromClose)
4) SwitchProcessWindowStation(Handle);

Inside Session 0 Isolation and the UI Detection Service – Part 2

Friday, March 28th, 2008

In part 1 of the series, we covered some of the changes behind Vista’s new Session 0 Isolation and showcased the UI Detection Service. Now, we’ll look at the internals behind this compatibility mechanism and describe its behavior.

First of all, let’s take a look at the service itself — although its file name suggests the name “UI 0 Detection Service”, it actually registers itself with the Service Control Manager (SCM) as the “Interactive Services Detection” service. You can use the Services.msc MMC snap-in to take a look at the details behind the service, or use Sc.exe along with the service’s name (UI0Detect) to query its configuration. In both cases, you’ll notice the service is most probably “stopped” on your machine — as we’ve seen in Part 1, the service is actually started on demand.

But if the service isn’t actually running yet seems to catch windows appearing on Session 0 and automatically activate itself, what’s making it able to do this? The secret lies in the little-known Wls0wndh.dll, which was first pointed out by Scott Field from Microsoft as a really bad name for a DLL (due to its similarity to a malicious library name) during his Blackhat 2006 presentation. The version properties for the file mention “Session0 Viewer Window Hook DLL” so it’s probably safe to assume the filename stands for “WinLogon Session 0 Window Hook”. So who loads this DLL, and what is its purpose? This is where Wininit.exe comes into play.

Wininit.exe too is a component of the session 0 isolation done in Windows Vista — because session 0 is now unreachable through the standard logon process, there’s no need to bestow upon it a fully featured Winlogon.exe. On the other hand, Winlogon.exe has, over the ages, continued to accumulate more and more responsibility as a user-mode startup bootstrapper, doing tasks such as setting up the Local Security Authority Process (LSASS), the SCM, the Registry, starting the process responsible for extracting dump files from the page file, and more. These actions still need to be performed on Vista (and even more have been added), and this is now Wininit.exe’s role. By extension, Winlogon.exe now loses much of its non-logon related work, and becomes a more agile and lean logon application, instead of a poorly modularized module for all the user-mode initialization tasks required on Windows.

One of Wininit.exe’s new tasks (that is, tasks which weren’t simply grandfathered from Winlogon) is to register the Session 0 Viewer Window Hook Dll, which it does with an aptly named RegisterSession0ViewerWindowHookDll function, called as part of Wininit’s WinMain entrypoint. If the undocumented DisableS0Viewer value isn’t present in the HKLM\System\CurrentControlSet\Control\WinInit registry key, it attempts to load the aforementioned Wls0wndh.dll, then proceeds to query the address of the Session0ViewerWindowProcHook inside it. If all succeeds, it switches the thread desktop to the default desktop (session 0 has a default desktop and a Winlogon desktop, just like other sessions), and registers the routine as a window hook with the SetWindowsHookEx routine. Wininit.exe then continues with other startup tasks on the system.

I’ll assume readers are somewhat familiar with window hooks, but this DLL providesjust a standard run-of-the-mill systemwide hook routine, whose callback will be notified for each new window on the desktop. We now have a mechanism to understand how it’s possible for the UI Detection Service to automatically start itself up — clearly, the hook’s callback must be responsible! Let’s look for more clues.

Inside Session0ViewerWindowProcHook, the logic is quite simple: a check is made on whether or not this is a WM_SHOWWINDOW window message, which signals the arrival of a new window on the desktop. If it is, the DLL first checks for the $$$UI0Background window name, and bails out if this window already exists. This window name is created by the service once it’s already started up, and the point of this check is to avoid attempting to start the service twice.

The second check that’s done is how much time has passed since the last attempt to start the service — because more than a window could appear on the screen during the time the UI Detection Service is still starting up, the DLL tries to avoid sending multiple startup requests.
If it’s been less than 300 seconds, the DLL will not start the service again.

Finally, if all the checks succeed, a work item is queued using the thread pool APIs with the StartUI0DetectThreadProc callback as the thread start address. This routine has a very simple job: open a handle to the SCM, open a handle to the UI0Detect service, and call StartService to instruct the SCM to start it.

This concludes all the work performed by the DLL — there’s no other code apart from these two routines, and the DLL simply acknowledges window hook callbacks as they come through in cases where it doesn’t need to start the service. Since the service is now started, we’ll turn our attention to the actual module responsible for it — UI0Detect.exe.

Because UI0Detect.exe handles both the user (client) and service part of the process, it operates in two modes. In the first mode, it behaves as a typical Windows service, and registers itself with the SCM. In the second mode, it realizes that is has been started up on a logon session, and enters client mode. Let’s start by looking at the service functionality.

If UI0Detect.exe isn’t started with a command-line, then this means the SCM has started it at the request of the Window Hook DLL. The service will proceed to call StartServiceCtrlDispatcher with the ServiceStart routine specific to it. The service first does some validation to make sure it’s running on the correct WinSta0\Default windowstation and desktop and then notifies the SCM of success or failure.

Once it’s done talking to the SCM, it calls an internal function, SetupMainWindows, which registers the $$$UI0Background class and the Shell0 Window window. Because this is supposed to be the main “shell”
window that the user will be interacting with on the service desktop (other than the third-party or legacy service), this window is also registered as the current Shell and Taskbar window through the SetShellWindow and SetTaskmanWindow APIs. Because of this, when Explorer.exe is actually started up through the trick mentioned in Part 1, you’ll notice certain irregularities — such as the task bar disappearing at times. These are caused because Explorer hasn’t been able to properly register itself as the shell (the same APIs will fail when Explorer calls them). Once the window is created and a handler is setup (BackgroundWndProc), the new Vista “Task” Dialog is created and shown, after which the service enters a typical GetMessage/DispatchMessage window message handling loop.

Let’s now turn our attention to BackgroundWndProc, since this is where the main initialization and behavioral tasks for the service will occur. As soon as the WM_CREATE message comes through, UI0Detect will use the RegisterWindowMessage API with the special SHELLHOOK parameter, so that it can receive certain shell notification messages. It then initializes its list of top level windows, and registers for new session creation notifications from the Terminal Services service. Finally, it calls SetupSharedMemory to initialize a section it will use to communicate with the UI0Detect processes in “client” mode (more on this later), and calls EnumWindows to enumerate all the windows on the session 0 desktop.

Another message that this window handler receives is WM_DESTROY, which, as its name implies, unregisters the session notification, destroys the window lists, and quits.

This procedure also receives the WM_WTSSESSION_CHANGE messages that it registered for session notifications. The service listens either for remote or local session creates, or for disconnections. When a new session has been created, it requests the resolution of the new virtual screen, so that it knows where and how to display its own window. This functionality exists to detect when a switch to session 0 has actually been made.

Apart from these three messages, the main “worker” message for the window handler is WM_TIMER. All the events we’ve seen until now call SetTimer with a different parameter in order to generate some sort of notification. These notifications are then parsed by the window procedure, either to handle returning back to the user’s session, to measure whether or not there’s been any input in session 0 lately, as well as to handle dynamic window create and destroy operations.

Let’s see what happens during these two operations. The first time that window creation is being acted upon is during the afore-mentionned EnumWindows call, which generates the initial list of windows. The function only looks for windows without a parent, meaning top-level windows, and calls OnTopLevelWindowCreation to analyze the window. This analysis consists of querying the owner of the window, getting its PID, and then querying module information about this process. The version information is also extracted, in order to get the company name. Finally, the window is added to a list of tracked windows, and a global count variable is incremented.

This module and version information goes into the shared memory section we briefly described above, so let’s look into it deeper. It’s created by SetupSharedMemory, and actually generates two handles. The first handle is created with SECTION_MAP_WRITE access, and is saved internally for write access. The handle is then duplicated with SECTION_MAP_READ access, and this handle will be used by the client.

What’s in this structure? The type name is UI0_SHARED_INFO, and it contains several informational fields: some flags, the number of windows detected on the session 0 desktop, and, more importantly, the module, window, and version information for each of those windows. The function we just described earlier (OnTopLevelWindowCreation) uses this structure to save all the information it detects, and the OnTopLevelWindowDestroy does the opposite.

Now that we understand how the service works, what’s next? Well, one of the timer-related messages that the window procedure is responsible for will check whether or not the count of top level windows is greater than 0. If it is, then a call to CreateClients is made, along with the handle to the read-only memory mapped section. This routine will call the WinStationGetSessionIds API and enumerate through each ID, calling the CreateClient routine. Logically, this is so that each active user session can get the notification.

Finally, what happens in CreateClient is pretty straightforward: the WTSQueryUserToken and ImpersonateLoggedOnUser APIs are used to get an impersonation logon token corresponding to the user on the session ID given, and a command line for UI0Detect is built, which contains the handle of the read-only memory mapped section. Ultimately, CreateProcessAsUser is called, resulting in the UI0Detect process being created on that Session ID, running with the user’s credentials.

What happens next will depend on user interaction with the client, as the service will continue to behave according to the rules we’ve already described, detecting new windows as they’re being created, and detection destroyed windows as well, and waiting for a notification that someone has logged into session 0.

We’ll follow up on the client-mode behavior on Part 3, where we’ll also look at the UI0_SHARED_INFO structure and an access validation flaw which will allow us to spoof the client dialog.

Inside Session 0 Isolation and the UI Detection Service – Part 1

Saturday, March 15th, 2008

One of the many exciting changes in Windows Vista’s service security hardening mechanisms (which have been aptly explained and documented in multiple blogs and whitepapers , so I’ll refrain from rehashing old material) is Session 0 Isolation. I’ve thought it would be useful to talk about this change and describe the behaviour and implementation of the UI Detection Service (UI0Detect), an important part of the infrastructure in terms of providing compatible behaviour with earlier versions of Windows.

As a brief refresher or introduction to Session 0 Isolation, let’s remember how services used to work on previous versions of Windows: you could run them under various accounts (the most common being System, Local Service and Network Service), and they ran in the same session the console user, which was logged-on to session 0 as well. Services were not supposed to display GUIs, but, if they really had to, they could be marked as interactive, meaning that they could display windows on the interactive window station for session 0.

Windows implemented this by allowing such services to connect to the Winsta0 Windowstation , which is the default interactive Windowstation for the current session — unlike non-interactive services, which belonged to a special “Service-0x0-xxx$” Windowstation, where xxx was a logon session identifer (you can look at the WDK header ntifs.h for a list of the built-in account identifiers (LUIDs)). You can see the existence of these windowstations by enumerating them in the object manager namespace with a tool such as Sysinternals’ WinObj.

winobj

Essentially, this meant three things: applications could either do Denial of Service attacks against named objects that the service would expect to own and create, they could feed malicious data to objects such as sections which were incorrectly secured or trusted by the service, and , for interactive services, they could also attempt shatter attacks — sending window messages with executable payloads in their buffer, exploting service bugs and causing the payload code to execute at higher privileges.

Session 0 Isolation puts an end to all that, by first having a separate session for the console user (any user session starts at 1, thus protecting named objects), and second, by disabling support for interactive services — that is, even though services may still display a UI, it won’t appear on any user’s desktop (instead, it will appear on the default desktop of the session 0 interactive windowstation).

That’s all fine and dandy for protecting the objects, but what if the service hasn’t been recompiled not to directly show a UI (but to instead use a secondary process started with CreateProcessAsUser, or to use the WTSSendMessage API) and depends on user input before continuing? Having a dialog box on the session 0 desktop without the user’s awareness would potentially have significant application compatibility issues — this is where the UI Detection Service comes into play.

If you’re like most Vista users, you’ve actually probably never seen the default desktop on session 0’s interactive windowstation in your life (or in simpler words, never “logged-on” or “switched to” session 0)! Since you can’t log on to it, and since interactive services which displayed UIs are thankfully rare, it remains a hidden mystery of Windows Vista, unless you’ve encountered such a service. So let’s follow Alice down the rabbit hole into session 0 wonderland, with some simple Service Controller (Sc.exe) commands to create our very own interactive service.

Using an elevated command prompt, create a service called RabbitHole with the following command:

sc create RabbitHole binpath= %SYSTEMROOT%\system32\notepad.exe type= interact type= own

Be careful to get the right spaces — there’s a space after each equal sign! You should expect to get a warning from Sc.exe, notifying you of changes in Windows Vista and later (the ones I’ve just described).

Now let’s start the service, and see what happens:

sc start RabbitHole

If all went well, Sc.exe should appear as if it’s waiting on the command to complete, and a new window should appear on your taskbar (it does not appear in the foreground). That window is a notification from the UI Detection Service, the main protagonist of this story.

session0detect

Get ready to click on “Show me the Message” as soon as you can! Starting an essentialy fake service through Sc.exe will eventually annoy the Service Control Manager (SCM), causing it to kill notepad behind your back (don’t worry if this happens, just use the sc start RabbitHole command again).

You should now be in Session 0 (and probably unable to read the continuation of this blog, in which case the author hopes you’ve been able to find your way back!) As you can notice, Session 0 is a rather deserted place, due to the lack of any sort of shell or even the Theme service, creating a Windows 2000-like look that may bring back tears of joy (or agony) to the more nostalgic of users.

Session0

On the other hand, this desolate session it does contain our Notepad, which you should’ve seen disappear if you stayed long enough — that would be the SCM reaching its timeout of how long it’s willing to wait around hoping for Notepad to send a “service start” message back (which it never will).

Note that you can’t start any program you want on Session 0 — Cmd.exe and Explorer.exe are examples of programs that for one reason or another won’t accept to be loaded this way. However, if you’re quick enough, you can use an old trick common to getting around early 90ies “sandbox” security applications found in many libraries and elementary schools — use the common dialog control (from File, Open) to browse executable files (switch the file type to *.*, All Files), go to the System32 folder, right-click on Explorer.exe, and select Open. Notepad will now spawn the shell, and even if the SCM kills Notepad, it will remain active — feel free to browse around (try to be careful not to browse around in IE too much, you are running with System privileges!)

That’s it for this introduction to this series. In part 2, we’ll look at what makes this service tick, and in part 3, we’ll look at a technique for spoofing the dialog to lie to the user about which service is actually requesting input. For now, let’s delete the RabbitHole, unless you want to keep it around for impressing your colleagues:

sc delete RabbitHole

Secrets of the Application Compatilibity Database (SDB) – Part 4

Sunday, June 17th, 2007

My apologies for the long delay until this fourth part was published. I have been teaching in Seattle for the previous two weeks, and have just started to settle in Cupertino for my Apple internship, and I had very few spare moments in my hands.

In Part 3, we discussed how generic shims modify key parts of the system, usually through API hooking or undocumented flags, in order to provide compatibility with a variety of applications. We looked at shims such as the Windows 9x Heap Manager implementation in NT, and several re-direction and reflection APIs, as well as even some security bypassing shims. Today, we’ll take a look at how certain applications have specific shims implemented specifically just for them. We can find these with CDD easily, by noticing that the Shim name is usually a program name, as well as looking in the DLL which implements it. Finally, specific shims never have any descriptive text describing them. While looking through the Shim dump, I’ve chosen this one (arbitrarly):

Dumping Entry:

SHIMNAME="CorelSiteBuilder"
DLLFILE="AcSpecfc.DLL"

Any continued analysis on this shim must be done through reverse engineering, since we have no hint as to what this shim is attempting to do. By using IDA on the DLL specified, one can notice it is a series of C++ classes, each which represent a specific shim (there are of course other classes such as CString and the generic Shim Engine initialization classes). The prefix for the specific shims seems to be “NS”, so it was easy to locate our target of interest: NS_CorelSiteBuilder. Every shim class also has an initialization function that gets called, and is responsible for initializing the class and its hooks. This is usually called IniitalizeHooksMulti. In the disassembly of this function, pay special attention to loc_714F3691. This is where this class initializes the API hooks that make up this specific shim (other specific shims can also have other types of hooks, such as patches or COM hooks). The tagHOOKAPI structure contains the information required to patch an API, and one can clearly see that SetWindowTextA inside user32.dll is being hooked, and re-directed to NS_CorelSiteBuilder::APIHook_SetWindowTextA.

Now the actual hook can be looked at, and I’ve provided an analyzed and commented disassembly here. This is a pretty simple hook, and seems to check on whether the window handlw and window text that are being sent as arguments match the previous window handle and window text that the shim had saved durinng the last call. If they do match, it will simply return TRUE (success) without actually calling the original API, otherwise, the hook will save the window text that’s being set as the “old” window text (so that when the hook is called again, it will compare against this name now), and then perform a call to the original API (in tagAPIHOOK+0xC) with the unmodified arguments.

In other words, the whole point of this shim is to “absorb” SetWindowTextA calls to the Corel Site Builder window if the new text that’s being set matches the previous text, and simply return success. The reason on why such a shim would be necessary is left as an excercise to the reader.

In the next article, I will release the first version of the CDD utility which I’ve used when showing some of the Shims available, and document some of its uses.

Secrets of the Application Compatilibity Database (SDB) – Part 3

Saturday, May 26th, 2007

Continuing over from where we left last time, today’s entry will look at how the loader interacts with the AppCompat/Shim Engine Interfaces to determine that a module requires shimming or not. Unfortunately, it seems like this process underwent several revisions inside Microsoft’s codebase, so it may be difficult to experiment on your own based on this information. I will however, present all the known implementations to me in a generic fashion, without going too much under the hood in terms of actual assembly code.

Like many Win32-specific features, the Shim Engine actually gets initialized by the parent process through kernel32.dll, and not by the actual PE Loader/Startup routines inside the NT System DLL (ntdll.dll), although it also plays an important role in the process. As CreateProcessInternalW executes, it eventually calls BasepCheckBadApp (which is actually an exported API). The first thing that immediately happens is a check on whether or not the Shim Engine is disabled, followed by a lookup inside the Application Compatibility Shim Cache (done through BaseCheckAppcompatCache).

This cache is implemented in 2 different ways depending on the OS. On pre-Windows 2003, kernel32 maintains a shared section which other instances can use for caching the information, and a lock/unlock is done each time the cache is accessed. On post 5.2 kernels, there is a new Native API, NtApphelpCacheControl which supports the following classes:

typedef enum _APPHELPCACHESERVICECLASS
{
    ApphelpCacheServiceLookup,
    ApphelpCacheServiceRemove,
    ApphelpCacheServiceUpdate,
    ApphelpCacheServiceFlush,
    ApphelpCacheServiceDump
} APPHELPCACHESERVICECLASS;

In both cases, if the cache lookup doesn’t find anything, a “long” lookup is performed. This is where the architectural differences are the largest. In Windows XP SP0, this is done by using CSRSS, and calling BaseSrvCheckApplicationCompatibility in basesrv.dll. In SP2, apphelp.dll is imported and ApphelpCheckExe is called directly. In Windows Server 2003, a connection to the LPC Port AELPort is made, and a lookup LPC message is sent. Finally, in Vista, we’re back to SP2’s method, albeit with a newer API, ApphelpCheckExeEx.

The end result, however, is that the Peb’s pShimData member is now filled out with Apphelp Information (we’ll see what happens with this later) if this is a “bad” application indeed, meaning that it needs to be shimmed. How are these checks actually made, however? Recall that one of the “constructs” or entries that an SDB can have is the Matching File entry. The checks first discover the “Executable” entry for the filename given, and if one is found, all Matching File entries are parsed. This can include the name of the application and its helper files, the publisher, vendor, company, version, file size, timestamp and even linker version and other obscure data. Several boolean operations are available which can be built on top of inclusion and exclusion rules. If the Matching File entries check out, then the pShimData is filled with an opaque Apphelp structure.

The next important part of the Shim Engine’s mingling with our application happens in LdrpInitializeProcess, which is part of the PE Loader inside ntdll.dll. Here, a check is made if pShimData is non-NULL. If this is the case, then this pointer is saved then cleared, and the Shim Engine DLL is loaded with a call to LdrpLoadShimEngine. A variety of callbacks are then setup through LdrpGetShimEngineInterface, which mostly consist of pre and post initialization, and DLL load/unload notifications.

A bit later during initialization, the pre-initialization hook is called, if the Shim Engine was previously loaded, and the old pShimData pointer is passed along to the Shim Engine, so that it may begin initialization. The routine is SE_InstallBeforeInit inside shimeng.dll, and most of the work is done by SeiGetShimData and SeiInit. The former unpacks the information from the PEB Shim Data pointer that it received. It also has a check to disable shimming for ntsd and windbg, as well as slsvc, on Vista (since this is a semi-protected process related to licensing). As for the latter, it will process all the compatibility layers, shims, flags and finally patches which are defined in the Apphelp entry for the executable.

Shims will usually consist of either internal flags that are saved inside shimeng.dll or inside the PEB (see +0x1d8 AppCompatFlags and +0x1e0 AppCompatFlagsUser), or by the IAT of the shimmed process to be hooked and redirected into one of the Ac***.dll files which contain an alternate, or hacked implementation. These contain two main exports, GetHookAPIs and NotifyShims which allow the Shim Engine to know which APIs should be hooked and to send notifications during loader events. The Shim Engine is smart and will also hook GetProcAddress to make sure that APIs are properly caught. Patches are done through a method that will be looked into more detail later.

During the next entry, we’ll take a look at an actual shimmed application in action, and future parts will cover patches/flags in more detail. It is my hope that this part was useful into giving some insight on how the hooking is performed. Many vendors of application/DLL hooking software risk of running into the Shim Engine during their testing and development process, so having a good handle on how and when everything happens is certainly helpful.

Part 3 of User-Mode Debugging Internals

Wednesday, January 31st, 2007

The last part in my series on how Windows XP and higher support user-mode debugging is now up on OpenRCE; this part covers the kernel-mode side of things, aka the Dbgk module. Read it and find out how to use the native system calls in your debugger, which let you do things like debug multiple processes from a single debugger!

I will post the article on my Publications page as well, shortly.

Coming up shortly: the secrets of RtlRemoteCall!

Publications

Tuesday, November 21st, 2006

Just realized I forgot to post these in the last update, but perhaps it was better anyways since the post was already large enough.

NTFS On-Disk Structure – A fairly large reference to all the structures used on NTFS as well as some of the technical details behind some implementations. Was going to cover EFS and those structures, but I stopped it short there. This was written quite some time ago, and the structures are in Visual Basic format, but it should still be pretty useful. My explenation of NTFS runs was one of the best things in it.

Process Internals – Was going to become Part 1 of a series of 3 or 4 documents on each of the main executive components of NT, the Process Manger, the Object Manager and the Executive itself. Not very happy about this one in retrospect, since a lot of the fields I had documented aren’t used anymore or the information was wrong, but I still think it’s a good reference (especially the later sections). Again, done when I was younger and writing Visual Basic code.

Visual Basic File FormatOne of the articles I’m most proud of, this one was the result of several weeks of independent study into the Visual Basic file format for compiled executables. It explains every field, structure, relationship, etc, that the compiler inserts into the file that is then read by the runtime. Allowed me to write a simple runtime library that was only 20KB (for basic MsgBoxes). Highly graphical and easy to read.

Native API Compression and Introduction to NT DesignAn older article of mine again, gave a short primer on Native APIs, then presented a set of useful compression APIs burried into NT, and gave some interesting study on their performance and compressibility.

NTFS Alternate Data StreamsBack when alternate data streams weren’t very popular (I think I participated into making them popular, I was approached several times for inclusion of this article into books, magazines and other websites), I wrote code and an article exposing them and the dangers they presented, as well as a scanner that could find them. Again, Visual Basic code, and done when I was younger.

Subverting Windows 2003 Service Pack 1 Kernel Integrity ProtectionMy latest large presentation/project, this one was presented at REcon 2006. Shows a way to defeat the new protection mechanisms added in 2003 to disable access to kernel-mode from user-mode administrative applications, and how to access physical memory again. Exposed a flaw in VDM present in all released (at the time) versions of Windows NT.

Windows XP/2003 User-Mode Debugging Internals, Part 1Part of a series about the User-Mode Debugging framework in kernel32, ntdll and ntoskrnl. This part deals with Win32.

Windows XP/2003 User-Mode Debugging Internals, Part 2Part of a series about the User-Mode Debugging framework in kernel32, ntdll and ntoskrnl. This part deals with Native.

Part 2 of User-Mode Debugging Internals Article

Friday, November 10th, 2006

I’ve almost finished setting up the remaining parts of my blog. I’ve added an About page and pretty much filled my BlogRoll with the blogs I try to read daily. Thanks to everyone that’s visited/linked here in the last few days.

I’m currently working on the “Publications” page of the blog to have a central repository with all my data. I will also duplicate it on OpenRCE, but that site requires a login, and I wanted to make sure anyone could freely access my stuff. The links aren’t live yet, but they should be within the day.

Also, Part 2 of my article should appear soon, but for those that want to beat the clock, you can download it for now directly here. If you haven’t read Part 1 first, make sure you do here.

Brief overview of what’s discussed:

  • Part 1 – Win32: DebugActiveProcess, DebugBreakProcess, DebugSetProcessKillOnExit, CheckRemoteDebuggerPresent, WaitForDebugEvent, ContinueDebugEvent, DebugActiveProcessStop.
  • Part 1 – Win32: Teb->DbgSsReservedData[0] and DBGSS_THREAD_DATA. SaveProcessHandle, SaveThreadHandle, MarkThreadHandle, MarkProcessHandle, RemoveHandles, CloseAllProcessHandles.
  • Part 2 – Native: DbgUiConnectToDbg, DbgUiDebugActiveProcess, DbgUiStopDebugging, DbgUiIssueRemoteBreakin, DbgUiRemoteBreakin, DbgUiGetThreadDebugObject, DbgUiSetThreadDebugObject, DbgUiContinue, DbgUiWaitStateChange, DbgUiConvertStateChangeStructure.
  • Part 2 – Native: Teb->DbgSsReservedData[1], DBGUI_WAIT_STATE_CHANGE, Teb->Tib.ArbitraryUserPointer, DBG_STATE, DBGKM_EXCEPTION, DBGKM_CREATE_THREAD, DBGKM_CREATE_PROCESS, DBGKM_EXIT_THREAD, DBGKM_LOAD_DLL, DBGKM_UNLOAD_DLL.

Part 3 will cover Kernel Mode and the Nt* APIs when it’s out.