免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
本次游戏没法给
内容参考于:微尘网络安全
上一个内容:6.x86游戏实战-C++实现跨进程读写-通过基址读取人物状态标志位
上一个内容通过基址得到了人物状态标志,这种操作属于读取,既然有读取那就有写入,所以本次来搞写入,本次通过找坐标改坐标实现瞬移来学习跨进程写数据。
这里有一件事,代码(c/c++代码)中用的那些函数(函数也叫api)怎么知道的?怎么就知道它能这样用?怎么知道有这种东西?
比如之前的 OpenProcess函数、ReadProcessMemory函数,怎么知道的这俩函数?
这都是老师讲的,逆向会常用OpenProcess、ReadProcessMemory这两个函数(当然不止这俩),这俩函数是Windows系统提供,自己找是真找不到,写这些字是为了那些钻牛角尖的,不要再钻了,我代码里写什么就学什么,否则其它的函数你就算知道了,也可能不知道怎么玩,纯浪废时间
Spy++
使用OpenProcess函数时要写一个pid,这个pid游戏重启、操作系统重启都会发送改变,每次都要找它的pid,有一个函数可以获取pid,这个函数需要Spy++里的一点东西,如下图打开Spy++
使用
找坐标
首先打开CE并附加游戏,游戏中小地图附近会有坐标信息(有些游戏没有,后面会写没有的怎么办)
如上图坐标现在是240,143,界面上显示的是整数,但它实际上是小数,很少有游戏坐标数据用整数,然后,如下图使用单浮点类型(为什么用单浮点?因为经验,也有的游戏会用双浮点,如果不知道用单浮点还是双浮点那就这俩都试一试,试完就知道用哪个了(错误的会找不到想要的数据),优先使用单浮点),来扫描内存,然后扫描类型是值介于...两者之间,游戏中坐标在窗口中看到的是100,它实际上可能是101、106、96这样的(所以这种找法不好,后面会有其它方式找坐标,只能做入门来用)
然后首次扫描,找到14511个数据
然后移动角色更改坐标
再次扫描,然后就剩下18个
然后把这些全部添加到下方列表中
然后再选中一半,然后鼠标放到选中的数据上如下图右击选择数值,把数据修改一下,如果把坐标修改了游戏中会有反应
把数据修改为50,然后游戏中没有反应,这说明坐标数据并不在这些数据中
然后选择剩下的数据做上方的操作
修改成60之后游戏有了反应(会瞬移)
然后现在还是有很多数据,具体哪个是坐标还不知道,然后先把这些改了没反应的给删除
然后再选一半改数据,这里改之前移动一下角色,让它恢复一下坐标(网络游戏本地改坐标没用,移动一下(发送数据包)就会恢复)
最终发现了两个,一个是人物头顶名字的坐标,一个是人物坐标
找到坐标之后使用c++代码对它们做出修改
代码:
// ConsoleApplication4.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#include <iostream> #include "Windows.h"int main() {/*FindWindowA函数通过窗口类和标题获取窗口句柄""是从Spy++中类里复制来的NULL表示啥也没有*/HWND hwd = FindWindowA("", NULL);DWORD pid;// 根据窗口句柄获取进程pid,pid也就是线程idGetWindowThreadProcessId(hwd, &pid);HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);DWORD* address = (DWORD*)0x457A555C;float ret = 60;/*h进程句柄address要修改的内存地址,或者说修改什么内存地址里存放的值ret意思是把address(457A555C)地址的值修改成ret的值NULL不重要*/WriteProcessMemory(h, address, &ret, 4, NULL);address = (DWORD*)0x457A5544;ret = 60;WriteProcessMemory(h, address, &ret, 4, NULL);//跨进程读内存(); }void 跨进程读内存() {/*PROCESS_ALL_ACCESS表示全部权限FALSE表示不继承,这个一般用不到,不用了解14384进程的Pid,详情看文章中的图h是进程句柄,句柄是用来代表一个进程的数字,由操作系统提供HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 14384); 这一句的意思是获取14384进程的所有权限,并把句柄放到h中 */ //HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 14384); /*DWORD* 的意思是,* 表示当前的数据认定成内存地址,DWORD是4字节数字DWORD* 的意思是把xxx认定成内存地址,内存地址里的值是一个4字节数字(DWORD*)0xA107BC也就是把0xA107BC它当做内存地址来看待,0xA107BC内存地址里的值是一个4字节数字 */ //DWORD* buffer = (DWORD*)0xA107BC; //DWORD ret; /*h要读取谁的内存buffer内存地址ret内存地址的数据4读取4个字节NULL没用&是取地址的意思,&ret的意思就是ret的内存地址ReadProcessMemory(h, buffer, &ret, 4, NULL); 这一句的意思是,从h的内存中的0x60BAA6A0位置开始读取4字节,放到ret它里面,如果ret的大小没有4字节会显示有问题或程序崩溃 */ //ReadProcessMemory(h, buffer, &ret, 4, NULL); //printf("%d", ret);HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 15052);DWORD* buffer = (DWORD*)0xA107BC;DWORD ret;ReadProcessMemory(h, buffer, &ret, 4, NULL);//printf("%d", ret);buffer = (DWORD*)(ret + 0x60);ReadProcessMemory(h, buffer, &ret, 4, NULL);buffer = (DWORD*)(ret + 0x14c);ReadProcessMemory(h, buffer, &ret, 4, NULL);printf("人物状态标志:%d\n", ret); }