|< Windows Process & Threads Programming 6 | Main | Windows Process & Threads Programming 8 >| Site Index | Download |
MODULE U1
PROCESSES AND THREADS: Win32/WINDOWS APIs
Part 7: More Program Examples
|
|
My Training Period: hours
Note: ...Continuation from previous Module...Program examples compiled using Win32 console mode application of the Visual C++ .Net (Visual studio .Net 2003). It is low-level programming and the .Net used is Unmanaged (/clr is not set: Project menu → your_project_name Properties… sub menu → Configuration Properties folder → General subfolder → Used Managed Extension setting set to No). This also applied to other program examples in other Modules of tenouk.com Tutorial that mentioned “compiled using Visual C++ .Net”. Other settings are default. Machine’s OS is standalone Win Xp SP2. Program examples have been tested for Non Destructive Test :o). All information recomposed for Win 2000 (NT5.0) above.
WARNING
Wrongly modified and run the program examples presented here might collapse your Windows machine or disturb its integrity. So for your Windows machine safety, make sure you fulfill the following conditions:
Abilities
▪ Able to understand and use various processes and threads functions (Windows APIs/Win32). ▪ Able to build and run your own simple processes and threads programs. ▪ Able to understand, build and run your own simple multithreading programs. ▪ Able to extract, understand and use functions information from MSDN documentation.
Note: For Multithreaded program examples, you have to set your project to Multithread project type.
Index
Enumerating All Modules For a Process
To determine which processes have loaded a particular DLL, you must enumerate the modules for each process. The following sample code uses the EnumProcessModules() function to enumerate the modules of current processes in the system.
|
// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
void PrintModules(DWORD processID)
{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;
// Print the process identifier.
printf("\nProcess ID: %u\n", processID);
// Get a list of all the modules in this process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID);
if (hProcess == NULL)
return;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
char szModPathName[MAX_PATH];
// Get the full path to the module's file.
if (GetModuleFileNameEx(hProcess, hMods[i], szModPathName, sizeof(szModPathName)))
{
// Print the module name and handle value.
printf("\t%s (0x%08X)\n", szModPathName, hMods[i]);
}
else
printf("GetModuleFileNameEx() failed!.\n");
}
}
CloseHandle(hProcess);
}
int main()
{
// Get the list of process identifiers.
DWORD aProcesses[2048], cbNeeded, cProcesses;
unsigned int i;
printf("Listing all the process's module...\n");
// If fail...
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
printf("EnumProcesses() failed!.\n");
else
printf("EnumProcesses() is OK!.\n");
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name of the modules for each process.
for (i = 0; i < cProcesses; i++)
PrintModules(aProcesses[i]);
return 0;
}
F:\myproject\myprocess\Debug>myprocess | more
Listing all the process's module...
EnumProcesses() is OK!.
Process ID: 0
Process ID: 4
Process ID: 468
\SystemRoot\System32\smss.exe (0x48580000)
C:\WINDOWS\system32\ntdll.dll (0x7C900000)
Process ID: 528
Process ID: 552
\??\C:\WINDOWS\system32\winlogon.exe (0x01000000)
C:\WINDOWS\system32\ntdll.dll (0x7C900000)
C:\WINDOWS\system32\kernel32.dll (0x7C800000)
[trimmed]
C:\WINDOWS\system32\comdlg32.dll (0x763B0000)
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2180_x-ww_a84f1ff9\comctl32.dll (0x773D0000)
C:\WINDOWS\system32\odbcint.dll (0x20000000)
[trimmed]
C:\WINDOWS\system32\NTDSAPI.dll (0x767A0000)
C:\WINDOWS\system32\DNSAPI.dll (0x76F20000)
Process ID: 596
C:\WINDOWS\system32\services.exe (0x01000000)
C:\WINDOWS\system32\ntdll.dll (0x7C900000)
[trimmed]
C:\WINDOWS\system32\umdmxfrm.dll (0x5B0A0000)
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2180_x-ww_a84f1ff9\comctl32.dll (0x773D0000)
C:\WINDOWS\system32\comctl32.dll (0x5D090000)
C:\WINDOWS\system32\secur32.dll (0x77FE0000)
[trimmed]
C:\WINDOWS\system32\PSAPI.DLL (0x76BF0000)
C:\WINDOWS\system32\wtsapi32.dll (0x76F50000)
Process ID: 608
C:\WINDOWS\system32\lsass.exe (0x01000000)
C:\WINDOWS\system32\ntdll.dll (0x7C900000)
[trimmed]
C:\WINDOWS\system32\umdmxfrm.dll (0x5B0A0000)
C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2180_x-ww_a84f1ff9\comctl32.dll (0x773D0000)
C:\WINDOWS\system32\comctl32.dll (0x5D090000)
C:\WINDOWS\system32\msprivs.dll (0x20000000)
[trimmed]
C:\WINDOWS\system32\pstorsvc.dll (0x743A0000)
C:\WINDOWS\system32\psbase.dll (0x743C0000)
Process ID: 756
C:\WINDOWS\system32\svchost.exe (0x01000000)
C:\WINDOWS\system32\ntdll.dll (0x7C900000)
[trimmed]
C:\WINDOWS\system32\USER32.dll (0x77D40000)
C:\WINDOWS\system32\GDI32.dll (0x77F10000)
-- More --
The output for this example has been trimmed because it is very long. You may redirect it to a text file. The main function obtains a list of processes by using the EnumProcesses() function. For each process, the main function calls the PrintModules() function, passing it the process identifier. PrintModules() in turn calls the OpenProcess() function to obtain the process handle. If OpenProcess() fails, the output shows only the process identifier. For example, OpenProcess() fails for the Idle and CSRSS processes because their access restrictions prevent user-level code from opening them. Next, PrintModules() calls the EnumProcessModules() function to obtain the module handles function. Finally, PrintModules() calls the GetModuleFileNameEx() function, once for each module, to obtain the module names.
The following example obtains a list of modules for the specified process. The ListProcessModules() function takes a snapshot of the modules associated with a given process using the CreateToolhelp32Snapshot() function, and then walks through the list using Module32First() and Module32Next(). The dwPID parameter of ListProcessModules identifies the process for which modules are to be enumerated, and is usually obtained by calling CreateToolhelp32Snapshot() to enumerate the processes running on the system. An example using it is presented in the next program.
A simple error-reporting function, printError(), displays the reason for any failures, which usually result from security restrictions. This example also can be used to list process and thread as demonstrated in the next program example.
// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
// Function prototypes...
BOOL ListProcessModules(DWORD dwPID);
void printError(TCHAR* msg);
int main(int argc, char argv[])
{
// 0 means current process, this program...
ListProcessModules(0);
return 0;
}
BOOL ListProcessModules(DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
printError("CreateToolhelp32Snapshot()");
return (FALSE);
}
// Set the size of the structure before using it.
me32.dwSize = sizeof(MODULEENTRY32);
// Retrieve information about the first module,
// and exit if unsuccessful
printf("\n******************************************\n");
printf("* List of module for current process *\n");
printf("******************************************");
if(!Module32First(hModuleSnap, &me32))
{
printError("Module32First()"); // Show cause of failure
CloseHandle(hModuleSnap); // Must clean up the snapshot object
return (FALSE);
}
// Now walk the module list of the process,
// and display information about each module
do
{
printf("\n\n MODULE NAME: %s", me32.szModule);
printf("\n executable = %s", me32.szExePath);
printf("\n process ID = 0x%08X", me32.th32ProcessID);
printf("\n ref count (g) = 0x%04X", me32.GlblcntUsage);
printf("\n ref count (p) = 0x%04X", me32.ProccntUsage);
printf("\n base address = 0x%08X", (DWORD) me32.modBaseAddr);
printf("\n base size = %d\n", me32.modBaseSize);
} while (Module32Next(hModuleSnap, &me32));
// Do not forget to clean up the snapshot object.
CloseHandle(hModuleSnap);
return (TRUE);
}
void printError(TCHAR* msg)
{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;
eNum = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL);
// Trim the end of the line and terminate it with a null
p = sysMsg;
while ((*p > 31) || (*p == 9))
++p;
do { *p-- = 0; }
while ((p >= sysMsg) && ((*p == '.') || (*p < 33)));
// Display the message...
printf("\n WARNING: %s failed with error %d (%s)\n", msg, eNum, sysMsg);
return 0;
}

