Archive for the ‘Debugging’ Category

Introduction to x64 debugging, part 1

Tuesday, July 11th, 2006

There are some subtle differences between using the Debugging Tools for Windows (DTW) toolset on x86 and x64 that are worth mentioning, especially if you are new to doing x64 debugging. Most of this post applies to all of the debuggers shipped in the DTW package, which is why I avoid talking about WinDbg or ntsd or cdb specifically, and often just refer to the “DTW debuggers”. This is the first post in a multipart series, and it provides a general overview of the options you have for doing 32-bit and 64-bit debugger on an x64 machine, and how to setup the debugger properly to support both, using either the 32-bit or 64-bit packages.

There are many ways to do x64 debugging, which can get confusing, simply because there are so many different choices. You can use both the 32-bit and 64-bit DTW packages, with some restrictions. Here’s a summary of the most common cases (including “cross-debugging” scenarios, where you are using the 32-bit debugger to debug 64-bit processes). For now, I’ll just limit this to user mode, although you can use many of these options for kernel debugging too.

  • Natively debugging 64-bit processes on the same computer using the 64-bit DTW package
  • Natively debugging 32-bit (Wow64) processes on the same computer using the 64-bit DTW package
  • Debugging 32-bit (Wow64) processes on the same computer using the 32-bit DTW package (running the debugger itself under Wow64)
  • Debugging 64-bit processes or 32-bit (Wow64) processes on the same or a different computer using either the 64-bit or 32-bit DTW package, with the remote debugging support (e.g. dbgsrv.exe, or -remote/-server). This requires a 64-bit remote debugger server.
  • Debugging 32-bit (Wow64) processes on the same or a different computer using either the 64-bit or 32-bit DTW package, with the remote debugger support (e.g. dbgsrv.exe, or -remote/-server). This works with a 32-bit remote debugging server.
  • Debugging a 64-bit or 32-bit dump file using the 32-bit or 64-bit DTW package. Both DTW packages are capable of doing this task natively.

There are actually even more combinations, but to keep it simple, I just listed the major ones. Now, as for which setup you want to use, there are a couple of considerations to keep in mind. Most of the important differences for the actual debugging experience stem from whether the process that is making the actual Win32 debugger API calls is a 64-bit or 32-bit process. For the purposes of this discussion, I’ll call the process that makes the actual debugger API calls (e.g. DebugActiveProcess) the actual debugger process.

If the actual debugger process is a 32-bit process under Wow64, then it will be unable to interact meaningfully with 64-bit processes (if you are using WinDbg, 64-bit processes will all show as “System” in the process list). For 32-bit processes, it will see them exactly as you would under an x86 Win32 system; there is no direct indication that they are running under Wow64, and the extra Wow64 functionality is completely isolated from the debugger (and the person driving the debugger). This can be handy, as the extra Wow64 infrastructure can in many cases just get in the way if you are debugging a pure 32-bit program running under Wow64 (unless you suspect a bug in Wow64 itself, which is fairly unlikely to be the case).

If the actual debugger process is a native 64-bit process, then the whole debugging environment changes. The native 64-bit debugging environment allows you to debug both 32-bit (Wow64) and 64-bit targets. However, when you are debugging 32-bit targets, the experience is not the same as if you were just debugging a 32-bit program on a 32-bit Windows installation. The 64-bit debugger will see all of the complexities of Wow64, which often gets confusing and can get in your way. I’ll go into specifics of what exactly is different and how the 64-bit debugger can sometimes be annoying when working with Wow64 processes in a moment; for now, stick with me.

So, if you need to do development on 64-bit computers, which debugging package is the best for you to use? Well, that really depends on what you are doing, but I would recommend installing both the 32-bit and 64-bit DTW packages. The main reason to do this is that it will allow you to debug 32-bit processes without having to deal with the Wow64 layer all the time, but it at the same time it will allow you to debug native 64-bit processes.

After you have installed the DTW packages, one of the familiar first steps with setting up the debugger tools on a new system is to register WinDbg as your default post-portem debugger. This turns out to be a bit more complicated on 64-bit systems than on 32-bit systems, however, in large part due to a new concept added to Windows to support Wow64: registry reflection. Registry reflection allows for 32-bit and 64-bit applications to have their own virtualized view of several key sections of the registry, such as HKEY_LOCAL_MACHINE\Software. What this means in practice is that if you write to the registry from a 32-bit process, you might not see the changes from 64-bit processes (and vice versa), depending on which registry keys are changed. Alternatively, you might see different changes than you made, such as if you are registering a COM interface in HKEY_CLASSES_ROOT.

So, what does all of this mean to you, as it relates to doing debugging on 64-bit systems? Well, the main difference that impacts you is that there are different JIT handlers for 32-bit and 64-bit processes. This means that if you register a 32-bit DTW debugger as a default postmortem debugger, it won’t be activated for 64-bit processes. Conversely, if you register a 64-bit DTW debugger as a default postmortem debugger, it won’t be activated for 32-bit processes.

