C++ TerminateProcess function - c++

I've been searching examples for the Win32 API C++ function TerminateProcess() but couldn't find any.
I'm not that familiar with the Win32 API in general and so I wanted to ask if someone here who is better in it than me could show me an example for,
Retrieving a process handle by its PID required to terminate it and then call TerminateProcess with it.
If you aren't familiar with C++ a C# equivalent would help too.

To answer the original question, in order to retrieve a process handle by its PID and call TerminateProcess, you need code like the following:
BOOL TerminateProcessEx(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_TERMINATE;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
if (hProcess == NULL)
return FALSE;
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}
Keep in mind that TerminateProcess does not allow its target to clean up and exit in a valid state. Think twice before using it.

Related

why openprocess function return different handle each time?

I want to get the process and thread handles about some games to inject dll, and I used OpenProcess() and OpenThread() to obtain these handles. But I found that I just get different handles each time I use these functions. And they are useless for me because they arent the true handles. Please tell me how I can get the true handles?
Thanks for your answers and comments! And I found that I did not describe my problem very well. Sorry.
Actually, if i used CreateProcess() funtion to launch a process and get handles from parameter lpProcessInformation pi. I could inject my dll into game through these handles named pi.hProcess and pi.hThread. And these handles seem like would not change during the program's runtime.
But if I got handles from OpenProcess() and OpenThread(), the process handle and thread handle were not same as the handle from CreateProcess() even though I got them in same run from a process.
So I thought that the handle from pi is the true handle, and the handle from OpenProcess() are fake. I dont know why they are different and why only handles from pi can work well.
Please tell me the difference about handles from OpenProcess() and
CreateProcess(). Or how I can get the handles same as CreateProcess() through PID.
This is the code how inject dll. And ony handles from pi.hProcess and pi.hThread can work.
void KInject::InjectDll(HANDLE hProcess, HANDLE hThread, ULONG_PTR param){
QueueUserAPC(
(PAPCFUNC)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"),
hThread,
(ULONG_PTR)param
);
}
void KInject::Inject2(HANDLE hProcess, HANDLE hThread, const char* szDLL ){
SIZE_T len = strlen(szDLL) + 1;
PVOID param = VirtualAllocEx(hProcess, NULL, len, MEM_COMMIT | MEM_TOP_DOWN /*MEM_RESERVE*/, PAGE_READWRITE);
if (param != NULL)
{
SIZE_T ret;
if (WriteProcessMemory(hProcess, param, szDLL, len, &ret)) {
InjectDll(hProcess, hThread, (ULONG_PTR)param );
}
}
}
This is the code how i get handles.
#include <Windows.h>
#include "tlhelp32.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
HWND hq = FindWindow(NULL, "Temp");
RECT rect;
DWORD dwThreadID;
DWORD dwProcessId;
GetWindowThreadProcessId(hq, &dwProcessId);
GetWindowRect(hq, &rect);
DWORD a = GetWindowThreadProcessId(hq, &dwProcessId);
THREADENTRY32 te32 = { sizeof(te32) };
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (Thread32First(hThreadSnap, &te32))
{
do {
if (dwProcessId == te32.th32OwnerProcessID)
{
dwThreadID = te32.th32ThreadID;
break;
}
} while (Thread32Next(hThreadSnap, &te32));
}
CloseHandle(hThreadSnap);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
CloseHandle(hThread);
CloseHandle(hProcess);
return 0;
}
There is nothing wrong with the API in this regard. Their return values are just what they are supposed to be, i.e. "handles" to the actual processes and threads. Exactly the same way as when you open a file, you get a handle to it, and if you open the same file multiple times, you may get different handles.
Having said that, just in the same way that files do have a more permanent name—which is their paths—processes and threads also do have a more permanent name and its called their "ID".
You can use the Win32 functions GetProcessId(HANDLE handle) and GetThreadId(HANDLE handle) to get to these more permanent identifiers.

