Rootkit检测防守指南:第一集——内核驱动

admin 2026-06-30 10:38:40 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 该文档深入分析了利用存在漏洞的签名内核驱动绕过Windows驱动签名强制(DSE)和PatchGuard防护的rootkit技术,重点解析了KDU工具通过加载VirtualBox、CPU-Z等存在CVE漏洞的驱动实现在内核空间执行任意代码的攻击链。文章详细阐述了内存映射、页表遍历等底层技术原理,并提供了基于Sysmon配置的检测方案,帮助防御者识别此类高级持久化威胁。 综合评分: 85 文章分类: 恶意软件,内核驱动,漏洞分析,威胁情报,红队


cover_image

Rootkit 检测防守指南:第一集——内核驱动

rootkid8 rootkid8

securitainment

2026年6月26日 10:50 中国香港

在小说阅读器读本章

去阅读

| 原文链接 | 作者 | | — | — | | https://labs.jumpsec.com/a-defenders-guide-for-rootkit-detection-episode-1-kernel-drivers/ | Thom |

引言

早在我出生之前,rootkit 就已经成为获取机器持久化最精密且最成功的手段之一。而到了 2020 年,从系统权限提权到内核的方式更是日益简单化。最近 JUMPSEC 最年轻的红队研究员 @batsec再次提高了门槛,利用 rootkit 技术全面绕过 Sysmon。这种击败 Windows 事件跟踪(Event Tracing for Windows)的方法堪称一项惊人的技术壮举,Windows 日志的世界因此为之震撼。正因如此,我们将深入内核驱动 rootkit 的兔子洞,专门研究利用存在漏洞的内核驱动提权至 ring-zero 的方法。首先我们需要从一些基础知识讲起——Windows 内核如何实现纵深防御、如何绕过这些限制,以及网络防御者和系统管理员如何能像攻击者实施这些技术一样”轻而易举地”检测到它们(文末附有 Sysmon 配置)。

操作系统基础

可能有些人并不了解,操作系统和常见 CPU 定义了分层保护域来实现纵深防御。在 CPU 上执行的代码运行于这些环(ring)之一中,使用 CPU 模式加以区分——其中 ring 3 为用户态,ring 0 为内核态。

只有需要访问底层设备和硬件的特定应用程序才应被允许在 ring 2、1 和 0 中运行代码,这在 CPU 微代码层面以及操作系统层面共同强制执行。从理论上讲,这种特权域是可靠的,它的引入终结了用户态中一行有 bug 的代码就能导致整个系统崩溃的时代。然而,这些环在操作系统层面的实现——更糟糕的是在驱动层面的实现——相当模糊且缺乏文档,这为内核驱动漏洞利用开辟了一整片天地,使其成为后渗透阶段的权限提升和持久化机制。

编写内核模式驱动

我们将更深入地研究 Windows 如何处理设备驱动,由于这些驱动允许访问内核空间,我们有望揭示一些无需使用签名驱动即可在内核模式下运行任意代码的方法。说实话,编写一个内核模式驱动并不是什么特别困难的任务,但如果你想让它在目标系统上运行,就需要在操作系统上设置”测试模式”或者全局完全禁用设备驱动签名强制(DSE),这需要访问启动设置,或者通过运行以下命令并重启来完成:

bcdedit /set testsigning on

这两种技术大约和用大铁锤来掩盖电钻噪音一样隐蔽——不仅大多数普通用户会注意到设备上的 Test Mode警告,许多组织还会在全组织范围内限制此功能,如果他们没有这样做的话,那确实应该做了。当然,有一种方法可以隐藏水印和警告,但这同样是大锤方案,因为 bcdedit 会被任何有一定水平的蓝队捕获。

相反,我们需要绕过驱动签名强制(Driver Signature Enforcement)和 PatchGuard——两者都是 Windows 内核保护机制。一个用于阻止未签名驱动加载,另一个通过完整性校验防止驱动修改关键内核数据结构。话又说回来,任何蓝队都应该能够检测到具有过期证书的驱动的加载——SwiftOnSecurity 的实用 Sysmon 配置就能做到!

一个内核驱动加载器的故事…

