In Part 1 I discussed a very simple and friendly way — just use GFlags to do it. And in all honesty, that probably should be your preferred option, unless you can start the process by yourself, in which case you don’t need these post series anyway 🙂
NOTE: Here are direct links to previous articles – Part 1, Part 3 and Part 4.
However, there are cases where the process is executed under different account (or under SYSTEM account). In such cases, even though debugger would launch, I haven’t found a straightforward way to access it. Here’s an example:
This starts the process and debugger but they’re running under SYSTEM account so I don’t really get to see neither of them:
So, how to solve that? Well, turns out that there’s quite a neat trick that I’ll show here. WinDbg allows you to specify “-c” parameter which stands for “commands that you want to execute as soon as it gets attached to the process”. Here’s what I’m going to specify:
-c "~* n; .detach; q"
Here’s how it looks like in GFlags:
What will happen the next time I launch notepad is that the debugger will attach immediately (just like it did in Part 1), and then it will execute the following commands:
- ~* n — which stands for “execute ‘n’ on all threads”. Without going too deep into it, the “n” stands for SUSPEND the specified thread(s). So this command effectively will increase the suspend counter on ALL threads (more on it afterwards).
- .detach — which detaches the debugger from the process without killing it.
- q — probably self-explanatory. It’s a “quit” command which closes the debugger.
What these three effectively achieve is that the process will start, debugger will attach immediately, increase Suspend counter on all threads and then detach, making it possible for another debugger to attach.
All you need to do now is start WinDbg from your session, attach to the process and resume the threads with “~* m”:
Now you’re free to proceed debugging the process any way you prefer 🙂
Why this works?
It works because there’s really nothing stopping you from attaching to a suspended process. But the tricky part is going from a WinDbg that is started by SYSTEM user all the way to detaching without resuming the process. And that’s where the “~* n” comes.
The thing is that when debugger attaches, it increases SUSPEND counter for each thread. If you observe the previous screenshot, you’ll see that “Suspend” counter for each thread is “2”. Well, for all threads except the last one. The last one is a thread started by WinDbg when I attached, hence the Counter is at 1.
In contrast, when debugger detaches (e.g. using “.detach” command), what happens is that SUSPEND counter decreases on each thread. And I’m guessing that when it reaches 0, the Thread resumes its work. So the problem is that if we attach then detach, the process will resume. Hence, by issuing the “~* n”, we are increasing suspend counter for each thread by 1, and when the original debugger detaches, suspend counters go back to 1, meaning they are still halted. So the process basically remains in suspended state until we manually attach and resume it 🙂
And that’s about it. For next article, I’m toying with the idea of injecting a DLL that has one function that invokes Window’s Sleep() function. This should allow me to put main process’ thread to sleep for X seconds, giving me enough time to attach manually 🙂
3 thoughts on “Attaching debugger immediately after process starts – Part 2”