Incorrect values from GetProcessHandleCount - c++

I faced with strange behavior of function GetProcessHandleCount().
At first I take a snapshot of all processes in the system as it is described in msdn:
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hProcessSnap, &pe32 ) )
{
CloseHandle( hProcessSnap );
return 0;
}
Then I walk the snapshot of processes, and count up open handles by using function
GetProcessHandleCount:
int count_of_handles=0;
DWORD dwHandleCount=0;
do {
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION,FALSE,pe32.th32ProcessID);
GetProcessHandleCount(hProcess,&dwHandleCount);
count_of_handles+=dwHandleCount;
if( hProcess != NULL )
CloseHandle( hProcess );
} while( Process32Next( hProcessSnap, &pe32 ) );
I checked this program in Windows 7 x64. Program displayed count_of_handles ~16000, but really this value was ~100 000 (if believe in Windows Task Manager).
Then I executed this program in Windows XP x32 (by VMWare), and count_of_handles was ~9000 (but in real it was ~8000).
What is wrong with my code? Thank you.

For one thing, GetProcessHandleCount might return zero (which signifies an error). This could explain coming to a result lower than what you expect. This might be caused in turn by OpenProcess failing (you don't check for that either).

As well as Jon's reason, the value from Task Manager1 includes handles open in the kernel – these will not be included in your total across processes.
1 For this kind of thing Process Explorer is far more effective. Including being able to list open handles per process and in the kernel, the system pseudo-process in Process Explorer's listing.

Related

how can i hook every system call a process makes [duplicate]

If I have a function foo() that windows has implemented in kernel32.dll and it always returns true, can I have my program: "bar.exe" hook/detour that Windows function and make it return false for all processes instead?
So, if my svchost, for example, calls foo(), it will return false instead of true. The same action should be expected for all other processes currently running.
If so, how? I guess I'm looking for a system-wide hook or something.
Take a look at Detours, it's perfect for this sort of stuff.
For system-wide hooking, read this article from MSDN.
First, create a DLL which handles hooking the functions. This example below hooks the socket send and receive functions.
#include <windows.h>
#include <detours.h>
#pragma comment( lib, "Ws2_32.lib" )
#pragma comment( lib, "detours.lib" )
#pragma comment( lib, "detoured.lib" )
int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send;
int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv;
int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags );
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags );
int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) {
// .. do stuff ..
return Real_Send( s, buf, len, flags );
}
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) {
// .. do stuff ..
return Real_Recv( s, buf, len, flags );
}
BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
switch ( dwReason ) {
case DLL_PROCESS_ATTACH:
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourAttach( &(PVOID &)Real_Send, Mine_Send );
DetourAttach( &(PVOID &)Real_Recv, Mine_Recv );
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
DetourDetach( &(PVOID &)Real_Send, Mine_Send );
DetourDetach( &(PVOID &)Real_Recv, Mine_Recv );
DetourTransactionCommit();
break;
}
return TRUE;
}
Then, create a program to inject the DLL into the target application.
#include <cstdio>
#include <windows.h>
#include <tlhelp32.h>
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 );
}
int main( int, char *[] ) {
PROCESSENTRY32 entry;
entry.dwSize = sizeof( PROCESSENTRY32 );
HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );
if ( Process32First( snapshot, &entry ) == TRUE ) {
while ( Process32Next( snapshot, &entry ) == TRUE ) {
if ( stricmp( entry.szExeFile, "target.exe" ) == 0 ) {
EnableDebugPriv();
char dirPath[MAX_PATH];
char fullPath[MAX_PATH];
GetCurrentDirectory( MAX_PATH, dirPath );
sprintf_s( fullPath, MAX_PATH, "%s\\DllToInject.dll", dirPath );
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, entry.th32ProcessID );
LPVOID libAddr = (LPVOID)GetProcAddress( GetModuleHandle( "kernel32.dll" ), "LoadLibraryA" );
LPVOID llParam = (LPVOID)VirtualAllocEx( hProcess, NULL, strlen( fullPath ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( hProcess, llParam, fullPath, strlen( fullPath ), NULL );
CreateRemoteThread( hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)libAddr, llParam, NULL, NULL );
CloseHandle( hProcess );
}
}
}
CloseHandle( snapshot );
return 0;
}
This should be more than enough to get you started!
EASYHOOK http://www.codeplex.com/easyhook
Dominate's all aformentioned techniques in simpleicty, flexability and functionality.
It was not discussed previously on Hook processes either. I've read all leaf's of this thread and with absolute certanty, EASYHOOK is vastly superiour. No matter if your using C, C++, CLR, whatever.
I'll paste a bit from the codeplex homepage, to ensure sufficient omage being paid.
The following is an incomplete list of features:
A so called "Thread Deadlock Barrier" will get rid of many core problems when hooking unknown APIs; this technology is unique to EasyHook
You can write managed hook handlers for unmanaged APIs
You can use all the convenience managed code provides, like NET Remoting, WPF and WCF for example
A documented, pure unmanaged hooking API
Support for 32- and 64-bit kernel mode hooking (also check out my PatchGuard 3 bypass driver which can be found in the release list)
No resource or memory leaks are left in the target
Experimental stealth injection mechanism that won't raise attention of any current AV Software
EasyHook32.dll and EasyHook64.dll are pure unmanaged modules and can be used without any NET framework installed!
All hooks are installed and automatically removed in a stable manner
Support for Windows Vista SP1 x64 and Windows Server 2008 SP1 x64 by utilizing totally undocumented APIs, to still allow hooking into any terminal session.
Managed/Unmanaged module stack trace inside a hook handler
Get calling managed/unmanaged module inside a hook handler
Create custom stack traces inside a hook handler
You will be able to write injection libraries and host processes compiled for AnyCPU, which will allow you to inject your code into 32- and 64-Bit processes from 64- and 32-Bit processes by using the very same assembly in all cases.
EasyHook supports RIP-relative addressing relocation for 64-Bit targets.
No unpacking/installation necessary.
The Visual Studio Redistributable is not required.
I'm happy that my hooker's still know a few tricks in comparison that makes me keep them around. But to be sure, when you need a HOOK, 99 times of 100, EASYHOOK'r will get you there faster. And it's quite actively maintained.
Please give more details of the function you want to hook! There are several ways to get your own code called in such a case, for instance:
You can build a fake DLL with the same name as the DLL that contains the function you want to hook (and copy it in the folder of foo.exe). This library would expose exactly the same functions as the original DLL. Each exposed function just bypasses the call to the original DLL, with the exception of the function you want to hook.
You can change the function pointer table during run-time, for instance with the (commercial) Detour package that has been mentioned by "kitchen". However, doing such hooking can be done easily by your own, see this article to learn how.
You can find out where the specific function is called in foo.exe and just replace the assembly code that calls the function with a code that "returns true". Basically, you're patching "foo.exe"..
For specific functions, Windows offers automatic hooking, e.g. for keys and mouse events. Check the function SetWindowsHook for this.
This depends somewhat on the version of Windows you're wanting to target. Nonetheless, if you're playing on Pre-Vista, you can simply use SetWindowsHookEx to inject your DLL into every running process. Your DLL would then need to hook the appropriate function using Detours or similar.
If you are writing your hook in assembly and not using Detours (for whatever reason), then you need some key information about returing FALSE:
Win32, set EAX to 0
Win64, set RAX to 0
You need to set EAX or RAX (depending upon platform) to zero as the last thing the function you are hooking does. That will result in the calling code receiving 0 as the return value (assuming they are returning an int or pointer type value).

