How do I see if another process is running on windows? - c++

I have a VC++ console app and I need to check to see if another process is running. I don't have the window title, all I have is the executable name. How do I get the process handle / PID for it? Can I enumerate the processes running with this .exe ?

Use the CreateToolhelp32Snapshot Function
hSnapShot = FCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Followed by Process32First and Process32Next.
You will get a PROCESSENTRY32 struct as follows with an szExeFile member.
PROCESSENTRY32W processInfo;
processInfo.szExeFile
Make sure to first acquire the privilege SeDebugPrivilege before enumerating, that way you will get all processes across all sessions and users.
To acquire the privilege so you get all sessions:
acquirePrivilegeByName(SE_DEBUG_NAME);// SeDebugPrivilege
Where acquirePrivilegeByName is defined as:
BOOL acquirePrivilegeByName(
const TCHAR *szPrivilegeName)
{
HANDLE htoken;
TOKEN_PRIVILEGES tkp;
DWORD dwerr;
//---------------- adjust process token privileges to grant privilege
if (szPrivilegeName == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!LookupPrivilegeValue(NULL, szPrivilegeName, &(tkp.Privileges[0].Luid)))
return FALSE;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &htoken))
return FALSE;
if (!AdjustTokenPrivileges(htoken, FALSE, &tkp, 0, NULL, NULL) ||
GetLastError() != ERROR_SUCCESS) // may equal ERROR_NOT_ALL_ASSIGNED
{
dwerr = GetLastError();
CloseHandle(htoken);
SetLastError(dwerr);
return FALSE;
}
CloseHandle(htoken);
SetLastError(ERROR_SUCCESS);
return TRUE;
} //acquirePrivilegeByName()
If you need the full process image name you can use QueryFullProcessImageName, but the szExeFile member may be enough for your needs.

You can use EnumProcesses to enumerate the processes on a system.
You'll need to use OpenProcess to get a process handle, then QueryFullProcessImageName to get the processes executable.

Related

OpenProcessBlocked even i use SetPrivilege(hToken, SE_DEBUG_NAME, true);

I have a problem, I want to read some values with ReadProcessMemory from a process, this process blocks OpenProcess, now I heard that I just need to Privilege the file who want to do OpenProcess with SE_DEBUG_NAME.
I googled and found this function :
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege){
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;}
Now i tried the following :
bool bStart(std::string szProcessName)
{
if (szProcessName.empty())
return false;
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
SetPrivilege(hToken, SE_DEBUG_NAME, true);
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
if (!SetPrivilege(hToken, SE_DEBUG_NAME, TRUE))
{
std::cout << "SetPrivilege";
// close token handle
CloseHandle(hToken);
// indicate failure
return false;
}
std::cout << "hi";
HANDLE hSnapshot = (CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
if (hSnapshot == INVALID_HANDLE_VALUE)
return false;
bool bFoundProcess = false;
PROCESSENTRY32 PE32 = { sizeof(PROCESSENTRY32) };
if (Process32First(hSnapshot, &PE32))
{
do
{
if (!szProcessName.compare(PE32.szExeFile))
{
m_dwProcessId = (XOR(PE32.th32ProcessID));
bFoundProcess = true;
break;
}
} while (Process32Next(hSnapshot, &PE32));
}
CloseHandle(m_hProcess);
if (!bFoundProcess)
return false;
m_hProcess = (XOR(OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_dwProcessId)));
if (m_hProcess == INVALID_HANDLE_VALUE)
return false;
return true;
}
I don't get any error or anything, but for any reason, the OpenProcess doesn't work. Can someone please help me?
Thanks in advance!
this process blocks OpenProcess
This means the game's anticheat is blocking process handle creation via a kernel mode anticheat.
There is nothing you can do to bypass this from usermode, you must also make a kernel driver and disable their protection.
The most simple way for them to prevent handle creation is with ObRegisterCallbacks so you will need to reverse engineer their implementation of that.
Keep in mind this technique is from 5+ years ago, they have much more complicated protection now.

Setting permissions to broadcast messages across multiple desktops

