【API】遍历进程的几种方式
1、说明
枚举进程的常见几种方法
方法1:CreateToolhelp32Snapshot()、Process32First()和Process32Next()
方法2:EnumProcesses()、EnumProcessModules()、GetModuleBaseName()
方法3:Native Api的ZwQuerySystemInformation
方法4:wtsapi32.dll的WTSOpenServer()、WTSEnumerateProcess()
CreateToolhelp32Snapshot()、Process32First()和Process32Next()
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <TlHelp32.h>
int main()
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE hProcessSanp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSanp == INVALID_HANDLE_VALUE)
{
printf("Error Get the Process SnapShot\n");
return -1;
}
BOOL bMore = Process32First(hProcessSanp, &pe32);
while (bMore)
{
printf("Process Name: %s\t\tProcess ID: %d\n", pe32.szExeFile, pe32.th32ProcessID);
bMore = Process32Next(hProcessSanp, &pe32);
}
CloseHandle(hProcessSanp);
getchar();
return 0;
}
EnumProcesses()、EnumProcessModules()、GetModuleBaseName()
#include "stdafx.h"
#include <windows.h>
#include "psapi.h"
#pragma comment (lib, "psapi.lib ")
void MyEnumProcess()
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) //枚举进程
return;
cProcesses = cbNeeded / sizeof(DWORD); //计算进程个数
for (i = 0; i < cProcesses; i++)
if (aProcesses[i] != 0)
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]); //获得进程句柄
if (NULL != hProcess)
{
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) //枚举进程模块信息
{
GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR)); //取得主模块全名,每个进程第一模块则为进程主模块
}
}
_tprintf(TEXT("%s (PID: %u)\n"), szProcessName, aProcesses[i]); //输出进程名及PID
CloseHandle(hProcess);
}
}
void main()
{
MyEnumProcess();
system("pause");
}
Native Api的ZwQuerySystemInformation
#include <ntddk.h>
#define SystemProcessesAndThreadsInformation 5
typedef struct _SYSTEM_PROCESSES
{
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2[2];
VM_COUNTERS VmCounters;
IO_COUNTERS IoCounters;
} _SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
NTSTATUS EnumSystemProcess( );
NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);
NTSTATUS status = STATUS_SUCCESS;
status = EnumSystemProcess( );
return status;
}
NTSTATUS EnumSystemProcess( )
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
*pRet = FALSE;
PSYSTEM_PROCESSES pProcessInfo = NULL;
PSYSTEM_PROCESSES pTemp = NULL;//这个留作以后释放指针的时候用。
ULONG ulNeededSize;
ULONG ulNextOffset;
if (NULL == pProcess)
{
return status;
}
//第一次使用肯定是缓冲区不够,不过本人在极少数的情况下第二次也会出现不够,所以用while循环
status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation , pProcessInfo, 0, &ulNeededSize);
while (STATUS_INFO_LENGTH_MISMATCH == status)
{
pProcessInfo = ExAllocatePoolWithTag(NonPagedPool, ulNeededSize, ‘1aes‘);
pTemp = pProcessInfo;
if (NULL == pProcessInfo)
{
KdPrint(("[allocatePoolWithTag] failed"));
return status;
}
status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation , pProcessInfo, ulNeededSize, &ulNeededSize);
}
if (NT_SUCCESS(status))
{
KdPrint(("[ZwQuerySystemInformation]success bufferSize:%x", ulNeededSize));
}
else
{
KdPrint(("[error]:++++%d", status));
return status;
}
do
{
KdPrint(("[imageName Buffer]:%08x", pProcessInfo->ProcessName.Buffer));
if (MmIsAddressValid(pProcessInfo->ProcessName.Buffer) && NULL != pProcessInfo)
{
KdPrint(("[ProcessID]:%d , [imageName]:%ws", pProcessInfo->ProcessId, pProcessInfo->ProcessName.Buffer));
}
ulNextOffset = pProcessInfo->NextEntryDelta;
pProcessInfo = (PSYSTEM_PROCESSES)((PUCHAR)pProcessInfo + pProcessInfo->NextEntryDelta);
} while (ulNextOffset != 0);
ExFreePoolWithTag(pTemp, ‘1aes‘);
return status;
}
wtsapi32.dll的WTSOpenServer()、WTSEnumerateProcess()
// WTSOpenServer.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <Wtsapi32.h>
#pragma comment (lib,"Wtsapi32.lib")
int main()
{
//WCHAR* szServerName = L""; //win10 不需要
WCHAR * szServerName = NULL;
HANDLE WtsServerHandle = WTSOpenServer(szServerName);
// 然后开始遍历终端服务器上的所有进程,这里我们是指本机的所有进程.
PWTS_PROCESS_INFO pWtspi;
DWORD dwCount;
if (!WTSEnumerateProcesses(WtsServerHandle, 0, 1, &pWtspi, &dwCount))
{
int a = GetLastError();
return 0;
}
for (DWORD i = 0; i < dwCount; i++)
{
printf("ProcessID: %d (%ls)\n", pWtspi[i].ProcessId,
pWtspi[i].pProcessName);
}
getchar();
}
2、参考
利用服务枚举进程
https://www.cnblogs.com/kekoukele987/p/7503004.html
ZwQuerySystemInformation function
https://docs.microsoft.com/en-us/windows/desktop/SysInfo/zwquerysysteminformation