Sunday, July 25, 2010

Debugging services startup in Svchost from a kernel mode debug session

Windows shared services allow us to run system services together in a single service by having multiple DLLs run in a single process called Svchost. This allows Windows to have many services to run with the overhead of a single process.   You can find more information about shared services here and here.

I like to do a lot of my user mode debugging from a kernel mode debugger. I can just attach to a Hyper-V VM though a virtual serial port and all my tools are available to me without having to set up a user mode debugger on the target, plus if my application calls into kernel mode I’m all set.

The Svchost process won’t load the DLL until it’s time to start the service, so it can be tricky to set the correct breakpoint to catch the service starting up. This is complicated by the fact that the dll entry point will usually be <module>!ServiceMain, however this is not necessarily the case.

We can leverage the fact that svchost.exe exists in the same shared memory across all the Svchost processes, and a change to this shared memory will affect all of the svchost process.  When you set a user mode breakpoint from a kernel mode debugger the debugger changes the user mode code by inserting an int 3 (the debugger changes the code back when it is executed).  We can take advantage of this functionality to set one breakpoint that will fire from any svchost process.

If we can get past the Svchost process loading the service dll, we can find the host process main function or any other function we want to set a breakpoint on.

First, find the process address of any Svchost. I’m just showing the first of a long list of processes:

kd> !process  0 0 svchost.exe
PROCESS fffffa80098c5970
   SessionId: 0  Cid: 0270    Peb: 7fffffd8000  ParentCid: 0204
   DirBase: 35986000  ObjectTable: fffff8a001115b20  HandleCount: 343.
   Image: svchost.exe

Now let’s get into the context of this Svchost (it doesn’t matter which one) and set a breakpoint.  .process –i sets an invasive breakpoint so we can get into the active context of the process.

kd> .process -i fffffa80098c5970
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.

Then go the debugger to enter the active process.

Read more: NTDebugging

Posted via email from .NET Info