This leaves you with a couple of options: Register both the 32-bit and 64-bit DTW packages as default postmortem debuggers (if you only want to use the 64-bit DTW package on 64-bit processes and not 32-bit (Wow64) processes as a JIT debugger), or register the 64-bit DTW debugger as a default postmortem debugger for both 32-bit and 64-bit processes. If you want to do the former, then what you need to do is as simple as logging in as an administrator and running both the 32-bit and 64-bit DTW debuggers with the -I command line option (install as default postmortem debugger), and then you’re set. However, if you want to use the 64-bit debugger for both 64-bit and 32-bit processes as a JIT debugger, then things are a bit more complicated. The best way to set this up is to install the 64-bit DTW debugger as a default postmortem debugger (run it with -I), and then open the 64-bit version of regedit.exe, navigate to HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AeDebug, and copy the value of the “Debugger” entry into the clipboard. Then, navigate to the 32-bit view of this key, located at HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug, create (or modify, if it already exists) the “Auto” string value and set it to “1”, then create (or modify, if it already exists) the “Debugger” string value and set it to the value you copied from the 64-bit view of the AeDebug key. For my system, the “Debugger” value is set to something like “C:\Program Files\Debugging Tools for Windows 64-bit\WinDbg.exe” -p %ld -e %ld -g. If you don’t see a Wow6432Node registry key under HKEY_LOCAL_MACHINE\Software, then you are probably accidentally running the 32-bit version of regedit.exe and not the 64-bit version of regedit.exe.

Now, there are a couple of other considerations to take into account when picking whether to use the 32-bit or 64-bit DTW tools on 32-bit processes. Besides the ease of use consideration (which I’ll come back to in more detail shortly), many third party extension DLLs (including my own SDbgExt, for the moment) are only available as 32-bit binaries. While these extension DLLs might support 64-bit targets, they will only run under a 32-bit debugger host.

I said I’d describe some of the reasons why debugging Wow64 processes under the native 64-bit debugger can be cumbersome. The main problem with doing this is that you need to be careful with whether the debugger is active as a 32-bit or 64-bit debugger. This is controlled by something that the DTW package calls the effective machine, which is a way to tell the debugger that it should be treating the program as a 32-bit or 64-bit program. If you are using the native 64-bit debugger on a Wow64 process, you will often find yourself having to manually switch between the native (x64) machine mode and the Wow64 (x86) mode.

To give you an idea of what I mean, let’s take a simple example of breaking into the 32-bit version of CMD.EXE, and getting a call stack of the first thread (thread 0). If you are experienced with the DTW tools, then you probably already know how to do this on x86-based systems: the “~0k” command, which means “show me a stack trace for thread 0”. If you run this on the 32-bit CMD.exe process, though, you won’t quite get what you were expecting:

0:000> ~0k
Child-SP          RetAddr           Call Site
00000000`0013e318 00000000`78ef6301 ntdll!ZwRequestWaitReplyPort+0xa
00000000`0013e320 00000000`78bc0876 ntdll!CsrClientCallServer+0x9f
00000000`0013e350 00000000`78ba1394 wow64win!ReadConsoleInternal+0x236
00000000`0013e4c0 00000000`78be6866 wow64win!whReadConsoleInternal+0x54
00000000`0013e510 00000000`78b83c7d wow64!Wow64SystemServiceEx+0xd6
00000000`0013edd0 00000000`78be6a5a wow64cpu!ServiceNoTurbo+0x28
00000000`0013ee60 00000000`78be5e0d wow64!RunCpuSimulation+0xa
00000000`0013ee90 00000000`78ed8501 wow64!Wow64LdrpInitialize+0x2ed
00000000`0013f6c0 00000000`78ed6416 ntdll!LdrpInitializeProcess+0x17d9
00000000`0013f9d0 00000000`78ef3925 ntdll!LdrpInitialize+0x18f
00000000`0013fab0 00000000`78d59630 ntdll!KiUserApcDispatch+0x15
00000000`0013ffa8 00000000`00000000 0x78d59630
00000000`0013ffb0 00000000`00000000 0x0
00000000`0013ffb8 00000000`00000000 0x0
00000000`0013ffc0 00000000`00000000 0x0
00000000`0013ffc8 00000000`00000000 0x0
00000000`0013ffd0 00000000`00000000 0x0
00000000`0013ffd8 00000000`00000000 0x0
00000000`0013ffe0 00000000`00000000 0x0
00000000`0013ffe8 00000000`00000000 0x0

Hey, that doesn’t look like the 32-bit CMD at all! Well, the reason for the strange call stack is that the 32-bit CMD’s first thread is sleeping in a system call to the 64-bit kernel, and the last active processor state for that thread was native 64-bit mode, and NOT 32-bit mode. You will find that this is the common case for threads that are not spinning or doing actual work when you break in with the debugger.

In order to get the more useful 32-bit stack trace, we’ll have to use a debugger command that is probably unfamiliar to you if you haven’t done Wow64 debugging before: .effmach. This command controls the “effective machine” of the debugger, which I previously described. We’ll want to tell the debugger to show us the 32-bit state of the debugger, which we can do with the “.effmach x86” command. Then, we can get a 32-bit stack trace for the first thread with the “~0k” command:

0:002> .effmach x86
Effective machine: x86 compatible (x86)
0:002:x86> ~0k
ChildEBP          RetAddr
002dfd68 7d542f32 KERNEL32!ReadConsoleInternal+0x15
002dfdf4 4ad0fe14 KERNEL32!ReadConsoleW+0x42
002dfe5c 4ad15803 cmd!ReadBufFromConsole+0xb5
002dfe88 4ad02378 cmd!FillBuf+0x174
002dfe8c 4ad02279 cmd!GetByte+0x11
002dfea8 4ad026c5 cmd!Lex+0x6b
002dfeb8 4ad02783 cmd!GeToken+0x20
002dfec8 4ad02883 cmd!ParseStatement+0x36
002dfedc 4ad164c0 cmd!Parser+0x46
002dff44 4ad04cdd cmd!main+0x1d6
002dffc0 7d4e6e1a cmd!mainCRTStartup+0x12f
002dfff0 00000000 KERNEL32!BaseProcessStart+0x28

Much better! That’s more in line with what we’d be expecting an idle CMD.EXE to be doing. We can now treat the target as a 32-bit process, including things like displaying and altering registry contexts, disassembling, and soforth. For instance:

 