OpenProcess the handle is invalid. CloseHandle not work

I don't know what something wrong with my code. i already put condition when the handle is invalid. it will CloseHandle. but it seems not work. this code trying to get processName. when i input exist PID. it return the processName. opposite when i input doesn't exist PID like 10000. it return handle is invalid. and Error Exception throw. but in my code i already put condition when invalid. it will Close Handle.
std::wstring GetProcessNameById(DWORD i_processId)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
if (hProcess != NULL)
{
wchar_t processFilePath[MAX_PATH];
if (GetModuleFileNameExW(hProcess, NULL, processFilePath, MAX_PATH))
{
CloseHandle(hProcess);
wchar_t *processFileName = PathFindFileNameW(processFilePath);
return processFileName;
}
else
{
CloseHandle(hProcess);
SystemErrorMessage();
}
}
else
{
CloseHandle(hProcess);
SystemErrorMessage();
}
}
int main()
{
std::wcout << GetProcessNameById(10000);
return 0;
}
A compact version of your code makes the bug obvious:
if (hProcess != NULL)
{
// Left out for brevity
}
else
{
// Here, hProcess is NULL
CloseHandle(hProcess);
SystemErrorMessage();
}
In essence, this is calling CloseHandle(NULL);, presumably setting the thread's last error code to ERROR_INVALID_HANDLE. SystemErrorMessage() probably blindly calls GetLastError (without evaluating whether it should), and throws an exception if the value returned is anything other than ERROR_SUCCESS.
To fix this, you need to fix the logic bug (remove the call to CloseHandle in the else branch, in which you know hProcess to be invalid). When done, rework your entire error handling. It won't work reliably. You cannot blindly call GetLastError, anytime an API call failed. When done with that, study the RAII idiom, so that you won't have to write manual cleanup code, like you would have to do with C.

Call to WaitForSingleObject not clear in combination with CreateProcess

I came across the following code in a program that keeps track of processes:
void StartProcess(const std::wstring& processName, const CString& argument)
{
...
STARTUPINFO stInfo;
PROCESS_INFORMATION prInfo;
ZeroMemory( &stInfo, sizeof(stInfo) );
stInfo.cb = sizeof(stInfo);
stInfo.dwFlags=STARTF_USESHOWWINDOW;
stInfo.wShowWindow=SW_SHOWDEFAULT;
bRet = CreateProcess(NULL,
(LPTSTR)(LPCTSTR)sCmdline,
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS,
NULL,
_T("."),
&stInfo,
&prInfo);
// Create process has gone OK and we have to wait.
if (bRet)
{
bRet = FALSE;
int nRetWait = WaitForSingleObject(prInfo.hProcess,0);
if (nRetWait == WAIT_OBJECT_0)
{
// Get the exit code of the process
DWORD dwExitCode = 0;
::GetExitCodeProcess(prInfo.hProcess, &dwExitCode);
if (0 == dwExitCode)
{
// The program succeeded
m_StartedServices.push_back(prInfo.dwProcessId;);
bRet = TRUE;
}
}
}
}
The code should start a process and then in a later stadium terminate it (using m_StartedServices). However I am wondering what added value the calls to WaitForSingleObject and GetExitCodeProcess have. I have looked around a bit and it seems that the WaitForSingleObject with a timeout of 0 is used to check if a process is still running, but it is just created, so why check? And why check the exit code of a process that is still running?
Can anybody clear this up?
Also I found that calls:
CloseHandle(prInfo.hThread);
CloseHandle(prInfo.hProcess);
are missing in this function. Have I found a handle leak, or is there some magic that would automatically close the handles?

C++ Process Monitoring (GetExitCodeProcess)

