TerminateProcess not working for specific processes - c++

I need to terminate some processes before my program can run, but whenever I run TerminateProcess(), GetLastError() returns 5. What I know so far is that this means that access is denied, I also know that to elevate my rights i need to use AdjustTokenPrivileges(), based on Rango's answer here and Microsoft's documentation here.
What i don't know is why it wont work. Based on what I've read, the following should work:
BOOL TerminateMyProcess(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_ALL_ACCESS;
//DWORD dwDesiredAccess = ACCESS_SYSTEM_SECURITY;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = NULL;
TOKEN_PRIVILEGES tp = { 0 };
LUID luid;
LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hProcess, FALSE, &tp, 0, NULL, NULL);
hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}
As you can tell from the above, I am not sure which dwDesiredAccess I am supposed to use. PROCESS_ALL_ACCESS lets me terminate other simple processes, such as chrome.exe or notepad.exe, but not what i need to terminate. ACCESS_SYSTEM_SECURITY is whats' said to be used by microsoft, but then i cannot terminate any process at all.
Also, is this even close to what i need to do, if not can you please point me in the right direction.
UPDATE: Added UpdatePrivilege() function from here, and called it before calling OpenProcess() function, still no bite.
UPDATE 2: The process I need to terminate is the "afwServ.exe" process, i.e. Avast's firewall. I need to do this so that my firewall is the sole firewall used by Windows. This a requirement of my project.

I think you misunderstood the difference between right and privileges, this answer explains it.
In this case, your current user may not have permission to terminate the specified process. You may first need to use LogonUser and use administrator identity to simulate the process context.
What you want to terminate is a service, you can try using ControlService with SERVICE_CONTROL_STOP to stop the services. But you also need to switch to the user with permission first.

Related

Proper use of RegOpenCurrentUser