0:002:x86> ~0s
KERNEL32!ReadConsoleInternal+0x15:
00000000`7d54e9c3 c22000  ret     0x20
0:000:x86> r
eax=00000001 ebx=002dfe84 ecx=00000000 edx=00000000 esi=00000003 edi=4ad2faa0
eip=7d54e9c3 esp=002dfd6c ebp=002dfdf4 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
KERNEL32!ReadConsoleInternal+0x15:
00000000`7d54e9c3 c22000  ret     0x20
0:000:x86> u poi(esp)
KERNEL32!ReadConsoleW+0x42:
00000000`7d542f32 8b4dfc  mov     ecx,[ebp-0x4]
00000000`7d542f35 5f      pop     edi
00000000`7d542f36 5e      pop     esi
00000000`7d542f37 5b      pop     ebx
00000000`7d542f38 e8545df9ff call KERNEL32!__security_check_cookie (7d4d8c91)
00000000`7d542f3d c9      leave
00000000`7d542f3e c21400  ret     0x14
00000000`7d542f41 90      nop

If we want to switch the debugger back to the 64-bit view of the process, we can use “.effmach .” to change to the native processor type:

0:000:x86> .effmach .
Effective machine: x64 (AMD64)

Now, we’re back to 64-bit mode, and all of the debugger commands will reflect this:

