Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

How to Create an unkillable Windows Process

3.25/5 (15 votes)
12 Oct 2010CPOL2 min read 63.6K   1.4K  
This article explains how to implement a relatively eternal process.
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.
C++
    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.

C++
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.

C++
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)