LinkGard Software Blog » Ashod Nakashian http://www.linkgard.com/software_blog Fri, 12 Feb 2010 08:04:47 +0000 en hourly 1 Windows Services (Part II) http://www.linkgard.com/software_blog/windows-services/windows-services-part-ii/ http://www.linkgard.com/software_blog/windows-services/windows-services-part-ii/#comments Fri, 12 Feb 2010 07:59:40 +0000 Ashod Nakashian http://www.linkgard.com/software_blog/?p=18 In Part I we took a quick tour of Windows Services. We ended our discussion with the difficultly of debugging Services. In Part II we will see how we can create a refined way of debugging Services in a systematic and usable fashion. A very cleaver technique for debugging services with UM debuggers by means [...]]]> In Part I we took a quick tour of Windows Services. We ended our discussion with the difficultly of debugging Services. In Part II we will see how we can create a refined way of debugging Services in a systematic and usable fashion.

A very cleaver technique for debugging services with UM debuggers by means of attaching a debugger to them is done by trying to delay the Service until a debugger is run and attached to it. A simple method would be to use Sleep(). This function would block the execution of the thread in question until the timeout expires. We may set our Service to Sleep for say 10 seconds, which should be enough for us to hook our debugger to it. To attach a debugger to a running process one needs to browse the list of running applications, find the process in question and attach the debugger to it. This is tedious, error prone (select another process and you have to start over, remember the sleep will most certainly timeout by then) and, after repeating a few time, boring. Consider also that you may have multiple instances of your application/Service running, so you need to distinguish the one you’re interested in from a list of identical image names. Not fun. But, there is a better way.

What if we find a way for the Service to hook itself to a debugger? Sounds tricky, but it’s doable, in a way. Remember that a program that issues an unhandled exception will get terminated by the OS. Windows displays an infamous message stating that the application in question has thrown the towel in, and asks the user whether they want to close the application or debug it. Now clicking that Debug button will get us to the debugger, automating along the way everything involved in attaching an application to a debugger including running the debugger itself! Great, but how can we generate an unhandled exception? How do we know whether a real exception occurred in our process or it’s the one we generated? Granted, in both cases you’d want to hook a debugger and investigate anyway, but if you know it’s your artificial exception then you wouldn’t need to do investigative work every time you employ this method even if out of sheer paranoia.

An interesting solution to this problem is to actually issue a breakpoint exception. As it turns out breakpoints are a special form of exceptions that debuggers catch and handle. If we use the same method we’d have accomplished many design goals in one go. For a start the exception is quite clearly not an application error and we don’t need to investigate it any further. Besides that, it’s an exception clearly dedicated to debugging, so it does document the fact that we are trying to debug the application and not just crash it. Finally, and perhaps most importantly, any debugger already attached to the application (including KM debuggers) will break where we throw the exception precisely because it’s a breakpoint exception (it won’t differentiate if it had inserted that breakpoint because the user had previously requested it or the application generated it). In other words, we’d get ourselves a nice permanent breakpoint. And here is a very important point to remember: never forget to remove such debugging techniques from your final production code!

So how do you do it?

Simple, really. In the code, wherever we want a debugger to be present, before that code section we simply add a line of assembly to raise interrupt 3.

In Intel Assembly Syntax:

__asm int 3

In GCC Assembly Syntax:

__asm(”int 3″);

That’s it. On that particular line of code you’d get an unhandled exception (assuming your Service doesn’t explicitly or implicitly handle breakpoint exceptions) and you’ll see the dreaded crash dialog. Simply choose to debug the application in question and select a debugger that is either running or a new instance.

Practical Service Debugging Workflow

With Visual Studio, I tend to have a session with the project in question open, Debug Configuration selected and full Debug info enabled. I compile the Service (make sure no instance of the service in question is running, otherwise you can’t replace the binary image), start it (either from the SCM console or using other tools), get the exception dialog-box, hit Debug and choose the instance of VS which has the Service project open. I instantly get the file/line where the breakpoint exception is and from there I start debugging the Service. Also, this method preserves other breakpoints that you may end up adding to your session, and they are saved with your project files (typically in the .suo file).

Using this trick, the workflow is smooth and logical. I don’t have to do any extra and tedious work to get my service in debug mode other than simply choosing to debug it once I get the crash dialog-box. Beyond that, VS is up and running with the project files loaded, breakpoints set and all ready to attach to the Service Process in question. You really can’t attach to a process any faster than that and start debugging right away.

