Windows: kill program that creates itself - c++

I've accidentally created a program that continues to call CreateProcess on itself - resulting in an infinite loop.
How would I go about killing this program once it's started to run? I have attempted killing this through the task manager, but because the program calls itself to start and immediately dies, it continues to disappear and reappear in the task manager making it 'unstoppable'.
The only way to stop this seems to be a reboot of the PC, which can be very inconvenient.
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow )
{
using namespace std;
CreateProcess( L"self.exe",
NULL, // No command line arguments
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
NULL, // Set handle inheritance to NULL
NULL, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&lpStartupInfo, // Pointer to STARTUPINFO structure
&lpProcessInfo // Pointer to PROCESS_INFORMATION structure
);
return 0;
//return (int)msg.wParam;
}

From a end-users point of view, the easy solution is to press Ctrl+Alt+Del and log off. If you want to keep the session alive the only solution to a fork-bomb like this is to use a tool that understands the process tree. taskkill /T /IM self.exe as suggested in the comments or the "Kill process tree" feature in Process Explorer. Child processes might still be able to sneak past so you might have to execute the kill command multiple times.
If I was programming a kill tool for this I would enumerate the processes and when a target process is found you open a handle to it and try to associate it with a job object. A job object allows you to deny the creation of child processes and allows easy termination of all processes in the job. Just call TerminateProcess if the process could not be added to a job.
You need to run this enumeration code in a loop until you have killed all the desired processes.

Related

Creating a command interpreter process and writing to it

I have been trying to create a cmd.exe from a c++-program and then being able to execute commands from the program inside the cmd.exe, so I can view the results of the operation in the cmd.exe. CreateProcessA() is the function I used:
_STARTUPINFOA CMD_StartupInfo = {};
CMD_StartupInfo.cb = sizeof(_STARTUPINFOA);
_PROCESS_INFORMATION CMD_ProcessInfo = {};
CreateProcessA("C:\\Windows\\System32\\cmd.exe",
0,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&CMD_StartupInfo,
&CMD_ProcessInfo);
The cmd.exe opened and it looked to be working. Then I thought I'd use PostMessage() to pass WM_KEYDOWN messages to the cmd.exe to execute a command. For this function I needed a window handle and it turns out that the process of getting a window handle from a process/thread ID which is obtained from the CreateProcessA() is f***ing complicated. You have to loop through all active windows with EnumWindows() that requires a callback function which needs to check whether or not the process ID of the current window is the same as the process ID of the process I created.
I did that and it turned out that none of the windows the function iterated over were my window.
So I presume that means that the thread of this process which I created has no windows but I can see a beautiful-looking cmd.exe right there. What is going on? Is this not considered a window? If not, how do I pass messages to the cmd.exe and if yes, how do I get the window handle?
Any help is appreciated (also ideas to do the entire cmd-thing differently).

Terminating Process in Windows 10 OS

Background Information: I'm developing an Windows 10 app. Within my app, some outputs are displayed onto a window console requiring a new process.
Code Snippet:
PROCESS_INFORMATION pi;
STARTUPINFO si;
// CreateProcess is defined in processthreadsapi.h
BOOL newProcess = CreateProcess (
0, pszCmdLine, 0, 0, FALSE, DEBUG_THIS_ONLY_PROCESS, 0, 0, &si, &pi
);
In the above code snippet, pszCmdLine can be "cmd.exe /c dir", "cmd.exe /c ipconfig", or essentially any Windows terminal cmd.
Problem: On the front end, a new cmd console is generated and the user is able to terminate it. However, it's kept alive in the background. I've attached snips below:
Before Process Accumulating:
In the above snip, it shows "cmd.exe /c dir" being executed and outputted into a cmd console.
After Processes Accumulates:
In the above snip, it shows how I launched the same cmd 4 times and closed it 3 times (i.e. the counter is "(4)" including the main process).
Real World Problem: This is essentially consuming memory and has the ability to degrade performance.
Initial Curiosity: Shouldn't the Windows OS handle the killing of this process when the user clicks the "x"?
Has anyone faced a similar issue before?
Solution:
Change DEBUG_ONLY_THIS_PROCESS to 0 or CREATE_NEW_CONSOLE.
My Thoughts:
I suppose the idea behind DEBUG_ONLY_THIS_PROCESS is to leave the window handle open for the user to observe the output whereas CREATE_NEW_CONSOLE allocates and frees the memory as needed.

Start a process not as a child

