原文发表于百度空间,2010-02-22
==========================================================================
某游戏的保护系统会检测一些ARK软件的存在,因为ARK的恢复HOOK等功能会对游戏的保护驱动造成一些影响。因此,在该游戏的驱动中内置了一些ARK驱动(也可能有其它类型驱动)的特征黑名单,用以检测这些驱动是否存在,若存在就会提示非法模块,要求重启后方可正常进行游戏。无意中发现了一点线索,索性研究了一下该驱动中驱动黑名单的具体实现~~
一、 基本思想
(1)检测某些名称的驱动是否存在,这一部分有个黑名单
(2)检测驱动中部分代码的特征是否匹配,这一部分用另外一个黑名单
每一个驱动都要经过以上两重检查,具体的算法实现就是计算驱动名称或部分代码的Hash值,然后在黑名单中进行匹配。
所以,你看不到任何敏感的字符串。具体的Hash算法就是变形的CRC32,如下:
ULONG GetStringCRCHash(BYTE *Str, int Length) { ULONG crc=0; int i=0; for (i=0;i<Length;i++) { crc = (Str[i] | (crc << 8)) ^( crc_32_tab[crc >> 24]); } return crc; }
crc_32_tab就是标准CRC32算法所使用的那个表(不知道的请自行百度),一样一样的~~
二、驱动名称黑名单
当保护驱动加载时,它会枚举系统所有已加载的模块(遍历PsLoadedModuleList和遍历Driver对象目录两种方式,以及在LoadImageNotify中检测到有驱动加载时),获取驱动模块的名称。
根据名称计算时,传入的参数就是驱动模块名称和长度,比如像这样:
HashValue=GetStringCRCHash("IsDrv122.sys",strlen("IsDrv122.sys"));
然后检查返回的Hash值是否在黑名单中,名称部分的黑名单如下:
===============================================================
kd> dd sysBase+b248 //黑名单,里面有15个驱动 ef0be248 fe607766 354f6c90 3f4cf161 b57e2692 ef0be258 1a589e5b f456ff77 7a0fe6a5 dec1b385 //1a589e5b就是IsDrv122.sys ef0be268 14d19e18 78b9a23a f5a85224 dc2cc9a5 ef0be278 92a5e0c7 04e84e4f cc0c3575 00000000
这里有15个驱动的黑名单,具体是哪些我也不知道,因为这是个单向算法,无法还原,只能像暴破md5那样来计算。
比如1a589e5b就是IsDrv122.sys的Hash值,所以冰刃位于黑名单中,一旦与游戏同时开启就会提示非法模块。
至于其它的那些Hash是哪些驱动的,有兴趣的可以算一算~~
三、驱动特征黑名单
枚举所有驱动,取驱动中某个固定偏移处的一段代码,用上面提到的Hash算法计算其Hash值,然后在黑名单中匹配。
kd> dd sysBase+ba50 //从这里开始就是一个特征码表 eefe1a50 00003240 aca0a4ca 001e001e 07d10004 eefe1a60 00003e1c 7f1bc30f 00280028 07d10006 eefe1a70 00000404 3bd6931d 00280028 07d10007 eefe1a80 00004832 aca0a4ca 001e001e 07d1000a eefe1a90 0000f018 811298bc 00300030 07d1000c //811298bc是IsDrv122.sys中一段代码的Hash eefe1aa0 000027a8 7ba66c8a 00240024 07d1000d ..... eefe1ca0 000034a8 ee0a5b0e 00180fff 07d10038 eefe1cb0 000044a8 ee0a5b0e 00180fff 07d10039 eefe1cc0 0000370a b3e90ed7 00320fff 07d1003a eefe1cd0 0000370c a82425d5 00300fff 00000000
内容比较多,我只列出一部分,特征黑名单共有41个.
特征的每一项是一个0x10大小的结构,如下:
typedef struct _HASH_INFO{ ULONG Offset; ULONG HashValue; WORD EndLen; WORD HashLen; ULONG Unknow1; }HASH_INFO,*PHASH_INFO;
就是说,从驱动基址开始偏移Offset处,取长度为HashLen的代码计算其Hash,检查计算结果是否与HashValue匹配。
HashLen与EndLen相等的是精确匹配,就是说确定了就是Offset开始处长度为HashLen的代码的Hash
HashLen与EndLen不相等的是模糊匹配,表示从OffSet开始在一定范围内每次取HashLen长度的代码计算其Hash值
每一个驱动都要分别与这41个黑名单进行匹配,直至找到相匹配的特征项,都没有匹配到,当然就认为是没有非法模块啦~~
我根据它的算法计算匹配了一下,不幸冰刃又名列其中,811298bc是IsDrv122.sys中偏移0xf018处开始长度为0x30的一段代码的Hash~~
所以,从以上分析来看,此黑名单检测对于大部分使用固定驱动名称的ARK(冰刃、狙剑、RKU等)就是一个下马威,而且只改名字还不行。像XueTr这样每次都随机驱动名的也可以用特征码方法搞定(不过XueTr似乎并未出现在黑名单里),总的来说,这个方案还是不错的,
四、如何Anti它的检测?
方法一:涂抹黑名单中的Hash值
随便改成其它值,它计算完当然就匹配不到了,但是想找到黑名单不是太通用,毕竟特征不够明显
方法二:涂抹CRC32_Table
前面说了,这个表就是标准CRC32算法所使用的那张表,所以匹配起来特别容易~~
我们可以涂抹这张表,这样它永远无法计算出正确的Hash,所有的黑名单也就失去意义了,哈哈~~
附张图:游戏与冰刃共存:
================================================================
后记:当年以调戏各类ARK和*P为乐的日子。。。