黑盒测试,逐步分析《守望先锋》反外挂技术

发表于:2017-9-08 15:20

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:GameRes    来源:51Testing软件测试网采编

  前言
  《守望先锋》作为目前最为火爆的游戏,赢得了广大玩家的青睐。在天梯赛开放过后,其反外挂机制受到了玩家的挑战。本文本着学习态度,通过“黑盒测试”的方式逐步分析其反外挂机制,最后再结合目前市面上的一款外挂验证其反外挂机制的有效性。
  反外挂之文件结构
  首先从《守望先锋》的文件入手,找到其反外挂机制的载体。《守望先锋》的文件结构树如图1所示。
  《守望先锋》文件结构树
  文件结构很清晰明了,可执行的文件包括:
  1. OverWatch.exe,该文件即为《守望先锋》的主程序;
  2. OverWatch_Launcher.exe,该文件即为《守望先锋》的登录程序;
  3. Bink2w64.dll,该文件为图像处理模块;
  4. Vivoxsdk_x64.dll,该文件为声音处理模块;
  5. Ortp_x64.dll,该文件为网络传输模块。
  包含的目录包括Cache,data,ErrorReporting目录。根据其命名,大小来猜测,Cache存放的是玩家一些数据缓存,包含玩家的皮肤等等,data存放的就是模型资源,ErrorReporting存放的即为异常上报的模块数据。
  文件结构按照功能分类存放,因此可以推断,反外挂机制就存在与主程序OverWatch.exe里面。
  OverWatch.exe是一个纯64位的程序,因此32位的系统是不能运行《守望先锋》的。在安装过程中,战网也会提示仅支持64位系统,如图2所示。
 
  《守望先锋》仅支持64位系统
  而根据OverWatch.exe的Section表来看,并没有发现市面上常见的PE保护方式,如图3所示。
  OverWatch.exe Section信息
  各个Section的名称很规范,给人感觉就是很干净。但实际上并非如此,IDA直接导入文件后发现,里面的内容并不友好,如图4所示。
  IDA直接反汇编OverWatch.exe
  没有常规的入口代码,IDA并不能直接分析出程序的流程图。因此可以认定,OverWatch.exe是经过保护的。
  以上为《守望先锋》文件结构分析。和大多数网游不同,《守望先锋》是一个纯64位的可执行程序,这样不仅能够充分发挥64位系统的性能优势,而且对反外挂也有帮助,即增加了调试分析,以及编写外挂程序的成本。
  反外挂之收集外挂特征
  外挂运行,必然会有一些特征。因此对于外挂特征的采集是反外挂机制的基础。接下来将会通过一些黑盒测试来猜测《守望先锋》的检测机制。
  首先登场的是大名鼎鼎的“Cheat Engine”。直接使用CE6.3版本附加到OverWatch.exe,等待数秒后,游戏提示错误,如图5所示。