Taking a Snapshot and Viewing Processes
The following simple console application obtains a list of running processes. First, the GetProcessList() function takes a snapshot of currently executing processes in the system using CreateToolhelp32Snapshot(), and then it walks through the list recorded in the snapshot using Process32First() and Process32Next(). For each process in turn, GetProcessList() calls the ListProcessModules() function and the ListProcessThreads() function.
A simple error-reporting function, printError(), displays the reason for any failures, which usually result from security restrictions.
// For WinXp
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
// Function prototypes...
BOOL GetProcessList();
BOOL ListProcessModules(DWORD dwPID);
BOOL ListProcessThreads(DWORD dwOwnerPID);
void printError(TCHAR* msg);
int main(int argc, char argv[])
{
GetProcessList();
return 0;
}
// =================Get the processes=====================
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("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
printf("\n\n*********************************");
printf("\nList of process & their info...\n");
printf("*********************************");
if (!Process32First(hProcessSnap, &pe32))
{
printError("Process32First()"); // Show cause of failure
CloseHandle(hProcessSnap); // Must clean up the snapshot object
return (FALSE);
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
printf("\n\n===========================================================");
printf("\nPROCESS NAME: %s", pe32.szExeFile);
printf("\n-----------------------------------------------------------");
// Retrieve the priority class.
dwPriorityClass = 0;
// OpenProcess() with all possible access rights for a process object,
// handle cannot be inherited and Identifier of the process to open...
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if (hProcess == NULL)
printError("OpenProcess()");
else
{
dwPriorityClass = GetPriorityClass(hProcess);
if (!dwPriorityClass)
printError("GetPriorityClass()");
CloseHandle(hProcess);
}
printf("\n Name of the exe = %s", pe32.szExeFile);
printf("\n Parent process ID = 0x%08X", pe32.th32ParentProcessID);
printf("\n Process ID = 0x%08X", pe32.th32ProcessID);
printf("\n Thread count = %d", pe32.cntThreads);
printf("\n Priority Base = %d", pe32.pcPriClassBase);
if(dwPriorityClass)
printf("\n Priority Class = %d", dwPriorityClass);
// List the modules and threads associated with this process
ListProcessModules(pe32.th32ProcessID);
ListProcessThreads(pe32.th32ProcessID);
} while (Process32Next(hProcessSnap, &pe32));
// Don't forget to clean up the snapshot object!
CloseHandle(hProcessSnap);
return (TRUE);
}
// =================List the process modules=====================
BOOL ListProcessModules(DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
// Take a snapshot of all modules in the specified process.
hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
if(hModuleSnap == INVALID_HANDLE_VALUE)
{
printError("CreateToolhelp32Snapshot(of modules)");
return (FALSE);
}
// Set the size of the structure before using it...
me32.dwSize = sizeof(MODULEENTRY32);
// Retrieve information about the first module,
// and exit if unsuccessful
printf("\n\n*****************************************");
printf("\nList of process module & their info...\n");
printf("*****************************************");
if (!Module32First(hModuleSnap, &me32))
{
printError("Module32First()"); // Show cause of failure
CloseHandle(hModuleSnap); // Must clean up the snapshot object
return (FALSE);
}
// Now walk the module list of the process,
// and display information about each module...
do
{
printf("\n\n MODULE NAME: %s", me32.szModule);
printf("\n executable = %s", me32.szExePath);
printf("\n process ID = 0x%08X", me32.th32ProcessID);
printf("\n ref count (g) = 0x%04X", me32.GlblcntUsage);
printf("\n ref count (p) = 0x%04X", me32.ProccntUsage);
printf("\n base address = %p", me32.modBaseAddr);
printf("\n base size = %d", me32.modBaseSize);
} while(Module32Next(hModuleSnap, &me32));
// Don't forget to clean up the snapshot object.
CloseHandle(hModuleSnap);
return (TRUE);
}
// =================List the process threads=====================
BOOL ListProcessThreads(DWORD dwOwnerPID)
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE)
return (FALSE);
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32);
// Retrieve information about the first thread,
// and exit if unsuccessful
printf("\n\n*****************************************");
printf("\nList of process thread & their info...\n");
printf("*****************************************");
if(!Thread32First(hThreadSnap, &te32))
{
printError("Thread32First()"); // Show cause of failure
CloseHandle(hThreadSnap); // Must clean up the snapshot object
return (FALSE);
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if (te32.th32OwnerProcessID == dwOwnerPID)
{
printf("\n\n THREAD ID = 0x%08X", te32.th32ThreadID);
printf("\n base priority = %d", te32.tpBasePri);
printf("\n delta priority = %d", te32.tpDeltaPri);
}
} while (Thread32Next(hThreadSnap, &te32));
// Don't forget to clean up the snapshot object.
CloseHandle(hThreadSnap);