简单游戏内存修改器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WUDAIJUN/article/details/8721916
     本实例通过对进程内存的查询和修改来实现简单内存修改器功能
     
     点击选择打开进程列表 选择目标进程:
     
     选择进程后,输入查找值,点击首次查找:
     
          在出现的一系列满足条件地址中,如果无法识别要修改的地址,则可以在目标值变化后,跟踪查询该值。如在Mine.exe中,等剩余雷提示到39时,再输入39,点击累计查询:
        
          此时出现唯一确定的地址值。选中该地址值,输入修改值,即可完成修改,之后将扫雷最小最大化一次(重绘),即可看到修改值:
        



     实现也比较简单:
  • 在用户选择进程后,用VirtualQueryEx查询目标进程区域块信息,并将所有区域块信息放入一个链表list<MEMORY_BASIC_INFORMATION> m_listMbi中。
BOOL CVMHelp::GetVMInfoList(DWORD dwProcessId)
{
	m_listMbi.clear();

	//打开目标进程
	HANDLE hProcess = INVALID_HANDLE_VALUE;
	if (dwProcessId != GetCurrentProcessId())
	{
		hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId);
		if (hProcess == NULL)
			return FALSE;
	}

	//查询区域块
	MEMORY_BASIC_INFORMATION mbi;
	DWORD size = sizeof(mbi);
	DWORD dwCurAddr = (DWORD)m_sysInfo.lpMinimumApplicationAddress;
	for (; dwCurAddr<(DWORD)m_sysInfo.lpMaximumApplicationAddress; )
	{
		VirtualQueryEx(hProcess, (LPCVOID)dwCurAddr, &mbi, size);
		m_listMbi.push_back(mbi);
		dwCurAddr += mbi.RegionSize;
	}
	CloseHandle(hProcess);
	return TRUE;
}

  • 在用户点击首次查找时,在m_listMbi中的每一个为提交状态(MEM_COMMIT)的区域块中用ReadProcessMemory不断读出一页数据,并在该页数据中逐个查找该DWORD值,如果找到,则将该地址加入另一个list<DWORD> m_listAddr中。
//第一次搜索 在m_listMbi中进行
UINT CVMHelp::VM_FirstSearch(DWORD dwProcessId, DWORD dwValue)
{
	//必要清空和检测
	if (m_listMbi.empty())
		return -1;
	m_listAddr.clear();

	//打开目标进程
	HANDLE hProcess = INVALID_HANDLE_VALUE;
	if(dwProcessId != GetCurrentProcessId())
	{
		hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId);
		if(NULL == hProcess)
			return -1;
	}

	//遍历m_listMbi 地址空间区域信息列表
	PBYTE pPageBuf = new BYTE[m_sysInfo.dwPageSize];
	list<MEMORY_BASIC_INFORMATION>::iterator iter = m_listMbi.begin();
	for (; iter!=m_listMbi.end(); iter++)
	{
		//只检测提交状态的区域
		if (iter->State != MEM_COMMIT)
			continue;
		
		DWORD dwReadBytes, dwSize=0;
		LPVOID lpAddr;
		//不断从区域中读取一页数据
		while(dwSize < iter->RegionSize)
		{
			lpAddr = (LPVOID)((DWORD)iter->BaseAddress+dwSize);
			if (FALSE == ReadProcessMemory(hProcess, lpAddr, pPageBuf, m_sysInfo.dwPageSize, &dwReadBytes))
			{
				dwSize += m_sysInfo.dwPageSize;
				continue;
			}
	
			//对该页数据进行逐个分析比较 如果等于目标值 则存入m_listAddr
			for (int i=0; i<=m_sysInfo.dwPageSize-3; i++)
			{
				if (*(DWORD*)(pPageBuf+i) == dwValue)
					m_listAddr.push_back((DWORD)lpAddr+i);

			}
			dwSize += m_sysInfo.dwPageSize;
		}
		if(m_listAddr.size() > MAX_ADDR_NUM)
			break;
	}
	CloseHandle(hProcess);
	delete []pPageBuf;

	return m_listAddr.size();
}

  • 如果用户点击累计查找,那么查找将在m_listAddr中进行,用ReadProcessMemory读出sizeof(DWORD)字节,将不等于新查询值的地址给删掉。累计查找可以进行多次。
//累计查找 在m_listAddr中进行
UINT CVMHelp::VM_ReSearch(DWORD dwProcessId, DWORD dwValue)
{
	if(m_listAddr.empty())
		return -1;

	//打开目标进程
	HANDLE hProcess = INVALID_HANDLE_VALUE;
	if (dwProcessId != GetCurrentProcessId())
	{
		hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId);
		if(hProcess == NULL)
			return -1;
	}

	//遍历m_listAddr:之前搜索匹配地址表
	DWORD dwReadBytes, dwCurValue;
	list<DWORD>::iterator iterTemp, iter = m_listAddr.begin();
	for (; iter!=m_listAddr.end();)
	{
		ReadProcessMemory(hProcess, (LPVOID)*iter, &dwCurValue, sizeof(DWORD), &dwReadBytes);
		iterTemp = iter++;
		if (dwCurValue != dwValue)	//移除不再与目标值相等的地址	
			m_listAddr.erase(iterTemp);
	}
	CloseHandle(hProcess);
	return m_listAddr.size();
}

  • 当用户点击修改时,用VirtualProtectEx修改目标进程该地址处的读写权限,用WriteProcessMemory修改该地址上的值,最后再用VirtualProtectEx恢复原来的读写保护。
//修改目标地址值
BOOL CVMHelp::VM_Modify(DWORD dwProcessId, DWORD dwTagAddr, DWORD dwValue)
{
	HANDLE hProcess = INVALID_HANDLE_VALUE;
	if (dwProcessId != GetCurrentProcessId())
	{
		hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
		if(hProcess == NULL)
			return FALSE;
	}

	DWORD dwOldProtect;
	DWORD dwWriteBytes;

	//修改虚拟地址读写权限
	VirtualProtectEx(hProcess, (LPVOID)dwTagAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
	//写入数据
	WriteProcessMemory(hProcess, (LPVOID)dwTagAddr, &dwValue, sizeof(DWORD), &dwWriteBytes);
	//改回该地址保护方式
	VirtualProtectEx(hProcess, (LPVOID)dwTagAddr, sizeof(DWORD), dwOldProtect, NULL);

	CloseHandle(hProcess);

	return TRUE;
}

源代码 下载地址:http://download.csdn.net/detail/wudaijun/5189295

猜你喜欢

转载自blog.csdn.net/WUDAIJUN/article/details/8721916