Is there a way to list every windows processes from cpp?

I'm recently looking to list every processes of a machine to do some action. But I'm struggling with processes which are not launched from my user (eg: system, administrator or an other user).
I tried some codes and some solutions but there is still anything who works.
I am working on the code proposed by microsoft to enumerate all the processes.
Here is the code :
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
// and compile with -DPSAPI_VERSION=1
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.
_tprintf( TEXT("%s (PID: %u)\n"), szProcessName, processID );
// Release the handle to the process.
CloseHandle( hProcess );
}
int main( void )
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return 1;
}
// 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 0;
}
This code works but does not allow you to view the processes of other users. Do you have an idea?
Thanks everyone for your time.
Regards
As a normal user, you are not going to get far by using OpenProcess on processes you don't own. If you elevate your process and enable the debug privilege you might have more luck. You will probably still be denied access to DRM and AntiVirus processes. In general the PSAPI functions expect a lot of access to the process with PROCESS_VM_READ being the biggest issue, Windows is not going to grant you memory read access to all other processes. Some of the newer APIs like GetProcessImageFileName have been upgraded (in Vista+) to only require PROCESS_QUERY_LIMITED_INFORMATION which you might be able to get for more processes.
I would suggest using the Toolhelp API instead, it should provide a little more info than EnumProcesses+OpenProcess. You can also get some information from the Performance Counters and WMI.
As a side note; EnumProcesses is the most useless API ever. It uses the NT API to get information about all processes then throws away all that information except the process ids.
If you are willing to use undocumented stuff, the NT Query/Information functions will give you more information than any documented API.
The most reasonable solution I think would be to use
CreateToolhelp32Snapshot
You can do some looking up on it at https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
Heres a small example
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
std::cout << "CreateToolhelp32Snapshot (of processes) failed with error " << GetLastError() << std::endl;
return;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcessSnap, &pe32))
{
std::cout << "Failed getting first process" << std::endl;
CloseHandle(hProcessSnap);
return;
}
do
{
std::cout << "Process: " << pe32.szExeFile << std::endl;
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);