Hi,
I'm trying to send messages between applications that are located on different desktops. In order to accomplish this, I'm using BroadCastSystemMessage using BSM_ALLDESKTOPS set for LPDWORD lpdwRecipients parameter.
As the MSDN documentation says, BSM_ALLDESKTOPS - Broadcast to all desktops. Requires the SE_TCB_NAME privilege.
In order to meet this requirement I've found the following example which generates the ERROR_NOT_ALL_ASSIGNED, with the code 1300 - Not all privileges or groups referenced are assigned to the caller, in the last if statement:
BOOL GrantPrivilege::SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid))
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. %u\n ", GetLastError());
return FALSE;
}
return TRUE;
}
Maybe the error is caused by the way I'm making the call for this function:
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
printf("%u", GetLastError());
GrantPrivilege gPriv;
gPriv.SetPrivilege(hToken, L"SeTcbPrivilege", true);
P.S. I've tried runing this application from an elevated prompt, but the result is the same, 1300 error code.
This error code means that current windows user is not allowed to use this privilege (this is why these are privileges, after all: not everyone have them). It is possible to grant a user such privilege, but I strongly advise against it. Instead, you should use some other form of inter-process communication. If you only need a signal without data, named event should be good. Otherwise, it could be a named pipe, socket, or shared memory section.

RegLoadKey is giving error code 5 (Access Denied)

Hi I'm trying to load a key from HKLM\\SYSTEM\\CurrentControlSet\\Services\\Fax but i'm getting error 5 (Access Denied). I'm not able to figure it out what is wrong with my code.
Here is my code
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
void _tmain(int argc, TCHAR *argv[])
{
HKEY hKey;
LONG lErrorCode;
HANDLE ProcessToken;
LPCWSTR subkey = L"SYSTEM\\CurrentControlSet\\Services\\Fax";
if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ProcessToken))
{
SetPrivilege(ProcessToken, SE_BACKUP_NAME, TRUE);
SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE);
SetPrivilege(ProcessToken, SE_RESTORE_NAME, TRUE);
}
lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,subkey ,
0, KEY_ALL_ACCESS, &hKey);
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in RegOpenKeyEx (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully Opened\n"));
}
lErrorCode = RegSaveKey(hKey,L"c:\\load.reg",0);
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in RegSaveKey (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully Saved \n"));
}
lErrorCode = RegLoadKey(HKEY_LOCAL_MACHINE,subkey,L"c:\\load.reg");
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in RegLoadKey (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully loaded \n"));
}
lErrorCode = RegCloseKey(hKey);
if (lErrorCode != ERROR_SUCCESS)
{
_tprintf(TEXT("Error in closing the key (%d).\n"), lErrorCode);
return;
}
else
{
_tprintf(TEXT("Key is successfully closed \n"));
}
}
This is the output
Key is successfully Opened
Key is successfully Saved
Error in RegLoadKey (5).
RegLoadKey can only be used to load a new hive into the registry. You can't use it to overwrite a subkey of an existing hive.
You probably want to use RegRestoreKey instead.
Additional:
To the best of my knowledge, hives can only be loaded at a registry root, i.e., they must be HKEY_LOCAL_MACHINE\foo or HKEY_USERS\foo, never HKEY_LOCAL_MACHINE\foo\bar. Also, I don't think you can load a hive with a name that already exists, e.g., you can't load a hive into HKEY_LOCAL_MACHINE\SOFTWARE. Even if you could do these things, you'd be changing your view of the content, not merging it, and when the system was rebooted the original content would reappear. As previously mentioned, if you want to insert data into an existing hive, use RegRestoreKey rather than RegLoadKey.
You ask about the use cases for RegLoadKey: there aren't many. Mostly, it's used by the operating system; for example, that's how your personal hive is loaded into HKEY_USERS\username when you log in. There are some oddball cases, such as resetting a password offline or otherwise modifying the registry of another Windows instance. The process I use for the unattended installation of Windows on the computers in my teaching lab depends on modifying the registry of the Windows installation image to disable the keyboard and mouse.

Got error code(5) access denied when use TerminateProcess to terminate the "mstsc.exe" process

