FPS游戏自动瞄准敌人头部?是如何实现的(一)模块动态加载与玩转堆栈
如何瞄准一个敌人?我们先看到敌人的位置,然后把鼠标挪过去。
换到程序这样也是一样的,程序先读取到敌人的X Y Z坐标,然后利用鼠标模拟或者直接修改准星坐标瞄准敌人。
所以只要实现了自瞄,就相当于实现了透视,只是需要开发者通过一系列算法将其绘制在屏幕上而已。而实现自瞄,对于有相关工作经验的人来说,也算不上难,一套公式,几乎“通杀”所有FPS。
那么要实现基本自瞄,需要在游戏里逆向出的数据有:
- 修改有效的准星数据地址或瞄准call
作用:填入敌人所在坐标,实现自动瞄准 - 敌我坐标,即敌我X Z Y坐标
作用:计算出敌我距离,敌人所在”圆的位置。
知晓了所需数据,下一步?当然是实践了:
模块动态加载
用OD附加创世某某游戏进程, 进入OD主界面以后, 我们CTRL+G 跳转到地址 00401000(系统默认通常游戏领空的起始地址)的时候发现了 错误。
也就是说代码段不在这了, 那跑哪去了?
为什么会有这样的错误呢? 首先我们先来看看什么是基地址 我们随便找一个其他游戏CE附加
如上图,基地址 00D0DF1C 实际上是可以继续拆分,我们直接写00D0DF1C其实是不对 的。
他等于 游戏主模块句柄也就是 xxxx.exe + 90DF1C, 而这个游戏主模块句柄 ,一般是固定的 , 系统为其分配成00400000。 00D0DF1C = 00400000 + 90DF1C 由于这个00400000 是不变的, 所以 00D0DF1C 也是不变的 ,我们就没有继续拆分了。
但是并不是所有游戏, 这个模块句柄 都是不变的。 也有游戏模块动态加载的,那今天这个游戏就是动态加载。
无论是代码段还是数据段都是动态加载的。 加载的地址每次变化,代码地址当然也是跟着搬家,每次变化了,加载的地址变化,模块句 柄每次 变化,未拆分的基地址当然也是变化的,很好理解。
下面来个例子 OD附加上游戏进程 我们点开E模块窗口,
发现游戏模块句柄不是00400000 而是12D0000
那么这种情况就是模块动态加载 模块句柄每次都是不一样的 我们重新启动游戏,此时 又变成了 1300000
我们双击进入游戏领空
由于模块是动态加载的 基地址和代码段地址,都是由模块句柄 + 偏移所得,所以每次启动游戏 他都是动态的。
例如我们随便到游戏里找一个有基地址的地址
该地址是 1301041 我们把他拆分成 模块句柄 +偏移 1301041 = 1300000 +1041 = 模块句柄 +1041 以后我们想直接到这个地址 就要 用 模块句柄 +1041了
同样基地址我们也进行拆分 22D92C0 = 1300000 + FD92C0 = 模块句柄 + FD92C0 我们想直接使用这个基地址就要用 模块句柄 + FD92C0了
那么模块句柄怎么获得呢? 用GetModuleHandleA这个函数就可以了 例如:
DWORD 模块句柄 = (DWORD)GetModuleHandleA(“Crossout.exe”);
用这样的方式就和固定加载00400000的游戏没有区别了 以后本游戏中所有基地址都以该方式表达。
玩转堆栈
我们想做FPS游戏的自瞄透视功能,最基础的数据就是周围所有目标的坐标值 只有确定了所有目标的位置,我们才能用算法写出自瞄和透视。
首先我们拿自身的血量当突破口,找出周围所有目标的遍历。 竞技场血量不好找,玩家乱跑乱攻击,会给我们制造很大的麻烦。 那么我们进练习场,用碰撞的方式减少自己血量。
扫描整数型自身血量不存在结果 扫描float型自身血量得到一个结果,如下:
在血量属性周围观察其他属性.
在血量 +1F0 +1F4 +1F8 的位置发现了 XZY
如果不拿血量当突破口,先去扫描坐标 ,由于游戏没有显示坐标,未知值去扫,会有很多结 果,很难筛选,最后会很有很多类似的结果,确定用哪一个也是一件比较累的事情。 所以选择一个合适的突破口,会事半功倍。
-58的位置也发现了 UTF_8的名称
确定了 属性 我们可以开始追踪了
对血量下断断到这条代码
如果我们往上追寄存器会非常的繁琐 代码非常多,而且返回多次,光是追寄存器就要追踪半小时,如果追踪能力不强很容易就丢 了
那么有没有什么好办法的呢?
有的,我们可以先去尝试 堆栈中是否出现过 该数值,如果出现过,我们直接到最先出现的位置继 续追就可以了,我们现在所在的位置相当于调用的较内层,而通过这样的方法 我们就直接来到了程序最先用该数值的地方,绕过了中间追寄存器的过程。
方法如下 首先断下以后 复制要追的寄存器的值
然后到堆栈中搜索
一直 CTRL+l 查找到最后一个位置,也就是程序中最先出现的位置
通过上图发现是一个call 的第一个参数(当然堆栈中的返回到是会欺骗我们的) 所以我们直接跳过去 下断验证
发现确实不对 第一个参数不是我们要追的数值 那么说明堆栈是有问题的 怎么办呢?我们可以 到倒数第二次出现的位置追 ,总之能省多少追踪的力气省多少
是这个返回到的第4个参数 那么我们 过去下断验证
发现是正确的 来源于ESI 我们返回上层继续追踪
再网上翻
找到了数组 公式很简单
[[22F6ECC]+esi*4]
熟悉并且玩转堆栈会让逆向事半功倍.
深入学习游戏逆向分析,****学院搜索-----吉林飞郁网络培训.
购课与选课咨询飞郁客服QQ:290330101,再根据自身情况与客服建议下购买学习,并享受不定额度优惠.