• C/C++ 遍历进程内存块


    期待的效果就像 PCHuntor 里的那样,如下:

    上代码

    #include "stdafx.h"
    #include <Windows.h>
    #include <vector>
    #include <iostream>
    #include <assert.h>
    #include <psapi.h>
    #include <tlhelp32.h>
    
    using namespace std; 
    
    /*枚举指定进程所有内存块
    assert(hProcess != nullptr);
    参数:
      hProcess:  要枚举的进程,需拥有PROCESS_QUERY_INFORMATION权限
      memories:  返回枚举到的内存块数组
    返回:
      成功返回true,失败返回false.
    */
    static bool EnumAllMemoryBlocks(HANDLE hProcess, OUT vector<MEMORY_BASIC_INFORMATION>& memories){
    	// 如果 hProcess 为空则结束运行
    	assert(hProcess != nullptr);
    
    	// 初始化 vector 容量
    	memories.clear();
    	memories.reserve(200);
    
    	// 获取 PageSize 和地址粒度
    	SYSTEM_INFO sysInfo = { 0 };
    	GetSystemInfo(&sysInfo);
    	/*
    		typedef struct _SYSTEM_INFO {
    		  union {
    			DWORD dwOemId;							// 兼容性保留
    			struct {
    			  WORD wProcessorArchitecture;			// 操作系统处理器体系结构
    			  WORD wReserved;						// 保留
    			} DUMMYSTRUCTNAME;
    		  } DUMMYUNIONNAME;
    		  DWORD     dwPageSize;						// 页面大小和页面保护和承诺的粒度
    		  LPVOID    lpMinimumApplicationAddress;	// 指向应用程序和dll可访问的最低内存地址的指针
    		  LPVOID    lpMaximumApplicationAddress;	// 指向应用程序和dll可访问的最高内存地址的指针
    		  DWORD_PTR dwActiveProcessorMask;			// 处理器掩码
    		  DWORD     dwNumberOfProcessors;			// 当前组中逻辑处理器的数量
    		  DWORD     dwProcessorType;				// 处理器类型,兼容性保留
    		  DWORD     dwAllocationGranularity;		// 虚拟内存的起始地址的粒度
    		  WORD      wProcessorLevel;				// 处理器级别
    		  WORD      wProcessorRevision;				// 处理器修订
    		} SYSTEM_INFO, *LPSYSTEM_INFO;
    	*/
    
    	//遍历内存
    	const char* p = (const char*)sysInfo.lpMinimumApplicationAddress;
    	MEMORY_BASIC_INFORMATION  memInfo = { 0 };
    	while (p < sysInfo.lpMaximumApplicationAddress){
    		// 获取进程虚拟内存块缓冲区字节数
    		size_t size = VirtualQueryEx(
    			hProcess,								// 进程句柄
    			p,										// 要查询内存块的基地址指针
    			&memInfo,								// 接收内存块信息的 MEMORY_BASIC_INFORMATION 对象
    			sizeof(MEMORY_BASIC_INFORMATION32)		// 缓冲区大小
    			);
    		if (size != sizeof(MEMORY_BASIC_INFORMATION32)){break;}
    			
    		// 将内存块信息追加到 vector 数组尾部
    		memories.push_back(memInfo);
    
    		// 移动指针
    		p += memInfo.RegionSize;
    	}
    
    	return memories.size() > 0;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);		// 进程快照句柄
    	PROCESSENTRY32 process = {sizeof(PROCESSENTRY32)};							// 接收进程信息的对象
    	vector<MEMORY_BASIC_INFORMATION> vec;										// 存放进程内存块的数组
    	/*
    		typedef struct _MEMORY_BASIC_INFORMATION {
    		  PVOID  BaseAddress;			// 内存块基地址指针
    		  PVOID  AllocationBase;		// VirtualAlloc 函数分配的基地址指针
    		  DWORD  AllocationProtect;		// 内存块初始内存保护属性
    		  SIZE_T RegionSize;			// 内存块大小
    		  DWORD  State;					// 内存块状态(COMMIT、FREE、RESERVE)
    		  DWORD  Protect;				// 内存块当前内存保护属性
    		  DWORD  Type;					// 内存块类型(IMAGE、MAPPED、PRIVATE)
    		} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
    	*/
    
    	// 遍历进程
    	while (Process32Next(hProcessSnap,&process)){
    		// 找到想要的进程
    		if(strcmp(process.szExeFile,"rundll32.exe") == 0){
    			// 获取进程句柄
    			HANDLE h_rundll32 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
    			if(!h_rundll32){cout << "OpenProcess failed." << endl;}
    
    			// 遍历该进程的内存块
    			if(EnumAllMemoryBlocks(h_rundll32,vec)){
    				for(int i=0;i<vec.size();i++){
    					// 输出
    					cout << "BaseAddress:" << vec[i].BaseAddress << endl;
    					cout << "AllocationBase:" << vec[i].AllocationBase << endl;
    					cout << "AllocationProtect:" << vec[i].AllocationProtect << endl;
    					cout << "RegionSize:" << vec[i].RegionSize << endl;
    					cout << "State:" << vec[i].State << endl;
    					cout << "Protect:" << vec[i].Protect << endl;
    					cout << "Type:" << hex << vec[i].Type << endl;
    					cout << "----------------------------------" << endl;
    				}
    			}else{cout << "EnumAllMemoryBlocks failed." << endl;}
    		}
    	}
    	
    	getchar();
    	return 0;
    }
    

    效果图:


    版权声明: 本博客,文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!

    警告:如果您恶意转载本人文章,则您的整站文章,将会变为我的原创作品,请相互尊重!
  • 相关阅读:
    哨兵模式(工作中使用)
    JVM调优-考虑方向
    Spring Cloud Gateway+Nacos出现服务乱串的问题记录
    golang笔记-cache组件应用: freecache/groupcache/golang-lru
    C++优化笔记: -O2/-O3/-ffast-math/SIMD
    linux笔记-查看L1/L2/L3 cache大小
    Dom4j 如何输出 Document 中的内容到文本
    是应该是用 Log 还是 Logger 来定义 Log
    IntelliJ IDEA 如何针对Java 代码快速打印 println
    如何用 Java 判断一个给定的数是不是素数
  • 原文地址:https://www.cnblogs.com/LyShark/p/15020090.html
Copyright © 2020-2023  润新知