Kill a process with its processID - c++

I'm trying to display all the running process along with their memory usage and provide a kill option, i've used the OpenProcess method to get the memory used by the current process. How do I kill a process with a processID?
Here is the code:
BOOL GetProcessList( )
{
HANDLE hProcessSnap;
HANDLE hProcess;
HANDLE hToken;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
PROCESS_MEMORY_COUNTERS pmc;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
return( FALSE );
}
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First") ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
if (!ImpersonateSelf(SecurityImpersonation))
return FALSE;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){
printError( TEXT("OpenThreadToken") );
return FALSE;
}
}
else
return FALSE;
}
SetPrivilege(hToken, SE_DEBUG_NAME, FALSE);
do
{
printf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
dwPriorityClass = 0;
SIZE_T dwMin, dwMax;
hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION , FALSE, pe32.th32ProcessID );
if(GetProcessMemoryInfo( hProcess, (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc)))
{
printf( "\nPagefileUsage: %d KB", pmc.PagefileUsage/1024);
} else{
printError( TEXT("GetProcessMemoryInfo") );
}
CloseHandle(hProcess);
}while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}

Since you have an hProcess to hand, you can just use that:
BOOL ok = TerminateProcess (hProcess, exit_code);
Where exit_code can be anything you like (try to make it meaningful, in case anything is waiting on the process and would like to know why it exited).
If you don't want to do it that way, you can use OpenProcess:
HANDLE hProcess = OpenProcess (PROCESS_TERMINATE, FALSE, process_id);
if (hProcess)
{
BOOL ok = TerminateProcess (hProcess, exit_code);
CloseHandle (hProcess);
}
else
{
DWORD err = GetLastError ();
...
}
You need to check that OpenProcess() succeeded because (amongst other things), you might not have sufficient access rights, and you need to close hProcess after you're done with it, even though you've killed the process itself.
Documentation for TerminateProcess() here.

Related

GetProcessMemoryInfo failed with error 6 Handle is invalid

I'm trying to get the list of processes running in the system using C++. I use the functions available in the Windows API (like OpenProcess & CreateToolhelp32Snapshot ) to get it done.
The problem is that the code works fine for most of the processes, but couldn't get the memory info for crucial system processes alone, I have given the seDebugPrivilege also and have run the program as administrator only.
I get the output like
File Name PID Memory Used
winlogon.exe 1248 2432 KB
fontdrvhost.exe 1308
WARNING: GetProcessMemoryInfo failed with error 6 (The handle is invalid)
dwm.exe 1384
WARNING: GetProcessMemoryInfo failed with error 6 (The handle is invalid)
svchost.exe 1448 4744 KB
My code is :
BOOL GetProcessList( )
{
HANDLE hProcessSnap;
HANDLE hProcess;
HANDLE hToken;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
PROCESS_MEMORY_COUNTERS pmc;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
char err[]="CreateToolhelp32Snapshot (of processes)";
printError( err );
return( FALSE );
}
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) )
{
char err[]="Process32First";
printError( err ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
if (!ImpersonateSelf(SecurityImpersonation))
return FALSE;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)){
char err[]="OpenThreadToken";
printError( err );
return FALSE;
}
}
else
return FALSE;
}
SetPrivilege(hToken, SE_DEBUG_NAME, FALSE);
do
{
printf( "%-25s", pe32.szExeFile );
dwPriorityClass = 0;
SIZE_T dwMin, dwMax;
hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION , FALSE, pe32.th32ProcessID );
printf("%-10d", pe32.th32ProcessID );
if(GetProcessMemoryInfo( hProcess, (PROCESS_MEMORY_COUNTERS *)&pmc, sizeof(pmc)))
{
printf( "%-10d KB", pmc.PagefileUsage/1024);
} else{
char err[]="GetProcessMemoryInfo";
printError( err );
}
printf("\n");
CloseHandle(hProcess);
}while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
To get this code to work, you have to change:
SetPrivilege(hToken, SE_DEBUG_NAME, FALSE)
to:
SetPrivilege(hToken, SE_DEBUG_NAME, TRUE)
As others have commented, to get this code to work properly, you have to:
check for and report all possible error conditions
release all resources when you are done, in this case release hToken (via CloseHandle()) and call revertToSelf() if needs be.
Other than that, it's a decent effort so thumbs up for that.
Link to SetPrivilege(), in case any future visitor needs it:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa446619.aspx
Happy hacking.

C++ iterate processes and find out command line args of each process

I have the following problem to solve (VS2012, C++)
I have to find out if a specific HTA app is running from my exe. For that, I have to find the process mshta and check if it has correct arguments (should have been started as "mshta somehta.hta"). My first attempt was to iterate over the processes/modules, which I can do now. I see mshta listed and its PID. But, I did not find the way to get the info, how it was started. Is there a way to do it?
ProcessExists(wchar_t* processName)
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return false;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
for ( i = 0; i < cProcesses; i++ )
{
if( aProcesses[i] != 0 )
{
PrintProcessNameAndID( aProcesses[i] );
}
}
return false;
}
void PrintProcessNameAndID( DWORD processID )
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
dprintf( TEXT("%s (PID: %u) %s %s\n"), szProcessName, processID );
// Release the handle to the process.
CloseHandle( hProcess );
}
I ended up to use the solution proposed here: http://www.codeproject.com/Articles/19685/Get-Process-Info-with-NtQueryInformationProcess

