简明传奇私服外挂开发教程
界面、功能虽简单,但外挂主要功能都有。且不会被反外挂检测到,这款私服的反外挂是ntprotect:有人会问,传奇私服大都有内挂:为什么还要做私服的外挂?因为内挂是要花钱的, 一个账号要花xx RMB。而且本文的外挂是基于内存挂,不是像大漠插件的图色+键鼠模拟外挂,是可以多开的。多开的意义不用我说。好了,进入主题吧:一、 开发前的准备: 上文提到了,本文是基于内存的Call挂,即注入DLL到游戏,调用游戏内的功能函数实现挂机。除了内存挂,还有图色挂和脱机挂。图色外挂就是识别游戏的图片,来判断怪物,怪物在什么地方,一般模拟键鼠来挂机,优点是开发快速,缺点是一台机器只能挂一个游戏,不能实现多开来挂机。因为键鼠分不了身啊。脱机挂是分析清除了游戏的传输数据协议,直接收发包来实现挂机。这款挂是基于C++加内嵌汇编开发的,常用的开发语言还有易语言。
1、 工具准备: CheatEngine、X32dbg、IDA、VT虚拟化调试器。由于游戏有反外挂,会检测调试器,所以要上VT。
2、 逆向分析:这个步骤很关键,因为是内存Call挂,自然需要逆向分析出各个关键数据存放的地址。不过大家放心,私服是非常少,或者不会更新里面数据的基地址的,所以找一遍地址就行。下面介绍关键数据和Call的找法: 1). 血量: 发现直接搜索血量能搜索到,但CheatEngine查找谁访问的基地址,怎么找都是找不到的。于是想到游戏或者反外挂做了手脚,因为这是对外挂最需要的数据。后来搜减少、减少的数值(类型为2字节),逐步缩小范围后找到了基地址:[[[+834]+4]+x*4]+582x为0代表自己的血量,x为其它数值代表怪物的血量。 2). 怪物坐标: 这个CE搜索人物的坐标,然后查找谁访问的基地址,可以找到: X坐标: [[[+834]+4]+x*4]+908 Y坐标: [[[+834]+4]+x*4]+A00 x为0代表人物的坐标,但也有例外,有很小几率x是0怪物的坐标。 这里科普下为什么搜索到人物的坐标后,要CE再查找谁访问的,因为搜索到人物的坐标是个堆栈地址,每次程序重启后,都不一样,所以要找出基地址。
上图右边的CE绿色的就是基地址。一般要查找几轮才能到达基地址,如下图:具体可以看网上的教程,这里不再详述。 3). 怪物数量: 按上面基地址的公式,观察内存中的数据可以得到:[[[+834]+8 4). 怪物名字:这个不能CE的查找谁访问找到,定位方式是:先用x32dbg找到怪物基地址。查找的方法可以借鉴网上的方法,但一般是对某个和人物有关的功能下断点,比如骑马、下马,bp Send后,栈回溯,Go到栈中的函数,可以看到上下文汇编代码有出现人物的基地址。 找到怪物基地址后,用CE搜怪物名字如”稻草人”得到地址A。再用CE搜A是哪个地址访问的值,得到地址B。最后B减去怪物基地址得到偏移。所以怪物名字基地址:[[[+834]+4]+x*4]+C24 5). 攻击怪物基地址: 选择一个怪物攻击,CE搜1,停止攻击怪,CE搜0,反复几次,然后查找谁访问或写入的,得出基地址: F7A8A4 6).地面物品数量: 方法同上,略: []+8 7). 地面物品坐标: 这个比较难用上面的方法搜索到,使用CE工具里面的Structure dissect看的,在里面输入物品结构体的地址:0091bb2c。然后逐级展开结构体: 最终确认地面物品坐标: [[[[[]+4]+x*4]+4]+0]+8 //X坐标 [[[[[]+4]+x*4]+4]+0]+C //Y坐标 x为第几个物品。 CE里还有个工具也很好用,若搜到数据后,不想查找对应的基地址,可以用指针扫描器: 填入扫描的地址,开始扫描后,多重启几次游戏,用这个工具对比,即可找到基地址。
8). 捡物call: 查找的方法是下断发包函数(bp send),然后分析栈中的函数,找到如下call: 然后查找eax的基地址,之后调用0x701620就行了。0x701620是因为游戏exe的基地址是0x400000,加上0x301620就是了。 这里给出捡物品的代码:
9). 走路call: 同样是下断发包函数(bp send),然后分析栈中的函数,找到如下call: 传奇游戏有走路和跑步call,且有8个方向,只是参数不一样。参数的确定,可以分别向8个方向走路或跑步,代码如下: 10). 自动寻路call: 我们点击小地图上的点时,是可以自动寻路的。于是想去找这个Call。但是并不顺利,这个call查找花了我好多功夫,一开始查找的call,是需要开启小地图,且寻路后鼠标会黏在小地图上。 然后想到使用A*或者B*算法去寻路,但需要提前制作好二值化地图数据,所有地图都需要制作,而且以后地图更新了,我们程序也得更新。 经过研究,找到完美call的方法: 先找到寻路状态的地址,寻路为1,不寻路为0。然后发现目的坐标写在后面,对其下硬件写入断点,断下函数逐层栈函数进行IDA分析。得到的call如下: 为了代码稳定起见,部分代码改成了C++实现: 为什么部分代码改为C++写就稳定了呢,因为比如遍历怪物数组时,怪物刷新了,导致访问数组就会崩溃。再比如A指向一块内存B,访问B的某偏移获得怪物某属性,而B此时释放了,怎么办? 解决方法是:先读取是否是有效的内存,再进行操作,比如使用ReadProcessMemory并判断返回值。
11).角色\怪物类型: 这个也是比较难定位的,就用自己写的程序(OffsetFind,见附件)去比较数组,得出来角色\怪物的类型。 原理是对比游戏内存中两个怪物数组的数据,设置好过滤条件,然后找出不同的地方: 比较出来的结果例如下图: 找出来的怪物类型如下图: 12).自动回收装备: 分析略。见附件代码: 13). 背包数组: 找法:CE搜索背包的第一格物品名称,并下断。然后把第一个物品移动到其它格子。会在mov ecx,00000426断下: 再根据上面的代码推导出公式: []+(0xC72+0*0x213)*8+1
14). 快捷栏数组: 分析方法同背包数组。公式: []+(0*0x213)*8+1
15). 方便玩家PK的小退、使用快捷栏物品、喊话: 小退在此断下: 对应的汇编调用代码如下: 使用随机传送石在此断下: 默认回城卷轴会在快捷栏第一格、随机卷轴会在快捷栏第二格: 对应的汇编调用代码如下:
喊话call在此断下: 对应的C++调用代码如下: 小结: 好了,关键数据的基地址和Call就分析完了,下面说一下小技巧: 1. CE查找谁访问或写入的地址时,发现是循环的值怎么办,分析其它搜索到的记录。或用CE的指针扫描器。 2. 查找call的方法是下断发包函数(bp send),但有的功能函数和发包函数不在一个线程,即专门有个发包的函数,这种情况定位功能call的方法可以见网上:https://blog.csdn.net/liujiayu2/article/details/57089112。 3. 有时候找血量或其它,不好找,先找其它属性,定位到基地址,然后再找。也可以用CE的Structure dissect查看。
二、 代码编写: 有了上面的逆向分析,我们就开始讲下代码吧。 外挂的功能主要是自动打怪、捡物品、装备回收。 打怪是往一个地址写入怪物ID就会打怪,停止打怪是设置这个地址为0。 自动打怪是一边寻路到挂机点一边打怪,挂机点是自动生成的,后面会介绍。 捡取物品是要踩到物品上,也就是走或跑到物品的坐标才能捡取。 一定范围的怪物打完才捡取物品,捡取所有物品。 打怪和捡取物品的入口函数如下:
装备回收是模拟用户操作界面点击回收按钮。当然不是模拟点击,而是call内部函数。
最主要功能就是上面所述。
1、 重难点优化: 下面介绍下开发中的遇到的问题及优化。 1). 卡角落打怪: 自动打怪过程中,是需要走\跑路过去打的。但有些是过不去的,如下图: 上图中选中的是楼上的怪物,因为走\跑路不了楼上,会一直卡在这。 上图中选中的是对面的怪物,因为走\跑路不过去,会一直卡在这。 可能是走\跑路到坐标点本身无法到达,我们需要解决这个问题。 在选择怪并执行打怪动作后,使用下面的函数进行检查: 若一段时间内检测打怪状态为0,且怪物血量不为0,说明卡角落打怪了,就调用寻路Call过去打怪。若此时还没检测到则放弃此怪物: 那什么时候重新打此怪物呢?人物自己移动了一定距离,不会卡障碍物就可以重新打怪物。
经过这样的优化,就不会出现挂机卡着了。
2). 聚怪打怪速度优化: 当周围怪物很多很多的时候,若要打的怪走动了,被别的怪挡住了,此时调用函数CheckAttack检查没有攻击怪,然后会寻路并等待,所以造成打怪停止半天,才接着打: 针对它的优化是当周围怪物达到6个以上时,使用CheckAccumulationAttack函数进行快速检查,若没有检查到攻击状态,则暂时放弃此怪物: 当怪物小于等于6时,放弃的怪物又可以重新打,以免暂时放弃的怪老跟着自己。
3).打一下怪物跑一下: 测试时自动打怪时,人物会打一下跑一下,再打,再跑一下。这样会拖慢挂机效率。针对此问题时选择怪物后,跑到怪物旁边去再攻击:
4). 卡地点不移动了: 有时候人物会卡在一个地点不动了,自动寻路也不会动,如下图:
猜测寻路算法已损坏,此时随便跑一下,接着寻路就可以动了: 5). 不捡别人的物品思路: 在捡取物品时,若物品是别的玩家的,会不断地捡取物品。 解决方法是调用捡物品Call时,记录下来物品ID,下次不再捡取。 6). 过服务器反外挂检测: 防止速度太快,服务器把自己定在一个位置: 解决方法是,在打怪时,适当休息一段时间:
7). 自动生成打怪坐标的优化: 一般的生成打怪坐标点是靠人工手动选取,附件代码里做了自动生成。 且生成的坐标点是按一定距离生成的。不会出现坐标点之间的距离很近,这样自动挂机就没有意义。同时会按照地图大小,调整这个距离。 这里还有个问题,就是很大的地图,自动生成坐标点会很慢。也做了优化,会映射到一个较小地图上,然后再随机生成坐标点。
总结: 就介绍到这里了,代码见附件。vs工程里还提供了一个代码注入器。生成的代码是可以挂机的。
页:
[1]