为了探索这些内核模式驱动,我们需要回顾一下历史。过去曾经存在(现在仍然存在)一些出色的内核模式驱动基础项目,与我们正在调查的类似。这些项目由该领域的传奇人物 @hfiref0x 编写——我们将从 TDL(Turla Driver Loader) 开始。大约 4 年前,这个工具可谓是 rootkit 开发者的梦中情器。它是 DSEFix 的继任者——另一个由 hfiref0x 编写的驱动加载器,后者因修改了被 PatchGuard 拦截的内核变量而变得过时,因此成为了一个保证会蓝屏的生成器——虽然是个有趣的恶作剧,但不是我们所需要的。

TDL 作为一个功能完备的驱动加载器,可以独立于 Windows 加载器运行。作为副产品,它也击败了 64 位驱动签名强制。Turla 的魔法在于它用来将自定义驱动加载到内核内存的进攻性技术。它内置了一个存在漏洞的 VirtualBox 内核模式驱动版本,加载并利用该驱动来用定制构造的驱动覆写内核内存,随后跳转到 DriverEntry 函数开始执行。其过程可以可视化如下:

这种技术有些类似于进程镂空(process hollowing),但不同于创建挂起的线程并将我们的代码映射其中,我们加载一个已知驱动并使用 shellcode 将恶意代码映射到该内存段中。

这一技术出奇地简单,却极其有效。由于 VirtualBox 驱动已经在内核模式下运行,通过投放现在在内核空间运行的 shellcode,我们可以执行一条 mmov、一条 mmap 和一条 jump(实际上比这复杂得多,但为简便起见,我们依赖这三条指令)。这意味着目标内核驱动只需要具备读写物理内存的权限,再加上一个代码执行 CVE,就可以成为内核驱动加载的候选者。

显然 hfiref0x 从不休息,在 TDL 之后不久,Stryker 随即发布——又一个内核驱动加载器。这次的加载器被设计为利用 CPU-Z 驱动来实施,功能与前身非常相似。然后到了 2020 年,hfiref0x 再次出击,仅两个月前就发布了 Kernel Driver Utility(KDU),使用的是相同的概念,但如今 KDU 支持多个存在漏洞的驱动作为”功能提供者”(functionality providers)。名字起得很有意思,这些功能提供者就是通往王国的钥匙——如果我们希望能够检测到使用这种技术的 rootkit,就需要理解 KDU 如何加载这些驱动、如何利用它们,以及我们可以在系统上搜索哪些痕迹来检查是否被入侵。

简要查看 Github 上的信息,我们可以看到该项目关联了 4 个 CVE:

  • cve-2015-2291 —— IQVW32.sys Intel 以太网驱动漏洞
  • cve-2019-18845 —— MsIo64.sys 和 MsIo32.sys Patriot Viper 漏洞
  • cve-2018-19320 —— GDrv 图形驱动漏洞
  • cve-2019-16098 —— RTCore64.sys 和 RTCore32.sys 漏洞

README 中还提到了更多提供者:

  • ASUSTeK WinFlash 实用工具各版本的 ATSZIO64 驱动
  • ASRock Polychrome RGB 版本 1.0.4 的 GLCKIO2 (WinIo) 驱动
  • G.SKILL Trident Z Lighting Control 版本 1.00.08 的 EneIo (WinIo) 驱动
  • EVGA Precision X1 版本 1.0.2.0 的 WinRing0x64 驱动
  • Thermaltake TOUGHRAM 软件版本 1.0.3 的 EneTechIo (WinIo) 驱动

关于这些漏洞最值得注意的是,它们都暴露了 ring-zero 代码执行能力,从而启用了 KDU 的整个攻击链。更有趣的是 CVE-2019-16098 甚至在描述中明确指出:这些已签名驱动也可用于绕过 Microsoft 驱动签名策略来部署恶意代码。

作为声明,我们可以注意到 hfiref0x 表示 KDU 及所有类似工具实际上并非黑客工具,而是为驱动开发者提供便利的。一个懒惰的 AV 会将此工具标记为恶意软件,但从很多意义上说,KDU 确实是恶意软件,就像为系统管理员设计的远程访问工具也可能是恶意软件一样。

静态分析

警告:前方兔子洞

