登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 184|回复: 0

简明传奇私服外挂开发教程

[复制链接]

40

主题

3

回帖

59

积分

版主

积分
59
发表于 2025-2-21 20:11:07 | 显示全部楼层 |阅读模式
                597552_DSWQYQFRHM8PUQK.jpg
    界面、功能虽简单,但外挂主要功能都有。且不会被反外挂检测到,这款私服的反外挂是ntprotect:
597552_QWGFT92HNPVF3HX.jpg
有人会问,传奇私服大都有内挂:
597552_N6BUH27PKD4FGEA.jpg
为什么还要做私服的外挂?因为内挂是要花钱的, 一个账号要花xx RMB。而且本文的外挂是基于内存挂,不是像大漠插件的图色+键鼠模拟外挂,是可以多开的。多开的意义不用我说。
好了,进入主题吧:

一、 开发前的准备:
       上文提到了,本文是基于内存的Call挂,即注入DLL到游戏,调用游戏内的功能函数实现挂机。除了内存挂,还有图色挂和脱机挂。
图色外挂就是识别游戏的图片,来判断怪物,怪物在什么地方,一般模拟键鼠来挂机,优点是开发快速,缺点是一台机器只能挂一个游戏,不能实现多开来挂机。因为键鼠分不了身啊。
脱机挂是分析清除了游戏的传输数据协议,直接收发包来实现挂机。
这款挂是基于C++加内嵌汇编开发的,常用的开发语言还有易语言。

        1、 工具准备:
        CheatEngine、X32dbg、IDA、VT虚拟化调试器。由于游戏有反外挂,会检测调试器,所以要上VT。

        2、 逆向分析:
这个步骤很关键,因为是内存Call挂,自然需要逆向分析出各个关键数据存放的地址。不过大家放心,私服是非常少,或者不会更新里面数据的基地址的,所以找一遍地址就行。下面介绍关键数据和Call的找法:
        1). 血量:
         发现直接搜索血量能搜索到,但CheatEngine查找谁访问的基地址,怎么找都是找不到的。于是想到游戏或者反外挂做了手脚,因为这是对外挂最需要的数据。
后来搜减少、减少的数值(类型为2字节),逐步缩小范围后找到了基地址:
[[[[F74388]+834]+4]+x*4]+582
x为0代表自己的血量,x为其它数值代表怪物的血量。
        2). 怪物坐标:
        这个CE搜索人物的坐标,然后查找谁访问的基地址,可以找到:
               X坐标: [[[[F74388]+834]+4]+x*4]+908
               Y坐标: [[[[F74388]+834]+4]+x*4]+A00
        x为0代表人物的坐标,但也有例外,有很小几率x是0怪物的坐标。
        这里科普下为什么搜索到人物的坐标后,要CE再查找谁访问的,因为搜索到人物的坐标是个堆栈地址,每次程序重启后,都不一样,所以要找出基地址。

597552_DJUP4GDSAKYQ46J.jpg
        上图右边的CE绿色的就是基地址。一般要查找几轮才能到达基地址,如下图:
597552_HASVJX7C6HGQRR9.jpg
具体可以看网上的教程,这里不再详述。
         3). 怪物数量:
            按上面基地址的公式,观察内存中的数据可以得到:
[[[[F74388]+834]+8
        4). 怪物名字:
这个不能CE的查找谁访问找到,定位方式是:先用x32dbg找到怪物基地址。查找的方法可以借鉴网上的方法,但一般是对某个和人物有关的功能下断点,比如骑马、下马,bp Send后,栈回溯,Go到栈中的函数,可以看到上下文汇编代码有出现人物的基地址。
找到怪物基地址后,用CE搜怪物名字如”稻草人”得到地址A。再用CE搜A是哪个地址访问的值,得到地址B。最后B减去怪物基地址得到偏移。所以怪物名字基地址:
[[[[F74388]+834]+4]+x*4]+C24
        5). 攻击怪物基地址:
           选择一个怪物攻击,CE搜1,停止攻击怪,CE搜0,反复几次,然后查找谁访问或写入的,得出基地址:
          F7A8A4
        6).地面物品数量:
           方法同上,略:
           [[0091bb2c]]+8
        7). 地面物品坐标:
        这个比较难用上面的方法搜索到,使用CE工具里面的Structure dissect看的,在里面输入物品结构体的地址:0091bb2c。然后逐级展开结构体:
597552_D24Q7P75X74T35E.jpg
      最终确认地面物品坐标:
      [[[[[[0091bb2c]]+4]+x*4]+4]+0]+8 //X坐标
      [[[[[[0091bb2c]]+4]+x*4]+4]+0]+C //Y坐标
      x为第几个物品。
      CE里还有个工具也很好用,若搜到数据后,不想查找对应的基地址,可以用指针扫描器:
