解密!起底非驱动类FPS游戏外挂的前世今生与原理和应对措施!「超详细版」文章很长,但文字很细腻,全文内容都是通过个人多年
文章很长,但文字很细腻,全文内容都是通过个人多年以来的了解及行业内部的广泛涉猎加之以实践总结的心路历程。无论您是否有相关编程经验都可以通过我事无巨细的文字逐步理解这其中的奥妙!让联机对抗类FPS游戏外挂不再是一个神秘且高端的代名词!
本文为优化总结之后的版本,原帖发布于CSDN上为同名原创@LeonXrek欢迎关注
一、引言
闲来无事,在浏览微信公众号的时候无意刷到了江西余江警方关于破获全国首例“AI自瞄”类外挂的案件,涉案金额达到惊人的3000余万。不得不感叹近年来AI相关科技发展之迅速及国内有关于FPS类及其他大类游戏作弊的黑产市场之大。
在工作学习之余,本人也曾对非内存对抗类的作弊技术有过浅薄的探究(因为Windows 内核编程学起来真的掉头发),故受到这次案子的启发,浅谈并整理一下我所了解的,近年来国内所出现过、现如今仍然流行的非内存对抗类的外挂程序其中的内部实现原理,以及这些外挂程序为了规避反作弊采取的措施和针对这些措施,以鄙人之拙见列出的反作弊一方可以采取的检测手段(矛与盾的攻防)。
对于游戏反作弊攻防领域,只有知己知彼,才能百战不殆。
本文意在科普除内存外挂以外的外挂作弊程序的实现原理,打破国内部分领域外挂过于“神化”的滤镜,为游戏厂商的反作弊工作提出更多思路,也为正义的游戏玩家科普一些相关领域知识武装自己,开拓见识。
文中提及到的所有源码、图片、技术皆为多年收集于各大论坛、QQ群等技术讨论平台,或间接或直接从相关“从业”人员口中得知或由相关程序文件结构反推得出。作者并非相关领域专业人士,文章如有遇到不严谨不正确的知识希望海涵。
本文的外挂类型仅局限于用作FPS类游戏作弊,其余如竞速类、格斗类、角色扮演类等其他类游戏方面的外挂不做涉及。
二、常见的五大类外挂
1、基于颜色识别的“找色”类外挂
(1)总述“找色类”外挂可以说是国内最早一批除了内存外挂以外的外挂类型。最早的找色自瞄外挂可以追溯到2015年甚至更早。随着大漠插件的问世再加上易语言这一简单易懂的编程语言的普及,简单易用且庞大的第三方模块库让早年间很多不是专门从事计算机领域的爱好者接触到了编写程序的快乐。在那个外挂仅仅是出于个人兴趣而免费制作出来供大家研究学习游玩的年代,找色类外挂就在各大编程论坛广为流传讨论。
(2)功能剖析找色外挂的核心就是找出游戏画面中敌人或者敌对目标身上的颜色特征,收集这些特征颜色,经过一系列函数处理,在屏幕中找到预先设置好的颜色值并给出这些颜色在屏幕中的精确坐标。得到了这些颜色坐标后,就可以对坐标进行二次加工从而开发出诸如“自瞄”、“自动扳机”、“磁性吸附”等功能。
如自瞄则是根据返回颜色的屏幕坐标值调用Windows api中有关鼠标移动的函数如Sentinput或者调用其他第三方键鼠盒子来模拟或者间接控制鼠标移动达到自瞄功能;自动扳机则是可以根据颜色坐标和当前鼠标坐标或者根据如穿越火线敌人会出现红色的名字,通过计算颜色坐标跟鼠标当前坐标的比例系数或者通过找红色名字的颜色色值在指定区域中是否出现来判断当前的时机是否需要开火以达到自动扳机的目的;磁性吸附则是稍微高级一点的自瞄功能,对于移动坐标进行二次处理如增加贝塞尔曲线、卡尔曼滤波、PID控制算法等,将生硬的鼠标移动轨迹软化,并设置自瞄激活范围区间,以达到当准星接近于设定的范围之内后进行轨迹平滑速度适中的“磁性自瞄”。
(3)原理分析找色外挂的原理其实也很简单。以国民级端游穿越火线举例。早期游戏中的人物颜色基调大多以暗色调为主,没有如今游戏里面那么多样式、不同颜色风格的人物。只要玩家装备了烟雾头盔这一道具后,游戏中人物的模型上就会默认戴着烟雾头盔(早期还不能隐藏装扮)。
带着烟雾头盔的角色或者不带烟雾头盔的早期角色模型中,其头部都有明显的“黑色”,不论你当前游玩的是什么地图,这个“黑色”的特征颜色并不会变,于是确认了这一特征颜色后,通过工具(比如QQ截图就可以显示鼠标处的颜色RGB色值)获得颜色的RGB数值(或者其他格式类型),调用现成的大漠插件或者其他的第三方库中有关的函数,就可以找到当前颜色在屏幕中的位置。
以大漠插件+易语言举例:
头部 = dm.FindColor (492, 374, 532, 408, #头部颜色值, 1, 0, x, y) 如果 (头部 = 1) sbwz = dm.GetCursorPos (x1, y1) x2 = x - x1 y2 = y - y1 + 7 dm.MoveR (x2, y2)
只需要以游戏准星也就是屏幕分辨率的二分之一的位置为中心向外扩张的矩形区域为范围,找到事先采集到的特征颜色,并返回颜色的坐标,拿到坐标再根据当前鼠标的坐标简单计算得到相对位移举例,就可以实现“自瞄”的功能。
这只是简单的找色实现,但是往往游戏的环境十分复杂,万一遇到了地图中恰好也有跟特征颜色值一样的颜色怎么办,那不就“误锁”了吗。聪明的人可能想到了,在找色之前加上前置条件,当触发前置条件后就可以证明当前是马上会与敌人“交战”的情形而不是咱们在地图中闲逛的时候。在穿越火线中,当鼠标准星移动到敌人附近的时候会显示敌人的红色名字,狙击枪开镜瞄准的时候同样也有大面积的黑色,那么就可以将上面的“红色名字”或者“黑色狙击镜”当作前置条件判断,利用FindColor函数,如果找到了上述的两个颜色,就代表即将遇敌,进而寻找特征颜色,那么就可以极大了规避“误识别”。将上面的代码优化一下。
人名 = dm.FindColorE (508, 426, 518, 440, “000000-000000”, 1, 1) 红名 = dm.FindColorE (508, 426, 518, 440, “A53A30-000000|cc4224-000000|f24a17-000000”, 0.9, 0) 如果 (红名 ≠ “-1|-1” 且 人名 ≠ “-1|-1”) 头部 = dm.FindColor (492, 374, 532, 408, #头部颜色值, 1, 0, x, y) 如果 (头部 = 1) sbwz = dm.GetCursorPos (x1, y1) x2 = x - x1 y2 = y - y1 + 7 dm.MoveR (x2, y2)
当然将上面的人名色值和红名色值换成黑色狙击镜色值就可以改成“狙击自瞄”。有了坐标可以再加上一些鼠标键盘的动作实现“遇敌快速击杀后换弹”、“狙击后切枪”等骚操作。
利用“寻找特征颜色,判断前置条件,得到坐标数据后进行二次开发”的核心思想,就可以创作出各种类型的“找色类”外挂,由于本文章以科普为目的就不进行展开了。
当然,在后来的找色类外挂发展中,有一些外挂作者另辟思路不仅仅局限于找色,基于图像二值化提取特征轮廓从而达到自瞄的目的开发的“轮廓自瞄”。
其底层原理其实也是基于颜色,只不过与“找色”的思想不同,轮廓自瞄首先会进行“滤色”,根据预先设置好的色值,比如HSV设定在色值图谱上的阈值,一个颜色最大值和最小值,然后在这个区间的颜色会予以保留,并且将这些也颜色过滤替换成白色,范围之外的颜色将会自动转化成黑色,滤色函数在opencv库中有现成的inRange函数进行滤色操作。
以瓦洛兰特游戏举例:
(左侧为处理之后图像 右侧为处理之前的图像)
滤色之后的图像中会存在很细微的白色轮廓。
接着创建一个4x4的矩阵,对滤色之后的图像进行膨胀操作,进一步扩大白色轮廓的面积为我们之后的处理做准备。
膨胀之后的图像由原先零散且稀疏的白色像素点变成现在面积较大且边缘连续的白色阴影面积,接着就可以使用opencv库中的findContours函数进行轮廓识别,识别出来的轮廓坐标再通过rectangle在原先处理之前的图像上绘制矩形就达到了识别敌人的目的。
拿到坐标之后就可以随心所欲在此基础上开发出各种功能。
2. 基于文字、图像识别的“自动识别压枪宏”
(1)总述鼠标宏这一技术的出现可谓令人又爱又恨。宏作为计算机运用过程中用于简化操作的一系列系统代码,其研发出来的本意是为了简化各类繁杂的操作,提高生产力。但是被游戏玩家用作游戏中,古往今来争议不断。严格意义上来说各类鼠标键盘宏并不属于外挂,它只是独立于游戏之外又或者内置在鼠标键盘PCB内存中的一段固定代码,最早用作《魔兽世界》里施法的同时使用游戏中的聊天系统发送信息等。后来在FPS游戏中又出现了“鼠标压枪宏”这一类的影响到了游戏公平性的宏。枪械后坐力作为FPS类游戏中一大游戏特色,玩家对于后坐力的控制,可以一定程度区分出玩家游玩游戏时的技术。
众所周知,FPS中的枪械后坐力粗略可分为水平和垂直方向后坐力。往往不同的枪械,垂直方向上的后坐力各有不同,但是垂直后坐力的数据是固定的,而水平后坐力往往是左右的不规则随机散步。所以可以采集不同枪械的垂直后坐力,得到散步坐标,再控制鼠标反向移动与后坐力抵消,就可以达到小范围的枪械抖动,如果收集到的后坐力数据十分精确,也可以做到几乎感受不出后坐力,不用玩家额外“压枪”就可以实现近乎“无后坐力”的效果。
(2)原理剖析压枪宏的核心就是“收集不同枪械的垂直后坐力散步坐标,反向控制鼠标移动再加以适当的水平控制”。所以收集到准确的枪械后坐力坐标就是开发时候的重点。出于这个目的,就可以开发一款工具去收集鼠标坐标的变化,或者使用另一种更加快捷的方式,那就是录制一段枪械的开火视频然后逐帧逐个弹孔去计算时间间隔与弹道偏移坐标量,虽然这样会很麻烦,但是仅仅是一些重复的工作。相反,工具就可以记录下每次鼠标改变的坐标和时间。如当按下预先设定好的按键开始记录时,调用win32 api循环获取当前鼠标坐标,并与上一次的鼠标坐标比较,计算出两次鼠标坐标的变化值并记录下两次变化的间隔时间,写出数据。在每一把枪械的一个弹夹的子弹打完之后停止鼠标记录,筛选保存在本地的坐标数据,将停止开火后的坐标与开火之前的坐标舍去,就能得到每一发子弹垂直后坐力的具体坐标,将所有的x、y轴坐标取反,控制鼠标移动就可以实现压枪。
这是Apex英雄中CAR步枪的部分垂直后坐力坐标数据
数据分别对应[x,y,time.sleep] 如0.0136 = 13.6 ms
"CAR": [[0, 0, 0.0136], [0, 3, 0.0136], [1, 1, 0.0136], [0, 1, 0.0136], [-1, 1, 0.0136], [1, -1, 0.0136], [1, 6, 0.0136], [1, -1, 0.0136], [0, 2, 0.0136], [1, 2, 0.0136], [1, 0, 0.0136], [-1, 2, 0.0136], [1, -1, 0.0136], [1, 3, 0.0136], [2, 3, 0.0136], [1, 0, 0.0136], [-1, 1, 0.0136], [1, 2, 0.0136], [1, 2, 0.0136], [0, 1, 0.0136], [0, -1, 0.0136], [1, 3, 0.0136], [2, 3, 0.0136], [1, 1, 0.0136], [-1, 1, 0.0136], [1, 3, 0.0136], [2, 2, 0.0136], [0, 1, 0.0136], [-1, 3, 0.0136], [1, 2, 0.0136], [-1, 1, 0.0136], [0, 1, 0.0136], [-1, 1, 0.0136], [-1, 2, 0.0136], [0, 1, 0.0136], [-1, 1, 0.0136], [0, 3, 0.0136], [1, 2, 0.0136], [0, 1, 0.0136], [-1, 0, 0.0136], [-1, 1, 0.0136], [1, 0, 0.0136], [-1, 1, 0.0136], [0, 1, 0.0136], [-2, 0, 0.0136], [-1, -3, 0.0136], [-1, 1, 0.0136], [0, 0, 0.0136], [-2, 0, 0.0136], [0, -1, 0.0136], [-1, 1, 0.0136], [0, 0, 0.0136], [-1, 2, 0.0136], [0, 0, 0.0136], [-1, 1, 0.0136], [0, -1, 0.0136], [2, 3, 0.0136], [1, -1, 0.0136], [0, 2, 0.0136], [0, -1, 0.0136], [3, 0, 0.0136], [1, -1, 0.0136], [1, 1, 0.0136], [0, -1, 0.0136], [2, 1, 0.0136], [1, -1, 0.0136], [0, 2, 0.0136], [0, -1, 0.0136]]
当然,完成基本压枪的功能仅仅是这类游戏辅助程序的基础。现在更加高级的压枪宏往往带有自动识别功能,不需要玩家自己手动切换当前使用的枪械,而是根据每一款游戏中对于枪械显示UI的位置,调用诸如OCR文字识别的API或者直接对比各类枪械图片的相似度来判断当前玩家使用的枪械,对应自动切换到每种枪械的压枪数据。甚至压枪程序更加灵活,可以根据玩家当前枪械剩余弹药量智能调整压枪数据。如一把30发子弹的枪械,当前枪械中剩余弹药量为25发,那么当玩家按下开火键的时候,压枪程序自动从枪械压枪数据的第5个数据开始模拟。
如果将一把枪的所有压枪数据都以数组形式存储:date_ak47[] = {......}
那么只需要:date_ak47 [ (all_ammo - ammo_count) ] 即可。
再根据实际游戏的特色,比如识别到手雷、近战武器的时候停止压枪模拟,加上更加细致化的前置条件判断。
3. 基于虚拟化技术的KVM-内存外挂
Kernel-based Virtual Machine的简称,是一个开源的系统虚拟化模块,自Linux 2.6.20之后集成在Linux的各个主要发行版本中。它使用Linux自身的调度器进行管理,所以相对于Xen,其核心源码很少。KVM已成为学术界的主流VMM之一。
KVM的虚拟化需要硬件支持(如Intel VT技术或者AMD V技术)。是基于硬件的完全虚拟化。而Xen早期则是基于软件模拟的Para-Virtualization,新版本则是基于硬件支持的完全虚拟化。但Xen本身有自己的进程调度器,存储管理模块等,所以代码较为庞大。广为流传的商业系统虚拟化软件VMware ESX系列是基于软件模拟的Full-Virtualization。
在游戏作弊领域,由于各种作弊功能的实现需要依靠获取游戏的内存数据,获取数据的方法大多是外挂作者编写或者购买专门用于绕过反作弊的内存读写驱动,从操作系统的内核态读取数据。但是这样的驱动程序往往受到了反作弊团队的高度重视,反作弊程序从某种方面来说可以是一个专门用于驱动对抗的程序,所以大部分情况下一个编写好的驱动往往才使用了很小一段时间就会被反作弊程序定位,进而封禁。驱动对抗领域反反作弊的成本居高不下,出于减小对抗成本,简化外挂开发流程,追求更加稳定的外挂使用周期,外挂作者将目光放在了KVM虚拟机技术。
简单来说,KVM就是将游戏程序放在一个干净的、专门提供给游戏运行的独立的虚拟机当中。专门用来运行游戏的虚拟机系统经过深度优化定制,完全移除了任何可能被游戏反作弊系统检测到并标记为虚拟机的特征,它与正常的操作系统无异,并且高度简化的操作系统,使得游戏调用计算机资源更加高效,往往游戏的画面表现、游戏帧率都有极大优化。
当游戏运行在虚拟机上的时候,游戏会正常地将游戏过程中需要的各项数据保存到内存当中,而外挂作者通过读取虚拟机的内存数据加上特定的偏移量,就可以间接地获取到游戏的内存数据。而这种读取的行为在游戏反作弊视角看来是完全“无痕”的,因为外挂是直接读取的虚拟机程序的内存数据,并没有直接读取游戏的数据,在反作弊看来,这只是操作系统正常的调用行为。虚拟机中运行游戏,主机上运行外挂,并且将诸如透视、物品信息等信息绘制在主机的屏幕上,再将虚拟机的游戏画面全屏,从视觉效果上与传统内存外挂的界面别无二致。
KVM技术,相当于将游戏及其反作弊放在了沙箱中运行,与本机的操作系统环境完全隔离,反作弊的各种检测手段在沙箱中便形同虚设,只能通过诸如行为检测等被动检测方法来检测异常行为,但往往外挂程序以及在这一方面做的滴水不漏,高度拟真的鼠标移动轨迹、非直接的敌方目标显示(比如CSGO的声纳外挂)再加上作弊者主观的高超“演技”,使得反作弊的行为检测变得不那么有效。
从代码层面来说,传统的外挂作者只需要想办法定位到虚拟机中游戏内存地址的偏移量,其余的写法直接参考内存外挂的正常写法即可实现KVM内存外挂。
但是KVM技术现如今不仅仅局限于内存外挂作弊,事实证明传统的找色外挂、新兴的AI外挂也可以结合KVM虚拟机技术达到规避反作弊检测的目的。
4. 基于物理外设硬件的DMA外挂
原理部分直接po了百度百科的内容过来。
直接内存访问(DMA,Direct Memory Access)是一些计算机总线架构提供的功能,它能使数据从附加设备(如磁盘驱动器)直接发送到计算机主板的内存上。
外设与存储器之间以及存储器与存储器之间的数据传输,通常采用程序中断方式、程序查询方式和DMA控制方式。程序中断方式和程序查询方式都需要CPU发出输入/输出(In/Out,I/O)的指令,然后等待I/O设备完成操作之后返回,期间CPU需要等待I/O设备完成操作。DMA在传输存储器和I/O设备的数据时,无须CPU来控制数据的传输,直接通过DMA控制器(direct memory access controller,DMAC)完成外设与存储器之间以及存储器与存储器之间的数据高速传输。
DMA传输原理
一个完整的DMA传输包括DMA请求、DMA响应、DMA传输和DMA结束4个步骤。DMA传输原理如图所示,图中I/O设备为源端设备,由I/O设备向目的端设备(存储器)传输数据,其DMA的基本传输过程如下:①CPU对总线控制器进行初始化,制定工作内存空间,读取DMAC中的寄存器信息,了解DMAC的传输状态[1];②I/O设备向DMAC发送DMA请求(DMA request,DREQ),DMAC收到此信号后,向CPU发出总线保持信号(HOLD); ③CPU当前总线周期执行结束后发出总线响应信号保持确认(hold acknowledgment,HLDA); ④DMAC收到总线授权后,向I/O设备发送DMA响应信号DMA确认(DMA acknowledgment,DACK),表示允许I/O设备进行DMA传送;⑤开始传输时,DMAC首先从源地址读取数据并存入内部缓存中,再写入目的地址,完成总线数据从源地址到目的地址的传输[1];⑥DMA传输完成后,DMAC向CPU发出结束信号,释放总线,使CPU重新获得总线控制权。一次DMA传输只需要执行一个DMA周期,相当于一个总线读/写周期,因而能够满足外设数据高速传输的需要。
DMA是所有现代电脑的重要特色,它允许不同速度的硬件设备来沟通,而不需要依于中央处理器的大量中断负载。否则,中央处理器需要从来源把每一片段的数据复制到寄存器,然后把它们再次写回到新的地方。在这个时间中,中央处理器对于其他的工作来说就无法使用。
DMA传输常使用在将一个内存区从一个设备复制到另外一个。当中央处理器初始化这个传输动作,传输动作本身是由DMA控制器来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的内存去。像是这样的操作并没有让处理器工作拖延,使其可以被重新调度去处理其他的工作。DMA传输对于高性能嵌入式系统算法和网络是很重要的。 举个例子,个人电脑的ISADMA控制器拥有8个DMA通道,其中的7个通道是可以让计算机的中央处理器所利用。每一个DMA通道有一个16位地址寄存器和一个16位计数寄存器。要初始化数据传输时,设备驱动程序一起设置DMA通道的地址和计数寄存器,以及数据传输的方向,读取或写入。然后指示DMA硬件开始这个传输动作。当传输结束的时候,设备就会以中断的方式通知中央处理器。
"分散-收集"(Scatter-gather)DMA允许在一次单一的DMA处理中传输数据到多个内存区域。相当于把多个简单的DMA要求串在一起。同样,这样做的目的是要减轻中央处理器的多次输出输入中断和数据复制任务。 DRQ意为DMA要求;DACK意为DMA确认。这些符号一般在有DMA功能的电脑系统硬件概要上可以看到。它们表示了介于中央处理器和DMA控制器之间的电子信号传输线路。
为了提高DMA设备的数据拷贝效率,针对DMA原理设计出来了PCIE接口的外置DMA设备,通过专用的芯片及独立的PCIE通道,加上诸如Type-C高速USB接口,使得数据拷贝速度再创新高。DMA设备的设计本意就是为了绕过CPU直接去访问内存数据,用于工业及其余领域中数据采集或者数据同步的作用。
由于FPS领域的游戏外挂,其核心就是对于游戏内存数据的读写,外挂稳定性也与读写行为是否会被反作弊系统检测挂钩,既然DMA可以直接绕过CPU,就可以直接物理绕过操作系统驱动层面的反作弊检测,基于内核编写的检测也失去作用。
DMA作弊往往是与双机技术相结合。DMA在获取到了主机上的游戏内存数据后,将数据同步传输到第二台电脑也就是副机上,副机上运行的外挂程序可以对这些数据进行分析,再将画面绘制输出到副机上,通过视频融合器:一种可以将外挂绘制画面与输入画面混合后输出的专门设备,将画面与主机的游戏画面融合,输出到显示器上。或者通过Kmbox等第三方键鼠设备,模拟鼠标移动控制主机达到自动瞄准等功能。
对于主机来说,既没有直接的内存数据读写,又没有可疑的重叠窗口绘制(内存外挂往往会把诸如人物坐标的框框和物品等信息绘制在一个透明的窗口上,再将窗口叠放在游戏的窗口之上,针对这一绘制行为反作弊有针对性检测),所以早期对于DMA的作弊,反作弊都不能起到有效的检测。
而且从外挂作者的视角来看,拥有了DMA设备之后,就不需要再将精力放在数据读取之上,因为传统的内存外挂作者往往需要费尽心思去寻找反作弊程序的检测代码,利用驱动和汇编知识将检测代码处理,比如直接用汇编语言将部分检测代码直接NOP掉。DMA设备往往会提供封装好的DLL供程序员调用,外挂作者只需要获取游戏的进程ID,再加上特定数据的内存地址和偏移量就可以轻而易举的获取到关键数据来开发外挂功能。
以Apex英雄举例:
int main(){const char* cl_proc = "cleaner.exe";const char* ap_proc = "R5Apex.exe";//const char* ap_proc = "EasyAntiCheat_launcher.exe";PrintVarsToConsole();//Client "add" offsetuint64_t add_off = 0x5650;std::thread aimbot_thr;std::thread actions_thr;std::thread itemglow_thr;std::thread vars_thr;std::thread recoil_thr;std::thread debug_thr;while(active){if(apex_mem.get_proc_status() != process_status::FOUND_READY){if(aim_t){aim_t = false;actions_t = false;item_t = false;recoil_t = false;g_Base = 0;aimbot_thr.~thread();actions_thr.~thread();//itemglow_thr.~thread();//recoil_thr.~thread();debug_thr.~thread();}std::this_thread::sleep_for(std::chrono::seconds(1));printf("Searching for apex process...n");apex_mem.open_proc(ap_proc);if(apex_mem.get_proc_status() == process_status::FOUND_READY){g_Base = apex_mem.get_proc_baseaddr();printf("nApex process foundn");printf("Base: %lxn", g_Base);aimbot_thr = std::thread(AimbotLoop);actions_thr = std::thread(DoActions);//itemglow_thr = std::thread(item_glow_t);//recoil_thr = std::thread(RecoilLoop);if (DEBUG_PRINT){debug_thr = std::thread(DebugLoop);debug_thr.detach();}aimbot_thr.detach();actions_thr.detach();//itemglow_thr.detach();//recoil_thr.detach();}}else{apex_mem.check_proc();}std::this_thread::sleep_for(std::chrono::milliseconds(12));}return 0;
代码中的apex_mem类就是基于封装好的DMA-DLL编写的内存读写类,而外挂代码中不再需要作者针对反作弊而去做出特别的处理,专注于功能的开发即可。
可笑的是,随着DMA技术的落地,再加上国外外挂作者积极地开源外挂源码,使得国内有越来越多的人冒着触犯刑法的风险,通过各种渠道获取到游戏最新版本的偏移量替代源码中过时的数据后,编译外挂进行贩售。并且DMA外挂的价格相较于传统内存外挂更加昂贵,一个月300、500的定价竟然是“性价比拉满”的选择。
起初DMA仅仅活跃于国外的逃离塔克夫、PUBG、CSGO游戏作弊圈子,后来国外的外挂作者将相关的外挂源代码开源在了Github上,并将DMA板子的原理图、固件源码一并开源。由Github和UnKnownCheats平台传入国内,国内外挂作者基于开源的源码二次开发将其应用到国服FPS游戏诸如穿越火线、逆战、CFHD、无畏契约等。外挂的种类也不仅局限于传统的透视自瞄,引申出来雷达、物品上色、无后座等花样繁多的功能,因为FPS类游戏关键数据都是本地计算的特性,获取了内存数据就可以基于数据进行无限的创作。
DMA硬件的固件烧录、配合DMA的外挂程序卡密售卖,加上各种第三方的键鼠盒子、外设,一条完整的双机、DMA外挂作弊黑产链条形成。在DMA作弊问世不久的年份,正常玩家可以说是饱受其害。
近年来随着诸如国内的ACE反作弊团队对于DMA外挂这一新型作弊方式的高度重视,DMA外挂在一定程度上予以了打击,但是早已铺开的庞大的黑产市场警醒着人们,这场新型反作弊的没有硝烟的战争只是开始,隐藏在地表深处的毒瘤还很庞大,外挂攻防之路还十分坎坷。
5. 基于Yolo及相关目标检测框架的AI自瞄外挂
(1)总述基于Yolo目标检测框架应用在FPS游戏上实现AI自瞄的相关视频在bilibili上最早可以追溯到2019年(实际上2016年Yolo问世后就有相关的帖子讨论将其应用在游戏作弊领域,但是最早都是将Yolo框架与搬砖类游戏结合比如梦幻西游、DNF之类的,利用目标检测完成自动化寻路、挂机脚本以及打金等功能),但是当时并没有太多人关注,Yolo框架刚问世不久,无论是效率、速度上都有欠缺,所以在FPS领域当时的效果仅仅是做到了类似于主机端手柄那样的辅助瞄准效果,并没有到达影响平衡性的地步。更多的是验证Yolo框架应用FPS领域自瞄等作弊功能的可行性。那时候国内流行的FPS游戏作弊还仅仅是停留在以驱动内存为内核的内存外挂作弊层面,DMA在那个时候也并没有宣传推广出来,游戏厂商的对抗仅仅是与内存外挂对抗。
后来随着Yolov4-tiny、Yolov5、v7、v8到如今yolov10等版本框架的推出,结合CUDA加速、TensorRT量化加速、Direct_ML加速等技术的加持,高效、快捷、准确度得以保证,配合专门针对FPS游戏制作的模型,AI自瞄这一新型外挂在21年之后得到疯狂传播,以cvcheat为代表的AI外挂制作团队借此疯狂敛财,并在23年9月落网。但是cvcheat的落网并没有抑制国内AI自瞄作弊的发展势头,随着更加便捷的易语言Yolo模块的封装,近年以易语言为主要编程语言开发的AI自瞄外挂遍布国内外挂市场。
相较于内存外挂需要较高的编程门槛,基于Yolo目标检测框架的AI自瞄的代码实现更加容易,并不需要过高的门槛,再加上互联网技术平台上唾手可得的教程,使得人人都可以制作,可与找色类外挂相提并论。
(2)原理剖析AI自瞄外挂大体分为8步:
(由于网上各种教程都很详细,这里就不再列出详细代码,仅仅从原理角度分析过程)
1. 实现循环截取电脑桌面局部图像,由于实现自瞄只需要以游戏准星为中心向外的正方形区域图像即可,不需要全屏截取以节省电脑资源开销,预留足够资源给游戏及Yolo推理。一般截取大小在320x320或者最大640x640范围的图像即可(320和640是由Yolo模型训练时候默认的推理大小决定的,大部分开源二改作者并不是精通Yolo目标检测框架,更多的只是应用层面的“程序员”,即便Yolo框架推理时候可以输入不同大小的图片,但是大多数作者并不会在此处理图像,所以大部分开源源码都是以输入320或者640尺寸图像为主)。常用到的截图第三方库有Opencv、Mss、DXGI、D3dshot,以及cvcheat团队制作的版本当中用到的注入Obs Studio,从显卡图像输出层Hook直接获取图像的方法获取截图图像,只要截图效率足够快,满足一秒采集60张图片,即稳定截图速度达到60帧以上就可以实现内存级别的AI锁死自瞄效果。相关代码可以参考以下帖子:
Python使用MSS截屏_python mss截图-CSDN博客
python调用dxgi实时快速截屏 - CSDN文库
C++ Windows下使用DXGI实现屏幕截图_dxgi截屏指定范围-CSDN博客
截图的方式有很多种,用作AI自瞄的常用截图方式有以上几种。
2.当获取到了截取的桌面图像后,就要对图片进行预处理。常做的就是将图片转化为numpy多维数组的数据结构,将图片四通道色域转化为三通道RGB格式。在python语言中,如果当前设备的Cuda加速可用,一般会使用nupy,即基于cuda加速的numpy库以加速图片处理的速度。将处理后的图片传入Yolo推理框架进行推理。截图常用多线程进行推理。截图一个线程、推理一个线程、监听鼠标键盘一个线程、移动一个线程。多线程不仅提高了截图、推理的效率,也可以将硬件资源利用最大化。
3.Yolo框架推理阶段。现阶段国内AI自瞄常用的Yolo推理框架有Yolov4-tiny,Yolov5-6.16.2版本,Yolo-X,Yolov8及Yolov9。其中最为流行的是Yolov5-基于CUDA加速以及TensorRT量化加速,针对NVIDIA显卡。对于AMD处理器及显卡常用Direct-ML加速,虽然效率远不及前两者,但是给了国内AMD显卡用户一个选择,虽然大部分用户还是NVIDIA显卡。确定使用的推理框架后,前往Github搜索相关关键字,有相应框架作者的部署源码,将源码拷贝,根据作者给出来的环境部署教程在本地部署CUDA加速工具包以及TensorRT环境,拷贝detect源码,将前文获取到的截图数据传入detect参数后即可得到预测框的坐标,拿到了坐标之后就可以进行下一步数据处理。
4.得到坐标之后,根据截取图片的大小可以反推出预测框坐标基于当前分辨率下桌面的精确坐标,这个坐标便是屏幕上识别出来的“敌人”的坐标。国内常用坐标计算方案是通过游戏FOV视角进行三维转二维坐标平面变换,因为得到的推理坐标是基于游戏内FOV缩放后的坐标,经过数学转换后便可以得到游戏内的具体坐标,即需要鼠标相对于当前准星需要移动的距离,也就是玩家需要操控准星从发现敌人到移动到敌人身上的操作。参考博客(只是原理示意,具体坐标公式我也没存): 视角与镜头焦距换算_视场角为160°左右的镜头焦距长度多少-CSDN博客
5.当获取到坐标之后,便是部位的处理。自瞄外挂可以根据需要选择瞄准头部、胸部等部位,这个坐标换算一般很简单。返回的预测框坐标里面包含了预测框的高度,大约高度x:0.22-0.25,也就是从预测框顶部向下大约三分之一的部分就是头部到脖子的位置;高度x:0.4-0.5大约是身子的位置,更多位置以此类推,按照比例计算。
6.经过一系列计算之后得到了需要移动的相对坐标,接下来便是调用鼠标移动部分。以国内游戏举例,如穿越火线,CFHD,生死狙击2等游戏,直接调用Win32系统Api中的Sentinput函数,通过系统预留的接口便可以模拟鼠标移动,在上面这些游戏里面都可以正常移动并且不会触发检测(貌似压根没有鼠标输入检测)。像是国服无畏契约,逆战这些游戏,利用Sentinput系统Api移动就不行了,无畏契约首先就屏蔽了这一虚拟鼠标模拟方式,逆战则是会检测模拟信号输入,触发反作弊。所以就需要用到了前文提到的Kmbox等一类的键鼠盒子。这种盒子的特点就是外置硬件设备并且可编程,也就是说程序员可以通过简单调用他们提供的dll,实现控制这些连接在电脑上的真实存在的键鼠硬件发送信号控制鼠标移动,因为这种鼠标信号的输入与咱们正常使用鼠标时候的输入是一模一样的,所以游戏反作弊并不会屏蔽,达到了自瞄的目的。
类似的键鼠盒子有:易键鼠、飞翼来、北京文盒、无涯键鼠盒子、Kmbox系列、Knight系列、幽灵键鼠、叛逆硬件。这些键鼠盒子均可在如淘宝的网购平台购买到。其中Kmbox-Net版盒子风头正盛,DMA外挂及AI外挂首选。当然,也早已被腾讯ACE反作弊盯上,至于制售硬件盒子的作者会怎样,咱们拭目以待。
7.轨迹拟真。得到的坐标并不能直接用作自瞄,因为生硬且快速的自瞄会直接触发反作弊针对玩家行为的检测,所以AI自瞄作者需要做到尽可能将移动的坐标“柔化”,让自瞄的轨迹不那么生硬,更加接近真人移动鼠标的轨迹,在保证了自瞄的准确性、速度的同时,降低反作弊的行为检测。常用的方法是将绝对移动改为相对移动,将移动的重点坐标进行二阶、三阶贝塞尔曲线拟真,PID控制算法拟真,非线性ARDC控制算法拟真后,将一段自瞄坐标分解为若干细小移动坐标分次移动(因为鼠标的回报率通常在1000HZ,也就是一秒可以检测鼠标移动1000次,所以这其中留给拟真轨迹的冗余量其实有很多,大可以把一段自瞄坐标分成100或者500次去移动,密集的点就可以形似看成曲线,也就更加接近真人的移动轨迹)来规避反作弊的检测。
截止截稿,又有一种新型模拟鼠标移动的方式便是基于操作系统内核态层面,也就是R0层的驱动IO模拟,给操作系统安装一个虚拟的人体学输入设备,通过从内核态模拟IO设备输入并将信号转接到当前连接电脑的设备上,也就是给正常鼠标的输入信号中插入一段模拟出来的信号达到额外的鼠标移动方式来实现。这个方法以及可以突破瓦洛兰特以及无畏契约基于屏蔽异常鼠标输入方式的反作弊措施,达到无需外置硬件即可实现单机AI自瞄的效果。
8.以上几个部分组合在一起就可以基本实现AI自瞄了,但是针对日益强劲的反作弊,AI自瞄外挂作者通常会对AI自瞄版本进行进一步深度包装以进一步规避反作弊的检测。事实证明在21年AI自瞄刚问世的时候,反作弊并没有针对AI自瞄有针对性检测,即便最基本的AI自瞄都可以规避反作弊,因为这一新型作弊方式没有对游戏数据进行读取写入,不会触发传统反作弊检测规则。随着AI自瞄逐渐走进大众视野,反作弊对于AI新型作弊有了针对性检测,作者们也想出来了很多技巧去进行反作弊攻防。
三、常用过反作弊检测手段及相应应对措施
1. 通用类过反作弊检测手段
1. 高频率更新软件本体(包括但不限于给主代码中插入无关代码以改变编译出来的成品特征、给软件本身添加压缩壳或者加密壳等,核心还是规避反作弊的特征扫描,定制类外挂稳定的秘诀也就是在此);
措施:大部分外挂的“更新”其实都属于不完全特征修改,因为往往只是改个名,加上部分垃圾代码等等,所以通过定位软件的内存特征就可以有效检测。针对加密壳加密后的软件也可以先标记再上传服务器解密,定位特征后针对性封禁。(外挂使用的加密壳大多都是vmp、se、sprotect等壳子,可以针对外壳类型定位)
2. 软件进行数字签名(网上有数字签名生成器,可以生成一些过期的非官方的数字签名,部分厂商早期反作弊会直接过滤掉有签名的软件,类似白名单,通过数字签名可以过一部分的反作弊,但是后来反作弊更加注重对此类盗版签名软件的检测,所以现如今的外挂作者更加偏向购买正版签名或者找第三方代签);
措施:验证签名密钥的有效性,验证密钥签发公司的合法性。
3. 利用内核驱动对软件进行文件隐藏、进程隐藏、防止反作弊扫盘读取软件特征(需要外挂作者会windows内核编程知识,较高端);
措施:反作弊从内核态进行驱动对抗。
4. 伪装软件为正规软件(如修改软件描述、图标、签名以达到模仿诸如QQ、微信、YY语音等正规第三方软件);
措施:其实从软件合法性角度来看,这样的伪装通常是拙劣的,也就只能骗一骗不是很懂计算机知识的小白。反作弊以正常扫盘特征的方式就可以检测出来。因为单从数字签名角度,可以模仿出高仿的数字签名,但是官方正版的数字签名是难以搞到的。除非外挂作者是公司的员工,那么这还会涉嫌一系列的后续法律隐患。
6. 附加进程伪装(通过将外挂编写成dll,修改dll加载的程序领空,以注入或者附加启动等方式随着正规第三方软件的运行而运行,由于其特殊性,外挂运行时候的进程是附加在了正规第三方软件的进程中,可以规避大部分反作弊基于进程扫描等手段的检测,事实上这个方法可以有效规避检测,但是其原理在网上的资料很少,只有部分作者会这一技术);
措施:类似内存外挂的检测手段,检测第三方程序是否被恶意注入或者软件启动时加载的文件是否被篡改。
7. 采取更加拟真的鼠标移动(如调用键鼠盒子或者给鼠标移动加入平滑算法、PID控制算法或者贝塞尔曲线函数让轨迹更加拟合真人操控鼠标的运行轨迹,以规避反作弊基于行为、轨迹的检测手段);
措施:收集真人移动曲线形成数据集,通过AI分析当前移动轨迹是否与真人相似来检测是否是由第三方外设硬件或者软件算法模拟的移动轨迹。针对常用的轨迹拟真函数拟真出来的曲线统一检测。检测标记第三方外设硬件特征。
8. 物理规避手段(将找色、自瞄的代码写到单片机中,通过HDMI线将单片机与计算机连接,单片机采集计算机的图像数据并传回,在单片机上计算结果并返回,操控鼠标完成自瞄);
措施:措施如上,从鼠标移动轨迹入手。
10. “自瞄鼠标”魔改鼠标PCB(有一些较为高端的找色自瞄作者通过魔改鼠标的PCB板,将上文中的单片机“内置”到鼠标中,将鼠标插到电脑上就自动进行识别,并且控制移动也是直接操控使用的鼠标,更加难以发现);
措施:定位硬件特征或者同上检测鼠标的异常轨迹行为。
11. 虚拟机、双机作弊(将游戏放在虚拟机主机中运行,本机副机运行找色、AI类外挂,通过虚拟机键鼠外设硬件间接或者直接控制虚拟机主机中的游戏程序达到自瞄的目的);
措施:针对检测虚拟机操作系统、双机串流软件、鼠标移动轨迹等。
2. DMA类外挂防反作弊措施
固件定制:较为主流的反反作弊手段,通过定制或者控制固件使用人数,来规避反作弊基于检测固件特征的检测手段。DMA硬件插到电脑上,操作系统会识别出来未知PCIE设备(开源或者通用固件,固件设计存在漏洞导致操作系统不能正确识别设备,市售普通DMA设备用的就是这一类固件,也是最容易被反作弊检测的一批固件),反作弊识别未知设备可以快速定位到DMA设备并予以封禁。更加高端的定制固件完善了开源固件设计时候的漏洞,并在代码中加入无关代码,更改固件的特征,并对固件的设备标识码予以伪装,高端硬件常常操作系统可以正确识别设备,不会在设备管理器中出现黄色叹号的未知设备。少数定制固件通过购买正规生产厂商的网卡、打印机设备,复制其固件的标识码,粘贴到DMA设备固件标识码中达到伪装设备来规避检测。
(正规设备出厂时候的识别码受统一的标准制约,外挂作者很难“凭空创造”这些标识码,当然可以随机修改VIDPID,但反作弊hi检测固件的依据很多,所以只能购买正规网卡设备来复制特征)。实践证明,通过固件定制规避检测是目前DMA类外挂最为直接有效的防反作弊手段。
针对固件定制这一手段,反作弊厂商可以综合多种检测手段,不要仅局限于固件的检测上。由于DMA设备在绕过CPU读取内存数据之前会和CPU通讯,申请内存读取,反作弊可以深入操作系统底层去监听这一请求来检测DMA设备。其次,扩大DMA固件的特征库,收集更多固件特征,配合警方对制作DMA设备、售卖DMA类外挂的作者予以线下抓捕。国内DMA设备可以很容易地在淘宝、拼多多等网购平台购买到,只有切断DMA设备来源、打击外挂程序源头才能从根本上遏制DMA类外挂。
其实,在游戏运行过程中,反作弊程序从底层屏蔽除显卡、声卡、采集卡以外的PCIE设备就可以很有效规避DMA类作弊,但是国内反作弊貌似没有在PCIE设备上做文章。对于伪装的DMA设备辨识起来也可以通过调用硬件看看是否能正常完成硬件功能来辨别是否是伪装的设备(比如网卡可以请求转发一段数据看设备是否可以正常转发等等)。由于本人对于DMA类外挂的了解比较浅显,并不能提供更加深入的意见参考,敬请谅解。
3. **AI类自瞄外挂反反作弊措施以及反作弊应对措施 **
OBS插件。由于OBS属于合法的第三方推流软件,常用于各大游戏直播平台主播推流游戏视频直播,所以常常位于反作弊的“白名单”之中。与前文提到的“伪装进程”的核心思想大同小异,通过编写OBS插件,将AI自瞄核心的截图、推理功能编写成DLL插件,以OBS插件的形式运行,这样AI作弊软件的进程就变成了OBS的进程,反作弊也不可能因为你电脑后台开着OBS而对你封禁,因为大多使用OBS的是没有开挂的主播。
针对这种以插件形式伪装进程方式来突破反作弊的,可以考虑从以下三点针对性检测:
轨迹检测:这个检测方式在腾讯的ACE反作弊系统已经有所实装,那便是检测当前玩家鼠标移动轨迹的加速度,以及综合分析轨迹的各方面数据,包括但不限于检测轨迹点迹密集区(AI自瞄的点迹常在以画面为中心向外的一个圆中心聚集,而正常玩家的点迹是相对均匀分布在画面各处)、轨迹连续程度、平滑度、关键点之间的延迟毫秒数(自瞄行为的关键点之间的间隔非常短,而人类的极限也就在100ms左右)等等。
驱动检测:更加底层的反作弊驱动。有攻就有防,如果反作弊可以对后台常驻软件进行深层的进程分析,那么就可以一定程度从伪装的进程中察觉出异常进程。(内核编程方面我不是专业的,所以不是很懂,只是个畅想)
文件检测:检测第三方软件的文件完整性。可以与常用的一些第三方软件开发团队合作,进行软件完整性检查,对于非法的插件予以标记检测。
采集卡图像采集并结合双机物理隔离作弊进程和高危行为。Cvcheat团队在落网之前开发的Cloud版本就是针对采集卡开发的AI自瞄程序。
(事实证明在主犯王某缓刑出来之后依然在卖针对AI作弊程序专用的采集卡盈利)
通过将本地的截图事件改为采集卡直接获取图像并传入第二台副机进行图像分析,调用外设键鼠控制主机移动。这样主机上类似DMA作弊,既没有AI自瞄的进程,又检测不到串流软件,可以物理上隔绝反作弊的检测。
针对采集卡或者双机串流类等物理隔离方案的检测:
针对第三方串流软件的检测。如Moonlight、NVIDIA推流等串流软件。双机作弊的底层需要采集到游戏画面的图像,如果前文提到的OBS可能有的主播需要用它进行直播,那么在游戏过程中,貌似没有需要串流软件的情况(向日葵那种远程软件除外)。可以直接屏蔽这些串流软件,以达到反作弊目的,具体细节需要按照实际情况加以区分和针对性方案。
给游戏画面加入肉眼不可识别的但是从数据层面会收到干扰的隐形噪音数据。现有图片保密技术可以给视频或者图片加入不可识别的隐形水印,可以从技术层面加大软件作者需要分析的工作量或者以技术壁垒使得短时间内外挂作者难以破解的技术加密游戏画面,让获取到图片数据后作者不能很容易地处理图片以传入推理进程进行正常推理,干扰推理结果。
针对鼠标轨迹的检测。
四、结语
起底非驱动类FPS游戏外挂的前世今生与原理和应对措施,撰写这篇文章的目的主要是想对于我过往在这一方面的认识与研究做出一个阶段性的总结,打破“高端定制外挂”的滤镜,科普相关技术知识让读过这篇文章的人们不再受到网上这些卖挂代理的蒙骗。
只要是游戏作弊程序就没有能长久稳定不封号的,封号快慢只是时间问题,当你投入相当一部分财力在游戏作弊上你就会慢慢明白我这句话的含金量。
游戏的初衷便是消磨时间、娱乐自己。贩卖游戏外挂盈利是写入刑法的刑事犯罪,不要为了追求一时的“快钱”,去断送你的未来。以文章开头引言提到的案件警醒,莫伸手,伸手必被抓!
相关知识
深度解析FPS游戏外挂+解决方案
梦幻西游前世今生2副本攻略推荐 前世今生2副本有什么通关技巧 干货
【转载】游戏外挂的编写原理和思路
剧情找找茬前世今生攻略
热血传奇百区新区什么时候开 热血传奇百区的前世今生 2023推荐
游戏外挂辅助制作方法原理
起底游戏外挂黑产:6000元可定制,厂商屡禁仍不止
游戏外挂制作原理
【FPS游戏设计初级指南】
令人“头疼”的外挂——浅谈网络游戏外挂的法律问题|游戏合规
推荐资讯
- 1老六爱找茬美女的烦恼怎么过- 4999
- 2博德之门3黄金雏龙法杖怎么得 4867
- 3《大侠立志传》剿灭摸金门任务 4312
- 4代号破晓官方正版角色介绍 4023
- 5赛马娘锻炼到底的伙伴支援卡事 3802
- 6闪烁之光11月兑换码大全20 3774
- 7原神原海异种刷怪路线-原神原 3547
- 8爆梗找茬王厕所特工怎么通关- 3542
- 9《我的世界》领地删除指令是什 3440
- 10原神开局星落湖怎么出去 原神 3426