思路:
每个程序打开后他们的数据的内存地址都会改变,但他们的静态基址和偏移不会变
关于获取的是静态基址,所以就算是关闭了游戏,再开启动,地址也是不变的也可以修改
所以我们用CE找到他的静态地址和偏移地址,再用C/C++里面的ReadProcessMemory和WriteProcessMemory进行修改就可以了。
下面用图文解析用CE找植物大战僵尸向日葵产生的那个Sunshine
首先打开CE,选择植物大战僵尸,如下图所示
然后搜索第一次值“150”
搜索完后,有很多数据,先不要管他,先种一朵花,花掉100点,这是我们可以看到一个数据有变化(如下图)
随后我们双击那个内存,然后在下面那个框里面右击,然后选择紫色框
随后我们找到这数据的详细信息,然后记录他的偏移地址0X5560和要查找的地址的可能值11565EA0(如下图所示)
接下来,我们查找这个值:11565EA0如下图所示
查找后经过筛选发现地址为0x27FA760的地址与游戏数据sunshine有关,我们记录下。如下图所示偏移地址为00x768,要查找的地址指针可能是027F9FF8
接下来我们查找这个地址0x027F9FF8,我们找到一个绿色的静态基址(绿色显示的是静态基址),如下所示
我们现在分析下这个静态基址经过两次偏移是不是就对应了sunshine
我们发现这个基址经过第一次偏移0x768和第二次偏移0x5560后在地址0x11568400地址里面的值是50,正好对应。所以我们已经找到了这个静态基址(读者可以修改尝试)
所以如果我们要做修改器。我们理一理思路
由地址0x006A9F38里的值+0x768后是个地址,
这个地址里的值+0x5560就是存储sunshine的内存单元。
所以我们C/C++代码如下(因为代码比较简单,遇到不会的函数可以查百度或者msdn,在此不再详细说明)
源码里面有注释
代码如下:
#include <Windows.h>
#include <stdio.h>
int main()
{
DWORD getLastError;
//找到窗口
HWND hWinmine = FindWindowW(NULL, L"植物大战僵尸中文版");
DWORD dwPID = 0;
GetWindowThreadProcessId(hWinmine, &dwPID); //获取进程标识
if (dwPID == 0)
{
printf_s("获取PID失败\n");
return -1;
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwPID);
if (hProcess == NULL)
{
printf_s("进程打开失败\n");
getLastError = GetLastError();
return -1;
}
DWORD dwNum = 0, dwSize = 0;
//基址
DWORD SunShineBaseAddress = 0x006A9EC0;
//基址值
DWORD SunShineBaseAddressValue = 0;
if (0 == ReadProcessMemory(hProcess, (LPVOID)SunShineBaseAddress, &SunShineBaseAddressValue, sizeof(DWORD), &dwSize))
{
printf_s("静态址获取失败\n");
getLastError = GetLastError();
return -1;
}
//一级偏移
DWORD SunShineOffsetFirst = 0x768;
//一级偏移值
DWORD SunShineOffsetFirstValue = 0;
if (0 == ReadProcessMemory(hProcess, (LPVOID)(SunShineBaseAddressValue + SunShineOffsetFirst), &SunShineOffsetFirstValue, sizeof(DWORD), &dwSize))
{
printf_s("一级偏移获取失败\n");
getLastError = GetLastError();
return -1;
}
//二级偏移
DWORD SunShineOffsetSecond = 0x5560;
//最后值
DWORD SunShineNum=0;
if (0 == ReadProcessMemory(hProcess, (LPVOID)(SunShineOffsetFirstValue + SunShineOffsetSecond), &SunShineNum, sizeof(DWORD), &dwSize))
{
printf_s("二级偏移获取失败\n");
getLastError = GetLastError();
return -1;
}
int modifySunshine;
printf_s("SunShineNum:%d\n", SunShineNum);
printf_s("输入你要修改后的值:");
scanf_s("%d", &modifySunshine);
WriteProcessMemory(hProcess, (LPVOID)(SunShineOffsetFirstValue + SunShineOffsetSecond), &modifySunshine, sizeof(DWORD), &dwSize);
CloseHandle(hProcess);
system("pause");
return 0;
}
运行结果如下图所示:
因为获取的是静态基址,所以就算是关闭了,再开,也可以修改。
下节课中我们用Qt封装下界面,就可以发给小伙伴使用了。