597552_XW4MKD2BN4WVQFV.jpg
        填入扫描的地址,开始扫描后,多重启几次游戏,用这个工具对比,即可找到基地址。

        8). 捡物call:
        查找的方法是下断发包函数(bp send),然后分析栈中的函数,找到如下call:
597552_4GSRFWQKZVG6Y85.jpg
        然后查找eax的基地址,之后调用0x701620就行了。0x701620是因为游戏exe的基地址是0x400000,加上0x301620就是了。
        这里给出捡物品的代码:
597552_7P5EFBCEUJ3GVE2.jpg

        9). 走路call:
        同样是下断发包函数(bp send),然后分析栈中的函数,找到如下call:
597552_VCGPA3YUAXHHETW.jpg
       传奇游戏有走路和跑步call,且有8个方向,只是参数不一样。参数的确定,可以分别向8个方向走路或跑步,代码如下:
597552_XN7BYQNU5J7JJSY.jpg
        10). 自动寻路call:
        我们点击小地图上的点时,是可以自动寻路的。于是想去找这个Call。但是并不顺利,这个call查找花了我好多功夫,一开始查找的call,是需要开启小地图,且寻路后鼠标会黏在小地图上。
        然后想到使用A*或者B*算法去寻路,但需要提前制作好二值化地图数据,所有地图都需要制作,而且以后地图更新了,我们程序也得更新。
        经过研究,找到完美call的方法: 先找到寻路状态的地址,寻路为1,不寻路为0。然后发现目的坐标写在后面,对其下硬件写入断点,断下函数逐层栈函数进行IDA分析。得到的call如下:
    597552_TH3VNKB8RY8X5AF.jpg
        为了代码稳定起见,部分代码改成了C++实现:
597552_QE5QN44Z3PYRMJ4.jpg
        为什么部分代码改为C++写就稳定了呢,因为比如遍历怪物数组时,怪物刷新了,导致访问数组就会崩溃。再比如A指向一块内存B,访问B的某偏移获得怪物某属性,而B此时释放了,怎么办?
        解决方法是:先读取是否是有效的内存,再进行操作,比如使用ReadProcessMemory并判断返回值。

        11).角色\怪物类型:
        这个也是比较难定位的,就用自己写的程序(OffsetFind,见附件)去比较数组,得出来角色\怪物的类型。
        原理是对比游戏内存中两个怪物数组的数据,设置好过滤条件,然后找出不同的地方:
597552_5A64RHQESCS33TA.jpg
        比较出来的结果例如下图:
597552_88E76ZCSDMD5SD5.jpg
        找出来的怪物类型如下图:
597552_A9DYQ5TWYP3QWUM.jpg
        12).自动回收装备:
        分析略。见附件代码:
597552_RRAFJ7EDUA349VS.jpg
        13). 背包数组:
        找法:CE搜索背包的第一格物品名称,并下断。然后把第一个物品移动到其它格子。会在mov ecx,00000426断下:
597552_KZ2WE56NTCKSD77.jpg
        再根据上面的代码推导出公式:
        [[0091BCDC]]+(0xC72+0*0x213)*8+1

        14). 快捷栏数组:
        分析方法同背包数组。公式: [[0091BCDC]]+(0*0x213)*8+1

        15). 方便玩家PK的小退、使用快捷栏物品、喊话:
        小退在此断下:
597552_U4ZVRWVQPVMX2CB.jpg
        对应的汇编调用代码如下:
       597552_4J3ENCUUWT3EYA7.jpg
            使用随机传送石在此断下:
597552_8WTCCYKE9J8NDFX.jpg
           默认回城卷轴会在快捷栏第一格、随机卷轴会在快捷栏第二格:
597552_J3BQ23VND77QV8H.jpg
        对应的汇编调用代码如下:


       597552_T8P6N9AA3CFZSNV.jpg
            喊话call在此断下:
597552_MRJJVN2AM55TEHR.jpg
           对应的C++调用代码如下:
597552_T392STF77JVHBKH.jpg
        小结:
        好了,关键数据的基地址和Call就分析完了,下面说一下小技巧:
        1.      CE查找谁访问或写入的地址时,发现是循环的值怎么办,分析其它搜索到的记录。或用CE的指针扫描器。
        2.      查找call的方法是下断发包函数(bp send),但有的功能函数和发包函数不在一个线程,即专门有个发包的函数,这种情况定位功能call的方法可以见网上:https://blog.csdn.net/liujiayu2/article/details/57089112
        3.      有时候找血量或其它,不好找,先找其它属性,定位到基地址,然后再找。也可以用CE的Structure dissect查看。


      二、 代码编写:
        有了上面的逆向分析,我们就开始讲下代码吧。
        外挂的功能主要是自动打怪、捡物品、装备回收。
        打怪是往一个地址写入怪物ID就会打怪,停止打怪是设置这个地址为0。
