Click here to Skip to main content
Click here to Skip to main content

How to Create an "unkillable" Windows Process

By , 12 Oct 2010
 
screen.jpg

The topic of killing Windows processes has been investigated by developers and users probably from the first day this operating system appeared. Besides the task manager where it is possible to kill (practically) any process, there are a lot of freeware and shareware programs that will do all the dirty job of ending any process you select. But what to do if you need to write an "unkillable" program?

Once I came across this problem, I analyzed how several adware programs were running, such as Gator Adware, using methods making it possible to avoid being ended by the user. As a result, I worked out a fairly simple solution that is described in this article. This example implements a relatively eternal process. It is assumed that the user does not use any special technical tools in order to kill the process, but uses only the task manager or similar software.

How It Works

Since we cannot forbid the user to select our process in the task manager with the mouse and select the "End Process" command, let's create two processes that are the same - one of them will directly execute the code of the program, while the other one will only monitor whether the main program is running or not. The first process will also monitor whether the second auxiliary process is running. With this kind of implementation, no matter which of the two processes the user kills, the remaining process will start a working copy and our program will continue to work. schema.jpg

Implementation - Main Code

This is the main code of the program. If nothing is passed in the command line, we run the second process that will keep monitoring and then start performing the main function. If the ID of the main process is passed in the command line, we just monitor it. If it is closed, it gets started again.
    CHAR theAppPath[MAX_PATH];
    HANDLE theParentProcess = NULL;

    BOOL CClient001App::InitInstance()
    {
        ....

	CString cmdLine = CString(::GetCommandLine());
	cmdLine = cmdLine.Right
	( cmdLine.GetLength()-cmdLine.ReverseFind(' ')-1);
	GetModuleFileName( AfxGetInstanceHandle(), theAppPath, MAX_PATH );
	DWORD procID = atoi(cmdLine);


	if( procID == 0 )
	{
	    _beginthread( AntikillThreadWaiter1, 0, NULL ); // starting the thread 
					// that will run and monitor the second copy
	}
	else
	{
		   HANDLE parentProc = OpenProcess
			   ( PROCESS_ALL_ACCESS, FALSE, procID );
		   if( parentProc )
		   {
			    theParentProcess = parentProc;
			   _beginthread( AntikillThreadWaiter2, 0, NULL );// starting 
					// the thread that will monitor whether 
					// the main program is running

			   while(1)
			   {
		                   Sleep( 500 );
			   }
		   }
	}

       /// the main code of the program goes here
        ....
}

Code of the AntikillThreadWaiter1 Thread

This thread only starts the second copy of the program to which it passes the current ID of the process in the command line. The second copy will wait till the main program is closed. If the user closes the second copy, this thread starts it again.

void AntikillThreadWaiter1(LPVOID param )
{
  while(1)
  {
	  STARTUPINFO si;
	  PROCESS_INFORMATION pi;
	  CHAR theNewPath[MAX_PATH];
	  DWORD pid = GetCurrentProcessId();
	  wsprintf( theNewPath,"%s %d\0", theAppPath, pid );

	  memset(&si, 0, sizeof(STARTUPINFO));
	  si.cb = sizeof(STARTUPINFO);
	  CreateProcess(NULL, theNewPath , NULL, NULL,
		  FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, p);

	  WaitForSingleObject( pi.hProcess, INFINITE );
  }
}

Code of the AntikillThreadWaiter2 Thread

In its turn, the second thread waits till the main program the ID of whose process was passed in the command line is closed. If the user closes this process, this thread starts it again.

void AntikillThreadWaiter2(LPVOID param )
{
	  WaitForSingleObject( theParentProcess, INFINITE );

	  STARTUPINFO si;
	  PROCESS_INFORMATION pi;
	  CHAR theNewPath[MAX_PATH];
	  wsprintf( theNewPath,"%s\0", theAppPath );

	  memset(&si, 0, sizeof(STARTUPINFO));
	  si.cb = sizeof(STARTUPINFO);
	  CreateProcess(NULL, theNewPath , NULL, NULL,
		  FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, p);
	  ExitProcess(0);

	  return; // :))
}

