你是否在游戏中遇到"高手"?不论是预判还是枪法都是一流,只要你露个头,就会瞬间被带走。躲在箱子,墙壁后面也无济于事,“高手”们还是可以轻松的找到你,有的甚至会“预判 ”,直接对着障碍物穿箱扫射,直接带走躲在后面的敌人。这些人仿佛长了“上帝之眼”,总能知道你躲在何处,仿佛落地自带八倍镜,“八百里开外”一枪爆头。究竟是真高手,还是“神仙”?仁者见仁智者见智。
透视自瞄——fps玩家永远甩不掉的梦魇,fps游戏最大的恶性毒瘤。
从最早的cs,到现在的吃鸡,都深深的受其毒害,无一幸免。那么该功能影响如此恶劣,为何游戏公司迟迟不将其和谐(封禁)?不是游戏公司不想,而是根本无能为力。与其它修改内存类辅助不同,自瞄完全可以在不修改内存的情况下用纯算法,配合鼠标移动,外设等硬件设备实现。严格意义上来说,自瞄算不上外挂,如图色自瞄,只是一种模拟人工,代替玩家实现瞄准的辅助。当然,某些直接修改内存准星数据实现的自瞄,已经达到外挂定义的范畴,而这种自瞄,也相对好检测。那么透视呢?其实自瞄就相当于知道了敌人的位置,透视只需将其所在位置画出来。
假设笔者是该游戏安全人员,同时也是给相关同行的建议,针对自动瞄准,应该如何检测: 1、模拟类自瞄 一、Hook windows所提供的所有按键操作、鼠标操作类接口,函数全部由游戏安全系统接管。 二、既然Hook了相关函数,那么就可以被突破,Hook被还原,还要在代码段上下crc,防止被还原Hook,在crc上多次套crc,多设防御关卡。 三、检测鼠标轨迹和移动速度,没有谁可以一直直线移动鼠标。
2、内存类自瞄 一、Hook windows所提供的所有“写内存”类接口,如WriteProcessMemory(),函数全部由游戏安全系统接管,检测到非自身或者未知程序调用该类型函数对游戏进行操作时,将其踢下线。 二、同模拟类自瞄第二条。 三、同模拟类自瞄第三条。 四、加密鼠标横轴(x坐标),且多个地址同步准星数据,当非法修改了准星位置,即准星数据不同步,即可知道非法修改了内存。
那么接下来,同笔者一起分析,透视自瞄究竟是如何实现的呢? 其实只要实现了自瞄,就相当于实现了透视,只是需要开发者通过一系列算法将其绘制在屏幕上而已。而实现自瞄,对于有相关工作经验的人来说,也算不上难,一套公式,几乎“通杀”所有FPS。自瞄算法可以简单的分为两种,一种通过玩家坐标和准星位置进行计算,一种为”矩阵自瞄“,计算模型骨骼等等,其实两种自瞄本质意义上区别不大,各有各的好处,只不过第二种更为精准,第一种则更为方便,需要的数据更少。
那么实现基本自瞄,需要的数据有哪些?笔者做了一个简单的总结:
1、视角、即FOV 作用:计算敌人是否在屏幕可视范围内。 2、修改有效的准星数据地址或瞄准call 作用:填入敌人所在坐标,实现自动瞄准 3、敌我坐标,即敌我X Z Y坐标 作用:计算出敌我距离,敌人所在”圆的位置。
知晓了所需数据,下一步?当然是实践了,说得再好,想得再美,不如亲自动手实践。首先是寻找视角(FOV)的思路,在这里再详细的了解下视角,视角即你所能看到的范围,在FPS游戏种,可以理解为你屏幕上所能看到的,那应该如何寻找这一屏幕所视?
熟悉FPS的都知道,在游戏中存在着”狙(和)击(谐) 抢“,(qiang 为敏感词,以下用 xx代替),而这种XX,有着瞄准镜,在进行瞄准的时候,可视距离变远,同时可视范围是不是变小了呢?没错,这就是很好的突破口。 根据以往分析的经验,这种表达坐标/范围的地址,往往都是浮点型,或者双浮点型,那么在未开镜的情况下,CE先尝试搜索未知的浮点型,如下图所示:
然后进行第一次开镜,如下图所示
开镜后,是不是如先前分析,所看到的物体变大,同时可视范围变小了呢?,那么搜索,减小的数值,如下图所示:
再次进行二次开镜,缩小可视范围,重复以上步骤:
关闭狙击镜之后,搜索增加的数值,如下图所示:
来回重复几次赛选之后,发现的绿色的地址,即为基地址,那么可以直接拿来使用。
(防止恶意用途,地址打码) 反外挂建议: 在不影响游戏流畅性的前提下,将视角地址存放在堆栈或临时申请的内存地址中,即用即销,增大逆向难度。
数据1 轻松搞定,由简到难,接下来分析准星数据/或者瞄准call。
首先整理一下思路,如何找到修改有效的准星坐标地址呢?玩家移动鼠标,画面跟着移动,同时准星在画面中所处的位置也跟着移动,而屏幕上是以2D的方式显示,2D可以有两个坐标,也就是X跟Y坐标。在fps游戏中,横轴是可以无限原地转圈的,而竖轴上下大概在180度左右,所以Y往往比X更合适用来当作这一数据的突破口。那么假设准星数据做了处理,应该如何找到瞄准call呢?搜索出与准星坐标相关的地址后,移动鼠标进行访问断,就有可能断到相关的函数。
前面有讲,坐标/范围类数据,通常都是浮点或双浮点,那么搜索未知的浮点值:
鼠标朝上,搜索增加的数值,鼠标朝下,搜索减少的数值,如下图 : 搜索减少的数值:
搜索增加的数值:
经过重复搜索,发现并没有找到我们想要的,那么尝试给他反一下,朝上为减少,朝下为增加,步骤同上,这回得出了我们想要的地址 且在+4的位置,发现了X坐标,但是X坐标做了简单加密:
存放准星数据的地址,并非基地址,也就是说下次重启游戏,或者换房间将会进行变化,还需要追寻它的来源,防止恶意用途,追寻来源过程这里省略,本文只做分析。接下来可以分析一下他是以何种方式给X轴加密。
FPS分析加密的X轴,其实不一定要去逆向他加密的过程,大多数情况可以观察数据变化做分析。观察一下X轴的变化,人物往左,值减小,一直逆时针自转,一直减小,甚至将值修改为-9999也可以识别,人物往右,值增加,一直顺时针自转,一直增加,甚至将值修改为9999也可以识别。这样看的话,往往容易被混淆。可以定一个点,记住地址的值,人物转一圈,回到原来的点,观察值增加/减少了多少,最终发现人物自转一圈的值为2π,那么这时候可以得出结果:
该游戏的X轴自转一圈,为2π,不论地址的值是多少,只要用值/2π 取余,就可知道准星在圆的具体位置。 除了要分析出加密的准星数据,还需要分析出坐标在”圆“中的分布情况,这个相对简单,只需分析出朝哪走,X坐标增加,朝哪个方向,X坐标减少,Y坐标同理 即可。笔者分析如下图分布:
反外挂建议: 该游戏虽然对准星进行了加密,但却过于简单。在不影响游戏流畅性的前提下,建议将X坐标进行动态加密,达到”肉眼无法分析“的效果,以增大逆向难度。
接下来可以简单的配出自瞄公式,如下: 0 —— pi/2 水平角 = #pi ÷ 2 - atan ((自身Y - 敌人Y) ÷ (自身X - 敌人X))
pi/2——pi
水平角 = atan ((敌人Y - 自身Y) ÷ (自身Y - 敌人Y)) + #pi ÷ 2
pi/-pi——-pi/2
水平角 = 0 - atan ((敌人Y - 自身Y) ÷ (敌人X - 自身X)) - #pi ÷ 2
-pi/2——0 水平角 = atan ((自身Y - 敌人Y) ÷ (敌人X - 自身X)) - #pi ÷ 2
敌人Z>自身Z 俯视角 = atan ((敌人Z - 自身Z) ÷ 距离)
敌人Z<自身Z 俯视角 = 0 -atan ((自身Z - 敌人Z) ÷ 距离)
还有最后一个数据,自身的坐标和玩家的坐标。相对前面两个数据,该数据与之比稍难。因为一般敌人/怪物坐标,都是以数据结构的形式进行遍历,牵扯到的相关数据较多。
既然牵扯到的相关数据较多,那么突破口也众多,如血量,人物坐标,敌人数量等等。
以人物坐标为例,3D坐标与屏幕2D坐标不同的是,多了一个Z坐标,2D即 X跟Y, 3D则 X Y Z。在寻找人物坐标时,Z坐标(高度)往往更合适当突破口。搜索大致流程如下:
人物站在地面,搜索未知的浮点。
人物站在高处,搜索增加的
来回重复几次,很容易筛选出一个修改有效的(可实现飞天遁地)地址,那么OD附加,顺着往上追,很容易的来到了人物对象首(CE查看访问代码也很容易看出),在对象上下段,轻而易举的来到了玩家数组,在玩家对象下 +E0 +E4 +E8 的位置,分别对应玩家的 X Z Y坐标,得到了坐标之后,配合上面分析的公式,计算出结果给其写入准星地址,即可实现自动瞄准。
前面有讲,实现了自动瞄准,其实就实现了透视,剩下的工作,就是将敌人所在位置,用代码绘制出来。至于绘制方式,有很多种,D3D绘制 GDI绘制甚至还有更夸张的 ,建立一个MFC透明窗口盖上去绘制都可以。唯一的难度就是如何将3D坐标转换为2D坐标。 这个时候,我们先前找的视角(FOV)派上用场了。首先视角,经过测试,我们只找了横向视角,不过没关系,只要知道一个,另外一个视角可以简单的口算出来。视角有什么作用呢?前面了解到,在FPS中,视角可以理解为游戏窗口显示的画面,那么,可不可以这样理解? 如下: 假设游戏分别率为1024*768 1024为X768 为Y X视角即=2D 1024 Y视角即=2D 768 前边公式可以知道敌人在“圆”的位置,那么就很简单的可以算出敌人是否在视角内,视角也是"圆"的一面,只要敌人在这个面内,就在可视范围之内。 假设X视角为 π/2,那么视角和2D屏幕的比例即为——1024/(π/2),那么如何知道Y视角?768*(1024/(π/2))这个比例就可以轻松得到,反之知道Y视角,也可算出X视角。 那么接下来就可以直接在2D窗口上绘制方框了,假设敌人在x视角内坐标 0.56 的位置,那么0.56*(1024/(π/2)),即敌人坐在屏幕X坐标,Y坐标同理。最终实现透视效果如下:
反外挂建议:
Hook所有读内存函数,跨进程实现透视功能,必须要读取游戏内存,读取数据时多多少少会留下痕迹,可用作判断是否有第三方程序越权。
|