是否有一种简单的方法可以检测 SSDT 是否已从内存转储中修补?

逆向工程 视窗 恶意软件
2021-06-10 05:28:13

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

2个回答

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

无论哪种方式,你需要一个完全转储,但问题是,恶意软件甚至可以勾负责功能的内核中,并修改什么被倾倒。这里有几件事情需要考虑。

如果恶意软件首先使用微不足道的方法进行挂钩,就可以检测到它。假设地址被替换为一个蹦床或另一个加载的图像内部(甚至在非分页池中的外部),然后您可以轻松检测到它。您可以简单地枚举所有模块并尝试找到 SSDT 内部地址所指向的模块。如果是蹦床,您必须拆开那里的说明以查看它跳跃/呼叫的位置。为此目的有很多库,例如udis86.

但是,如果恶意软件是偷偷摸摸的,它可以在加载到内存中时使用可执行文件(例如内核)内部的自然间隙。您可能知道,PE 文件(例如ntoskrnl.exe和朋友)在磁盘和内存中的表示方式不同。磁盘文件格式更简洁。加载到内存中后,这些部分以 PE 标头中描述的特定方式对齐。这样,部分的实际大小(结束)和正确对齐的部分大小(“填充”)之间可能会存在间隙。这留下了藏身之处类似于蹦床或比简单蹦床更多的外壳代码。因此,像上面这样的简单检查——即枚举模块并检查 SSDT 函数是否指向内核映像内部——将不起作用。它会被足够复杂的恶意软件绕过,以执行我刚刚描述的操作。

正如您可以想象的那样,这意味着事情 - 就像所有恶意软件/反恶意软件一样 - 很快就会变成一场军备竞赛。我强烈建议你附加一个内核调试器(WinDbg通过 Firewire 想到),并在你调查时让受感染(或据称受感染)的机器处于不确定状态。当您连接并闯入调试器时,被调试者无法执行任何操作。这可用于实时调试系统,并且 - 假设恶意软件还不够狡猾以进行操作kdcom- 获得有价值的指标 - 它还可以用于直接创建故障转储(请参阅 WinDbg 帮助)。如果您有确凿的证据表明一台机器被感染,由于它表现出的症状,很可能恶意软件并不是太复杂,您将不必关心我概述的特殊情况。但是,请记住,这种特殊情况下只能算一个出来的用来隐藏许多可能的情况下。长话短说:没有绝对可靠的方法来做你想做的事。

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


如何故意引起蓝屏死机

可以告诉键盘驱动程序导致 BSOD:

HKLM\CurrentControlSet\Services\kbdhid\Parameters

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

HKLM\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters

并设置了一个REG_DWORD命名CrashOnCtrlScroll1.

在下次重新启动后,您可以通过强制蓝屏Ctrl+ ScrollLk+ ScrollLk在这种情况下,错误检查代码将是0xE2( MANUALLY_INITIATED_CRASH)。


旁注:我也读过,但我自己从未在内核调试会话或任何类型的 FLOSS 实现中看到它,某些方法试图从磁盘上的映像重新加载内核并通过早期的初始化步骤运行它,从而创建一个“影子”SSDT。然后这个将是原始的,可以用来从原始 SSDT 中一举“解开”所有东西。同样,还没有看到这个实现,但根据我对内部的了解,这似乎是一种可能性。当然,这更多地是为了检测/解除rootkit 的功能,而不是为了获得受感染系统的内存转储的初衷。

Volatility可以根据其支持的任何格式的内存映像检测此类挂钩

特别是,线程插件会将任何带有 SSDT 钩子线程标记为HookedSSDT,并且ssdt插件将转储出 SSDT 中的所有函数并给出包含每个函数的内核模块的名称。

另一种可能会检测到更微妙的损坏类型的方法是使用 WinDbg(在实时系统或故障转储上),并使用该chkimg命令来审核每个内核模块,例如:

chkimg -d nt

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