0:000> r
rax=000000000000000c rbx=000000000013e3a0 rcx=0000000000000000
rdx=00000000002df1f4 rsi=0000000000000000 rdi=00000000003e0cd0
rip=0000000078ef148a rsp=000000000013e318 rbp=00000000002dfdf4
r8=000000007d61c929  r9=000000007d61caf1 r10=0000000000000000
r11=00000000002df1f4 r12=00000000002dfe34 r13=0000000000000001
r14=00000000002dfe84 r15=000000004ad2faa0
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000244
ntdll!ZwRequestWaitReplyPort+0xa:
00000000`78ef148a c3               ret

That should give you a basic idea as to what you will be needing to do most of the time when you are doing Wow64 debugging. If you are running the 32-bit debugger packages, then all of this extra complexity is hidden and the process will appear to be a regular 32-bit process, with all of the transitions to Wow64 looking like 32-bit system calls (these typically happen in places like ntdll or user32.dll/gdi32.dll).

That’s the end of this post. The next in this series will go into more detail as to what has changed when you take the plunge and start debugging things on a 64-bit system.

SDbgExt extensions – part 2.

Monday, July 10th, 2006

Last post, I discussed some of the major extensions available in SDbgExt.  This post is a continuation that explains the remaining major / interesting extensions available in the extension library.

 Another set of extensions that may prove useful if you do frequent C++ development are the STL datastructures display functions.  These allow you to interpret many of the complicated STL container datastructures and format them in more understandable forms from the debugger.  At present, the extension DLL only understands the Visual C++ 7.0 / 7.1 STL structure layout (no support for VC6 or VC8 as of yet, sorry).  This complements the built-in WinDbg support for STL, which does not cover all of VC7 (or at least did not the last time I checked).  The SDbgExt STL type display functions do not rely on type information contained in symbols, so you can use them to help debug third party programs that you do not have symbols for.  However, some extensions will require you to have a bit of knowledge about the structures contained in an STL container (usually the size of a container item).  These extensions will work on local or remote 32-bit targets.

The main functions that you might find useful in this grouping are these:

!stlmap allows you to traverse an std::map (binary tree) and optionally dump some bytes from each of the key and value types.  Due to the layout of the std::map type, you will need to tell SDbgExt about the size of the key and value types.

!stlset allows you to traverse an std::set (binary tree) optionally dump some bytes from each of value types.  It is very similar to the !stlmap extension, except that it works on std::set structures and thus only needs information about a value type and not an additional key type.

!stllist and !stlvector allow you to display the contents of an std::list or std::vector, respectively.  Optionally, you may provide the size of an element to dump some bytes from each element to the debugger.

!stlstring and !stlwstring allow you to display std::string and std::wstring structures.  If you are displaying very long strings (>16K characters), then you will need to provide a second argument specifying the maximum number of characters to display.  This limit is always capped at 64K characters.

Most of the STL datastructures traversal functions have only minimal protection against damaged or corrupted datastructures.  If you attempt to use them on a datastructure that is broken (perhaps it has a link that references itself, causing an infinite loop), then you will need to break out of the extension with Ctrl-C or Ctrl-Break depending on which debugger you use.  To ensure that your system remains responsive enough to have the option of breaking out, SDbgExt will lower its priority to at least normal (WinDbg runs at high priority by default) temporarily, for the duration of the call to the extension (the original priority is restored before the extension returns).

The last major category of functions supported by SDbgExt are those that are related to Windows UI debugging.  These extensions generally always require a live 32-bit target on the local computer in order to function (no remote debugging).  They work by directly querying internal window structures or by calling user32/gdi32 APIs about a particular UI object.  These can be used as a handy replacement for Spy++, which has a nasty tendancy to break badly (and break every GUI application on the same desktop with it) when it encounters a GUI program that is frozen in the debugger.

The !hwnd extension is the primary UI debugging extension supported by SDbgExt.  It will dump many of the interesting attributes about a window given its handle (HWND) to the debugger console.  Additionally, it can be used to enumerate the active windows on the current thread.  This extension is particular useful for programs that store things like class object pointers at GWLP_USERDATA or DWLP_USERDATA, which are normally hard to get at from WinDbg.

The !getprop extension can be used to enumerate window properties associated with a particular window, or to query a single specific window property associated with a particular window.  These are useful if a program stores information (like a class object pointer) in a window property and you need to get at it from the debugger, which is something that you cannot easily do from WinDbg normally.

The !msg extension will display information about a MSG structure given a pointer to it.  It has a limited built in set of message names for some of the most common standard window messages.  It will also display information about the window with which the window message is associated with (if any).

Finally, there are a couple of misc. functions that SDbgExt supports which don’t fit cleanly into any specific category.  Many of these are niche extension that are only useful for very specific scenarios.

The !switchdesk extension will switch the active desktop for the computer hosting the debugger.  This can be useful if you are debugging a full screen DirectX program using a GUI debugger on an alternate desktop and a console debugger in full screen mode connected to the GUI debugger using remote debugging on the same desktop as the program being debugged.

The !lmx extension will allow you to view the loaded module list in the various forms that the loader maintains it (in-load-order, in-memory-order, in-initialization-order).  When used on kernel targets, there is only one loaded module list, so the list identification parameter is unused in that usage case.

!findwfptr (courtsey of skape) allows you to scan the address space of the debuggee for function pointers that are located in writable memory.  It willl work on all target types.  For live targets, it can also optionally place breakpoints at all of the functions pointed to by pointers residing in writable memory.  This extension is useful if you are auditing a program for potential security risks; many of the static addresses (i.e. global variables) in standard system DLLs that contain function pointers have been changed to encode the pointer values based on a random cookie to prevent exploits from overwriting them to gain control over the program.  This extension can help you identify which function pointers might be used by an attacker to compromise your program when used in conjunction with certain types of security flaws.

!cmpmem allows you to compare ranges of memory over time, with the ability to exclude modified ranges.  This is particularly useful if you want to watch a data structure (or even the global variables of an entire module) and quickly determine what changes when a particular operation happens in the context of the debuggee.  For example, if you are trying to reverse engineer a function and want to understand some of the side effects it has on data structures or global variables, this function can help quickly identify modified areas without requiring you to analyze the entire function in a disassembler.

 That’s all for this series.  There are a couple of extensions that I didn’t mention, but they are either very obvious or not generally useful enough to be worth mentioning.  The online help (!help) provides basic syntax and a very brief description about all extensions supported by SDbgExt, so you can find parameter information about all of the extension I mentioned there.

Using SDbgExt to aid your debugging and reverse engineering efforts (part 1).

Friday, July 7th, 2006

One of the programs up on my homepage (does anyone call their website a “homepage” anymore?) is SDbgExt, a WinDbg-compatible extension DLL.  It’s a little collection of various debugging tools that I have put together over time that you might find useful.  There is some minimal documentation included, but not a whole lot to tell you where and when certain extensions are useful – hence, the topic of today’s blog post.

 This posting series assumes that you have already installed WinDbg, installed the Visual C++ 2005 Runtimes, and placed SDbgExt.dll into your Debugging tools for Windows\WinExt directory.  At present, SDbgExt can only be loaded into the 32-bit WinDbg package, although some extensions do support 64-bit targets (such as 64-bit kernel debugging targets).

To get started using SDbgExt, you’ll need to load it into your debugger.  For WinDbg, ntsd, cdb, and kd, you can use the “.load SDbgExt” command to do this.  If you then use the “!sdbgext.help” command, you should be presented with a list of the available extensions supported by SDbgExt.  Most of the extensions are targetted at live 32-bit processes on the local computer (such as the extensions dealing with displaying HWND information).  The documentation does not specify which targets are supported by each extension yet, so if you aren’t sure whether an extension is supported against your current debugging target, just try it; if not, it will harmlessly fail in an obvious manner.

Many of the SDbgExt extensions have very specific purposes, so I’ll try to several of them  address them individually and describe what they are best used for.  Additionally, most of the SDbgExt extensions can be broken down into several categories, such as symbol management, UI debugging, STL datastructures manipulation, kernel object support, and debuggee state manipulation.  I’ll be skipping some of the extensions that are either obvious or not generally useful, but I’ll try to cover most of the interesting ones.

To start off, I’ll talk about some of the debuggee state manipulation extensions.  These extensions allow you to control the state of a live 32-bit target process that is running on the same computer as the debugger (remote debugging and 64-bit targets are not supposed yet by these extensions).  The extensions that fall under this category include:

  • !valloc, !vallocrwx, !heapalloc, !heapfree: Allocate memory within the address space of the target.
  • !remotecall, !remotecall64: Call a function in the target, using the currently active thread (symbols are not required, unlike “.call”).
  • !loaddll, !unloaddll: Load or unload a .dll within the address space of the target, using the currently active thread.
  • !close: Close a kernel object handle in the targets handle space.
  • !killthread: Terminate a thread in the target process.
  • !adjpriv: Alter privileges of the target process or currently active thread.
  • !ret: Effect a virtual function return in the context of the currently active thread.

Many of these extensions are useful if you are doing some runtime patching of a target or are trying to see how the target will react to specific circumstances.  If you are trying to reverse engineer or modify the behavior of a target, in particular, you might find several of these extensions very useful.

The first group of extensions are used for managing memory allocation in the targets address space – either by directly allocating pages within the target or allocating heap memory.  The latter requires that you resume execution of the target as internally the remote heap manipulation functions use the remote function call support to call the heap manager in the target process.  Perhaps the most common use for this family of functions is if you need to allocate some space on the fly if you are adding some code to the debuggee on the fly (maybe you need to patch a function and add several instructions, in which case you could allocate memory with !vallocrwx, and then patch a jump instruction to refer to the newly allocated memory block).

The next two groups of functions are used for directly calling functions in the target, from the context of the currently active thread in the debuggee.  Be warned that this is an invasive operation and may cause undesirable side effects in the context of the debuggee.  The main advantage of the !remotecall family of extensions over the built-in .call command is that you do not need to have private symbols for the target, which makes it particularly useful if you are reverse engineering something or need to call a Win32 API function in the context of the debuggee from the debugger.  These functions can allow you to do complicated things that are difficult or impossible to do remotely (from the debugger), such as calling SetHandleInformation to mark a handle closable or nonclosable from WinDbg. You can use !loaddll and !unloaddll as shortcuts (as opposed to using !remotecall on kernel32!LoadLibraryA/kernel32!FreeLibrary manually) for DLL management in the target process space.

!close is mostly analagous to the .closehandle built-in command, and is used to close a handle in the context of a debuggee.

!killthread is useful if you need to instantly terminate a thread in the debuggee process, for whatever reason.  You can manually achieve something like this with a command like “r eip=kernel32!ExitThread;g” for Win32 targets, but this extension provides a more elegant means to killing debuggee threads (for instance, you might want to kill a thread that is crashed so that it doesn’t take down the rest of the process in the default SEH handler, for certain scenarios).

!adjpriv is useful if you are debugging problems related to the privileges that are enabled in a primary or impersonation token.  You can use the built-in !token extension to determine what privileges are currently present, enabled, or disabled in a token, and the !adjpriv extension to manipulate these privileges from the debugger itself.  This can also be used to work around buggy programs that don’t properly enable privileges before they try to do certain privileged operations (such as things written for Win9x).

!ret is primarily useful in conditional breakpoints if you want to return from the middle of a function at a breakpoint location based on a particular condition.  It alters the context of the currently active thread (modifying the stack pointer, instruction pointer, and optionally return address registers) according to its arguments.

The next group of extensions that I’d like to describe are the symbol management extensions.  These are extremely useful if you are reverse engineering a program and want to synchronize your work between a disassembler (such as IDA) and the debugger.  The two extensions that fall into this category are !loadsym and !unloadsym.

These two extensions allow you to either create or remove custom virtual symbols in the target.  A virtual symbol allows you to name an address (although it does not allow you to convey type information, unfortunately).  This can be extremely useful if you are debugging a third-party program that has no symbols, and you want to name certain addresses to make them easier to recognize.

Both extensions can operate on two different types of symbol files: a custom format that is specific to SDbgExt and allows you to specify all possible attributes that are supported by virtual symbols (primarily the size of the symbol, name, and its offset from a base module), and a standard linker .map file.  The latter is generally the most useful of the two formats, as there are many things that can write symbol information to a .map file which you can then load into SDbgExt and access through WinDbg.  For instance, IDA allows you to dump all names in a database (disassembly project) to a .map file, which you could then load using SDbgExt and have names in WinDbg that match the work you have done in IDA.  These commands can also be useful if the only symbols you have for a particular binary are the linker map files (which has happened to me once or twice, on rare occasions).

Both extensions require a 32-bit target, although the target may be a remote target and can be either a user mode or kernel mode target.  For kernel targets, the symbol loading support will apply to modules in the kernel mode loaded module list primarily.  Virtual symbols are automatically unloaded whenever you reload symbols (such as with the “.reload” command), so you may find yourself needing to re-apply the custom symbols more than once in a session.  Additionally, due to a bug / limitation in how DbgHelp and DbgEng manage virtual symbols, the process of creating virtual symbols unfortunately gets exponentially slower relative to how many virtual symbols are currently in existance.  As a result, creating more than a couple thousand virtual symbols may take a while.

The last group of extensions that I am going to cover in the first installment of this series is the kernel object support extension group.  These extensions are intended to complement the built-in support (such as !handle or !token) for querying kernel objects by allowing access to things that are otherwise not easily queryable from the debugger.  Although the information available from the built-in debugger support is usually sufficient, in special cases you may need additional information (such as security descriptor information).  Most of these extensions require a live 32-bit target on the local computer to operate correctly.

The !objname extension takes an object handle relative to the handle space of the debuggee and returns the full name for it.  This is similar to the built-in !handle extension, except that it works on all kernel object types (unlike !handle, which does not work on some object types, such as file object handles).

!tokeninfo will allow you to inspect some additional information about an access token object, beyond that which the built-in !token extension makes available to you (either given a token handle, or by operating on the primary or impersonation token that is effective for the currently active thread).  The most useful pieces of information available from this extension are the TokenId (uniquely identifying a token object throughout the system) and the ModifiedId (which increments whenever a tokens attributes are altered in any way).

The !objsec extension is useful for displaying detailed information about the security descriptor of an object given an object handle.  In kernel mode, you can use the !sd extension based on the security descriptor pointer embedded in a kernel object header, but this extension allows you to perform a similar function from user mode.  It has built-in knowledge about the object specific access rights supported by all of the kernel object types (as of Windows Server 2003 SP1) and will automatically translate access right values in access masks to more human readable values.

If you are dealing with a raw access mask directly (perhaps passed to a security related function as a parameter), and you want to know what it means given a particular object type, then you can use the !amask extension to have SDbgExt interpret the access mask bits as they apply to a particular object type.  The !objtypes extension lists the object type names that are supported by !amask.  If you do not supply an object type argument to !amask, it will only interpret generic and standard access rights.

The !sidname extension can be used to convert a SID into an account name.  Unlike most extensions, this extension does not operate on the debuggee at all; instead, it simply takes a string SID as a single argument and attempts to resolve it against the security database of the computer hosting the debugger.  This is a shortcut for command line utilities (like PsGetSid) that could do the same for you, since many of the access token related functions will give you back a raw string SID and will not translate it into a more understandable account name.

The !threadinfo extension will display some basic information about a thread running in the debuggee.  It will only work on local targets on the same computer as the debugger.  This extension allows you to view a couple of rarely-used fields that aren’t easily viewable from the debugger in user mode, like processor affinity or thread and exit times.

 That’s all for this post.  The next post in this series will cover the remaining major extensions in SDbgExt.

On the selection of blogging software.

Wednesday, July 5th, 2006

After wasting about 4 hours on this subject, I think it has deserved the right to be spoken about.

 Since I decided to finally give this whole blogging thing a try, I went looking for an appropriate set of blogging software to use.  My first instinct was to try Community Server with SQL Server 2005 Express Edition.  Hey, it works for Microsoft (MSDN Blogs is powered by Community Server), so it should work for me, right?  And to make things even better, it’s a native Windows solution (I was planning on the deploying the blog on a Windows box), not a Unix port (which in my experience tend to be half-hearted and generally low quality, as far as applications go).

 Boy, was I wrong.

 After waiting about half an hour (I think) for SQL Server 2005 to install on my interim hosting box (which, although it isn’t the fastest box in the world, should really install the “lite” edition of SQL Server a little bit faster than that, I think), I set to work on setting up my blog.

 So I start the setup app, and everything is going great until the install almost finishes and goes into the configuration wizard, which then wants me to enter in my database information.  Now, I’m no SQL Server expert, but I (foolishly) think – how hard can this be?  I try the defaults – create the default database name on the locally running SQL Server.  Well, the installer freezes for about 30 seconds and then comes up with an error messagebox saying that it can’t talk to the database or I gave it invalid credentials.  Since SQL Server 2005 Express is supposed to used integrated Windows authentication by default and I am running the installer as admin (and told it to use integrated Windows authentication, per recommendations), I discount that possibility for the moment.

 I remember back to when I setup SQL Server 2005 half an hour ago, and it having said something about disabling all remote network access (a good thing from a security perspective!).  So, I figure, something must be stupid here and is trying to connect with one of the network transports instead of one of the local transports and that is why things are failing.  I (foolishly, as it turns out!) try to cancel out of the Community Server configuration wizard so that I can reconfigure SQL Server 2005 to enable network access.

 That was mistake no. 1. The Community Server installer comes back into focus with a big happy “setup was successful!” dialog and no option to go back and re-run the wizard.  Oops.  I had to uninstall the *whole thing* and reinstall it to get the post-installation configuration wizard back (which had failed, mind you, not ran successfully!) after reconfiguring SQL Server.  So, after waiting around for the Community Server installer to take its time, I get back to the SQL Server selection dialog.  Again, no dice – nothing I enter seems to appease it.

 Now, I’m starting to get pretty annoyed.  This was supposed to be a quick and easy thing to setup, not something that I wanted to spend my whole afternoon on.  Well, after doing a bit of research on how SQL Server works (not exactly what I was expecting to have to do, this was supposed to all work out of the box, remember?), I figure out that the default configuration is supposed to listen on port 1433 if you selected TCP/IP for a network transport (which I did, for the SQL Server 2005 Surface Area Configuration Wizard thingie).  Well, a “netstat -anp tcp” says that nobody is listening on that port.  Oops, something is clearly wrong here, even though I followed all of the rules and used the supported UI and everything to configure SQL Server.  Well, I start poking around a bit more with the management tools that SQL Server installed, and eventually I got to where you tell the TCP transport which IP addresses that it should listen on.  I figure that maybe I need to manually tell SQL Server to listen on the IP I want on port 1433 here, if it wasn’t already (even though the TCP transport was enabled according to everything I could see).

 Now, this is a prime example of how you should not design a UI.  The UI for selecting the IP addresses/interfaces to listen on is vaguely reminsicent of the Visual Studio property pages where you have a column of property types (descriptions) and a column of property values (that you enter in to configure it).  Each IP address has a bunch of options that you can pick in this form.

Unfortunately, because I had turned on IPv6 support for this box, it has about 26 IP addresses (due to IPv6 over IPv4 automatic tunneling interfaces) between all of the VMware virtual NICs and the two physical NICs in the box.  And all of the IP addresses were “expanded” by default, in this tiny listbox that only had room for one and a half a property set per IP address.  To make matters even worse, the IP that I wanted to enable the listern for was #3, but the sorting for the UI was wrong – it goes 1, 10, 11, … 2, 20, 21 … and so forth, so the third IP address was at the *end* of the list.  Great UI here, guys!

 Anyways, after agonizing over that particular piece of user interface meets train wreck, I (or so I think) tell SQL Server to listen on my internal LAN IP for port 1433, hit OK, and restart the service.

 Then, I go try hitting “Next” on the Community Server setup.  Again, it doesn’t work.  Back to netstat and SQL Server STILL isn’t listening on port 1433.  Aaargh!  Well, next I do a “netstat -anpo tcp” and match the listening process IDs and port numbers with the SQL Server process ID to see if SQL Server is actually listening on ANYTHING.  It turns out that it IS listening, but on some completely unexpected (to me, anyway) port – 1398.  Huh??  The TCP transport uses 1433 by default!  Furthermore, I had configured it through the UI to listen on 1433.  Well, not being an expert on SQL Server, I start hunting around for how to convince Community Server’s setup wizard to use port 1398 for a remote TCP connection (still having no idea why the local connection mechanism doesn’t work, as that too is enabled in the SQL Server configuration manager).

It turns out that I have to go and define a “connection alias” in the SQL Server Native Client Configuration section of the SQL Server manager UI.  After filling in everything here – connect to the IP that SQL Server was listening on with port 1398, and hitting OK, I went back to the Community Server setup wizard and hit Next, praying for it to work.

 Success! Only about 2.5 hours into the installation attempt, I’ve at least got it talking to the database.  The next steps are to give it my initial account and password for the Community Server administrator account when creating the database.  I enter in the information and continue through the next steps in the wizard, and finally get to the end.  After hitting the last “Next” button, naturally, I get an error message; Community Server failed to create the database properly.  I am then presented with a Notepad view of the setup log, where the problem is quickly evident – apparently, the Community Server setup app didn’t both to escape its strings before passing them to SQL queries, and blew up because the password I used had a ‘ (single quote) in it.  This is just giving me warm fuzzies about how safe Community Server is going to be against SQL injection attacks, if I ever got it working, let me tell you.

So, I back out of that part of the wizard and pick a new password that doesn’t have any characters that are unfriendly to SQL if not properly escaped.  Now I get ANOTHER error at the end of the wizard; the setup program failed to create the database because it already exists.  Apparently, the wizard doesn’t roll back all of its changes if it fails partway through, and some of the database goo from the unsuccessful previous configuration attempt is still there.

 So, then I’m back to uninstalling and reinstalling Community Server for about the 5th time today, and getting madder every minute.  After the reinstall finally finishes, and I reenter all of my information yet another time, the configuration wizard actually completes without any visible errors (yay!!!).  So, the last thing the wizard wants to do is launch the Community Server site for the local IIS install so that I can see all of the Community Server goodness that is now installed.

Guess that?  The site doesn’t load.  Instead, I’m presented with a 404 Not Found in my browser window, from the URL that the configuration wizard so nicely launched at completion.  Apparently, there were several problems here: default.aspx wasn’t properly registered as an index document, and Community Server had picked the wrong IIS site to configure itself on (without even asking me which one I had wanted).

At this point, I’ve had it – after having burned a couple of hours on this problem, I’m just not willing to give it any more of my time.  I uninstalled SQL Server and Community Server and went in search of other alternatives, which lead me to my current blog software, WordPress.

 WordPress is not exactly what you would call a native Windows solution – it relies on PHP, and the only backend database provider that it can talk to is MySQL.  None of these were really designed to work on Windows, but nonetheless, at this point I’m ready to try anything that doesn’t touch SQL Server or doesn’t have Community Server in it’s name.  All in all, it only took me about 15 minutes to download everything I needed (from various sites, too, not one centralized location) to get WordPress to work on IIS (Win32 PHP 5, Win32 MySQL, and of course WordPress itself), work through one or two minor setup hiccups (made a typo in the database user password in the MySQL console once, forgot to tell PHP where to find php.ini, forgot to enable the PHP MySQL extension dll), and get everything working.

 Wow.  Now, I’m not what you would call a Unix guy – I do as much as I can on Windows and avoid Unix whereever possible, and here I am, having figured out this “crude” set of tools that don’t even have any friendly, advanced setup wizards or anything (well, MySQL has a relatively nice GUI setup, actually), learned how to create the database that WordPress needed myself in MySQL, and debugged setting up a complicated ISAPI extension in IIS with partially outdated documentation in a mere fraction of the time as what the leading Windows solution (with it’s do-everything-for-you-the-right-way setup wizards and all) took to get into an almost-working state.  I hate to admit it, but sometimes software that came from Unix just does things better sometimes.

VMware Server and RDP don’t always play nicely together.

Wednesday, July 5th, 2006

Steve already stole my thunder (well, if that makes sense, since it was my paper anyway) by posting my analysis of this earlier, but I figure that it is also worth discussing here.

 Recently, I finally* got a got a new development box at work – multiproc, x64 capable (with the ability to run 64-bit VMs too!), lots of RAM, generally everything you would want in a really nice development box.  Needless to say, I was rather excited to see what I could do with it.  The first thing I had in mind was setting up a dedicated set of VMs to run my test network on and host various dedicated services such as our symbol server here at the office.

 (*: There is a long, sad story behind this.  For a long time, I’ve been having a VM running on an ancient ~233MHz box that nobody else at the office wanted (for obvious reasons!).  I had been trying to get a replacement box that didn’t suck so much to put this VM (and others) on to run full time, but just about every thing that could possibly go wrong with requesting a purchase from work did go wrong, resulting in it being delayed in the order of over half a year…).

 The box came with Windows XP Professional x64 Edition installed, so I figured that I might as well use the install instead of blowing it away and putting Windows Server 2003 on for now.  As it turned out, this came around to bite me later.  After installing all of the usual things (service packs, hotfixes, and soforth), I went to grab the latest VMware Server installer so that I could put the box to work running my library of VMs.  Everything seemed to be going okay at the start, until I began to do things that were a bit outside the box, so to speak.  Here, I wanted to have my XP x64 box route through a VM running on the same computer.  Why on earth would I possibly want to do that, you ask?  Well, I have an internal VPN-based network that overlays the office network here at work and connects all of the VMs I have running on various boxes at the office.  I wanted to be able to interconnect all of those VMs with various services (in particular, lots and lots of storage space) running on the beefy x64 box over this trusted VPN network instead of the public office network (which I have for testing purposes designated the untrusted Internet network).  If I have the x64 box routing through something that is connected to the entire overlay network, then I don’t need to worry about creating connections to every single other VM in existance to grant access to those resources.  (At this point, our x64 support is still in beta, and XP doesn’t have a whole lot of useful support for dedicated VPN links.)

 Anyways, things start to get weird when I finally get this setup going.  The first problem I run into is that sometimes on boot, all of the VMs that I had configured to autostart would appear to hang on startup – I would have to go to Task Manager and kill the vmware-vmx.exe processes, then restart the vmserverdWin32 service before I could get them to come up properly.  After a bit of poking around, I noticed a suspicious Application Eventlog entry that seemed to correlate with when this problem happened on a boot:

Event Type: Information
Event Source: VMware Registration Service
Event Category: None
Event ID: 1000
Date:  6/13/2006
Time:  2:10:06 PM
User:  N/A
Computer: MOGHEDIEN
Description:
vmserverdWin32 took too much time to initialize.

 Hmm… that doesn’t look good.  Well, digging a bit deeper, it turns out that VMware Server has several different service components, and apparently there are dependencies between them.  However, the VMware Server developers neglected to properly assign dependencies between all of the services; instead, they appear to have just let the services start in whatever order and have a timeout window in which the services are supposed to establish communication with eachother.  Unfortunately, this tends to randomly break on some configurations (like mine, apparently).

 Fortunately, the fix for this problem turned out to be fairly easy.  Using sc.exe, the command line service configuration app (which used to ship with the SDK, but now ships with Windows XP and later – a handy tool to remember), I added an SCM dependency between the main VMware launcher service (“VMServerdwin32”) and the VMware authorization service (“VMAuthdService”): 

C:\Documents and Settings\Administrator>sc config vmserverdWin32 depend= RPCSS/VMAuthdService
[SC] ChangeServiceConfig SUCCESS
After fixing the service dependencies, everything seemed to be okay, but of course, that wasn’t really the case…

 When I went home later that day, I decided to VPN into the office and RDP into my new development box in order to change some hardware settings on one of my VMs.  In this particular case, some of the VPN traffic from my apartment to the development box on the office happened to pass through that router VM which I had running on the development box.  Whenever I tried to RDP into the development box, it would just freeze whenever I tried to enter my credentials; the RDP connection would hang after I entered valid logon credentials at the winlogon prompt until TCP gave up and broke off the connection.  This happened every single time I tried to RDP into my new box, but the office connection was fine (I could still connect to other things at the office while this was happening).  Definitely not cool.  So, I opened a session on our development server at the office and decided to try an experiment – ping my new dev box from it while I try to RDP in.  The initial results of this experiment were not at all what I expected; my dev box responded to pings the whole time while it was apparently unreachable over RDP while the TCP connection was timing out.  The next time I tried RDPing in, I ran a ping from my home box to my dev box, and the pings were dropped while I was trying to make the RDP session connection to the console session after providing valid logon credentials, and yet the box still responded to pings from a different box at the office.

After poking around a bit more, I determined that every single VM on my brand new dev box would just freeze and stop responding whenever I tried to RDP into my dev box from home (but not from the office).  To make matters even more strange, I could connect to a different box at the office, and bounce RDP through that box to my new dev server and things would work fine.  Well, that sucks – what’s going on here?  A partial explanation stems from how exactly I had setup the routing on my new dev box; the default gateway was set to my router VM (running on that box) using one of the VMnet virtual NICs, but I had left the physical NIC on the box still bound to TCP (without a default gateway set however).  So, for traffic destined to the office subnet, there is no need for packets to traverse the router VM – but for traffic from the VPN connection to my home, packets are routed through the router VM.

 Given this information, it seemed that I had at least found why the problem was happening, on some level – whenever I tried to RDP into my new dev box over the VPN, all of the VMs on my new dev box would freeze.  Because traffic through the VPN to my new dev box is routed through a VM on the new dev box, the RDP connection stalls and times out (because the router VM has hung).

 At this point, I had to turn to a debugger to understand what was going on.  Popping the vmware-vmx.exe process corresponding to the router VM open in the debugger and comparing call stacks between when it was running normally and when it was frozen while I was trying to RDP in pointed to the thread that emulated the virtual CPU becoming blocked on an internal NtUser call to win32k.sys.  At this point, I couldn’t really do a whole lot more without resorting to a kernel debugger, making that my next step.

 With the help of kd, I was able to track down the problem a bit further; the vmware CPU simulator thread was blocking on acquiring the global win32k NtUser lock that almost all NtUser calls acquire at the start of their implementation.  With the `!locks’ command, I was able to track down the owner of the lock – which happened to be (surprise!) a Terminal Server thread in CSRSS for the console session.  This thread was waiting on a kernel event, which turns out to be signalled when the RDP TCP transport driver receives data from the network.  So, we have a classical deadlock situation; the router VM is blocking on win32k’s internal NtUser global lock, and there is a CSRSS thread that is holding the win32k internal NtUser global lock while waiting on network I/O (from the RDP client).  Because the RDP client (me at home connecting through the VPN) needs to route traffic through the router VM to reach the RDP TCP transport on my new dev box, everything appears to freeze until the TCP connection times out.

 Unfortunately, there isn’t really a very good solution to this problem.  Installing Windows Server 2003 would have helped, in my case, because then VMware Server and its services would be running on session 0, and RDP connections would be diverted to new Terminal Server sessions (with their own per-session-instanced win32k NtUser locks), thus avoiding the deadlock (unless you happened to connect to Terminal Server using the `/console’ option).

 So there you have it – why VMware Server and RDP can make a bad mix sometimes.  This is a real shame, too, because RDPing into a box and running the VMware Server console client “locally” is sooo superior to running the VMware Server console client over the network (updates *much* faster, even over a LAN).

 If you’re interested, I did a writeup of most of the technical details of the actual debugging (with WinDbg and kd) of this problem that you can look at here – you are encouraged to do so if you want to see some of the steps I took in the debugger to further analyze the problem.

 In the future, I’ll try not to gloss over some of the debugger steps so much in blog posts; for this time, I had already written the writeup before hand, and didn’t want to just reformat the whole thing for an entire blog post.

 Whew, that was a long second post – hopefully, future ones won’t be quite so long-winded (if you consider that a bad thing).  Hopefully, future posts won’t be written at 1am just before I go to sleep, too…