Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2022-37969 — 针对 CVE-2022-37969 的概念验证漏洞利用程序,这是一个 Windows 通用日志文件系统驱动程序本地权限提升漏洞。演示了堆喷射、令牌窃取和任意内核写入,以实现 SYSTEM 权限。 | Kitploit
工具/GitHubGitHub/fortra/cve-2022-37969
权限提升内存取证漏洞分析漏洞利用二进制利用
GitHubfortra/cve-2022-37969

CVE-2022-37969

针对 CVE-2022-37969 的概念验证漏洞利用程序,这是一个 Windows 通用日志文件系统驱动程序本地权限提升漏洞。演示了堆喷射、令牌窃取和任意内核写入,以实现 SYSTEM 权限。

查看仓库
1353883年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2022-37969 Windows 本地权限提升 PoC

作者:Ricardo Narvaja 和 Daniel Kazimirow (Solid)

仅用于演示目的。完整的漏洞利用适用于易受攻击的 Windows 11 21H2 系统。

基于先前 Zscaler 发布的信息 的功能性 PoC。

查看相关文章 理解 CVE-2022-37969 Windows 通用日志文件系统驱动程序本地权限提升。

用法

理解 CVE-2022-37969 Windows 通用日志文件系统驱动程序本地权限提升。

利用过程详解:

  • 创建初始的 BLF 日志文件
    • 创建多个随机的 BLF 日志文件
    • 构造初始日志文件
    • 执行受控的堆喷射
    • 准备 CreatePipe() / NtFsControlFile() 方法
    • 内存准备就绪后触发漏洞
    • 读取系统令牌
    • 验证令牌
    • 用系统令牌覆盖我们进程的令牌
    • 以系统权限执行进程
    • 逆向补丁:分析结构体
    • 破坏 “pContainer” 指针
    • 重新审视补丁
    • 破坏 SignatureOffset
    • 破坏更多值
    • 控制用于读取 SYSTEM 令牌的函数
    • 写入我们自己的进程以实现本地权限提升
    • PoC 源代码

此处使用的场景是 Windows 11 21H2 (OS Build 22000.918) clfs.sys v10.0.22000.918

创建初始的 BLF 日志文件

第一步是使用 CreateLogFile() 函数在公共文件夹 (%public%) 中创建一个名为 MyLog.blf 的文件:

创建多个随机的 BLF 日志文件

然后,它使用循环创建多个名称随机的日志文件。

在循环内部,它调用我们的 getBigPoolInfo() 函数:

它调用 NtQuerySystemInformation(),第一个参数为 0x42 (十进制 66),该调用将在 v5 中返回关于 bigpool 中 raid 的信息,其结构体类型为 SYSTEM_BIGPOOL_INFORMATION。

我们需要调用此函数两次。第一次会返回错误,但会给出正确的缓冲区大小,以便第二次调用时获取所需信息。

Interfaz de usuario gráfica, Aplicación Descripción generada automáticamente

v5 将接收 SYSTEM_BIG_POOL_INFORMATION 结构体的信息。

bigpool 中分配的数量存储在第一个字段 Count 中,第二个字段是 SYSTEM_BIGPOOL_ENTRY 结构体的数组。

然后,我们遍历所有结构体,查找标签为 “Clfs” 且大小为 0x7a00 的项。

它将这些结构体的第一个字段(VirtualAddress)存储在一个名为 kernelAddrArray 的数组中,这些结构体具有 CLFS 标签和大小 0x7a00。从现在起,同时满足这两个条件的池被称为 “正确池”。

除了将每个 正确池 存储在数组中之外,它还将最后找到的 正确池 存储在函数参数 a2 指向的内容中。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

这样,a2 始终指向最后创建的具有 CLFS 标签和大小 0x7a00 的 正确池。

变量 v26 始终存储前一个找到的 正确池,因为它在调用 getBigPoolinfo() 之前等于 v24 (v26=v24),但退出此调用后,v24 会更新为最后找到的 正确池,而 v26 保持为前一个找到的 正确池。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

然后,它计算两个地址的差值,如果结果为负,则交换操作数以确保结果始终为正。

Interfaz de usuario gráfica, Texto, Aplicación Descripción generada automáticamente

这样,v32 将存储最后两个 正确池 的 VirtualAddress 之间的差值。

然后,它执行类似的操作,此例中 v23 初始为零,因此第一次执行 v23=v32。

下次循环时,v23 仍保持相同值且不为零,因此跳出并转到此处。

V32 包含最新的差值,v23 包含前一个差值,如果它们相等,则跳出并递增一个计数器,否则将计数器重置为零。

其目的是找到 6 个连续的 CLFS 标签和大小 0x7a00 的池,它们之间的差值相等,且该差值应为 0x11000。我们将会看到,当找到 6 个(因为从零开始)连续且距离相等的池时,它会给出它们之间的差值。

Texto Descripción generada automáticamente

在这里我们看到,它找到了 6 个连续的池,并退出了创建日志文件的循环。

在 “public” 文件夹中,我们可以看到创建的文件

构造初始日志文件:

我们的 craftFile() 函数打开原始文件 (MyLog.blf) 并修改它以触发漏洞。

修改文件后,必须更改 CRC32,否则会出现文件损坏错误。

该值位于文件的偏移量 0x80C 处。

执行受控的堆喷射

接下来,它执行堆喷射,使用 VirtualAlloc() 函数在任意地址 0x10000 和 0x5000000 上分配内存,并在第二个分配 (0x10000) 中,每 0x10 字节存储值 0x5000000。

准备 CreatePipe() / NtFsControlFile() 方法

它使用 CreatePipe() 创建一个匿名管道,并调用 NtFsControlFile(),使用 0x11003c 作为参数来添加一个属性,之后可以再次调用此函数,使用 0x110038 参数来读取该属性。

关于此方法的更多详细信息,请参见 此处

此处我们看到输入缓冲区就是我们要添加的属性,如果再次调用 NtFsControlFile() 并传入参数 0x110038,输出应该返回相同的这个属性。

在池中搜索创建的属性的标签(NpAt)

当找到它时,将该池的 VirtualAddress 保存在 v30.Pointer 中。

V30.pointer+24 指向内核池中的 AttributeValueSize,并将其保存到我们之前进行的堆喷射之一中。

其想法是写入该内核地址+8,以覆盖 AttributeValue。

Texto Descripción generada automáticamente

PipeAttribute 结构体的第一个字段是一个大小为 16 字节的 LIST_ENTRY,接着是一个指向属性名称的指针,大小为 8 字节,然后在偏移量 0x18 (24 十进制) 处是 AttributeValueSize 字段,这就是我们存储在堆喷射中的那个字段。

之后,我们在用户模式下加载 CLFS.sys 和 ntoskrnl,并使用 GetProcAddress() 找到 ClfsEarlierLsn() 和 SeSetAccessStateGenericMapping() 函数的地址。

下载工具