0x00:
- 使用工具
Cheat Engine 5.6.1
- 将要修改游戏
PlantsVsZombies.exe - 植物大战僵尸
- 修改器开发环境
MingW and gcc
注:
VC等IDE也可以.
相关文件会在后面添加下载链接
0x01:
使用CE查询分析游戏内存数据
首先打开游戏, 开始游戏, 然后暂停游戏.
这时候使用CE打开PlantsVsZombies.exe进程
在CE中输入当前阳光值的大小, 默认一开始是50, 点击首次查询 会出现很多地址, 别担心, 我们进一步继续挖掘.
再回到游戏里面, 等待收集一个阳光值.
再到CE中输入75点击再次扫描, 现在的结果比较好了, 只有一个值了.
双击这个地址, 添加到地址列表里面, 验证找的对不对, 可以修改这个地址的值, 在游戏中查看阳光值是否发生变化, 在这里我就不再演示了.
这个地址上面右击选择, 找出是什么改写了了这个地址
回到游戏中去种一颗植物, 会在列表中找到一个操作. 点击详细信息
可以看到一些汇编代码, 和寄存器的值. 我们先记录下来
- EAX=0000004B
- EBX=00000032
- ECX=FFFFFFFF
- EDX=20C8DCA8
- ESI=00000019
- EDI=20C8DCA8
- EBP=0018FB94
- ESP=0018FAE8
- EIP=00433F8C
-
- Probable base pointer =20C8DCA8
-
- 00433f82 - jg 00433f90
- 00433f84 - sub esi,ebx
- 00433f86 - mov [edi+00005578],esi
- 00433f8c - mov al,01
- 00433f8e - pop esi
其中有一个mov指令, 这个是写入内存值的操作, 偏移是0x5578, 那么其实它写入的地址为EDI+0x5578 这个我看一下EDI寄存器的值是: 0x20C8DCA8
- 00433f86 - mov [edi+00005578],esi
我们再次回到CE中勾选hex, 输入EDI寄存器的值, 点击新的扫描 这次找到的东西也不少, 也是比较麻烦的, 只能根据经验和多次尝试了. 这里有一个小技巧, 首先去找那些和别的地址不太一样的地址, 比如我在这里就比较轻松的找到了.
好了, 到了这一步, 我们点击手动添加地址, 勾选指针, 输入我们找的那个地址和上面的偏移值. 如果是这样的, 说明我们找的没错
下一步, 我们在第二个指针上面右击, 这次选择找出是什么访问了这个地址
选择第一个, 切换到游戏里面
很快在列表里面出现好多访问
我们选择其中任意一个地址, 看一下详细信息, 找到可能值为ESI寄存器的值, 我们去查询一下, 出现我们想要的结果了 图中我们看到了地址为绿色的, 第一个绿色的地址就是我们要找的地址. 我们再次记录一下这个 我们找到的地址是: 0x7794F8 偏移: 0x868
- EAX=023BB760
- EBX=20D1A534
- ECX=09B802B6
- EDX=00A50002
- ESI=00000021
- EDI=20C8DCA8
- EBP=00189760
- ESP=0018968C
- EIP=00476667
-
- Probable base pointer =023BB760
-
- 0047665e - int 3
- 0047665f - int 3
- 00476660 - cmp dword ptr [eax+00000868],00
- 00476667 - jne 0047666c
- 00476669 - xor al,al
下一步, 手动添加地址 勾选指针, 输入我们找到的地址: 0x7794F8, 偏移0x868 再点击添加指针, 输入偏移0x5578, OK. 最后的结果, 可以在第三个地址修改值, 看看游戏中的阳光值变化.
第一步完成了, 找到了我们最终要使用的地址和偏移值.
- 我们的要找的正确的内存地址的计算方式: *(*(*(0x7794f8) + 0x868) + 0x5578)
0x02:
修改器的开发, 我们这里使用C语言
首先了解一下做修改器的关键API:
- BOOL ReadProcessMemory(
- HANDLE hProcess,
- PVOID pvAddressRemote,
- PVOIDpvBufferLocal,
- DWORD dwSize,
- PDWORDpdwNumBytesRead
- );
- 参数:
- hProcess [in]远程进程句柄, 被读取者
- pvAddressRemote [in]远程进程中内存地址, 从具体何处读取
- pvBufferLocal [out]本地进程中内存地址, 函数将读取的内容写入此处
- dwSize [in]要传送的字节数, 要写入多少
- pdwNumBytesRead [out]实际传送的字节数, 函数返回时报告实际写入多少
- BOOL WriteProcessMemory(
- HANDLE hProcess,
- LPVOID lpBaseAddress,
- LPVOID lpBuffer,
- DWORD nSize,
- LPDWORD lpNumberOfBytesWritten
- );
- 参数:
- hProcess [in]远程进程句柄, 被读取者
- lpBaseAddress [in]要写的内存首地址, 再写入之前, 此函数将先检查目标地址是否可用, 并能容纳待写入的数据.
- lpBuffer [in]指向要写的数据的指针.
- nSize [in]要写入的字节数.
-
- 返回值
- 非零值代表成功.
0x03:
原理
修改器的基本原理就是读取游戏线程的内存数据, 根据我们之前找到的计算方式, 在最后得到地址写入阳光值.
关键代码实现
- DWORD d1, d2;
- // 得到0x7794f8地址的内存值, 其值保存到d1, d2为真实读到数据的大小, 这里如果不为4则读取错误
- ReadProcessMemory(hProc, (void *)0x7794f8, &d1, 4, &d2);
- printf("0x%X 0x%X\n", d1, d2);
-
- // 得到上面地址+0x868的内存值
- ReadProcessMemory(hProc, (void *)(d1+0x868), &d1, 4, &d2);
- printf("0x%X 0x%X\n", d1, d2);
-
- // 要写入阳光值的地址
- ads_ps = d1+0x5578;
-
- // 得到上面地址+0x5578的内存值
- ReadProcessMemory(hProc, (void *)(d1+0x5578), &d1, 4, &d2);
- // 输出当前阳光值的大小
- printf("%d 0x%X\n", d1, d2);
-
- printf("ads_ps: 0x%X\n", ads_ps);
- // 在我计算出来的地址里面写入阳光值的大小
- WriteProcessMemory(hProc,(void *)ads_ps, &value, 4, NULL); //写内存
0x04:
最后来一个效果图, 希望这个教程会帮助大家学习
0x05:
下载地址: PlantsVsZombies: http://pan.baidu.com/s/1kVDck5L 密码: 7ooj 修改器源码: http://pan.baidu.com/s/1c1HJRu4 密码: wa2n
解压密码: 52pojie
|