Windows开发——内存读写API

我们知道数据都是写在内存中的,通过一些API我们可以访问并修改内存中的数据,达到修改游戏数据的功能。

通过一个小项目,了解windos读写内存API,以及进程id获取相关API。

                                                          

大体思路如下:

(1)先找到进程:(API:CreateToolhelp32Snapshot、Process32First、Process32Next)

void ShowProcessList() //功能1显示进程
{
	PROCESSENTRY32 pc;//定义一个32接收变量
	pc.dwSize = sizeof(pc);

	int count = 0;  //进程计数
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//进程状态“快照”
	BOOL bMore = Process32First(hProcessSnap, &pc);                //“快照”中获取第一个进程
	while (bMore)
	{
		cout << "\n---------------------------------------\n";
		cout << "id: " << pc.th32ProcessID << endl;               //.th32ProcessID获取进程id
		wprintf(L"name:%s\n", pc.szExeFile);          
		bMore = Process32Next(hProcessSnap, &pc);                 //转向下一进程
		count++;
	}
	CloseHandle(hProcessSnap);
	cout << "目前进程数:" << count << endl;

}

涉及API:

CreateToolhelp32Snapshot

Process32First

Process32Next

(2)编辑进程   (设计两轮查找,API: OpenProcess、WriteProcessMemory)

void EditProcessData() //功能2 编辑进程
{
	DWORD dwId = 0;
	DWORD dwSearchValue = 0;
	DWORD dwAddrList[4 * KONEK] = { 0 };
	DWORD dwAddrCount = 0;
	BOOL bRet = false;

	scanf_s("%d", &dwId);       //输入需要编辑的进程id
	
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);//获取进程句柄(打开进程)
	system("pause");
	printf("Please input the value which you want search first round:");
	
    scanf_s("%u", &dwSearchValue);//输入修改的进程内数据的当前值

	//首轮查找   待修改进程  查找目标值    存放数组    找到目标计数      空间
	FirstRound(hProcess, dwSearchValue, dwAddrList, &dwAddrCount, 4 * KONEK);

	ShowAddrList(dwAddrList, dwAddrCount);//显示搜索结果(目标数为):
 
		if (dwAddrCount == 0)      //无目标:返回
		{
			return;
		}
		else if (dwAddrCount == 1) //一个目标:直接修改
		{
			DWORD value;

			printf("input the value which you want to set");
			scanf_s("%u", &value);                       //修改唯一值
			//改写内存数据
			bRet = WriteProcessMemory(hProcess, (LPVOID)dwAddrList[0], (LPVOID)&value, sizeof(DWORD), NULL);
			
		}
		else                       //多个目标:二轮查找
		{

			DWORD dwSecondRoundSearchValue = 0;
			DWORD dwTargetList[KONEK] = { 0 };
			DWORD dwTargetCounter = 0;

			scanf_s("%u", &dwSecondRoundSearchValue);   //二次查找(需对数据进行修改)
			//二轮查找   进程      二轮查找目标值          原(1轮)地址     原(1轮)目标计数     新目标地址       新目标计数   
			SecondRound(hProcess, dwSecondRoundSearchValue, dwAddrList, dwAddrCount, dwTargetList, &dwTargetCounter);
			ShowAddrList(dwTargetList, dwTargetCounter);

			DWORD value;
			scanf_s("%u", &value);    //想要改成的数值
			for (DWORD i = 0; i < dwTargetCounter; i++)//对二轮查找的所有值进行修改
			{
				bRet = WriteProcessMemory(hProcess, (LPVOID)dwTargetList[i], (LPCVOID)&value, sizeof(DWORD), NULL);

			}
		}
	}
	CloseHandle(hProcess);
}

涉及API:

OpenProcess

WriteProcessMemory

(3)结束进程  (API:OpenProcess、TerminateProcess)