I want to monitor a process in c++, so I'm using:
std::wstring windowName = TEXT("needle");
HWND windowHandle = FindWindowW(NULL, windowName.c_str());
The FindWindow function, as I understand it, checks the title for all windows (Why did Microsoft name their OS after a core part of it, checking windows in Windows, madness). If a title matches "needle" then it gives me the...
HWND windowHandle
Next I am using:
DWORD* PID;
GetWindowThreadProcessId(windowHandle, PID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, *PID);
This gives me the processID or PID as I've named it. I can then use that to...
HWND p;
DWORD state;
GetExitCodeProcess(p, &state);
... get the state of the process, I'm going to check for it being "STILL_ACTIVE", like so:
if (state != STILL_ACTIVE) {
std::cout << "excessive profanity\n";
}
else {
std::cout << "sigh of relief\n";
}
Except this doesn't work, "cout-ing" (new verb) the value of state gives me some kind of hexadecimal code. It's never "STILL_ACTIVE" despite having multiple windows with "needle" as the title. The code compiles fine, it's just something to do with conversion, pointers, LPCWSTR's or something I've never come across. Help would be appreciated. Thanks
You have two problems:
1) As PaulMcKenzie points out in his answer, PID points to nothing, and will cause problems. Instead you should declare a DWORD and pass a pointer to it to GetWindowThreadProcessId:
DWORD PID;
// note: &PID instead of just PID
GetWindowThreadProcessId(windowHandle, &PID);
// note: Just PID instead of *PID
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
2) GetExitCodeProcess needs a handle to a process, not an uninitialized HWND. Instead you should give it the handle returned from OpenProcess:
DWORD state;
// note: this is the hProcess returned from OpenProcess
GetExitCodeProcess(hProcess, &state);
Note that this will still only work for one process. If multiple processes have windows with the title "needle" then the result of your FindWindow call will be unpredictable.
One error (and probably not the only error) is that there is no way this can work correctly:
DWORD* PID;
GetWindowThreadProcessId(windowHandle, PID);
You are giving GetWindowThreadProcessId an uninitialized pointer, PID. There is nothing that the function can do with it except dereference it (causing undefined behavior), or at best, check if the value is NULL.
When a function asks for a pointer, it doesn't mean you literally declare a pointer and pass it to the function. The function wants the address of an existing entity:
DWORD PID;
GetWindowThreadProcessId(windowHandle, &PID);

C++ Hooking kernel32.dll OpenProcess with detours

I am trying to hook OpenProcess from Kernel32.dll in order to prevent so called "injector" programs from injecting other dll`s into my process:
// -------------------------------------------------------------------
HANDLE WINAPI myOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
{
//
if (dwDesiredAccess == PROCESS_ALL_ACCESS || dwDesiredAccess == PROCESS_VM_OPERATION ||
dwDesiredAccess == PROCESS_VM_READ || dwDesiredAccess == PROCESS_VM_WRITE)
{
printf("Blcoked Process ID : %d , DesiredAccess : %d ", dwProcessId, dwDesiredAccess);
return false;
}
//
return dOpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
}
What do I need to add, in order to "detect" if anybody opens the process for "injecting" ?
I do not want to "prevent", I wish to "detect" injection and decide what to do.
The diagram depicts the steps the injector usually do to inject the dll into another process. Your program should do the behavioral analysis to decide whether it is injecting or not. you need to hook other apis like VirtualAlloc \ WriteProcessMemory, CreateRemoteThread etc.
Below shows the approach to follow to analyse the injector flow and
block the execution when needed. Injector uses many techniques to
inject a dll, the below won't be sufficient to all methods.
//
//HookOpenProcess keep track of opened process handle
//
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
/*
HookVirtualAlloc Check whether the first param is openprocess handle :: Make the suspicion level 3
*/
LPVOID arg = (LPVOID)VirtualAllocEx(process, NULL, ...);
/*
HookWriteProcessMemory Check whether the first param is openprocess handle :: Make the suspicion level 2
*/
int n = WriteProcessMemory(process, .....);
/*
HookCreateRemoteThread Check whether the first param is openprocess handle :: Make the suspicion level 1 and block it from execution
*/
HANDLE threadID = CreateRemoteThread(process, .........);