【API】遍历进程的几种方式

本文详细介绍了四种常见的枚举进程的方法,包括使用CreateToolhelp32Snapshot()、Process32First()和Process32Next();EnumProcesses()、EnumProcessModules()、GetModuleBaseName();NativeApi的ZwQuerySystemInformation;以及wtsapi32.dll的WTSOpenServer()、WTSEnumerateProcess()。每种方法均附带了具体的代码示例,帮助读者深入理解并掌握进程枚举的技术细节。

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

转载于:https://www.cnblogs.com/17bdw/p/9770602.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值