如果你对 KDU 源代码或枯燥的操作系统细节不感兴趣,请跳至动态分析。

审视 KDU 的源代码,我们可以看到驱动加载器实现了一个抽象层,每个提供者具有以下结构:

typedefstruct _KDU_PROVIDER {
    ........................................................
struct {
        provRegisterDriver RegisterDriver; //optional
        provUnregisterDriver UnregisterDriver; //optional

        provAllocateKernelVM AllocateKernelVM; //optional
        provFreeKernelVM FreeKernelVM; //optional

        provReadKernelVM ReadKernelVM;
        provWriteKernelVM WriteKernelVM;

        provVirtualToPhysical VirtualToPhysical; //optional
        provReadControlRegister ReadControlRegister; //optional

        provQueryPML4 QueryPML4Value; //optional
        provReadPhysicalMemory ReadPhysicalMemory; //optional
        provWritePhysicalMemory WritePhysicalMemory; //optional
    } Callbacks;
} KDU_PROVIDER, *PKDU_PROVIDER;

我忽略了一些无关紧要的字段,但从这里我们可以理解构建一个提供者需要什么,并且可以看到需要以下函数指针:

  • 读写虚拟内存
  • 虚拟地址映射到物理地址
  • 读写物理地址
  • 读取两个内核寄存器——PML4 和控制寄存器(Control Register)

到目前为止,为什么我们需要能够读写物理和虚拟内存地址应该相当清楚了,但 PML4 和控制寄存器是什么,为什么利用它们需要这些?如果你熟悉 Linux 内核,那么 PML4 就是内核用来将线性虚拟地址空间映射到进程的多级页表的基地址。为了在内存中替换我们的驱动,我们需要能够找到它存储在内存中的位置,这需要从页表中读取以找到目标驱动的地址空间。因此我们可以从 PML4 寄存器中读取此基地址。

控制寄存器对于内核开发者或汇编爱好者来说应该也很熟悉,但对于不了解的人来说——它是一个 64 位寄存器,具有一些虚拟内存映射和分页所需的重要用途。在既没有定义虚拟内存到物理内存的映射函数、也没有读取 PML4 的功能时,KDU 使用控制寄存器的值来查找页目录地址。这使其能够将虚拟地址转换为物理地址,从而遍历页表并覆写物理内核内存区域:

