本文是基于Win32 API函数实现遍历进程、遍历线程和遍历进程加载模块等获取系统信息的操作。
需要用到的函数
CreateToolhelp32Snapshot 函数
此函数可以通过获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程建立一个快照。
函数声明
HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
参数
VALUE | 含义 |
---|---|
TH32CS_INHERIT | 指示快照句柄是可继承的 |
TH32CS_SNAPALL | 在快照中包含系统中所有的进程和线程 |
TH32CS_SNAPHEAPLIST | 在快照中包含在th32ProcessID中指定的进程的所有的堆 |
TH32CS_SNAPMODULE | 在快照中包含在th32ProcessID中指定的进程的所有的模块 |
TH32CS_SNAPPROCESS | 在快照中包含系统中所有的进程 |
TH32CS_SNAPTHREAD | 在快照中包含系统中所有的线程 |
th32ProcessID 指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了TH32CS_SNAPHEAPLIST或者TH32CS_SNAPMODULE后才有效,在其他情况下该参数被忽略,所有的进程都会被快照。
返回值
调用成功,返回快照的句柄;调用失败,返回INVALID_HANDLE_VALUE 。
Process32First 和 Process32Next 函数
当我们利用函数CreateToolhelp32Snapshot()获得当前运行所有进程的快照后,我们可以利用Process32First函数来获得第一个进程的句柄,Process32Next函数来获得下一个进程的句柄。
Thread32First 和 Thread32Next 函数
当我们利用函数CreateToolhelp32Snapshot()获得当前运行所有线程的快照后,我们可以利用Thread32First函数来获得第一个线程的句柄,Thread32Next函数来获得下一个线程的句柄。
Module32First 和 Module32Next 函数
当我们利用函数CreateToolhelp32Snapshot()获得指定进程的快照后,我们可以利用Module32First函数来获得进程第一个模块的句柄,Module32Next函数来获得进程下一个模块的句柄。
实现方式
大家可以从上面的函数介绍可以看出,重点理解CreateToolhelp32Snapshot这个函数的操作。我们遍历进程、遍历线程以及遍历进程加载模块等3个操作,都是基于CreateToolhelp32Snapshot函数进行下一步实现的。
对于遍历进程的实现原理是:
首先,使用CreateToolhelp32Snapshot 函数获取所有进程的快照
然后,根据进程快照,使用Process32First 和 Process32Next 函数进行遍历快照,并获取快照信息
最后,关闭上面获取的快照的句柄
对于遍历线程的实现原理是:
首先,使用CreateToolhelp32Snapshot 函数获取所有线程的快照
然后,根据线程快照,使用Thread32First 和 Thread32Next 函数进行遍历快照,并获取快照信息
最后,关闭上面获取的快照的句柄
对于遍历进程模块的实现原理是:
首先,使用CreateToolhelp32Snapshot 函数获取指定进程的所有模块快照。
然后,根据模块快照,使用Module32First 和 Module32Next 函数进行遍历快照,并获取快照信息
最后,关闭上面获取的快照的句柄。
实现代码
遍历进程
BOOL EnumProcess()
{
PROCESSENTRY32 pe32 = { 0 };
pe32.dwSize = sizeof(PROCESSENTRY32);
// 获取全部进程快照
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hProcessSnap)
{
ShowError("CreateToolhelp32Snapshot");
return FALSE;
}
// 获取快照中第一条信息
BOOL bRet = ::Process32First(hProcessSnap, &pe32);
while (bRet)
{
// 显示 Process ID
printf("[%d]\t", pe32.th32ProcessID);
// 显示 进程名称
printf("[%s]\n", pe32.szExeFile);
// 获取快照中下一条信息
bRet = ::Process32Next(hProcessSnap, &pe32);
}
// 关闭句柄
::CloseHandle(hProcessSnap);
return TRUE;
}
遍历线程
BOOL EnumThread()
{
THREADENTRY32 te32 = { 0 };
te32.dwSize = sizeof(THREADENTRY32);
// 获取全部线程快照
HANDLE hThreadSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (INVALID_HANDLE_VALUE == hThreadSnap)
{
ShowError("CreateToolhelp32Snapshot");
return FALSE;
}
// 获取快照中第一条信息
BOOL bRet = ::Thread32First(hThreadSnap, &te32);
while (bRet)
{
// 显示 Owner Process ID
printf("[%d]\t", te32.th32OwnerProcessID);
// 显示 Thread ID
printf("[%d]\n", te32.th32ThreadID);
// 获取快照中下一条信息
bRet = ::Thread32Next(hThreadSnap, &te32);
}
// 关闭句柄
::CloseHandle(hThreadSnap);
return TRUE;
}
遍历指定进程模块
BOOL EnumProcessModule(DWORD dwProcessId)
{
MODULEENTRY32 me32 = { 0 };
me32.dwSize = sizeof(MODULEENTRY32);
// 获取指定进程全部模块的快照
HANDLE hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if (INVALID_HANDLE_VALUE == hModuleSnap)
{
ShowError("CreateToolhelp32Snapshot");
return FALSE;
}
// 获取快照中第一条信息
BOOL bRet = ::Module32First(hModuleSnap, &me32);
while (bRet)
{
// 显示 Process ID
printf("[%d]\t", me32.th32ProcessID);
// 显示 模块加载基址
printf("[0x%p]\t", me32.modBaseAddr);
// 显示 模块名称
printf("[%s]\n", me32.szModule);
// 获取快照中下一条信息
bRet = ::Module32Next(hModuleSnap, &me32);
}
// 关闭句柄
::CloseHandle(hModuleSnap);
return TRUE;
}
主程序
int _tmain(int argc, _TCHAR* argv[])
{
// 遍历进程
if (FALSE == EnumProcess())
{
printf("Enum Process Error!\n");
}
system("pause");
system("cls");
// 遍历线程
if (FALSE == EnumThread())
{
printf("Enum Thread Error!\n");
}
system("pause");
system("cls");
// 遍历指定进程模块
if (FALSE == EnumProcessModule(6876))
{
printf("Enum Process Module Error!\n");
}
system("pause");
return 0;
}