I need to start a process and run it as a detached process. I have some sort of starter application which purpose is to run another exe and immediately exit. What is a best way to achieve that?
I read CreateProcess documentation several times but still have questions. Documentation says that I need to call CloseHandle after I finish. But my parent app shouldn't wait for a child to exit. Another part of documentation says that I can leave handles alone - the system will close them when the parent process terminates. Does that means that child application exits immediately after parent? It seems not true - I close a starter but my child process still runs.
There's a DETACHED_PROCESS flag that seem what I'm looking for. But documentation says something about console. What console? I don't care about console.
DETACHED_PROCESS flag documentation states
For console processes, the new process does not inherit its parent's console (the default)
that means: if you have a console process and you start a new one, it will not inherit its parent's console.
If you don't have a console process you don't have to worry about it.
CreateProcess creates a child process but does not wait for the child process to finish, so you're already all set.
If you wanted to wait for the child process to complete, you should have called CreateProcess and then WaitForSingleObject
To summarize:
// Version 1) Launch and wait for a child process completion
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
if (CreateProcess(L"C:\\myapp.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) {
::WaitForSingleObject(processInfo.hProcess, INFINITE); // DO WAIT for the child to exit
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
// ----------------------------------------------------------------
// Version 2) Launch and do NOT wait for a child process completion
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
if (CreateProcess(L"C:\\myapp.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) {
CloseHandle(processInfo.hProcess); // Cleanup since you don't need this
CloseHandle(processInfo.hThread); // Cleanup since you don't need this
}
notice that version 2 will not terminate your child process. Only resources which are no longer needed will be released.
I read CreateProcess documentation several times but still have questions. Documentation says that I need to call CloseHandle after I finish. But my parent app shouldn't wait for a child to exit.
Okay, then don't wait. You can call CloseHandle immediately in the parent.
Another part of documentation says that I can leave handles alone - the system will close them when the parent process terminates. Does that means that child application exits immediately after parent? It seems not true - I close a starter but my child process still runs.
No, it doesn't. I'm not sure how you got that from the documentation, but that's not what it means.
There's a DETACHED_PROCESS flag that seem what I'm looking for. But documentation says something about console. What console? I don't care about console.
If you don't care, then don't worry about it.

how to terminate a process created by CreateProcess()?

I have created a process using CreateProcess(). This is the code:
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
result = CreateProcess("C:\\AP\\DatabaseBase\\dbntsrv.exe", NULL, NULL, NULL, FALSE, 0, NULL, "C:\\ADP\\SQLBase", &si, &pi)
How can I get the Handle and processId of this specific process? And eventually use it to close this process?
Thank You.
In the struct pi you get:
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
The first parameter is the handle to the process.
You can use that handle to end the process:
BOOL WINAPI TerminateProcess(
__in HANDLE hProcess,
__in UINT uExitCode
);
hProcess [in]
A handle to the process to be terminated.
The handle must have the PROCESS_TERMINATE access right. For more information, see Process Security and Access Rights.
uExitCode [in]
The exit code to be used by the process and threads terminated as a result of this call. Use the GetExitCodeProcess function to retrieve a process's exit value. Use the GetExitCodeThread function to retrieve a thread's exit value.
A handle to the process is returned in the PROCESS_INFORMATION structure, pi variable.
The TerminateProcess() function can be used to terminate the process. However, you should consider why you need to kill the process and why a graceful shutdown is not possible.
Note you need to set the cb member of si before calling CreateProcess():
si.cb = sizeof(STARTUPINFO);
EDIT:
To suppress the console window specify CREATE_NO_WINDOW, as the creation flag (the sixth argument) in the CreateProcess() call.
EDIT (2):
To suppress the window try setting following members of STARTUPINFO structure prior to calling CreateProcess():
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = FALSE;
Closing the process cleanly
To close the process cleanly, you should send a close signal first:
How To Terminate an Application "Cleanly" in Win32.
If you absolutely must shut down a process, follow these steps:
Post a WM_CLOSE to all Top-Level windows owned by the process that you want to shut down. Many Windows applications respond to this message by shutting down.
NOTE: A console application's response to WM_CLOSE depends on whether or not it has installed a control handler.
Use EnumWindows() to find the handles to your target windows. In your callback function, check to see if the windows' process ID matches the process you want to shut down. You can do this by calling GetWindowThreadProcessId(). Once you have established a match, use PostMessage() or SendMessageTimeout() to post the WM_CLOSE message to the window.
Use WaitForSingleObject() to wait for the handle of the process. Make sure you wait with a timeout value, because there are many situations in which the WM_CLOSE will not shut down the application. Remember to make the timeout long enough (either with WaitForSingleObject(), or with SendMessageTimeout()) so that a user can respond to any dialog boxes that were created in response to the WM_CLOSE message.
If the return value is WAIT_OBJECT_0, then the application closed itself down cleanly. If the return value is WAIT_TIMEOUT, then you must use TerminateProcess() to shutdown the application.
NOTE: If you are getting a return value from WaitForSingleObject() other then WAIT_OBJECT_0 or WAIT_TIMEOUT, use GetLastError() to determine the cause.
By following these steps, you give the application the best possible chance to shutdown cleanly (aside from IPC or user-intervention).
See this answer for code.
Terminating the process
If you don't care about clean shutdown, you can use TerminateProcess(). However, it is important to note that TerminateProcess() is asynchronous; it initiates termination and returns immediately. If you have to be sure the process has terminated, call the WaitForSingleObject() function with a handle to the process.
Note: Access rights PROCESS_TERMINATE and SYNCHRONIZE are required.
TerminateProcess(pi.hProcess, 0);
// 500 ms timeout; use INFINITE for no timeout
const DWORD result = WaitForSingleObject(pi.hProcess, 500);
if (result == WAIT_OBJECT_0) {
// Success
}
else {
// Timed out or an error occurred
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
Not closing, just wait until finished
If the process will finish on its own, instead of terminating you can wait until it has finished.
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
This is explained thoroughly in MSDN:
If result is non-zero (which means that it succeeded) you will get the handle and processid in the pi structure.
In order to kill the process you can use TerminateProcess

How to launch console application using CreateProcess with Minimized main window

I have a native c++ windows application that is launching two child processes using the following code -
if (!CreateProcess(NULL, // No module name (use command line)
cmdLine, // szCmdline, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
false, // Set handle inheritance to FALSE
CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS // Process Create Flags
NULL, // Use parent's environment block
NULL, // workingDir, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
with all parameters in STARTUPINFO block 0. This code works fine in launching the processes. However, I need to be able to launch the windows c++ console applications with their windows minimized.
If I add CREATE_NO_WINDOW to the Process Create Flags, I can launch the processes without any windows. This will be unacceptable.
In my research, there does not appear to be a way force a console application to open in a minimized mode. Is this correct?
Yes, I know that I could minimize the child application windows from within their own process, however, the other programmers on the team prefer not to do this.
You need to specify in the STARTUPINFO structure that you want your console window to be initially minimized:
ZeroMemory(&si);
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_MINIMIZE;