【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

posted @ 2018-10-11 09:21  17bdw  阅读(3168)  评论(0编辑  收藏  举报