share save 171 16 Windows Services (Part II)

]]>
http://www.linkgard.com/software_blog/windows-services/windows-services-part-ii/feed/ 0
Windows Services (Part I) http://www.linkgard.com/software_blog/windows-services/windows-services-part-i/ http://www.linkgard.com/software_blog/windows-services/windows-services-part-i/#comments Fri, 12 Feb 2010 07:02:16 +0000 Ashod Nakashian http://www.linkgard.com/software_blog/?p=23 Windows Services fill the gap between mortal user applications and the privileged, high-profile kernel-mode drivers. They are neither user applications nor do they make the cut to be fully fledged kernel modules. Services are still user-mode applications. They don’t get any higher privileges than their other user-mode applications (this is not entirely correct, as kernel-mode [...]]]> Windows Services fill the gap between mortal user applications and the privileged, high-profile kernel-mode drivers. They are neither user applications nor do they make the cut to be fully fledged kernel modules. Services are still user-mode applications. They don’t get any higher privileges than their other user-mode applications (this is not entirely correct, as kernel-mode drivers may be run as services, but that’s outside the scope of this post). However, they do serve some very useful needs for which they are designed.

When are Services useful?

Perhaps the most obvious application of Services is the need to run some application without the requirement that a specific use be logged-in. That is, either we need to run an application before any user logs in or regardless of who (read: which account) has logged-in.

But that’s not all. Services have other very powerful features, including dependencies (Services may be automatically started or stopped based on the state of their dependencies) and auto-run modes. Automatic activity logging (in Event Logs). System-wide visibility. Administrator-only configuration. Running under system or arbitrary accounts. And many more.

How do they work?

We are really interested in understanding how Windows manages Services, how they are run and what responsibilities we have, as developers and administrators, when we deal with Services. The details and inner workings of Windows Services are of course extremely interesting, however without a good grasp of how things work on the outside, the internal details don’t mean much.

As far as developers are concerned, Services run as normal applications. The only and main difference is that unlike a normal stand-alone, user-mode application, Services have different and multiple entry-points. Each binary image may host one or more Service. Each Service needs to register a ServiceMain entry-point as well as an SCM (Service Control Manager) Control Handler entry-point.

Services are run based on a preset through which an administrator may decides when and if a Service should run. A common setting is to auto-run the service on boot (called Automatic). Another option is to run it only when some application (could be the SCM via user interaction) requests a Service to be run (by sending the Service the Start Control Code.) This mode is called Manual.

It should be clear that unlike other applications, Services by definition need a different method for running and controlling them. And in fact that is the case. An interesting consequence of this would be the difficulty in debugging Services while developing them. The reason is, of course, that one cannot debug past the StartService function which is the function used to run and start a Service.

Debugging Services

The reason that StartService function is the last point where debugging works is that we assume we are using a user-mode debugger. StartService by definition needs to transition to kernel-mode and upon return the service would be on its way to start (assuming creating the ServiceMain thread succeeded). However, StartService doesn’t wait, nor does it guarantee that the Service in question succeeded in starting. The state of Service could be queries via the QueryServiceStatus function.

But all is not lost. User-mode Service can still be debugged, yes, with a user-mode debugger. After all, user-mode Services run in user-mode. The trick is to get a debugger hooked after a Service has started running.

Debugging can be started basically in 3 different manners. The first is the most invasive, Kernel-Mode Debugging. In KM debugging, the debugger is typically either run during booting and stays resident at all times, or it’s attached from a debugger machine to a debuggee via some –typically serial– port. Most all KM debuggers can debug UM applications. However, KM debugging has many drawbacks. Besides the fact that they are complicated to setup and complicated to run (at least relative to UM debugging) there are other issues. For one, some software implement sophisticated protection mechanisms that primarily check for the existence of a debugger and if so they either work differently (typically in reduced functionality mode) or stop working altogether. This is a completely undesirable side-effect, especially if the application we are interested in debugging depends on other components/services/applications that may be sensitive to the presence of a debugger. Notice that a KM debugger will be visible to all applications and doesn’t require hooking to any particular one. It’s invasive.

The next two are UM debugging. The second manner is to run an application from within a debugger. That is, start the application in debug-mode. This method is very useful if we need to debug application start-up code and other entry-point related issues. Unfortunately for us, we can’t use this method with Services (the reason should be obvious by now).

We are stuck with the last method: Attaching the debugger to a running process. With Services this means running the service and then attach a UM debugger to it after it’s run successfully. This method works great and we can even set breakpoints within the Control Handler function used by the SCM to send Control Codes and we will break in our debugger when/if a control code is sent to our service. However there is one very significant disadvantage to this method that might not be obvious at first. The fact that we have to attach a debugger at some arbitrary point after the service is run means that we can’t debug start-up code. Put in another way, we must race with time to attach a debugger to our service to catch it at an as early point in its execution as possible. Clearly, this is not a fun thing to do, nor it’s very reproducible, let alone that you can’t set a breakpoint at a very early point in the start-up sequence (in the entry-point function). Or can we?

In the next part we will see what tricks we can utilize to have a user-friendly and humane way of debugging Services.

share save 171 16 Windows Services (Part I)

]]>
http://www.linkgard.com/software_blog/windows-services/windows-services-part-i/feed/ 1