void KillProcess() //功能3 结束进程
{
	BOOL bRet = FALSE;             //进程结束是否成功标志
	DWORD dwId = 0;                //需结束的进程ID
	cout << "Please input process id which you want to kill...\n";
	while (!scanf_s("%d", &dwId))
	{
		/*fflush(stdin);*/
		rewind(stdin);
		cout << "Please input process id which you want to kill";
	}
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId); //打开进程

	if (hProcess != NULL)
	{
		bRet = TerminateProcess(hProcess, 0);      //结束进程
	}
	CloseHandle(hProcess);

	if (bRet)
	{
		cout << "kill process success\n";
	}
	else
	{
		cout << "kill process filed\n";
	}
	return;
}

涉及的API:

OpenProcess

TerminateProcess

ReadProcessMemory:读取进程内存

WriteProcessMemory:写入进程内存

void FirstRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax) //首轮内存查找
{
	DWORD dwBaseAddr = 64 * KONEK;  //查找首地址
	DWORD dwPageCount = (2 * KONEG - 64 * KONEK * 2) / KPAGE; //查找计数 用以确定合法范围  
                             |          |    。。。   |       |                        |
	                     //  |前64k     |用户程序区   |64k禁区 |       2G内核区           |
	                     //  |NULL指针区 |            |       |                       |
    printf("%u pages\n", dwPageCount);    
	printf("Start searching...\n");


	DWORD dwBeginAddr = dwBaseAddr;
	for (; dwBaseAddr< 2 * KONEG - 64 * KONEK; dwBaseAddr += KPAGE)
	{
		if (!CompareOnePage(hProcess, dwBaseAddr, dwValue, pAddrList, pAddrListCounter, addrListMax))
		{
			return;
		}
		//计算进度百分比
		DWORD page = (dwBaseAddr - dwBeginAddr) / KPAGE + 1;
		printf("current is %u page\n", page);
		double temp = ((double)page / dwPageCount) * 100;
		printf("-----------%%%f---------\n", temp);
	}
	printf("\nSearch finished...\n");
	system("pause");
}
bool CompareOnePage(HANDLE hProcess, DWORD dwBaseAddr, DWORD dwValue, DWORD *pAddrList, DWORD *pAddrListCounter, const DWORD addrListMax) //对单页内数据进行遍历 比对
{
	BYTE byPage[KPAGE] = { 0 };
	if (!ReadProcessMemory(hProcess, (LPCVOID)dwBaseAddr, (LPVOID)byPage, KPAGE, NULL))
	{
		printf("Read Memory error!!!\n");
		return true;
	}

	DWORD *pdwPointer = NULL;
	pdwPointer = (DWORD*)byPage;

	for (DWORD i = 0; i < KONEK; i++)
	{
		if (*pAddrListCounter >= addrListMax)
		{
			printf("Too many data, can not save...\n");
			return false;
		}
		if (pdwPointer[i] == dwValue)
		{
			pAddrList[*pAddrListCounter] = dwBaseAddr + i*sizeof(DWORD);
			(*pAddrListCounter)++;
		}
	}
	return true;
}

void ShowAddrList(DWORD *pDwAddrList, DWORD dwAddrListCount)
{
	printf("\n--------------Address list begin---------------\n");
	for (DWORD i = 0; i < dwAddrListCount; i++)
	{
		printf("%X\n", pDwAddrList[i]);
	}
	printf("\n--------------Address list end---------------\n");
}

void SecondRound(HANDLE hProcess, DWORD dwValue, DWORD *pAddrList, DWORD dwAddrListCounter, DWORD *pTargetList, DWORD *pTargetCounter)
{
	DWORD dwTemp = 0;
	for (DWORD i = 0; i < dwAddrListCounter; i++)
	{
		if (ReadProcessMemory(hProcess, (LPVOID)pAddrList[i], &dwTemp, sizeof(dwTemp), NULL))
		{
			if (dwTemp == dwValue)
			{
				pTargetList[*pTargetCounter] = pAddrList[i];
				(*pTargetCounter)++;
			}
		}
	}
}

完整代码:

https://github.com/zjq4688/Myproject.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LionelMessi7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值