CVE-2021-34486: Event Tracing for Windows (ETW) TimerCallbackContext 对UAF 漏洞分析
字数 1033 2025-08-12 11:33:49
Windows ETW TimerCallbackContext UAF漏洞分析 (CVE-2021-34486)
漏洞概述
本漏洞存在于Windows事件跟踪(ETW)机制中,具体是EtwpUpdatePeriodicCaptureState函数中的Use-After-Free(UAF)漏洞。攻击者可以通过精心构造的请求,控制分配和释放一个0x30字节的缓冲区,并随后重用该内存执行任意代码。
受影响组件
- 组件: Windows事件跟踪(ETW)机制
- 内核模块: ntoskrnl.exe
- 相关函数:
EtwpUpdatePeriodicCaptureState,PeriodicCaptureStateTimerCallback,SendCaptureStateNotificationsWorker
漏洞触发机制
1. 初始请求
- 内核通过用户传入的LoggerId获取对应的
EtwpLoggerContext对象 - 验证用户传入的Guid数组是否具有0x80访问权限
- 调用
ExAllocateTimer创建定时器:- 定时器回调函数:
PeriodicCaptureStateTimerCallback - 回调参数类型:
_WORK_QUEUE_ITEM
- 定时器回调函数:
- 激活定时器,等待超时触发回调
关键代码分析
__int64 __fastcall EtwpUpdatePeriodicCaptureState(unsigned int LoggerId, unsigned int DueTime, unsigned __int16 NumOfGuids, GUID *Guids)
{
// 如果没有定时器存在则直接创建定时器
if ( !LoggerContext_->ExTimerObject )
{
TimerContextInfo = (CONTEXTINFO *)ExAllocatePoolWithTag(NonPagedPoolNx, 0x30ui64, 'UwtE'); // 分配0x30字节缓冲区
TimerContextInfo_ = TimerContextInfo;
if ( !TimerContextInfo )
goto RETURN_ERROR_C0000017;
TimerContextInfo->LoggerId = LoggerId; // 设置LoggerId
TimerContextInfo->Unknown = v22;
TimerContextInfo->WorkItem.WorkerRoutine = SendCaptureStateNotificationsWorker; // 设置worker回调函数
TimerContextInfo->WorkItem.Parameter = TimerContextInfo; // 设置回调参数
TimerContextInfo->WorkItem.List.Flink = 0i64;
LoggerContext_->ExTimerObject = ExAllocateTimer((PEXT_CALLBACK)PeriodicCaptureStateTimerCallback, TimerContextInfo, 8u); // 创建定时器
}
ExTimerObject = (PEX_TIMER)LoggerContext_->ExTimerObject;
LoggerContext_->DueTime = 0xFFFFFFFFFF676980ui64 * DueTime;
ExSetTimer((ULONG_PTR)ExTimerObject); // 设置超时时间
LODWORD(LoggerContext_->ExTimerState) = 1;
// ...省略其他代码...
}
2. 触发UAF的第二个请求
- 传入当前用户没有权限访问的Guid
- 触发以下流程:
FREE_POOLS_AND_RESET:
GuidsPool = (void *)LoggerContext_->GuidsPool;
if ( GuidsPool )
{
ExFreePoolWithTag(GuidsPool, 0); // 释放内存池
LoggerContext->GuidsPool = 0i64;
LOWORD(LoggerContext->NumOfGuids) = 0;
}
// 检查Guid访问权限
if ( (_DWORD)NumOfGuids_ )
{
while ( 1 ) // 循环判断用户传入的guid是否具有访问权限
{
res_EtwpCheckNotificationAccess = EtwpCheckNotificationAccess(&Guids[v4].Data1,(__int64)&LoggerContext_->field_0[0x124]);
if ( res_EtwpCheckNotificationAccess < 0 )
break;
if ( ++v4 >= (unsigned int)NumOfGuids_ )
goto LABEL_30;
}
goto FREE_POOLS_AND_RESET; // 如果发现无权限的Guid,跳转到释放流程
}
3. 定时器回调触发UAF
- 定时器超时后调用
PeriodicCaptureStateTimerCallback - 该函数调用
ExQueueWorkItem将_WORK_QUEUE_ITEM放入系统队列 - 最终调用
SendCaptureStateNotificationsWorker函数 - 此时之前释放的内存可能被重用,导致UAF
漏洞利用条件
- 能够调用
NtTraceControl系统调用 - 能够控制传入的ETW_UPDATE_PERIODIC_CAPTURE_STATE结构
- 能够精确控制定时器触发时机
数据结构
触发漏洞的关键数据结构:
typedef struct _ETW_UPDATE_PERIODIC_CAPTURE_STATE {
ULONG LoggerId;
ULONG DueTime; // system time units (100-nanosecond intervals)
ULONG NumOfGuids;
GUID Guids[ANYSIZE_ARRAY];
} ETW_UPDATE_PERIODIC_CAPTURE_STATE, *PETW_UPDATE_PERIODIC_CAPTURE_STATE;
漏洞修复建议
- 在释放内存前检查定时器状态
- 增加引用计数机制确保内存安全
- 验证回调函数参数的有效性
攻击面分析
由于该功能存在于ntoskrnl.exe中,部分功能可以在沙箱中访问到,这使得该漏洞特别受攻击者关注。攻击者可以通过精心构造的请求序列,利用UAF漏洞实现权限提升或任意代码执行。