Debugging services..


How to debug Windows services covers the main points – but I think a common issue is debugging why a service won’t start.


 


When the service is failing on start – you can’t simply start it and then quickly attach the debugger – you need to have the debugger attach to it on start.


 


I like to do this via gflags.exe which is included with the debugger package when you install it. Here is an example of connecting to spoolsv.exe when you start the spooler service:


 




 


 


 


On any services General tab, you can see the path to the .exe ..in this case  spoolsv.exe, which you place in the image file.


 


This will also create  a registry key  such as HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\spoolsv.exe  with the “debugger” value set to the value you placed in gflags.exe


 


 


 


 


 


One of the big problems is the SCM timeout when you launch the service under the debugger the service times out  – the ServicesPipeTimeout  reg value will get around that.


 


The next problem you may run into is that the debugger is not visible when the service launches.


 


This is because the service is not configured to interact with the desktop:


 




 


Many services run as Local Service or Network Service or some other account  and will not be able to interact with the desktop. In these cases I like to do something a little more complex.


 


First, I change the debugger to cdb.exe and  set it up to immediately start a server which I can attach to remotely.


 




 


Then, I create a batch file like so:


 


It’s all a one liner.


 


Debug_svc.bat


 






 


C:\debugger\windbg.exe  -remote tcp:server=localhost,port=1234 -g –c “$$< :c\debugger\commands.txt” -y srv*c:\symbols*http://msdl.microsoft.com/download/symbols


 


 


The switches are summarized below:


 


-remote  : Connect to the server which was kicked off when the service started via cdb.exe


 


-g  : Ignores the initial breakpoint in target application. This option will cause the target application to continue running after it is started or WinDbg attaches to it.


 


-c  : Specifies the initial debugger command to run at start-up. The  $$<  basically says look to this script file and do what it says.


 


-y  : The symbol path.



 


The c:\debugger\commands .txt looks like this:


 






Bp  advapi32!regqueryvalue


Bp foo!func1


Bd*


Bp  foo!func2


G


 


I like to do this to save time from resetting breakpoints each time I need to try and start the service, as well as the flexibility of easy changes and a history of my breaks.  The file above shows that I set some BP’s , then when I wanted to  add\remove etc… So, I set a breakpoint on regqueryvalue(), and Func1(), decided I didn’t need them disabled all previous bp’s and set a bp on func2() then  did a “go”


 


You then can do a “net start service”   and then “debug_svc.bat”.


 


You will basically see the windbg.exe GUI come up and then hit your breakpoint at the exact spot you want to start debugging at, and it wont time out on you since you set ServicesPipeTimeout.


 


The last thing which could cause you some pain is the fact that many services run under svchost.exe.


 


Debugging an instance of svchost with 10 other dependant services in it, well it’s not always acceptable to put them all on hold J


 


Like the CertPropSvc


 



 


You can split it out into its own service by running:


“sc config <service> type= own”


And revert it via


“sc config <service> type= share”


 



 


Here we can see that it is in a shared svchost:


 


C:\debugger>tasklist /svc


 








Image Name


======================


System Idle Process


System


<snip>


svchost.exe


svchost.exe


Ati2evxx.exe


svchost.exe


svchost.exe


 


 


 


svchost.exe


 


 


 


 


audiodg.exe


SLsvc.exe


    PID


=======


      0


      4


 


    972


   1004


   1100


   1116


   1148


 


 


 


   1164


 


 


 


 


   1260


   1316


Services


============================================


N/A


N/A


 


RpcSs


WinDefend


Ati External Event Utility


Audiosrv, Dhcp, Eventlog, lmhosts, wscsvc


AudioEndpointBuilder, CscService, EMDMgmt,


hidserv, Irmon, Netman, PcaSvc, SysMain,


TabletInputService, TrkWks, UxSms,


WdiSystemHost, Wlansvc, WPDBusEnum, wudfsvc


AeLookupSvc, BITS, CertPropSvc, EapHost,


gpsvc, IKEEXT, iphlpsvc, LanmanServer,


MMCSS, ProfSvc, RasMan, Schedule, seclogon,


SENS, ShellHWDetection, Themes, Winmgmt,


wuauserv


N/A


slsvc


 


 


We will change it like so:


 


 


C:\debugger>sc config CertPropSvc type= own


[SC] ChangeServiceConfig SUCCESS


 


 


 


Make sure you get that space in the after the =’s sign


 


Then  you  restart the service..and note that it’s in it’s own instance of svchost.exe


 


C:\debugger>tasklist /svc      


 








Image Name


=======================


System Idle Process


System


smss.exe


csrss.exe


csrss.exe


wininit.exe


services.exe


winlogon.exe


<snip>


WmiPrvSE.exe


svchost.exe


tasklist.exe


 


   PID


======


     0


     4


   396


   528


   576


   584


   632


   660


 


  1672


  5680


  2032


Services


==============


N/A


N/A


N/A


N/A


N/A


N/A


N/A


N/A


 


N/A


CertPropSvc


N/A


 


 


When you are done – revert it via:


 


 


C:\debugger>sc config CertPropSvc type= share


[SC] ChangeServiceConfig SUCCESS


 


 


If you want to break it into its own svchost  but named something unique so you can use image file executions on it


 


See http://support.microsoft.com/kb/934650


 


Basic steps are – copy svchost.exe to  a unique name ( like svchost_1.exe ) , find the service’s and modify the imagepath to use your svchost_1.exe and restart the service.


 


 


 


Have a great day!


 


 


Spat

Comments (2)

  1. Calin Iaru says:

    With admin privileges, you can also attach to the services.exe process and then enable child debugging.