修改游戏内存、使用脚本和自动化程序有封号风险
游戏版本基于:wowclassic.exe 1.13.4.33728
计划实现
1、游戏中,实现后台自动跳跳跳。还可以进一步做多个动作,必须搓绷带,随机走几步,喊喊话之类的。防止服务端大数据检测。
2、检测到掉线后,自动将魔兽窗口激活到前台,并自动重登。
3、检测到重登成功,回到步骤1。
难点在于
1、如何判断游戏掉线。由于是后台操作,且必须在30秒内完成重登操作,否则就加入排队大军。如果用找图取色方法,性能很低,且还无法使用。因此最佳方式只有高效率的内存读取。反正已经用了自动脚本,读内存还是找图模拟,该封都是封,没什么区别。
2、已经测试按键精灵9/2014加载乐玩插件可以实现后台跳跳跳。但取色、找图、鼠标都无效。只有后台键盘正常。
3、按键精灵+大漠7.2002可以读取游戏基址。大漠读出来的是vbLongLong数据类型的10进制的基址,和vbLong数据类型的游戏指针地址相加,按键精灵会报错(程序做的真差)。用大漠的Int64ToInt32函数转换基址,转出来是个负数……因此按键精灵的路线彻底over。
4、由于魔兽世界是64位程序,因此32位的CE、按键精灵各版本、seraph、autoit、大漠插件、乐玩插件统统无效。只有64位的autoit可以成功读取魔兽世界内存。但64位的autoit又无法注册大漠/乐玩插件,只能使用autoit内置自带的功能和函数。并且autoit无法读取中文内存数据。所以最终的选择方案,就是使用32位autoit,或者64位autoit加上#AutoIt3Wrapper_UseX64=n命令,配合大漠7.2002,实现脚本的内存读取和全流程控制。不过因为之前没用过autoit,所以一时半会还写不出来完整的掉线重登脚本。
研究成果
经过国外论坛学习和几天的研究,目前成功读取到了游戏的内存数据,且可以用来作为是否掉线的判断。
下面先来张成果图:
CE里列表的内存地址,都可以用于是否掉线的判断。在游戏中,数据都有。掉线了数据都是0。当读蓝条的时候,loadingscreen=1。
CurMgrPointer实际上是一个很重要的“对象管理器”地址指针。通过这个指针,再加上几个辅助地址,可以读取游戏内大部分的物品、人物等信息。不过我没有再进一步研究,再研究就是做刷金脚本/飞天外挂了。
重点1、脚本每次运行必须获得游戏的基址。64位的魔兽世界程序,每次运行基址都是变的,不像32位程序基址是固定值。autoit用KryMemory.au3可以直接通过_Process_GetBaseAddress获取游戏基址。然后,在autoit里按照CE的地址偏移格式,即可读取到数据。比如 CurMgrPointer=wowclassic.exe+2387C88 这种格式,或者 LocalGUID=[wowcliassic.exe+2387C88]+58 指针偏移。
重点2、游戏版本一更新,内存地址就会变动。即使是一个微小的版本更新,内存地址也有可能变动。所以如何找内存地址就又是一个难事。但一般而言,只要游戏的数据结构不变,那偏移层数和偏移量是不变的。基于此,可以用CE查找一个好找的数值后,逆向查找游戏基址,再推算出其他所有基址。比如搜索小地图显示的所在位置,然后已知偏移量0,找上一层地址。类似于 “已知小地图位置的动态显示地址”=[wowclassic.exe+X]+0,求X的值。找到X的值后,又已知上一个版本 基址B=基址X+10,那么新的基址B大概率仍然是“新的基址X+10”。
至于再深一层的研究,比如找人物基址指针,遍历内存获取周围所有人物或者怪物的名字、坐标;或者找到人物XYZ坐标、镜头角度;或者获取各种CALL……我水平不够,研究不出来。而且这些也属于刷钱脚本/飞天外挂范围,并没有做外挂的打算。
游戏版本更新,修正内存地址
2020年4月30日更新文章
魔兽怀旧服客户端版本更新到了1.13.4.34219。之前的内存地址失效了。正好写一下如何根据以前内存地址的格式,找到新版本内存地址。
上文提到过,只要游戏不做重大代码重构,那游戏的数据结构是不会变的。也即游戏的基址会变,但几级偏移是不会变的(偏移量可能微幅变动),只要找出一个新版本的内存地址,其他地址做一下加减法就可以。这里我用读取游戏角色名字内存格式为引子,更新游戏内存地址。因为读取角色名是直接基址+角色名内存地址的方式获取的,没有偏移量,更没有多层指针偏移,方便好找。
我们已知读取游戏名字内存地址格式为:[游戏进程基址+角色名内存地址] 。其中游戏进程基址脚本和CE都可以自动获取,不用操心;角色名内存地址上个版本是$PlayerNameAddr = 0x2688828,现在要找新的角色名内存地址。新的内存地址离旧地址不会太远,就在旧地址附近(经验之谈),因此初始内存地址设置为0x02660000。
在之前autoit读取角色名脚本基础上,简单加了一个读取内存地址遍历来找新地址。
1 2 3 4 5 6 7 | $nameadddrtmp = 0x02660000 Do $PlayerName = $dm.ReadString($hwnd, HEX($BaseAddr+$nameadddrtmp),2,0) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $PlayerName = ' & $PlayerName & @CRLF) ;### Debug Console ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $nameadddrtmp = ' & HEX($nameadddrtmp) & @CRLF) ;### Debug Console $nameadddrtmp = $nameadddrtmp + 0x1 Until $PlayerName == "恭喜你" |
运行脚本,几分钟就可以显示出最新的角色名内存地址。
角色名新地址是0x266C8B8。接下来换算一下就可以知道其他内存地址了。
先算一下新旧地址的差值:角色名旧地址0x2688828 - 角色名新地址0x266C8B8 = 1BF70
小地图所在位置文字旧地址$GetMinimapZoneTextAddr = 0x025A8C40,所以新地址就是 0x025A8C40 - 1BF70 = 258CCD0
剩下的地址自己算一遍,CE里检查一遍没问题就OK。
文章评论
能否加个QQ 1468236111 为什么我用大漠调用出来的 是乱码 转码后 总是少一个汉字
@会飞的知了 是什么语言和大漠?大漠得用最新版7.2002的
您好,在nga论坛看到你的帖子,没想到百度搜索到你的博客了。
我是偶然需要弄一下魔兽怀旧服辅助,但是遇到游戏内数据无法传递游戏外的情况,看到你的帖子,想请教一下64位CE是如何在读取的时候不崩溃的
@陈 搜索内存是不崩溃的,会崩溃的操作是 下断点、监控内存写入、注入wow进程等操作。这些操作会被wow反外挂系统监测出来,导致程序直接崩溃,而且有可能导致封号。但因为这些地址都是动态地址,想逆推基址的话,不监控内存写入是没办法成功的,所以CE是没法找到基址。
不监控内存写入是没办法成功的,所以CE是没法找到基址。
其中游戏进程基址脚本和CE都可以自动获取,不用操心;
这2句话 是不是矛盾的。
@abc 不矛盾。是我没说清楚。“不监控内存写入是没办法成功的,所以CE是没法找到基址”这句说的基址指的是游戏里一个功能的内存地址指针基址。比如[[ABCDEF]+EAX*4]+10,ABCDEF就是指针基址。“其中游戏进程基址脚本和CE都可以自动获取”这句说的基址指的是游戏进程的内存地址基址。32位系统固定是00400000开始,64位系统是动态的。
KryMemory.au3 这个东西我咋没有
@Kiven KryMemory.au3不是autoit自带的函数库,是我从国外autoit论坛里找的第三方库。我文章末尾的附件AutoIt-wow-dm-readmemory.zip 里带了KryMemory.au3库。
在NGA看到你的帖子 跟到了这里来。 NGA也私信你了 怕你看不到特意在这里也留言 希望你能看到 就是想请教下如何使用对象管理器CurMgrPointer
wlk前夕更新后:
BaseAddr:0x7ff600920000
以下是我通过CE扫描内存得出的地址
PlayerNameAddr:0x163A3A6E2E8
PlayerNameAddr居然跑到BaseAddr的 前面去了。
而且每次退出再进入,BaseAddr不变。PlayerNameAddr却变化。
难道是我找的PlayerNameAddr地址不对么?
请楼主解惑
怀旧服 WLK 3.4.0.45435
PlayerNameAddr的偏移量找到了,PlayerNameAddr:0x2ea5eb8
用dm.ReadString(hwnd, hex(BaseAddr+PlayerNameAddr),2,0)可以找到人物名字
但是CurMgrPointer,GetMinimapZoneText的偏移量还是找不到啊
麻烦楼主给查找一下。
@wcy 其实我也是照抄的地址,自己找的话我还没研究。我是从这里看到的,你可以自己翻翻帖子 https://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-memory-editing/