免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
本次游戏没法给
内容参考于:微尘网络安全
上一个内容: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也就是线程id GetWindowThreadProcessId(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); }