使用AFL模糊测试《反恐精英:全球攻势》地图文件的技术实践

本文详细介绍了如何利用AFL模糊测试工具对《反恐精英:全球攻势》的地图文件进行安全测试,发现了多个内存损坏漏洞,并分享了测试设置、技术细节和漏洞分析过程。

使用AFL模糊测试《反恐精英:全球攻势》地图文件

RealWorldCTF 2018有一个非常有趣的挑战叫做"P90 Rush B",这是对Valve游戏《反恐精英:全球攻势》中一种战术的影射。该挑战要求发现并利用CS:GO服务器使用的地图文件加载器中的漏洞。

在CTF期间,我利用了一个栈缓冲区溢出漏洞,后来另一个团队在他们的报告中很好地描述了这个漏洞。由于这个漏洞也影响了官方的CS:GO Windows客户端,符合Valve的漏洞赏金计划条件,实际上它只是一个旧报告的小变种,所以我在CTF结束后很快报告了它,并迅速得到了修复。

BSP文件格式与攻击面

CS:GO(可能所有Source引擎游戏)使用的地图文件格式称为BSP,是二进制空间分割的缩写,这是一种方便的n维空间对象表示方法。然而,这种格式支持的远不止3D信息。BSP文件由服务器和客户端共同处理,因为两者都需要地图信息的某个子集来执行各自的任务。这是一个远程攻击面,因为客户端会在服务器发起的地图变更时从服务器下载未知地图。

模糊测试设置

为了简单起见,我决定模糊测试Linux服务器二进制文件,而不是实际的客户端(也可以在Linux上运行)。用这种方法显然无法发现客户端特有的问题,但我希望能找到共享代码中的低悬果实。

我编写了一个简单的包装器来处理服务器二进制文件使用的共享库,最重要的几个是:

  • engine.so - 主要Source引擎代码(包含BSP解析器)
  • dedicated.so - 专用服务器实现(包含应用程序入口点)
  • libtier0.so - 可能与Steam/应用程序管理相关

AFL修改

我对AFL做了一些简单的修改:

  • 输入文件必须以.bsp结尾才能被GetModelForName正确解析
  • 需要能够指定自定义的fork服务器启动点
  • 增加等待fork时的超时乘数

漏洞分类与根因分析

我们需要将"好"的漏洞与不感兴趣的漏洞(如纯越界读取)分开。我基于调用栈进行了简单的去重,然后在Valgrind中运行每个独特样本。

经验总结

从这个小型项目中我学到了:

  1. AFL在QEMU模式下非常灵活,可以攻击特定代码段
  2. 输入文件大小非常重要,从300KB降到16KB后性能至少提高了5倍
  3. 分类对于筛选以前未经过模糊测试的代码库非常重要
  4. 堆上的内存损坏不是一个安全问题 :)

示例漏洞:CVirtualTerrain::LevelInit中的堆缓冲区溢出

在CVirtualTerrain::LevelInit中发生堆缓冲区溢出,因为dphysdisp_t::numDisplacements变量可能大于g_DispCollTreeCount,而检查这种情况的断言在发布版本中不存在。攻击者可以很大程度上控制堆内容,因此很可能被利用,特别是在Windows 7上许多模块没有启用ASLR的情况下。

[附上一个BSP文件,其中numDisplacements = 0xffff且g_DispCollTreeCount = 2,可以可靠地使csgo.exe崩溃]

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计