1. 程式人生 > 其它 >C/C++ 遍歷程序記憶體塊

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;
}

效果圖:

文章出處:https://www.cnblogs.com/lyshark
許可協議: 文章中的程式碼均為學習時整理的筆記,部落格中除去明確標註有參考文獻的文章,其他文章【均為原創】作品,轉載請務必【添加出處】,您添加出處是我創作的動力!

防惡意轉載:如果發現您在轉載時,沒有新增本人部落格連結,本人將通過爬蟲批量爬取您部落格中所有內容,打上本人原創版權水印,並進行二次發行,請相互尊重,你尊重我的勞動成果,我才會尊重你。