597552_4EXHHY2KVH8D7T9.jpg
        自动打怪是一边寻路到挂机点一边打怪,挂机点是自动生成的,后面会介绍。
        捡取物品是要踩到物品上,也就是走或跑到物品的坐标才能捡取。
        一定范围的怪物打完才捡取物品,捡取所有物品。
        打怪和捡取物品的入口函数如下:
597552_PHVKPYV9H85H54X.jpg

        装备回收是模拟用户操作界面点击回收按钮。当然不是模拟点击,而是call内部函数。
597552_R6578WDFDWXDPJG.jpg
        最主要功能就是上面所述。

        1、 重难点优化:
        下面介绍下开发中的遇到的问题及优化。
        1). 卡角落打怪:
           自动打怪过程中,是需要走\跑路过去打的。但有些是过不去的,如下图:
597552_5F72SGH4BXQN9JY.jpg
        上图中选中的是楼上的怪物,因为走\跑路不了楼上,会一直卡在这。
597552_3CVYUR3E9HCAAGC.jpg
        上图中选中的是对面的怪物,因为走\跑路不过去,会一直卡在这。
        可能是走\跑路到坐标点本身无法到达,我们需要解决这个问题。
        在选择怪并执行打怪动作后,使用下面的函数进行检查:
597552_76FMAM2C73EB4Q7.jpg
        若一段时间内检测打怪状态为0,且怪物血量不为0,说明卡角落打怪了,就调用寻路Call过去打怪。若此时还没检测到则放弃此怪物:
597552_GP22G8T9MABR246.jpg
         那什么时候重新打此怪物呢?人物自己移动了一定距离,不会卡障碍物就可以重新打怪物。
597552_KVUQAGZ6F9338QA.jpg

        经过这样的优化,就不会出现挂机卡着了。

        2). 聚怪打怪速度优化:
        当周围怪物很多很多的时候,若要打的怪走动了,被别的怪挡住了,此时调用函数CheckAttack检查没有攻击怪,然后会寻路并等待,所以造成打怪停止半天,才接着打:
597552_JHEWAP5D2J6XSQS.jpg
         针对它的优化是当周围怪物达到6个以上时,使用CheckAccumulationAttack函数进行快速检查,若没有检查到攻击状态,则暂时放弃此怪物:
597552_ZU6RT2C73KYG2DC.jpg
        当怪物小于等于6时,放弃的怪物又可以重新打,以免暂时放弃的怪老跟着自己。

        3).打一下怪物跑一下:
        测试时自动打怪时,人物会打一下跑一下,再打,再跑一下。这样会拖慢挂机效率。针对此问题时选择怪物后,跑到怪物旁边去再攻击:
597552_NN9BWW739SUXWA6.jpg

        4). 卡地点不移动了:
           有时候人物会卡在一个地点不动了,自动寻路也不会动,如下图:
597552_DR39KDZ9FTC93E5.jpg

       猜测寻路算法已损坏,此时随便跑一下,接着寻路就可以动了:
597552_8JZRP8UCUP89YPB.jpg
        5). 不捡别人的物品思路:
        在捡取物品时,若物品是别的玩家的,会不断地捡取物品。
        解决方法是调用捡物品Call时,记录下来物品ID,下次不再捡取。
597552_S7TR43ZQHJ9SMVE.jpg
        6). 过服务器反外挂检测:
        防止速度太快,服务器把自己定在一个位置:
597552_TAPKMFKVWAXPT9C.jpg
           解决方法是,在打怪时,适当休息一段时间:
597552_3VUR257PSD9UNC9.jpg

        7). 自动生成打怪坐标的优化:
        一般的生成打怪坐标点是靠人工手动选取,附件代码里做了自动生成。
        且生成的坐标点是按一定距离生成的。不会出现坐标点之间的距离很近,这样自动挂机就没有意义。同时会按照地图大小,调整这个距离。
        这里还有个问题,就是很大的地图,自动生成坐标点会很慢。也做了优化,会映射到一个较小地图上,然后再随机生成坐标点。
597552_ZRTWJKJV5NMVHGT.jpg
        总结:
        就介绍到这里了,代码见附件。vs工程里还提供了一个代码注入器。生成的代码是可以挂机的。

OffsetFind.zip (6.25 KB, 下载次数: 1) SFG.zip (201.81 KB, 下载次数: 1)

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-4-5 07:09 , Processed in 0.210831 second(s), 23 queries , Yac On.

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表