SSDT是Windows NT内核内部的调度表,用于处理对各种内部内核API的调用。通常,恶意软件会更改SSDT中的地址,以挂钩某些内核功能。在内存转储中发现这种东西真是太棒了,因为它可以让我识别出潜在的rootkit。有没有办法可靠地检测它们?需要哪种内存转储?

#1 楼

没有绝对可靠的方法,没有。

这两种方法都需要完整的转储,但是问题在于,恶意软件甚至可以钩住内核中负责的功能并修改要转储的内容。在这里有几件事情需要考虑。

如果恶意软件首先使用了一种简单的方法进行挂钩,则可以检测到它。假设该地址被一个替换为蹦床或另一个已加载图像的内部(甚至是非页面缓冲池中的另一个),那么您可以轻松地检测到它。您可以简单地枚举所有模块,然后尝试从SSDT内部找到地址指向的模块。如果是蹦床,则必须在此处拆解说明,以了解蹦床/跳床的位置。有大量的库可用于此目的,例如udis86

但是,如果恶意软件是偷偷摸摸的,则当加载到内存中时,它可以利用可执行文件(例如内核)中的自然间隙。 。您可能知道,PE文件(例如ntoskrnl.exe和friends)在磁盘和内存中的表示方式不同。磁盘上的文件格式更简洁。加载到内存中后,各节将按照PE标头中描述的特定方式对齐。这样,部分的实际大小(末端)和正确对齐的部分大小(“填充”)之间可能会存在间隙。这样就可以隐藏蹦床之类的东西,甚至比简单的蹦床还隐藏更多的外壳代码。因此,像上面这样的天真检查-即枚举模块并检查SSDT函数是否指向内核映像内-将不起作用。它会被足够复杂的恶意软件绕过,足以执行我刚才描述的操作。

可以想象,这意味着事物-就像所有恶意软件/反恶意软件一样-迅速成为军备竞赛。我强烈建议您连接一个内核调试器(通过Firewire进行WinDbg调试),并在进行调查时使受感染(或据称受感染)的计算机处于混乱状态。当您连接并闯入调试器时,调试对象将无法执行任何操作。这可以用于实时调试系统,并且-假设恶意软件不够偷偷摸摸还不能操纵kdcom-获得有价值的指标-它也可以用于直接创建故障转储(请参见WinDbg帮助)。如果您有确凿的证据表明机器由于其症状而受到感染,则很可能是该恶意软件并不十分复杂,您也不必在意我概述的特殊情况。但是,请记住,这种特殊情况只能被视为用于隐藏的许多可能情况中的一种。这么长的话很短:没有绝对可靠的方法可以做您想要的事情。

有时有人说-的确-攻击者只需要从无限数量的攻击中找到一个即可向量,而防御者只能防御有限数量的已知攻击向量。从中得到的教训应该是,作为反恶意软件行业(我从事的行业),我们总是可以声称我们在系统上没有找到任何东西,但是声称系统是干净的是错误的。


如何故意导致BSOD

可以告诉键盘驱动程序引起BSOD:

HKLM\CurrentControlSet\Services\kbdhid\Parameters


或(对于较旧的PS / 2键盘)

HKLM\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters


,然后将名为REG_DWORDCrashOnCtrlScroll设置为1。下次重新启动时,可以通过Ctrl + ScrollLk + ScrollLk强制蓝屏。在这种情况下,错误检查代码将是0xE2MANUALLY_INITIATED_CRASH)。


旁注:我本人还是在任何形式的FLOSS实现中都读过但从未见过,有些方法试图从磁盘上的映像重新加载内核并通过早期的初始化步骤运行它,从而创建一个“阴影” SSDT。然后,这将是原始的,并且可以用来“解钩”所有来自原始SSDT的一切。再说一次,还没有看到这种实现,但是据我对内部结构的了解,这似乎是有可能的。当然,这与检测/解除rootkit功能的想法相比,要比获取受感染系统的内存转储的初衷更为重要。

#2 楼

易失性可以基于任何受支持格式的内存映像来检测此类挂钩。

尤其是,线程插件将使用SSDT挂钩将任何线程标记为HookedSSDT,而ssdt插件将转储所有功能。在SSDT中输入名称,并给出包含每个功能的内核模块的名称。

另一种方法可能会检测到更细微的损坏,将使用WinDbg(在实时系统或崩溃转储),然后使用chkimg命令审核每个内核模块,例如:

chkimg -d nt


这将从MS Symbol服务器下载内核的原始副本并报告任何与内存版本的差异。请注意,这可能不会检测到每个线程SSDT中放置的任何挂钩。

评论


糟糕,感谢您抓住@ 0xC0000022L。固定。

–布伦丹·多兰·加维特(Brendan Dolan-Gavitt)
13年4月2日,下午1:28