传奇英雄杀怪经验倍数脚本编写教程 从内存定位到完整代码实现全步骤

来源: 作者: 点击:
写英雄杀怪经验倍数脚本,核心思路是找到经验值在内存里的位置,通过修改或者挂钩的方式改变经验增长的数值。这类脚本和普通的按键脚本不一样,需要接触内存操作,新手建议先把基础的内存读写工具用熟,再动手写具体功能。

准备工具阶段,CE也就是Cheat Engine是必须的,用来搜索经验值的内存地址。编写工具选易语言或者Delphi都可以,新手推荐易语言,中文语法上手快,内存操作的模块也多。OD调试器可以备着,遇到需要分析汇编代码的时候用得上。工具不用装太多,CE加易语言基本就能搞定大部分情况。

第一步是定位经验值的基地址。打开CE附加到游戏进程,先让英雄打一只怪,记下获得的经验数值,在CE里搜这个数。然后再打一只怪,经验涨了之后再搜新的数值,反复几次,剩下的地址数量会越来越少。一般最后会剩下一两个绿色地址,那就是经验值的动态地址。光有动态地址不够,每次重启游戏地址会变,得找出它的基址和偏移。

找基址的方法,右键那个动态地址,选"找出是什么访问了这个地址",然后回去让英雄再获得一次经验,CE会记录下访问这个地址的汇编指令。点进去看指令,比如是mov eax,[esi+00000320]这种格式,那esi就是指针,偏移就是320。接着搜esi的值,找到指向它的上级指针,一层层往上找,直到找到一个地址在游戏模块里,而且每次重启游戏都不变,那就是基地址了。

找到基址和偏移之后,就可以开始写脚本的框架了。用易语言的话,先写进程取ID的函数,通过窗口标题或者进程名找到游戏的进程ID。然后打开进程,获得进程句柄,后面读写内存都要用到这个句柄。这些基础函数网上有现成的模块,直接调用就行,不用自己从零写。

读当前英雄经验的函数,就是沿着基址加偏移的路径一层层读。先读基地址的值,得到一级指针,加上一级偏移再读,得到二级指针,一直加到最后一层偏移,读出来的就是当前的英雄经验值。写个专门的读经验子程序,返回当前经验值,后面做判断和修改都要调用它。

经验倍数的实现有两种思路,一种是定时检测经验变化,变化了就按倍数加上去;另一种是hook获得经验的函数,直接修改返回的经验值。新手推荐第一种,不用改游戏代码,不容易出问题,虽然精度差点但够用。第二种效果好,但是要会汇编和hook技术,门槛高一些。

定时检测的写法,开一个时钟控件,间隔设成100毫秒左右。每次时钟触发的时候,读一次当前英雄经验,跟上一次存的经验值比较,如果比上次大,说明刚获得了经验。算出差值,乘以你想要的倍数,比如两倍的话就差值乘2减差值,等于多加一份经验。算出来的额外经验写到当前经验地址里,然后把当前经验存下来当下次的比较基准。

要注意数值溢出的问题,比如当前经验已经快到升级临界点了,再加倍经验可能直接超过升级所需的经验值,导致等级跳级或者数据异常。可以加个判断,先读一下升级需要的总经验,如果加完之后的经验超过了升级经验,就只加到刚好升级的数值,剩下的等升级之后再处理。嫌麻烦的话倍数别开太高,一般两倍三倍问题不大。

英雄经验和主号经验是两个独立的地址,别搞混了。找英雄经验的时候,确保主号经验不动,只让英雄打怪获得经验,这样搜出来的才是英雄的。有些版本主号和英雄的经验结构是类似的,基址可能只差一个固定偏移,找到一个之后另一个可以顺着找,省不少事。

写内存操作的代码,要用对读写函数。易语言里常用的是ReadProcessMemory和WriteProcessMemory这两个API,注意参数的类型,尤其是数据类型要定义对,经验值一般是四字节整数,也就是整数型。每次读写之后判断一下返回值,确认读写成功了再往下走,不然读到空值容易出各种奇怪的bug。

调试的时候先在易语言里加个标签,显示当前读到的英雄经验,运行起来看数值对不对,是不是和游戏里显示的一致。如果数值不对,先检查基址和偏移有没有抄错,CE里的偏移是十六进制的,易语言里如果用十进制要转一下。数值一直是零的话,大概率是进程没打开对,或者句柄获取失败了。

测试经验倍数功能,先把倍数设小一点,比如1.5倍,打一只怪看看经验涨多少。算一下原本应该得多少经验,实际加了多少,对得上说明功能没问题。倍数不要一下开十倍二十倍,数值变动太大会被检测,而且容易把经验值写超,导致角色数据出问题。稳定第一,慢慢调。

hook方式实现经验倍数,需要先找到获得经验的函数入口。用CE的"找出是什么改写了这个地址"功能,获得经验的时候会触发写入,记下那条汇编指令的地址。用OD跳到那个地址,往上翻找到函数的开头,分析一下参数,一般经验值会存在某个寄存器里,比如eax或者edx。

然后用inline hook,跳转到自己写的函数里,把经验值乘以倍数之后再跳回去。这种方法是实时的,经验一获得就直接改了,没有延迟,也不会因为检测间隔漏掉。但是对技术要求高,要处理好堆栈平衡,还要注意原指令的长度,跳转的时候别把后面的指令覆盖坏了。新手不建议一上来就搞hook,先把内存读写的方式写通再说。

脚本加个开关功能,别一运行就一直生效。做个热键切换,比如按F1开启倍数,F2关闭,方便随时调整。倍数也可以做个编辑框,自己填数字,不用每次改代码重新编译。界面不用做太复杂,能用就行,毕竟这类脚本主要是自己用。

防止被检测,要注意几个点。一是不要频繁地写内存,间隔太短数据变动太规律容易被盯上。二是数值不要改太夸张,倍数控制在合理范围,别一下升几十级。三是内存操作的方式尽量隐蔽,别用太出名的内存读写模块,容易被特征码识别。有条件的话可以用驱动级的读写,ring3层的检测工具就查不到了。

常见问题里,经验地址每次重启游戏都变,说明找的是动态地址不是基址,回去重新找基址和偏移。有些游戏有地址随机化,每次启动基址也会变,这时候就要用模块名加偏移的方式,比如"游戏名.exe+0012A3B0",CE里绿色地址就是模块偏移,直接用这个格式就行,易语言里先取模块基址再加偏移。

写好的脚本闪退或者游戏崩溃,多半是写内存写错了地址。比如偏移算错了,写到别的数据上去了,破坏了游戏的内存结构。遇到崩溃先把写内存的代码注释掉,只保留读的部分,看还崩不崩,不崩的话就是写的地址有问题,重新核对偏移。hook方式崩溃的话,一般是堆栈没平衡好,或者跳转回去的位置不对。

英雄经验倍数脚本,本质上就是内存读写加上简单的数值计算。只要能准确找到英雄经验的内存地址,剩下的逻辑都不复杂。新手刚开始找地址可能会觉得麻烦,多找两次熟练了,十来分钟就能定位好。写的时候多测试,每加一个功能都测一遍,别攒到最后一起调,出了问题都不知道是哪一步错的。