Windows program to freeze other running programs
Why
One of the program services on my computer kept respawning despite my attempts to kill it, suspend it, or disable it via different means. I then had an idea to pause it in a way that would prevent it from annoying me, while still maintaining an impression that it was active.
How
Simply killing the process from e.g. a Task Manager won’t be effective, as it will be restarted. Suspending it via a more advanced Process Explorer won’t work reliably as something else in the system (presumably services.exe
) is resuming it quite quickly.
One idea was to give the process the lowest priority possible so that it would be just starved by the OS scheduler while still being alive. Of course, this would not completely negate the harm it was doing. So then it hit me: debugging it! Attaching a debugger keep the debuggee alive, but completely under control of the debugger. This means that the process will remain frozen and unresponsive unless the debugger says so.
It was possible to attach an existing debugger such as MS VS Studio to a running process. It worked in my initial experiments. But having a full-blown IDE just hanging in background doing nothing was an overkill. So I decided to write a small program that does the initial debugger connection without actually providing the majority of usual debugger functions.
Details
The idea is to use WinAPI’s DebugActiveProcess()
to connect to the victim process as a debugger. A regular debugger would then proceed with processsing debuggee events in a loop. The debuggee’s thjreads would become unfrozen and continue running at some point. In contrast, my application simply goes into an endless loop. No events are consumed and the attached application remains frozen.
Killing the debugger process kills the debuggee as well. This is WinAPI’s default behavior.
This logic is stored in stallattach.cpp
.
Dealing with Permissions
It is not always allowed to attach a random process as a debugger to another process. I read somewhere that additional SE_DEBUG_NAME
capabilities were required for the debugger process. So I added such logic of requesting them to the program.
In the code, privilege.cpp
provides a function to deal with this task. I’ve borrowed this sniipet from MSDN (there was a problem with #pragma
that I addressed).
Usage
Call stallattach.exe
followed by PID of the process you want to stop. It is recommended to do so from an elevated command prompt (I hope you understand the security consequences of such actions). But it also worked for me if run as a regular user, for some reason.
Sources and disclaimers
The sources are published here: https://github.com/grigory-rechistov/stallattach.
I used a default console application template project generated by the IDE for me. A lot of crap was included into it, such as precompiled headers, resources etc. etc. I let it stay.
I built them using MS VS 2017 on Windows 10 x64. Not sure what exact build dependencies are, which development kits one needs to install etc. You can never know with Windows.
I do not know if this software will be useful to anyone in any way. I am not responsible if it will cause any damage to you. Do not mess with system-critical processes, or be prepared to lose data.
Acknowledgements
A borrowed a few code pieces and ideas from different sources below.
- MSDN article https://docs.microsoft.com/sv-se/windows/win32/secauthz/enabling-and-disabling-privileges-in-c—
- “Writing a basic Windows debugger” by Ajay Vijayvargiya, https://www.codeproject.com/Articles/43682/Writing-a-basic-Windows-debugger
- Stackoverflow Q&A: https://stackoverflow.com/questions/4880197 and https://stackoverflow.com/questions/2523099
- “GetLastError as std::string” by Orjan Westin, https://www.codeproject.com/Tips/479880/GetLastError-as-std-string