Boost Library to find parent's process ID

I am really messed up with the code base I have and I am working on portability of C++ code.
As of now the code seems to be windows specific and it tries to take the parent's process ID that is executing itself. Eg: I write a code in C++ that uses the Parent's process ID of the cmd that is executing the corresponding EXE created by its (code's)compilation.
DWORD getParentPID()
{
HANDLE hSnapshot;
PROCESSENTRY32 pe32;
DWORD parentPID = 0, PID = GetCurrentProcessId();
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
__try{
if( hSnapshot == INVALID_HANDLE_VALUE ) __leave;
ZeroMemory( &pe32, sizeof( pe32 ) );
pe32.dwSize = sizeof( pe32 );
if( !Process32First( hSnapshot, &pe32 ) ) __leave;
do{
if( pe32.th32ProcessID == PID ){
parentPID = pe32.th32ParentProcessID;
break;
}
}while( Process32Next( hSnapshot, &pe32 ) );
}
__finally{
if( hSnapshot != INVALID_HANDLE_VALUE ) CloseHandle( hSnapshot );
}
return parentPID;
}
Obviously, this code is not intended to work on Linux and I don't want any precompilation, Looking forward to some platform independent code using Boost C++.
PS: Precompilation up to som extent is accepted. Mainly Targeted platforms are Windows and Linux.I might be missing on some small points due to the workload.
Any Lead is appreciated, thanks in advance.

TerminateProcess not suceeding on Windows 10

Our C++ app launches a separate .exe ( which may start its own sub-processes) using CreateProcess as below.
BOOL started = ::CreateProcess(NULL, // application
p, // parameters
NULL, // process security
NULL, // thread security
TRUE, // inherit handles flag
0, // flags
NULL, // inherit environment
dirLP, // inherit directory
&startup, // STARTUPINFO
&procinfo); // PROCESS_INFORMATIO
In case we need cancel the "job" we use CreateToolhelp32Snapshot to iterate through the process list to find any child processes of the one we launched.
static BOOL TerminateProcessTree (HANDLE parentProcess,UINT exitCode)
{
BOOL result=TRUE;
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of the processes
DWORD parentID=GetProcessId(parentProcess);
if(parentID==0){
PrintLastError("GetProcessId");
return FALSE;
}
if (Process32First(hProcessSnap, &pe32)) {
do{
if(pe32.th32ParentProcessID==parentID){
HANDLE hProcess = OpenProcess (PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
if(hProcess!=NULL){
BOOL terminateChildren=TerminateProcessTree(hProcess,exitCode);
BOOL terminatedChild = TerminateProcess(hProcess, exitCode);
if (!terminatedChild){
PrintLastError("TerminateProcess");
}
CloseHandle(hProcess);
if(!terminatedChild || !terminateChildren){
result=FALSE;
break;
}
} else{
PrintLastError("OpenProcess");
}
}
}while (Process32Next(hProcessSnap, &pe32));
}
CloseHandle (hProcessSnap);
DWORD checkCode=0;
BOOL terminated;
if(GetExitCodeProcess(parentProcess,&checkCode) && checkCode==STILL_ACTIVE){
terminated=TerminateProcess(parentProcess,exitCode);
if (!terminated){
PrintLastError("TerminateProcess");
result= FALSE;
}
}
return result;
}
As noted, this works fine on Windows 7. Windows 10 fails with "Access Denied" on the first call "TerminateProcess". Clearly something has changed in the Windows security model when it comes to processes.
The robust way to deal with controlling a process tree of objects is to use Job objects as noted in the comment threads.
The one thing to keep in mind is that a process can only belong to a single job, and by default any EXE that the OS determines needs appcompat help is put into a job object automatically managed by the "Program Compatibility Assistant". This makes using a Job object to manage arbitrary 3rd party EXEs a little bit more complicated (i.e. AssignProcessToJobObject fails for these processes).
If you are using CreateProcess you can make use of the flag CREATE_BREAKAWAY_FROM_JOB. See this blog post. This works fine as long as the target EXE has the same rights as the calling object.
For a Standard User EXE to run an EXE that might need Administrator rights (i.e. they contain a manifest which marks it as requireAdministrator), you have to use ShellExecute or ShellExecuteEx as calling CreateProcess in this case will fail. If your target EXEs are all using the proper manifest elements then it won't be put into a PCA Job object.. You can use the trick of passing SEE_MASK_FLAG_NO_UI which will have the side-effect of avoiding the PCA job behavior. If you are launching arbitrary 3rd party EXEs, you should use ShellExecuteEx and not CreateProcess.
bool SpawnProcess( const WCHAR* szExePath, const WCHAR* szExeArgs )
{
if( !szExePath )
return false;
// NOTE: szExeArgs can be nullptr.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH] = {0};
wcscpy_s( szDirectory, szExePath );
PathRemoveFileSpec( szDirectory );
// ShellExecute or ShellExecuteEx must be used instead of CreateProcess
// to permit the shell to display a UAC prompt asking for consent to
// elevate when the target executable's manifest specifies a run level
// of "requireAdministrator".
//
// You can only use CreateProcess if you know that the application you
// are spawning will be at the same run level as the current process.
// Otherwise, you will receive ERROR_ACCESS_DENIED if the elevation
// consent could not be obtained.
SHELLEXECUTEINFO info = {};
info.cbSize = sizeof( info );
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if( !ShellExecuteEx( &info ) )
return false;
return true;
}
Note that if you want to wait until this process exits, you can use:
bool SpawnProcessAndWait( const WCHAR *szExePath, const WCHAR *szExeArgs, DWORD *pdwExitCode )
{
if( !szExePath )
return false;
// NOTE: szExeArgs and pExitCode can be nullptr.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH] = {0};
wcscpy_s( szDirectory, szExePath );
PathRemoveFileSpec( szDirectory );
// See SpawnProcess for information why ShellExecute or ShellExecuteEx
// must be used instead of CreateProcess.
SHELLEXECUTEINFO info = {};
info.cbSize = sizeof( info );
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if( !ShellExecuteEx( &info ) )
return false;
// Wait for process to finish.
WaitForSingleObject( info.hProcess, INFINITE );
// Return exit code from process, if requested by caller.
if( pdwExitCode )
GetExitCodeProcess( info.hProcess, pdwExitCode );
CloseHandle( info.hProcess );
return true;
}
You haven't noted if your "master" application here is using administrator or Standard User rights. Ideally it is using Standard User rights per the User Account Control guidelines dating back to Windows Vista. If your app is running as Standard User, then it's likely that your code no longer works due to security improvements to keep non-Administrator malware from doing this kind of thing to other processes.
For general appcompat questions about Windows 10, be sure to read the Windows and Windows Server compatibility cookbook and look back at the Windows 8.0 and Windows 8.1 material if you are jumping directly from Windows 7 to Windows 10.

Using Module32First/Next to Enumerate 32bit Process Modules from 64bit Process

Here's the code:
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE32, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
return( r_mi );
}
me32.dwSize = sizeof( MODULEENTRY32 );
if( !Module32First( hModuleSnap, &me32 ) )
{
CloseHandle( hModuleSnap );
return( r_mi );
}
do
{
MessageBoxA(0,me32.szModule,0,0);
} while( Module32Next( hModuleSnap, &me32 ) );
Problem is that when trying to enumerate the modules of a 32bit process from a 64bit process, only the x64 modules are being listed.
From MSDN for TH32CS_SNAPMODULE32:
Includes all 32-bit modules of the process specified in th32ProcessID in the snapshot when called from a 64-bit process.
But still, it's only listing the x64 modules
Anyone know a work around for this?
You have to use TH32CS_SNAPMODULE32 | TH32CS_SNAPMODULE
thanks for Hans Passant for figuring this out.