I use the CreateProcess() function to launch the rdp client app using "mstsc.exe". After that, I want to terminate it so I use TerminateProcess() function, but it fails with error code of 5. If I replace the "mstsc.exe" with "notepad.exe", the terminate function works. The code are as follows:
TCHAR szCommandLine[] = TEXT("mstsc.exe");
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi;
BOOL bResult = CreateProcess(NULL, szCommandLine, NULL, NULL,
FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
::Sleep(3000);
if (TerminateProcess(pi.hProcess, 0) == 0) {
printf("failed: %d", GetLastError());
}
Can anyone help explain it and solve it?
What I observed is that the pid of the pi returned is different from the id of the process "mstsc.exe" observed in taksmanager or "Process Explorer".
Is your host process 32-bit and you are running on 64-bit windows?
If so, you are invoking the 32-bit mstsc and it is spawning a 64-bit version, hence the different PID. Check out this thread
You must gain the privilege before terminating another process.
Try this:
void UpdatePrivilege(void)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken))
{
LookupPrivilegeValue(NULL,SE_DEBUG_NAME, &luid);
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
}
}
Call this function before calling TerminateProcess.

Does using ReadDirectoryChangesW require administrator rights?

The MSDN says that using ReadDirectoryChangesW implies the calling process having the Backup and Restore privileges.
Does this mean that only process launched under administrator account will work correctly?
I've tried the following code, it fails to enable the required privileges when running as a restricted user.
void enablePrivileges()
{
enablePrivilege(SE_BACKUP_NAME);
enablePrivilege(SE_RESTORE_NAME);
}
void enablePrivilege(LPCTSTR name)
{
HANDLE hToken;
DWORD status;
if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tp = { 1 };
if( ::LookupPrivilegeValue(NULL, name, &tp.Privileges[0].Luid) )
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL result = ::AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
verify (result != FALSE);
status = ::GetLastError();
}
::CloseHandle(hToken);
}
}
Am I doing something wrong? Is there any workaround for using ReadDirectoryChangesW from a non-administrator user account? It seems that the .NET's FileSystemWatcher can do this. Thanks!
Update: Here is the full code of the class:
class DirectoryChangesWatcher
{
public:
DirectoryChangesWatcher(wstring directory)
{
enablePrivileges();
hDir = ::CreateFile(directory.c_str(),
FILE_LIST_DIRECTORY | FILE_FLAG_OVERLAPPED,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
ensure (hDir != INVALID_HANDLE_VALUE, err::SystemException);
::ZeroMemory(&overlapped, sizeof(OVERLAPPED));
overlapped.hEvent = dirChangedEvent.getHandle();
}
~DirectoryChangesWatcher() { ::CloseHandle(hDir); }
public:
Event& getEvent() { return dirChangedEvent; }
FILE_NOTIFY_INFORMATION* getBuffer() { return buffer; }
public:
void startAsyncWatch()
{
DWORD bytesReturned;
const BOOL res = ::ReadDirectoryChangesW(
hDir,
&buffer,
sizeof(buffer),
TRUE,
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE,
&bytesReturned,
&overlapped,
NULL);
ensure(res != FALSE, err::SystemException);
}
private:
void enablePrivileges()
{
enablePrivilege(SE_BACKUP_NAME);
enablePrivilege(SE_RESTORE_NAME);
}
void enablePrivilege(LPCTSTR name)
{
HANDLE hToken;
DWORD status;
if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tp = { 1 };
if( ::LookupPrivilegeValue(NULL, name, &tp.Privileges[0].Luid) )
{
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL result = ::AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
verify (result != FALSE);
status = ::GetLastError();
}
::CloseHandle(hToken);
}
}
private:
HANDLE hDir;
OVERLAPPED overlapped;
Event dirChangedEvent;
FILE_NOTIFY_INFORMATION buffer[1024];
};
}
Update: Good news! It turned out the problem really was in the FILE_SHARE_WRITE flag in the call to CreateFile. The notifications did not come unless I was an admin. When I removed this flag, everything is now working ona non-admin account too.
I have used ReadDirectoryChangesW without requiring administrator rights, at least on Vista. I don't think you need to manually elevate the process in order to use it on a folder the user already has permissions to see.
It would be more helpful to see the actual code you are using to call ReadDirectoryChangesW, including how you create the handle you pass in.
I don't see where MSDN says you need either backup or restore privileges. It instructs you to call CreateFile with the File_Flag_Backup_Semantics flag set, and in that flag's description, MSDN says this:
The system ensures that the calling process overrides file security checks when the process has SE_BACKUP_NAME and SE_RESTORE_NAME privileges.
The way I read it, if you have those privileges, then the system will override the file security checks for you. So if you don't have those privileges, then the program will simply continue to be bound by whatever file security checks would ordinarily be in effect.
Alex, in your CreateFile() call you put FILE_FLAG_OVERLAPPED into wrong position. It should be moved from 2nd to 6th parameter.