WINAPI VirtualQueryEx - invalid handle

I am trying to read some pages of memory of a 32 bit process using VirtualQueryEx using Visual Studio 2012.
However when I run the program I get VirtualQueryEx Error 6: Invalid Handle. However there is no error with the handle itself [hProcess] and I am passing in the appropriate parameters. What could be it?
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
// Forward declarations:
BOOL GetProcessList( );
BOOL ListProcessModules( DWORD dwPID );
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR* msg );
int main( void )
{
GetProcessList( );
system("pause");
return 0;
}
BOOL GetProcessList( )
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
return( FALSE );
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof( PROCESSENTRY32 );
// Retrieve information about the first process,
// and exit if unsuccessful
if( !Process32First( hProcessSnap, &pe32 ) )
{
printError( TEXT("Process32First") ); // show cause of failure
CloseHandle( hProcessSnap ); // clean the snapshot object
return( FALSE );
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
//If the process name equals foo_process.exe
if (!_tcscmp(pe32.szExeFile, _T("foo_process.exe")))
{
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, pe32.th32ProcessID );
if( hProcess == NULL )
printError( TEXT("OpenProcess") );
unsigned char *addr = NULL;
MEMORY_BASIC_INFORMATION meminfo;
if (VirtualQueryEx(hProcess, addr, &meminfo, sizeof(meminfo)) == 0){
printError( TEXT("VirtualQueryEx") );
//return FALSE;
}
}
} while( Process32Next( hProcessSnap, &pe32 ) );
CloseHandle( hProcessSnap );
return( TRUE );
}
void printError( TCHAR* msg )
{
...
}
EDIT: Handle has value:
EDIT 2: More Info:
Windows 7 64bit platform.
Visual Studio 2012 (32 bit debugger) ran
as Administrator
Process is *32 (32bit)
unsigned char *addr = NULL;
You're asking VirtualQueryEx to Query address 0 which is not valid, causing the failure.

OpenProcess() return error access denided?

I wrote the function GetProcessHandleAndID() as below code:
bool GetProcessHandleAndID( char* _processName, PROCESS_INFORMATION* _processInfo /* out */ )
{
HANDLE SnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( SnapShot == INVALID_HANDLE_VALUE )
{
return false;
}
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( SnapShot, &procEntry ) )
{
CloseHandleSafely(SnapShot);
return false;
}
do
{
if( strcmp( procEntry.szExeFile, _processName ) == 0 )
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procEntry.th32ProcessID);
if(hProcess != NULL)
{
_processInfo->hProcess = hProcess;
_processInfo->dwProcessId = procEntry.th32ProcessID;
CloseHandleSafely(SnapShot);
return true;
}
}
}
while( Process32Next( SnapShot, &procEntry ) );
CloseHandleSafely(SnapShot);
return false;
}
OpenProcess(PROCESS_ALL_ACCESS, FALSE, procEntry.th32ProcessID)work fine on Administrator account, But it will return NULL with GetLastError() = 5 = Access_Denied when run on Normal accounts.
Note that I have called function EnableDebugPriv() before GetProcessHandleAndID().
void EnableDebugPriv()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), NULL, NULL);
CloseHandle(hToken);
}
I have search and read more about this error, but I don't know how to make it work fine on normal user without making it "Run As Administrator"!
Many thanks,
T&T

How to determinate if my application is running under SYSTEM account or not?

How could I decide if my application is running under LocalSystem Account or not? Is there an easy way to do that?
Thanks!
Thanks for your help, but I might have found a way. Not the best, I know, but it works.
BOOL CheckIfRunningAsSYSTEM( VOID )
{
DWORD i, dwSize = 0, dwResult = 0;
HANDLE hToken;
PTOKEN_USER Ptoken_User;
// Open a handle to the access token for the calling process.
if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) )
{
printf( "OpenProcessToken Error %u\n", GetLastError() );
return FALSE;
}
// Call GetTokenInformation to get the buffer size.
if ( !GetTokenInformation( hToken, TokenUser, NULL, dwSize, &dwSize ) )
{
dwResult = GetLastError();
if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
{
printf( "GetTokenInformation Error %u\n", dwResult );
return FALSE;
}
}
// Allocate the buffer.
Ptoken_User = ( PTOKEN_USER )GlobalAlloc( GPTR, dwSize );
// Call GetTokenInformation again to get the group information.
if ( !GetTokenInformation( hToken, TokenUser, Ptoken_User, dwSize, &dwSize ) )
{
printf( "GetTokenInformation Error %u\n", GetLastError() );
return FALSE;
}
LPWSTR SID = NULL;
if ( !ConvertSidToStringSidW( Ptoken_User->User.Sid, &SID ) )
{
printf( "\nConvertSidToStringSidW failed. Error = %d", GetLastError() );
return FALSE;
}
else printf( "\nConvertSidToStringSidW succeeded." );
if ( _wcsicmp( L"S-1-5-18", SID ) == 0 ) printf( "\nRunning under SYSTEM" );
else printf( "\nNOT running under SYSTEM" );
if ( Ptoken_User ) GlobalFree( Ptoken_User );
return TRUE;
}//CheckIfRunningAsSYSTEM