前一篇提到了Warden的基本工作原理,这一篇从具体实现上来看看它到底是如何运作的。首先要说明的是,我在warden上没有花很多功夫,只是一些不完整的分析,也不保证我说的都是正确的。
在游戏客户端连接到game server进入游戏的时候(WOW为登录的时候),客户端和服务器端先negotiate一个新的session key(128位RC4)用于随后的warden通信。negotiate过程也是加密的(即上文提到的Maiev.mod)。这里重点要明白的是,客户端和服务器端之间warden的数据交换是加密的,密钥是动态生成的。
实际的作弊检测模块(一般称为warden mod,以后简称.mod)放在服务器端。warden session建立后服务器端用packet AE把.mod发送到客户端,客户端用packet 66做为应答。应答数据的格式跟具体的.mod有关,不是固定的,也不是简单的发回一个yes或no说有没有作弊,因此想伪造一个对所有.mod都通用的应答是行不通的。为了适合传输,暴雪把.mod做的非常紧凑,格式类似于DLL,由代码段、重定位段、IAT等数据构成。客户端收到的原始.mod数据是经过压缩的(一般只有几KB),解压后客户端根据最开始的一段数据对.mod进行装配(类似于dll的加载),然后调用.mod的检测入口函数执行真正的检测代码。
.mod header格式如下:
很显然,对于有经验的程序员来说,一看到Process32First/Process32Next就知道它要搜查可疑(外挂)进程,看到Module32First/Module32Next就知道他要搜查可疑(外挂)DLL,看到EnumWindows/FindWindowA这些就知道他要寻找特定窗口。不过需要指出的是IAT里列出API都会用到,比如这里它也可能只用Module32First/Module32Next。另一方面为了加大分析难度,也不是所有.mod用到的API在IAT里都会列出来。
在Warden出现的早期,检测外挂经常用的手段是服务器端用packet AE把需要检测的DLL名称列表传过来,.mod通过Module32First/Module32Next枚举游戏进程内所有DLL,如果你加载的外挂在它的黑名单上,你就被抓了。比如这个列表可能为:d2maphack.dll,d2hackit.dll,easymap.dll,那么如果你用easymap就倒霉了,如果用d2hackmap就没事-这就是为什么d2hackmap的完全版没做反检测,在很长时间里都没被抓的原因。值得一提的是,服务器端传过来的DLL列表并不是像“d2maphack.dll,d2hackit.dll,easymap.dll”这样的明文字符串,而是这些字符串的hash(SHA-1 hash),.mod枚举出DLL后比较的是它们的hash。也就是说,如果你想用sniffer抓包观察它到底想抓哪些DLL是很困难的。
在WOW中,早期的warden通过Process32First/Process32Next抓了一些外挂,(WOW!Sharp等)。由于侦测的是游戏之外的进程,暴雪的这种做法引起了广泛的争议。WOW的黑客Hoglund写的一篇文章:Is the warden spyware?被国外媒体(BBC等)广为报道。这事儿甚至惊动了著名的密码学家Bruce Schneier(经典著作《应用密码学》的作者),他也为此事发表了评论。Hoglund为此还专门写了一个监控程序:The Governor - KEEPING BLIZZARD HONEST-名字起的很牛,其实做的事情很简单,就是截获几个API喷一些信息而已。