I went here and made a test program to see if it actually disables the task manager. Basically a simple bool switch on then switch off to see if the task manager was actually disabled. It works as intended when i compiled and ran it.
Edit: the code now looks like this
#include <iostream>
#include <Windows.h>
using namespace std;
void LockTaskManager(bool Lock);
void main(void) {
LockTaskManager(true);
cout << "Testing task manager disable." << endl;
getchar();
LockTaskManager(false);
cout << "Testing task manager enabled." << endl;
getchar();
}
void LockTaskManager(bool Lock)
{
HKEY currKey;
DWORD dwDisposition;
DWORD dwType, dwSize;
DWORD value;
if (Lock)
value = 1;
else
value = 0;
LRESULT lResult = RegOpenCurrentUser(KEY_WRITE, &currKey);
if (RegCreateKeyEx(currKey,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\system"),
0,
NULL,
0,
KEY_SET_VALUE,
NULL,
&currKey,
&dwDisposition) == ERROR_SUCCESS)
{
dwType = REG_DWORD;
dwSize = sizeof(DWORD);
RegSetValueEx(currKey, TEXT("DisableTaskMgr"), 0, dwType, (PBYTE)&value, dwSize);
RegCloseKey(currKey);
}
}
However, after i moved the .exe to a guest user on the same computer, it does not disable the task manager. So i went to look into how and why it worked, from microsoft's MSDN here i found that HKEY_CURRENT_USER does not change and requires the use of RegOpenCurrentUser to set the current key to the user that is running that program. i know about this post but the answer is not conclusive.
So with that said, I wish to know the correct way to approach this. The goal here is to make whoever that runs the .exe of this code be unable to run task manager.
FYI, Just so whoever reads this knows, i intend to use this as a defense mechanism in the event a flag is triggered, i want to stop malicious entities from killing this process through task manager.
what is HKEY_CURRENT_USER ? this is really \REGISTRY\USER\<UserSid> where <UserSid> some sid. when process first time use HKEY_CURRENT_USER (root of the current user key is yet not opened) system query current user sid ( TokenUser ), convert sid to string, append \REGISTRY\USER\ prefix, open and cache opened key. when process next time use, HKEY_CURRENT_USER - used already opened and cached key. even if thread is impersonating - this change nothing. however some time we need access different user key, after impersonating. exactly for this situation and RegOpenCurrentUser and used. this api query current thread (or process) token for TokenUser, format path based on current user sid, open \REGISTRY\USER\<UserSid1> and return handle to you. it not cache this handle, instead you must close it, when you no longer need the returned handle.
so at first senseless use RegOpenCurrentUser if you not impersonating current thread.
at second, this code always senseless:
LRESULT lResult = RegOpenCurrentUser(KEY_READ, &hkey);
if (RegCreateKeyEx(HKEY_CURRENT_USER,..
you not use returned hKey anyway. what sense open it in this case ?
need use it in place HKEY_CURRENT_USER !
LRESULT lResult = RegOpenCurrentUser(KEY_READ, &hkey);
if (RegCreateKeyEx(hKey,..
why code not worked under guest ? when you call RegCreateKeyEx and resulting key (system in your case) yet not exist - you need have KEY_CREATE_SUB_KEY access to the parent (Policies key). however by default guest have not any write access to key. you simply have not KEY_CREATE_SUB_KEY access. and KEY_SET_VALUE you also have not. sure that under guest call RegCreateKeyEx return ERROR_ACCESS_DENIED to you.

Using CreateProcess() and exit/close the opened Application

I am building a program that would open Sublime text and after a period of time would close the application itself . I can't figure out how to close the application using the existing code .
This is what I have so far :
STARTUPINFO siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
if (CreateProcess(L"C:\\Program Files\\Sublime Text 2\\sublime_text.exe",
L" source.cpp",
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
NULL,
&siStartupInfo,
&piProcessInfo) == FALSE)
WaitForSingleObject(piProcessInfo.hProcess, INFINITE);
::CloseHandle(piProcessInfo.hThread);
::CloseHandle(piProcessInfo.hProcess);
First, you are calling WaitForSingleObject() and CloseHandle() if CreateProcess() fails, which is useless. Don't call those functions unless it succeeds instead.
Second, you are calling the Unicode version of CreateProcess(), which has a caveat that your code is not handling. Per the CreateProcess() documentation:
lpCommandLine [in, out, optional]
The command line to be executed. The maximum length of this string is 32,768 characters, including the Unicode terminating null character. If lpApplicationName is NULL, the module name portion of lpCommandLine is limited to MAX_PATH characters.
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
Third, if you want to terminate the process after a timeout, you could use TerminateProcess(), but that is brute force and should be avoided when possible. Sublime has a UI, so the preferred solution is to ask the UI to close itself down and then wait for it to do so, as documented on MSDN:
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).
With that said, try something more like this:
BOOL CALLBACK SendWMCloseMsg(HWND hwnd, LPARAM lParam)
{
DWORD dwProcessId = 0;
GetWindowThreadProcessId(hwnd, &dwProcessId);
if (dwProcessId == lParam)
SendMessageTimeout(hwnd, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 30000, NULL);
return TRUE;
}
...
STARTUPINFO siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
WCHAR szFilename[] = L"C:\\full path to\\source.cpp";
if (CreateProcess(L"C:\\Program Files\\Sublime Text 2\\sublime_text.exe",
szFileName,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
NULL,
&siStartupInfo,
&piProcessInfo))
{
CloseHandle(piProcessInfo.hThread);
WaitForInputIdle(piProcessInfo.hProcess, INFINITE);
if (WaitForSingleObject(piProcessInfo.hProcess, SomeTimeoutHere) == WAIT_TIMEOUT)
{
EnumWindows(&SendWMCloseMsg, piProcessInfo.dwProcessId);
if (WaitForSingleObject(piProcessInfo.hProcess, AnotherTimeoutHere) == WAIT_TIMEOUT)
{
// application did not close in a timely manner, do something...
// in this example, just kill it. In a real world
// app, you should ask the user what to do...
TerminateProcess(piProcessInfo.hProcess, 0);
}
}
CloseHandle(piProcessInfo.hProcess);
}

How to control Windows services using Windows API easily?

Issue
I would like to control any Windows service using Windows API, but I cannot :(
= What's wrong with my "wanting solution"?
Current solution
The ugliest but functional way I use is following (for Stop command):
void StopService()
{
ShellExecute(Application->Handle,
"open",
"stop.bat",
NULL,
ExtractFilePath(Application->ExeName).c_str(),
SW_SHOW);
}
Where stop.bat is a Windows batch file with following commands:
::the command
sc stop "service name"
::a pause to see if something goes wrong
pause
It is very annoying to have to close launched cmd windows...
Wanting solution
The function bellow appears to be ok. If I try to perform a command to stop an unexisting service, it will show a error message. BUT when I try to run it for an existing service, it runs, but nothing happens with the service (if I ordain to stop it, it does nothing)...
void ControlService(AnsiString ServiceName, DWORD Order)
{
SC_HANDLE Scm, Svc;
SERVICE_STATUS Status;
Scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if(Scm != 0)
{
Svc = OpenService(Scm, PChar(ServiceName.c_str()), SERVICE_ALL_ACCESS);
if(Svc != 0)
{
ControlService(Svc, Order, &Status);
// handle Status....
CloseServiceHandle(Svc);
}
else
{
ShowLastError();
}
CloseServiceHandle(Scm);
}
else
{
ShowLastError();
}
}
void ShowLastError()
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Display the string.
MessageBox(NULL, (char*)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION);
// Free the buffer.
LocalFree(lpMsgBuf);
}
What's wrong?????
Two possible issues you might have run into:
You are checking state of service too soon. The ServiceControl returns immediately, without waiting for the service to complete the request. Your service could transition to SERVICE_STOP_PENDING, and in this case you will have to give it some time and check again.
There are dependent services in running state. You will have to enumerate dependent services, shut them down first, then stop your service.
On #2, there is good explanation with a sample code on MSDN. Here is a quote from the same page:
However, if the SCM determines that other running services are dependent on the specified service, it will not forward the stop request. Instead, it returns ERROR_DEPENDENT_SERVICES_RUNNING. Therefore, to programmatically stop such a service, you must first enumerate and stop its dependent services.

How to Compare Two variable of HANDLE type

I have a variable of HANDLE type.
First HANDLE variable is a process HANDLE (with name hProcess) that does not have PROCESS_QUERY_INFORMATION access right.
Second variable is a process HANDLE (with name hwndProcess) too that I have opened via OpenProcess function and have PROCESS_QUERY_INFORMATION access right. I am sure both processes should have same handle.
But when i compare them as below, it returns false;
if (hProcess==hwndProcess) {do something}
How shall I do it?
There is not an explicit way to check whether two handles refer to the same process. The only way would be to query the process information and check that, e.g. using GetProcessId on each handle to check the process IDs.
If you don't have the necessary access rights to call the desired query functions then you can try calling DuplicateHandle to get a new handle with more access rights. However, if this fails then you have no way of telling whether the handles are to the same process or not.
hProcess must not hold the ProcessHandle of the Process that will be closed. It can and will most times be NULL. I'm doing something similar to get the PIDs of terminated processes.
if((hProcess == NULL) || (hProcess == GetCurrentProcess())){
pid = GetCurrentProcessId();
} else {
pid = ProcessHandleToId(hProcess);
}
Are your sure, that it's an access rights problem and your function doesn't fail, because the handle is NULL?
The Windows 10 SDK has CompareObjectHandles(HANDLE, HANDLE) which returns TRUE if the handles refer to the same underlying kernel object.
And you don't have to worry about access rights.

how to get process handle from process id?

I have process Id , I want to get its process handle.
Is there any API available for that.
I tried to use OpenProcess but it returns NULL, and GetLastError =0.
This I am trying on Vista.
I guess I need to enable SeDebugPrivilege before using OpenProcess .
But for enabling SeDebugPrivilege I need to get its Process handle.
OpenProcess(PROCESS_ALL_ACCESS, TRUE, procId);
You'll need to verify that you're using a valid process ID, and that you're permitted the access rights you request from the process.
Is this what you are looking for?
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
CloseHandle(processHandle);
Also, here is some code I use to set debug privledge before injecting DLLs.
void Loader::EnableDebugPriv(void)
{
HANDLE hToken;
LUID SeDebugNameValue;
TOKEN_PRIVILEGES TokenPrivileges;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &SeDebugNameValue))
{
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Luid = SeDebugNameValue;
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(AdjustTokenPrivileges(hToken, FALSE, &TokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
CloseHandle(hToken);
}
else
{
CloseHandle(hToken);
throw std::exception("Couldn't adjust token privileges!");
}
}
else
{
CloseHandle(hToken);
throw std::exception("Couldn't look up privilege value!");
}
}
else
{
throw std::exception("Couldn't open process token!");
}
}
I've used the above code on Windows Vista with success.
You would need elevated privileges. Also look at similar question here.
I just had the exact same issue as described: OpenProcess() == NULL and GetLastError() == 0.
Turned out to be the Common Language RunTime Support setting, was set to "Pure" should have been just "Common". Took me ages to find.
For VS2010 c++ goto -> Project Properties -> Configuration Properties -> C/C++ -> General
If you have a process identifier, you can get the process handle by calling the OpenProcess function. OpenProcess enables you to specify the handle's access rights and whether it can be inherited.
FYI:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684868(v=vs.85).aspx