OverWatch检测CE
  看来OverWatch对于CE是有检测的。
  接下来换一个改版过的CE,还是直接附加上OverWatch,如图6所示。
 OverWatch未检测改版CE
  等待数秒,甚至经过几轮游戏过后,游戏并没有提示错误,CE也依旧能正常工作
  两个版本CE区别在于窗口标题,控件名称。
  接下来进一步分析,这次分析的目标为HOOK常见的获取标题API,观察OverWatch是否有调用,以及调用过后游戏是否提示错误,选取HOOK的API有EnumWindows,GetWindowTextA,GetWindowTextW等常见获取控件标题的API。
  结果如图7所示。在检测到含有标题为“Cheat Engine 6.3”的窗口后,游戏会提示错误。
  OverWatch获取窗口名
  那么除了获取窗口之外,《守望先锋》是否还枚举了进程名,模块名之类显性的特征吗?
  这次HOOK的API选取CreateToolhelp32Snapshot,ProcessFirst32,ModuleFirst32等一系列枚举当前系统信息的API。
  结果令人吃惊,在进行接近两个小时的游戏时间内,OverWatch并没有调用这些API来获得信息。
  从以上两个测试来看,OverWatch收集外挂特征的手段比较局限,仅通过获取窗口标题来判断,类似进程名的信息并没有上报(不排除暴雪每天采用不同的方式获取外挂特征),而外挂特征库也不够丰富,相同的工具,修改标题名就绕过了检测,如果外挂不够出名,也可能会检测不到。
  反外挂之代码完整性检测
  代码完整性检测可以说是反外挂方案的基石。代码完整性检测又分为对系统代码的校验以及对游戏自身代码的校验,以下就以系统模块D3D11.DLL以及游戏自身代码为例来测试一下《守望先锋》的检测。
  接下来再请出“Fraps”,Fraps是一款通用的屏幕录制软件,基本原理就是修改D3D获取到图像信息,行为和外挂无异。
  先运行Fraps,在运行《守望先锋》,会得到如图8所示的提示。
 
  OverWatch检测Fraps
  此时OverWatch.exe并未执行,提示该窗口的是战网客户端。点击确认过后,OverWatch.exe正常运行,并没有像之前CE那样提示错误,而Fraps也可以正常工作,通过观察d3d11.dll的完整性可以确认,Fraps确实修改了D3D11.DLL,如图9所示。
  D3D11.dll被Fraps修改
  带着Fraps持续游戏1个小时,也没有得到错误提示,过程中对d3d11的代码进行内存读观察,也并没有发现OverWatch访问的痕迹,由此可以推断:OverWatch并没有对D3D11.DLL做完整性检测,允许第三方软件对D3D11.DLL进行修改。
  修改系统代码,OverWatch并没有检测,那修改OverWatch自身的代码会不会有检测呢?
  首先观察OverWatch的内存分布情况,如图10所示:
  OverWatch内存分布情况
  可以发现在每一段具有可执行属性的内存后面都分配了一段不可访问的内存,使得整个程序的内存不是连续分布的,这样就不能直接Dump整块内存进行静态分析。值得注意的另外一个点为:所有的内存仅具有只读属性,并没有写属性。
  通过HOOK VirtualProtect还可以发现,在游戏执行过程中,OverWatch会修改所有代码段的属性为读执行,如图11所示。
  OverWatch设置.text代码段属性
  还有一个细节需要注意, OverWatch还HOOK了SetUnhandledExceptionFilter。HOOK逻辑如图12,13所示。
  OverWatch HOOK SetUnhandledExceptionFilter的逻辑
  OverWatch处理SetUnhandledExceptionFilter的逻辑
  处理SetUnhandledExceptionFilter的逻辑非常简单,即将OverWatch的异常处理地址返回了,并没有执行系统原先设置异常处理链的逻辑,这就说明OverWatch接管了自己的异常处理,并且不允许其他程序覆盖。
  以上种种细节表示:OverWatch接管了异常处理,并将代码修改为只读属性,任何只要修改代码的行为,就会触发只读属性异常并直接被OverWatch捕获到,也就是OverWatch对自身代码完整性校验是通过异常捕获来实现的。
  回到修改代码的目的:劫持调用。劫持调用的方法除了改代码,还有硬件断点的方式,而OverWatch并没有很好的防护,游戏过程中并没有发现调用ZwGetThreadContext,而硬件断点也没有占坑,如图14所示。
  OverWatch主线程硬件断点
  反外挂之反调试
  OverWatch反调试的方式比较单一,目前64位调试程序比较少,或许暴雪并不害怕外挂作者分析OverWatch。
  OverWatch会修改ntdll的DbgBreakPoint以及DbgUserBreakPoint,将原先的Int 3修改为NOP。由图8所示。
  Over线程对的系统HOOK点
  将这两个函数NOP掉之后,调试器没有办法直接附加上。
  在分析OverWatch反调试细节上还发现,OverWatch的导入表也是经过处理的。如图16所示,系统调用并没有直接显示出系统函数的地址。
  OverWatch内存中调用系统函数的方法
  图16标红的地址实际对应到的内存地址如图17所示,系统函数地址也经过简单的加减异或运算保护,使得CE不能够直接显示出来。
  OverWatch对系统函数做保护
  反外挂之加速检测
  影响FPS游戏平衡性的外挂功能还有加速,所谓“天下武功,无坚不摧,唯快不破”。OverWatch对加速的处理是相当专业的,这里首先点个zan!
  下面请出的是国内某系统加速软件,该软件原理为修改内核的时间计数达到了加速,如图18所示。
  驱动级别的系统加速
  这个加速器开启10倍加速时,通过QQ闪烁的频率可以明显感知。但是在游戏过程中,画面依旧平稳,人物移动速度不仅没有随着系统时间的加快而加快,更没有发生服务器修正人物坐标发生的跳帧。猜测守望先锋并没有依赖客户端的系统时间,而是有着自己的时间体系。当调整加速时间为20倍加速时,游戏直接提示错误。可见暴雪对于加速外挂真的是零容忍。
  风险点分析
  在本文最后,通过一款外挂的分析,来具体感受一下守望先锋的反外挂机制,也顺便通过这款外挂进一步说明FPS游戏面临的风险点。
  外挂功能界面如图19所示。
  OverWatch某款外挂
  外挂的核心功能有两块:方框透视和自瞄。
  外挂并没有向OverWatch注入功能模块,所有功能全部在进程外实现。
  实现方框透视需要知道敌人坐标,而外挂就赤裸裸的跨进程读取了人物的坐标,如图20所示。
  外挂读取游戏坐标
  自瞄的方法就更加简单了,将敌人坐标转换为屏幕坐标过后,直接通过鼠标模拟实现,如图21所示。
  
  外挂自瞄的方式
  简单粗暴,丧心病狂,回顾上述列举的反外挂手段,似乎是道高一尺魔高一丈。
  实际上,守望先锋的这款外挂反映的是整个FPS类游戏面临的两大外挂问题:透视和自瞄。
  透视又分为方框透视和人物透视。方框透视的原理简单来说分为三个步骤:
  1、分析游戏数据结构,找到世界坐标存储的具体位置;
  2、将三维世界坐标转换为二维屏幕坐标;
  3、将二维屏幕坐标绘制出来。
  3个步骤缺一不可,但关键的步骤是前两个,因为直接涉及到游戏逻辑。而《守望先锋》并没有对自己的代码做过多的保护,至少在内存中代码没有明显的保护痕迹,使用CE可以轻松逆向出关键的数据结构与逻辑。
  对于人物透视,《守望先锋》似乎更是缺少防范。人物透视的原理为劫持系统渲染的逻辑,劫持的方法最简单就是篡改D3D11.DLL的完整性。在上述的代码完整性检测案例中,Fraps修改了D3D11.DLL却没有受到即时的提示,这点侧面印证了守望先锋还可能会面临人物透视外挂的风险。除了关注自身代码完整性之外,《守望先锋》还需要关注一下系统代码的完整性。
  自瞄是方框透视的附带功能,但是比方框透视更难以检测。因为自瞄从原理上来说仅仅是模拟了鼠标的移动,并没有实际对游戏进行干涉。难以检测并不代表有很好的解决方案,《守望先锋》完全可以从源头和结果两个方面进行一个自瞄的检测,即从源头区分鼠标的移动是否是真实物理设备发出,从结果来判断瞄准的模式是否具有规律。
  如果《守望先锋》能在外挂特征收集以及代码保护方面肯下功夫的话,上述的外挂不会轻易扩散,排位赛也不会轻易受到影响。
  写在最后
  暴雪在客户端的反外挂机制比较基础,面对国内这种腥风血雨的外挂环境似乎有些水土不服,但是谁又能保证暴雪没有在游戏后台做了作弊行为的检测呢?目前暴雪的处罚方式也仅仅局限于秋后算账,永封帐号,缺乏实时处罚的策略。有些外挂还打出了“封号包赔”的口号,结果就是暴雪稳赚不赔,作弊玩家没有得到处罚,真正受苦的还是剩下的真心热爱游戏的玩家。反外挂道路漫漫,净化游戏靠你靠我靠大家。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号