BOOL PwVirtualToPhysical(
    _In_ HANDLE DeviceHandle,
    _In_ provQueryPML4 QueryPML4Routine,
    _In_ provReadPhysicalMemory ReadPhysicalMemoryRoutine,
    _In_ ULONG_PTR VirtualAddress,
    _Out_ ULONG_PTR* PhysicalAddress)
{
    ULONG_PTR   pml4_cr3, selector, table, entry = 0;
    INT         r, shift;

    *PhysicalAddress = 0;

if (QueryPML4Routine(DeviceHandle, &pml4_cr3) == 0)
return0;

    table = pml4_cr3 & PHY_ADDRESS_MASK;

for&nbsp;(r =&nbsp;0; r <&nbsp;4; r++) {

&nbsp; &nbsp; &nbsp; &nbsp; shift =&nbsp;39&nbsp;- (r *&nbsp;9);
&nbsp; &nbsp; &nbsp; &nbsp; selector = (VirtualAddress >> shift) &&nbsp;0x1ff;

if&nbsp;(ReadPhysicalMemoryRoutine(DeviceHandle,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table + selector *&nbsp;8,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &entry,
sizeof(ULONG_PTR)) ==&nbsp;0)
&nbsp; &nbsp; &nbsp; &nbsp; {
return0;
&nbsp; &nbsp; &nbsp; &nbsp; }

if&nbsp;(PwEntryToPhyAddr(entry, &table) ==&nbsp;0)
return0;

if&nbsp;((r ==&nbsp;2) && ((entry & ENTRY_PAGE_SIZE_BIT) !=&nbsp;0)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table &= PHY_ADDRESS_MASK_2MB_PAGES;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; table += VirtualAddress & VADDR_ADDRESS_MASK_2MB_PAGES;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *PhysicalAddress&nbsp;= table;
return1;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }

&nbsp; &nbsp; table += VirtualAddress & VADDR_ADDRESS_MASK_4KB_PAGES;
&nbsp; &nbsp; *PhysicalAddress&nbsp;= table;

深入研究源代码后,我们实际上发现这里有两个驱动在起作用:一个受害者驱动(victim driver)和一个存在漏洞的驱动(vulnerable driver)。最初我以为它们是同一个驱动,但代码似乎先解压、加载并启动存在漏洞的驱动——这就是提供者——之后它调用 KDUMapDriver 尝试加载受害者驱动。

在 KDU 的情况下,受害者驱动始终是 Process Explorer 的 PROCEXP152.sys 驱动。它将 shellcode 引导注入到 PROCEXP152 的 IRP_MJ_DEVICE_CONTROL 回调中,然后最终卸载它,触发 shellcode 在 PROCEXP152 内部执行,从而允许目标驱动被加载到内核内存中。

最后,让我们看一下核心加载功能,我们想要理解 shellcode 的引导过程以及所使用的系统调用,以帮助我们确定可以实现何种级别的检测。这段代码片段是 KDUSetupShellCode中引导发生的地方:

//
// Resolve import (ntoskrnl only) and write buffer to registry.
//
isz = FileHeader->OptionalHeader.SizeOfImage;

DataBuffer = supHeapAlloc(isz);
if&nbsp;(DataBuffer) {
RtlCopyMemory(DataBuffer, Image, isz);

printf_s("[+] Resolving kernel import for input driver\r\n");
supResolveKernelImport((ULONG_PTR)DataBuffer, KernelImage, KernelBase);

&nbsp; &nbsp; lResult =&nbsp;RegOpenKey(HKEY_LOCAL_MACHINE,&nbsp;NULL, &hKey);
if&nbsp;((lResult == ERROR_SUCCESS) && (hKey !=&nbsp;NULL)) {

&nbsp; &nbsp; &nbsp; &nbsp; lResult =&nbsp;RegSetKeyValue(hKey,&nbsp;NULL,&nbsp;TEXT("~"), REG_BINARY,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DataBuffer, isz);

&nbsp; &nbsp; &nbsp; &nbsp; bSuccess = (lResult == ERROR_SUCCESS);

RegCloseKey(hKey);
&nbsp; &nbsp; }
supHeapFree(DataBuffer);
}

我们看到它首先查找 ntoskrnl.exe的基地址——这是内核映射内存区域的起始地址空间,包含重要结构,如系统上所有进程的映射内存页目录。这很重要,因为大多数进程监控工具应该能够检测到此映像是否被加载。之后它对传入的驱动文件名调用 KDUStorePayload——有趣的是,这个函数将一个字节缓冲区——即 rootkit.sys(或你指定的任何输入内核模式驱动)的原始字节——写入 HKLM中键名为 “~” 的注册表配置单元:

[4d5a是 MZ的十六进制表示,也就是 PE 映像头部中的魔术字节。]

这个注册表写入的一个有趣之处在于 KDU 不会自行清理,因此即使 KDU 被删除后,这个痕迹仍作为 IOC(入侵指标)留在系统上。我随手写了一个 PowerShell 脚本,你可以在附录中找到,用于事件响应人员检查是否有任何 PE 数据被写入注册表项。它将检测默认状态下的 KDU 以及任何修改目标配置单元的 KDU 基础变体,还有任何其他将可执行数据写入注册表的工具。

此外,我们在 victim.cpp的 VictimBuildName函数调用中发现,它将受害者驱动 .sys写入 %TEMP%目录:

LPWSTR&nbsp;VictimBuildName(
&nbsp; &nbsp; _In_ LPWSTR VictimName
)
{
&nbsp; &nbsp; LPWSTR FileName;
&nbsp; &nbsp; SIZE_T Length = (1024&nbsp;+&nbsp;_strlen(VictimName)) *&nbsp;sizeof(WCHAR);

&nbsp; &nbsp; FileName = (LPWSTR)supHeapAlloc(Length);
if&nbsp;(FileName ==&nbsp;NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
&nbsp; &nbsp; }
else&nbsp;{

&nbsp; &nbsp; &nbsp; &nbsp; DWORD cch =&nbsp;supExpandEnvironmentStrings(L"%temp%\\", FileName, MAX_PATH);
if&nbsp;(cch ==&nbsp;0&nbsp;|| cch > MAX_PATH) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
supHeapFree(FileName);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FileName =&nbsp;NULL;
&nbsp; &nbsp; &nbsp; &nbsp; }
else&nbsp;{
_strcat(FileName, VictimName);
_strcat(FileName, L".sys");
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }

return&nbsp;FileName;
}

这令人兴奋,因为文件写入也是检测恶意活动的可靠手段,特别是当写入操作被硬编码到可执行文件中而非动态生成或随机化时。

动态分析

现在我们已经从源代码中获得了一些 KDU 执行的潜在指标:注册表写入、文件写入和映像加载。我们将编写一些测试来验证这在实践中如何运作。为了测试这些提供者,我从源代码编译了 KDU,编写了一个充当微型示例 rootkit 的自定义内核模式驱动,并编写了一个批处理脚本,依次使用每个提供者重复执行 kdu -map -prv <ID> rootkit.sys。在每种情况下,我们分析系统变更——本例中使用 Procmon 和 Sysmon。

Procmon 测试展示了非常清晰的事件模式,如下图所示:

Sysmon 输出

使用我们定制的 Sysmon 配置,我们还看到 Sysmon 追踪到了以下事件:

  1. Create %TEMP%PROVIDER.sys
  2. Set HKLMSystemCurrentControlSetServices*PROVIDER*Start 注册表值为 3(手动启动)
  3. Set HKLMSystemCurrentControlSetServices*PROVIDERImagePath 为 %TEMP%PROVIDER*.sys
  4. *驱动已加载:PROVIDER.sys
  5. Create %CD%PROCEXP152.sys
  6. Set HKLMSystemCurrentControlSetServices*PROCEXP152*Start 注册表值为 3(手动启动)
  7. Set HKLMSystemCurrentControlSetServices*PROCEXP152ImagePath 为 %CD%PROCEXP152*.sys
  8. *驱动已加载:PROCEXP152.sys
  9. 未签名映像加载 rootkit.sys

如果我们理解 HKLMSystemCurrentControlSetServices中的注册表值是在 Windows 服务加载时设置和取消的,而且这些操作实际上并非由 KDU 代码直接执行,这一切就更容易理解了。相反,这些事件应该被理解为:

  1. 将存在漏洞的(提供者)驱动解压到 %CD%
  2. 启动它
  3. 将 rootkit 二进制数据写入 HKLM~注册表配置单元
  4. 将受害者驱动(PROCEXP152.sys)解压到 %TEMP%
  5. 启动它
  6. 未签名 rootkit 内核驱动被加载到内核内存

这几乎完全对应从源代码中可见的模式,尽管我们必须添加一条显式规则来捕获 HKLM~中的二进制数据。我们还可以注意到,这整个过程依赖于加载一个非常特定版本的存在漏洞的驱动——这意味着它会有一个特定的哈希值,我们也可以将其用作签名——而最后一个事件——一个未签名驱动仍然被加载到内存中——是发生可疑活动的最大告警信号。

结论

当然,我们本可以在一开始就直接执行 KDU 并立即获得 IOC,但那样有什么乐趣呢?相反,你现在应该理解了一种从系统权限提权到内核的较为通用的技术,内核级驱动加载器的内部工作原理(以及许多使用这种技术的类似工具),以及我们如何检测它们。

然而,这些检测技术并非特别高级,没有什么能阻止对手修补或调整这些变量使 KDU 写入不同的注册表配置单元或磁盘位置。更糟糕的是,让程序从内存中加载受害驱动和存在漏洞的驱动而不是先将它们转储到磁盘上——在这种情况下我们只能看到存在漏洞的驱动和受害者驱动服务的启动和停止。然后只需在加载前用任意空字节修补存在漏洞的驱动就会修改 Sysmon 检测到的哈希值。这就是网络安全生活的现实……在第二部分中,我们将研究 rootkit 使用的一些更高级的规避技术,以及如何也能检测到它们,敬请期待!

我在这个领域的全部功劳都归功于先行者们的工作。像 @hfiref0x、@fuzzysec,当然还有我们的老兄 @batsec这样的人不断寻找突破 Windows 内核的方法并使我们操作系统的完整性失效,这是这个世界众多奇迹之一。

附录

  1. 一些用于检测 KDU 及类似工具的 Sysmon 规则(DriverLoad 和 ImageLoad 事件可能需要你更新排除过滤器),因为被加载的存在漏洞的驱动通常看起来是合法的,在 PROCEXP152.sys的情况下甚至由 Microsoft 签名。
<Sysmonschemaversion="4.23">
&nbsp; &nbsp; <EventFiltering>
&nbsp; &nbsp; &nbsp; &nbsp; <RuleGroupname=""groupRelation="or">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <DriverLoadonmatch="include">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <ImageLoadedcondition="contains"name="MITRE_REF=T1014,NAME=Rootkit">Temp\PROCEXP152.sys</ImageLoaded>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Hashescondition="is"name="MITRE_REF=T1014,NAME=Rootkit">C06DDA757B92E79540551EFD00B99D4B</Hashes>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </DriverLoad>
&nbsp; &nbsp; &nbsp; &nbsp; </RuleGroup>
&nbsp; &nbsp; &nbsp; &nbsp; <RuleGroupname=""groupRelation="or">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <ImageLoadonmatch="include">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Signedname="MITRE_REF=T1014,NAME=Rootkit"condition="is">false</Signed>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <ImageLoadedname="MITRE_REF=T1014,NAME=Rootkit"condition="is">C:\Windows\System32\ntoskrnl.exe</ImageLoaded>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </ImageLoad>
&nbsp; &nbsp; &nbsp; &nbsp; </RuleGroup>
&nbsp; &nbsp; &nbsp; &nbsp; <RuleGroupname=""groupRelation="and">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <FileCreateonmatch="include">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetFilenamename="MITRE_REF=T1014,NAME=Rootkit"condition="contains">AppData\Local\Temp\PROCEXP152.sys</TargetFilename>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </FileCreate>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <FileCreateonmatch="exclude">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Imagecondition="contains">procexp64.exe</Image>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Imagecondition="contains">procexp.exe</Image>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Imagecondition="contains">procmon64.exe</Image>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Imagecondition="contains">procmon.exe</Image>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </FileCreate>
&nbsp; &nbsp; &nbsp; &nbsp; </RuleGroup>
&nbsp; &nbsp; &nbsp; &nbsp; <RuleGroupname=""groupRelation="or">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <RegistryEventonmatch="include">
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">PROCEXP152\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">RTCore64\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">Gdrv\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">ATSZIO\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">MsIo64\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">MsIo\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">GLCKIo2\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">EneIo64\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">EneIo\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">WinRing0x64\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">WinRing0_1_2_0\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">EneTechIo64\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">EneTechIo\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">NalDrv\ImagePath</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <TargetObjectname="MITRE_REF=T1014,NAME=Rootkit"condition="contains">HKLM\~</TargetObject>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </RegistryEvent>
&nbsp; &nbsp; &nbsp; &nbsp; </RuleGroup>
&nbsp; &nbsp; </EventFiltering>
</Sysmon>
  1. 一个供事件响应人员使用的基础 PowerShell 脚本,用于在目标机器上执行分析。该脚本简单地递归遍历整个 HKLM注册表空间,检查是否有任何可执行数据(通过检查 PE 头魔术字节和条目长度来判断)。

https://gist.github.com/thomjs/e7c5f6087ff646acf32dae89e9c7ecf2

参考资料

  1. https://blog.dylan.codes/evading-sysmon-and-windows-event-logging/
  2. https://github.com/hfiref0x/KDU/
  3. https://swapcontext.blogspot.com/2020/01/unwinding-rtcore.html
  4. https://eclypsium.com/wp-content/uploads/sites/2/2019/08/EXTERNAL-Get-off-the-kernel-if-you-cant-drive-DEFCON27.pdf
  5. https://www.secureauth.com/labs/advisories/gigabyte-drivers-elevation-privilege-vulnerabilities
  6. https://www.fuzzysecurity.com/tutorials/expDev/23.html

免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:securitainment rootkid8 rootkid8《Rootkit 检测防守指南:第一集——内核驱动》

评论:0   参与:  0