枚举进程再来两弹
看了刚出几个博友的博客,感觉人家的量大,详细,干货量实足啊,
所以我就把另外两种常见的枚举进程的方法简单说下心得,
一个是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; }