暴雪和黑客的战争五:Warden的不完全技术分析

前一篇提到了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格式如下:

struct  WardenModHeader_t
{
    DWORD cbAllocSize; 
//+00
    DWORD offsetFunc1; //+04
    DWORD offsetRelocAddressTable; //+08
    DWORD nRelocCount; //+0c
    DWORD offseModEntry; //+10
    DWORD _2[2];
    DWORD offsetImportAddressTable; 
//+1c
    DWORD nImportCount; //+20
    DWORD nSectionCount; //+24
    DWORD _3[1014];
// below follows code section
}
;

cbAllocSize指明为该.mod分配了多少内存(通过VirtualAlloc)。offsetRelocAddressTable给出 重定位表偏移。nRelocCount给出有多少项需要重定位(需要重定位的一般是一些全局变量)。offsetModEntry为.mod检测函数入 口,客户端把.mod加载好后调用这个函数进行检测,检测结果通过packet 66传回服务器端。offsetImportAddressTable给出IAT表的偏移,IAT表指明.mod需要用到哪些外部函数(一般是 Windows API)。分析.mod的第一步往往是观察IAT表,看看它调用的Windows API,有时候就可以简单的判断出这个.mod的行为。这是我截获过的一个.mod的IAT部分数据:

seg000:1B7730A0 aKernel32_dll db 'KERNEL32 . dll' , 0
seg000:1B7730AD aProcess32first db 'Process32First'
, 0
seg000:1B7730BC aIsbadreadptr db 'IsBadReadPtr'
, 0
seg000:1B7730C9 aModule32first db 'Module32First'
, 0
seg000:1B7730D7 aProcess32next db 'Process32Next'
, 0
seg000:1B7730E5 aGetmodulehandl db 'GetModuleHandleA'
, 0
seg000:1B7730F6 aCreatetoolhelp db 'CreateToolhelp32Snapshot'
, 0
seg000:1B77310F aModule32next db 'Module32Next'
, 0
seg000:1B77311C aClosehandle db 'CloseHandle'
, 0
seg000:1B773128 aLstrcmpia db 'lstrcmpiA'
, 0
seg000:1B773132 aUser32_dll db 'USER32
. dll' , 0
seg000:1B77313D aGetwindowtexta db 'GetWindowTextA'
, 0
seg000:1B77314C aEnumwindows db 'EnumWindows'
, 0
seg000:1B773158 aCharupperbuffa db 'CharUpperBuffA'
, 0
seg000:1B773167 aFindwindowa db 'FindWindowA'
, 0

 很显然,对于有经验的程序员来说,一看到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喷一些信息而已。

你可能感兴趣的:(war)