Windows編程_Lesson008_內存_內存修改器

###內存修改器
修改指定進程名字中的內存

####單線程版本

#include <Windows.h>
#include <stdio.h>
#include <vector>


// 第一次查找
void FirstFind(HANDLE hProcess, BYTE *pBuffer, DWORD dwPageSize, DWORD dwVal, std::vector<DWORD> &vecAddr)
{
	DWORD dwOneGB = 1024 * 1024 * 1024;
	for (DWORD dwBaseAddr = 0; dwBaseAddr < dwOneGB*2; dwBaseAddr += dwPageSize)
	{
		// 讀取一頁大小的內存空間
		if (ReadProcessMemory(hProcess, (LPCVOID)dwBaseAddr, pBuffer, dwPageSize, nullptr))
		{
			// 從一頁地址中查找相等的值,並記錄
			DWORD *pdw = nullptr;
			for (DWORD i = 0; i < dwPageSize - 3; ++i)
			{
				pdw = (DWORD *)&pBuffer[i];
				if (pdw[0] == dwVal)
				{
					vecAddr.push_back(dwBaseAddr + i);
				}
			}
		}
	}
}

// 下一次查找
void NextFind(HANDLE hProcess, DWORD dwPageSize, DWORD dwVal, std::vector<DWORD> &vecAddr)
{
	DWORD dwCount = 0;
	DWORD dwSize = vecAddr.size();
	DWORD dwReadVal = 0;
	for (DWORD i=0; i<dwSize; ++i)
	{
		if (ReadProcessMemory(hProcess, (LPCVOID)vecAddr[i], &dwReadVal, sizeof(DWORD), nullptr))
		{
			if (dwReadVal == dwVal)
			{
				vecAddr[dwCount++] = vecAddr[i];
			}
		}
	}
	vecAddr.resize(dwCount);
}


int main()
{
	do
	{
		// 查找窗口
		printf("Please input the process name:");
		char strProcessName[MAXBYTE] = { 0 };
		gets_s(strProcessName, MAXBYTE);
		HWND hWnd = FindWindowA(nullptr, strProcessName);
		//HWND hWnd = FindWindowW(nullptr, L"Plants vs. Zombies 1.2.0.1073 RELEASE");
		if (hWnd == nullptr)
		{
			printf("the handle of window do not found!");
			break;
		}

		// 根據窗口句柄查找進程ID
		DWORD dwProcessId = 0;
		GetWindowThreadProcessId(hWnd, &dwProcessId);
		if (dwProcessId == NULL)
		{
			printf("process Id do not found!");
			break;
		}

		// 打開進程
		HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
		if (hProcess == nullptr)
		{
			printf("open the process failed!");
			break;
		}

		// 在讀取內存的時候,最好以頁的大小爲單位,這樣可以提高讀取效率,獲取頁面大小
		SYSTEM_INFO system_info = { 0 };
		GetSystemInfo(&system_info);
		DWORD dwPageSize = system_info.dwPageSize;
		// 判斷是否是32位程序運行在64位操作系統下面,以便於確定起始地址,如果是的話,輸出值爲TRUE,其餘情況都爲FALSE
		// 在這裏無論是32位系統還是64位系統,它們的起始地址都是0x10000,所以起始地址就固定了,但是對於結束地址,這裏就
		// 按照32位查找了,因爲64位的太大了,所以暫時沒有必要判斷多少位系統
		//BOOL bWow64 = FALSE;
		//IsWow64Process(hProcess, &bWow64);
		//if (bWow64)
		//{
		//	
		//}
		
		BYTE *pByte = new BYTE[dwPageSize];
		memset(pByte, 0, dwPageSize * sizeof(BYTE));
		// 定義一個vector
		std::vector<DWORD> vecAddr;

		DWORD dwVal = 0;
		printf("The value to find:");
		scanf_s("%d", &dwVal);

		DWORD dwPrevTime = GetTickCount();
		FirstFind(hProcess, pByte, dwPageSize, dwVal, vecAddr);
		printf("The first find used time:%d ms\r\n", GetTickCount() - dwPrevTime);

		while (vecAddr.size() > 1)
		{
			printf("The value to find:");
			scanf_s("%d", &dwVal);
			NextFind(hProcess, dwPageSize, dwVal, vecAddr);
		}

		printf("The value to modify:");
		scanf_s("%d", &dwVal);
		WriteProcessMemory(hProcess, (LPVOID)vecAddr[0], &dwVal, sizeof(DWORD), nullptr);
	}
	while (false);

	system("pause");
	return 0;
}

####多線程版本

#include <Windows.h>
#include <stdio.h>
#include <vector>
#include <process.h>

typedef struct _tagParam
{
	DWORD dwPageSize;
	DWORD dwStartAddr;
	DWORD dwEndAddr;
	DWORD dwFindVal;
	HANDLE hProcess;
	std::vector<DWORD> vecAddr;
}Param;

unsigned int __stdcall ThreadFunc(void *lParam)
{
	Param *pParam = (Param *)lParam;
	BYTE *pByte = new BYTE[pParam->dwPageSize];
	for (DWORD dwStartAddr=pParam->dwStartAddr; dwStartAddr<pParam->dwEndAddr; dwStartAddr+=pParam->dwPageSize)
	{
		if (ReadProcessMemory(pParam->hProcess, (LPCVOID)dwStartAddr, pByte, pParam->dwPageSize, nullptr))
		{
			DWORD *pDword = nullptr;
			for (DWORD i=0; i<pParam->dwPageSize-3; ++i)
			{
				pDword = (DWORD *)&pByte[i];
				if (pDword[0] == pParam->dwFindVal)
				{
					pParam->vecAddr.push_back(dwStartAddr + i);
				}
			}
		}
	}

	delete[] pByte;
	return 0;
}

