【旧文章搬运】说说某游戏保护驱动中驱动黑名单的具体实现

原文发表于百度空间,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为乐的日子。。。

原文地址:https://www.cnblogs.com/achillis/p/10183329.html