天天看点

驱动黑名单实现

一、 基本思想

(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算法计算其Hash值,然后在黑名单中匹配。

特征的每一项是一个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个黑名单进行匹配,直至找到相匹配的特征项,都没有匹配到,当然就认为是没有非法模块啦~~

四、如何Anti这种检测?

方法一:涂抹黑名单中的Hash值

随便改成其它值,它计算完当然就匹配不到了,但是想找到黑名单不是太通用,毕竟特征不够明显

方法二:涂抹CRC32_Table

前面说了,这个表就是标准CRC32算法所使用的那张表,所以匹配起来特别容易~~

我们可以涂抹这张表,这样它永远无法计算出正确的Hash,所有的黑名单也就失去意义了,哈哈~~

继续阅读