// 第一次查找
void FirstFind(HANDLE hProcess, BYTE *pBuffer, DWORD dwPageSize, DWORD dwVal, std::vector<DWORD> &vecAddr)
{
	DWORD dwOneGB = 1024 * 1024 * 1024;
	for (DWORD dwBaseAddr = 0; dwBaseAddr < dwOneGB*2; dwBaseAddr += dwPageSize)
	{
		// 讀取一頁大小的內存空間
		if (ReadProcessMemory(hProcess, (LPCVOID)dwBaseAddr, pBuffer, dwPageSize, nullptr))
		{
			// 從一頁地址中查找相等的值,並記錄
			DWORD *pdw = nullptr;
			for (DWORD i = 0; i < dwPageSize - 3; ++i)
			{
				pdw = (DWORD *)&pBuffer[i];
				if (pdw[0] == dwVal)
				{
					vecAddr.push_back(dwBaseAddr + i);
				}
			}
		}
	}
}

// 下一次查找
void NextFind(HANDLE hProcess, DWORD dwPageSize, DWORD dwVal, std::vector<DWORD> &vecAddr)
{
	DWORD dwCount = 0;
	DWORD dwSize = vecAddr.size();
	DWORD dwReadVal = 0;
	for (DWORD i=0; i<dwSize; ++i)
	{
		if (ReadProcessMemory(hProcess, (LPCVOID)vecAddr[i], &dwReadVal, sizeof(DWORD), nullptr))
		{
			if (dwReadVal == dwVal)
			{
				vecAddr[dwCount++] = vecAddr[i];
			}
		}
	}
	vecAddr.resize(dwCount);
}

int main()
{
	do
	{
		// 查找窗口
		printf("Please input the process name:");
		char strProcessName[MAXBYTE] = { 0 };
		gets_s(strProcessName, MAXBYTE);
		HWND hWnd = FindWindowA(nullptr, strProcessName);
		//HWND hWnd = FindWindowW(nullptr, L"Plants vs. Zombies 1.2.0.1073 RELEASE");
		if (hWnd == nullptr)
		{
			printf("the handle of window do not found!");
			break;
		}

		// 根據窗口句柄查找進程ID
		DWORD dwProcessId = 0;
		GetWindowThreadProcessId(hWnd, &dwProcessId);
		if (dwProcessId == NULL)
		{
			printf("process Id do not found!");
			break;
		}
		// 打開進程
		HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
		if (hProcess == nullptr)
		{
			printf("open the process failed!");
			break;
		}
		// 在讀取內存的時候,最好以頁的大小爲單位,這樣可以提高讀取效率,獲取頁面大小
		SYSTEM_INFO system_info = { 0 };
		GetSystemInfo(&system_info);
		
		DWORD dwThreadCount = system_info.dwNumberOfProcessors;

		BYTE *pByte = new BYTE[system_info.dwPageSize];
		memset(pByte, 0, system_info.dwPageSize * sizeof(BYTE));
		// 定義一個vector
		std::vector<DWORD> vecAddr;

		DWORD dwVal = 0;
		printf("The value to find:");
		scanf_s("%d", &dwVal);

		DWORD dwPrevTime = GetTickCount();
		//FirstFind(hProcess, pByte, dwPageSize, dwVal, vecAddr);
		
		DWORD dwStartAddr = 0;
		DWORD dwOneGB = 1024 * 1024 * 1024;
		DWORD dwSizePerThread = 16 * 1024 * 1024;	// 每個線程讀取16MB的空間
		HANDLE *hThreads = new HANDLE[system_info.dwNumberOfProcessors];
		Param *pParams = new Param[system_info.dwNumberOfProcessors];

		for (DWORD i = 0; i < system_info.dwNumberOfProcessors; ++i)
		{
			pParams[i].dwStartAddr = dwStartAddr;
			dwStartAddr += dwSizePerThread;
			pParams[i].dwEndAddr = dwStartAddr;
			pParams[i].hProcess = hProcess;
			pParams[i].dwPageSize = system_info.dwPageSize;
			pParams[i].dwFindVal = dwVal;
			pParams[i].vecAddr.clear();
			hThreads[i] = (HANDLE)_beginthreadex(nullptr, 0, ThreadFunc, &pParams[i], 0, nullptr);
		}

		for (; dwStartAddr<dwOneGB*2; )
		{
			DWORD dwRet = WaitForMultipleObjects(system_info.dwNumberOfProcessors, hThreads, FALSE, INFINITE);
			pParams[dwRet].dwStartAddr = dwStartAddr;
			dwStartAddr += dwSizePerThread;
			pParams[dwRet].dwEndAddr = dwStartAddr;
			for (DWORD i=0; i<pParams[dwRet].vecAddr.size(); ++i)
			{
				vecAddr.push_back(pParams[dwRet].vecAddr[i]);
			}
			pParams[dwRet].vecAddr.clear();
			hThreads[dwRet] = (HANDLE)_beginthreadex(nullptr, 0, ThreadFunc, &pParams[dwRet], 0, nullptr);
		}
		WaitForMultipleObjects(system_info.dwNumberOfProcessors, hThreads, TRUE, INFINITE);

		printf("The first find used time:%d ms\r\n", GetTickCount() - dwPrevTime);

		while (vecAddr.size() > 1)
		{
			printf("The value to find:");
			scanf_s("%d", &dwVal);
			NextFind(hProcess, system_info.dwPageSize, dwVal, vecAddr);
		}

		printf("The value to modify:");
		scanf_s("%d", &dwVal);
		WriteProcessMemory(hProcess, (LPVOID)vecAddr[0], &dwVal, sizeof(DWORD), nullptr);

		delete[] pByte;
	}
	while (false);

	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章