首页 > 代码库 > 枚举进程再来两弹

枚举进程再来两弹

  看了刚出几个博友的博客,感觉人家的量大,详细,干货量实足啊,

所以我就把另外两种常见的枚举进程的方法简单说下心得,

一个是EnumProcesses和CreateToolhelp32Snapshot系列的Tool help API的 Process32First和Process32Next函数完成列举进程。

 这两种都是比较简单实用的 https://github.com/Arsense/WindowsCode

  蛮简单的  需要编译好的源码的 支持vs2015,低版本的VS想编译 简单右键工程 属性设置下低版本的编译器就行,如下

技术分享

 

0x01 基本思路

 有两种方法  第一种方法调用EnumProcesses遍历进程,

并调用ListProcessModules1函数和

ListProcessThreads函数列举模块和线程

 

调用Process32First和Process32Next遍历进程,

并调用ListProcessModules2函数列举模块,

调用ShowProcessMemoryInfo函数显示内存使用情况

 

细微的区别是 EnumProcesses 可以一次性列举所有进程(以PID的形式返回),但是没有

Process32First 和 Process32Next获取的信息丰富

 

 

0x02 代码流程

    本实例是使用EnumProcesses函数获取所有进程的PID,然后使用OpenProcess、函数

各进程的句柄,然后获取相关信息

 

 

* 功能    调用EnumProcesses遍历进程,
*        并调用ListProcessModules1函数和
*        ListProcessThreads函数列举模块和线程
*
* 无参数,无返回值
**************************************/
VOID WINAPI EnumProcess1()
{
    // 假设不超过1024个进程
    DWORD aProcesses[1024], cbNeeded, cProcesses;
    unsigned int i;
    // 调用EnumProcesses
    if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
        return;
    // 进程数
    cProcesses = cbNeeded / sizeof(DWORD);
    for ( i = 0; i < cProcesses; i++ )
    {
        // 显示进程信息
        printf( "\n\n**************************************************" );
        printf("\nPROCESS : %u\n\n",aProcesses[i]);
        printf( "\n****************************************************" );
        // 列举模块信息和线程信息
        ListProcessModules1( aProcesses[i] );
        ListProcessThreads( aProcesses[i] );
    }
}

 

      而CreateToolhelp32Snapshot函数通过获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD]建立一个快照

0x03  使用 PSAPI 库枚举进程  这两个都是这个库里面的
在 Windows NT 中,创建进程列表使用 PSAPI 函数,这些函数在 PSAPI.DLL 中。这个文件是随 Platform SDK 一起分发的:

使用这个库所需的 PSAPI.h 和 PSAPI.lib 文件也在该 Platform SDK 中。
为了使用 PSAPI 库中的函数,需将 PSAPI.lib 添加到代码项目中,同时在所有调用 PSAPI API 的模块中包含 PSAPI.h 文件。记住一定要随可执行文件一起分发 PSAPI.DLL,因为它不随 Windows NT 一起分发。

主要的代码实现如下

  

#include<stdio.h>
#include<psapi.h>
#pragma comment(lib,"psapi.lib")

int main()
{
    //进程结构
    PROCESSENTRY32 Pe32;  
    //用之前要知道大小
    Pe32.dwSize = sizeof(Pe32);
    //创建进程快照
    HANDLE ProcessSnapHandle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,
        0);
    HANDLE ModuleSnapHandle = NULL;
    if (ProcessSnapHandle == INVALID_HANDLE_VALUE)
    {
        printf("[-]ProcessSnapHandle Error!\r\n");
        int Error = GetLastError();
        printf("Error is : %d\r\n", Error);
        return -1;
    }
    BOOL NextProcess = Process32First(ProcessSnapHandle,&Pe32);

    HANDLE ProcessHandle = 0;
    WCHAR ProcessPath[MAX_PATH] = { 0 };
    MODULEENTRY32 pModule;  //模块的结构

    pModule.dwSize = sizeof(MODULEENTRY32);
    BOOL Return = FALSE;
    //准备好了  开始遍历
    while (NextProcess)
    {
        //先打开进程对象得到句柄
        ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pe32.th32ParentProcessID);
        //得到模块的路径
        GetModuleFileNameEx(ProcessHandle, NULL, ProcessPath, _MAX_PATH);
        wprintf(_T("ProcessPath:%s\n ProcessName : %s\t\t ProcessID : %d\n\n"), ProcessPath, Pe32.szExeFile, Pe32.th32ProcessID);

        //创建模块的快照
        ModuleSnapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
            Pe32.th32ProcessID);

        Return = Module32First(ModuleSnapHandle, &pModule);

        while (Return)
        {
            //枚举输出
            wprintf(_T("\t\tModual:%s\tBase:%2x\n"), pModule.szExePath, pModule.modBaseAddr);
            Return = ::Module32Next(ModuleSnapHandle, &pModule);

        }

        CloseHandle(ModuleSnapHandle);
        NextProcess = Process32Next(ProcessSnapHandle, &Pe32);
    }
    CloseHandle(ProcessSnapHandle);
    return 0;
}

 

枚举进程再来两弹