Instead of the Conclusion

The given mechanism can be used as a variant for realization of "permanent" programs, for example for client applications of monitoring systems or parental control. In this article, I used C++ and MFC, but it isn't a restriction of the idea as it can be realized in any other languages.

The Russian version of this article can be found at http://plaincodesource.blogspot.com/2010/10/windows.html.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

va_dev
Software Developer
Russian Federation Russian Federation
Member
Professional Windows/Java Mobile/Web-applications developer since 2000.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
BugWeak code/solutionmemberBrandon T. H.28 Mar '12 - 2:59 
If your devloping something serious or using it against something serious.
 
If the clone program or the main program start the target program again it becomes it's child, then you could use End Process Tree, this will terminate or kill any process/program/file that this process started up automatically or anything assciated with it. For example, I have process "a" and "b," I terminate process a, process b starts a again without me knowing, so All I have to do in order to COMPLETELY Shut it down is to use "End Process Tree," and poof, the clone and the main processes are both toast.
 
So you see there is weakness in this code or method, if a program starts another program, that other process is under "whatever process that started it"'s name or identity.
Simple Regards,
Brandon

GeneralMy vote of 1memberLegnylsEtros10 May '11 - 4:27 
A very simple way of trying to keep your running application alive.
 
More interesting is Thread / Dll injection techniques or how you set the priviliges to end processes.
 
The more elegant but also more intrusive way is perhaps to intercept the process list struct when returned at kernel level?
Generali like itmemberkazemtnt10 May '11 - 2:16 
i like it   thank you
GeneralAnother OLD method But ..........!!memberAdore C++5 Nov '10 - 9:43 
Dear all
 
well i recall an old method but i don't know how much it strong , well deep inside any win32 program there is a loop which receive all the windows message and begin to process it Like mouse move , mouse click , .........etc , the method in brief that when the task manager send a quit msg ( Plus its ID ) to the app. , any normal app. will just process it and quit (without check the ID) but the new here that we add some code to the check the Process ID for the process which sent such quit msg if its not the same as our app (parent window) then it's external process try to kill me so just ignore it else quit its user who want quit
 
any comment about that ??
 
thanks all
bye
GeneralMy vote of 5memberJaded Hobo2 Nov '10 - 9:52 
I like this concept for process monitors in embedded systems. Sometimes a process just has to keep running no matter what or our customer looses a heap of money.
GeneralMy vote of 2memberArchElf22 Oct '10 - 8:48 
If you are to prevent the process group being killed:
- do not create one process from an another directly as they can be killed with 'kill process tree'
- hook win api to prevent killing
- use service (or better, multiple services, one with watchdog function)
GeneralMy vote of 2memberSandeep Datta18 Oct '10 - 8:37 
Not a good enough solution...right click on the parent process in process explorer and choose kill process tree!
GeneralMy vote of 2memberPatLeCat16 Oct '10 - 4:58 
I answered already
AnswerWell,memberSlava Archibasov16 Oct '10 - 1:51 
In the first, the given project isn't a virus, more likely, having read this article, you can understand how virus on your PC works.
 
In the second, this article won't be brought in the Guinness Book of World Records, but you will gain more control over your process using this mechanism, rather than using other ready APIs, such as Services or Security descriptors, which themselves depend on system calls
 
And in the third,it is clearly written in the article, that process is relatively permanent. I know self at least four ways to kill this process, but is means nothing. This code has advantages, it works in the tens of programms since 2005, and I think this idea is worth to be shared with respected Codeproject community.
AnswerRe: Well,memberPatLeCat16 Oct '10 - 4:51 
What you seem to solve is what is called a watchdog process. But they are done in a different and more "harmless" way where the user can control everything (with enough knowledge though). But thanks for the effort.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 12 Oct 2010
Article Copyright 2010 by va_dev
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid