You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VC++实时ETW消费者:如何从PEVENT_RECORD的UserData获取文件名?

从PEVENT_RECORD的UserData获取文件名的实现方法

完全可以从PEVENT_RECORD的UserData字段提取文件名,ETW的Microsoft-Windows-Kernel-File事件会把文件操作的详细数据(包括文件名)封装在UserData中。具体实现需要以下步骤:

1. 确定目标事件ID

Microsoft-Windows-Kernel-File包含多个文件操作事件,常用的有:

  • 文件创建:EventID 256 (FileCreate)
  • 文件打开:EventID 257 (FileOpen)
  • 文件关闭:EventID 261 (FileClose)
    不同事件的UserData结构略有差异,但核心的文件名字段逻辑一致。

2. 声明对应事件的结构体

根据微软公开的ETW事件定义,以FileCreate(EventID 256)为例,对应的UserData结构体可按如下声明:

// 对应FileCreate事件的UserData结构体
typedef struct _FILE_CREATE_DATA {
    UINT32 FileNameLength;  // 文件名的字节长度(宽字符,所以实际字符数是长度/2)
    UINT32 FileNameOffset;  // 相对于UserData起始地址的偏移量,指向文件名起始位置
    // 其他可选字段:FileAttributes、CreationTime、FileSize等,可按需添加
} FILE_CREATE_DATA, *PFILE_CREATE_DATA;

3. 在ProcessEvent中解析UserData

在你的ProcessEvent函数中,先判断事件ID,再将UserData转换为对应结构体,最后通过EventRecordGetString安全提取文件名(避免直接指针访问的内存风险):

#include <Evntcons.h>

VOID WINAPI ProcessEvent(PEVENT_RECORD pEvent)
{
    wprintf(L"ProcessEvent: processID: %d\n", pEvent->EventHeader.ProcessId);

    // 处理FileCreate事件(EventID 256)
    if (pEvent->EventHeader.EventDescriptor.Id == 256)
    {
        PFILE_CREATE_DATA pData = (PFILE_CREATE_DATA)pEvent->UserData;
        PWSTR pFileName = NULL;

        // 调用API提取文件名
        if (EventRecordGetString(pEvent, pData->FileNameOffset, pData->FileNameLength, NULL, &pFileName) == ERROR_SUCCESS)
        {
            wprintf(L"File Created: %s\n", pFileName);
            // 释放API分配的内存
            LocalFree(pFileName);
        }
    }
    // 扩展处理FileOpen事件(EventID 257)
    else if (pEvent->EventHeader.EventDescriptor.Id == 257)
    {
        typedef struct _FILE_OPEN_DATA {
            UINT32 FileNameLength;
            UINT32 FileNameOffset;
            // 其他字段如OpenOptions等可按需添加
        } FILE_OPEN_DATA, *PFILE_OPEN_DATA;

        PFILE_OPEN_DATA pOpenData = (PFILE_OPEN_DATA)pEvent->UserData;
        PWSTR pFileName = NULL;

        if (EventRecordGetString(pEvent, pOpenData->FileNameOffset, pOpenData->FileNameLength, NULL, &pFileName) == ERROR_SUCCESS)
        {
            wprintf(L"File Opened: %s\n", pFileName);
            LocalFree(pFileName);
        }
    }
}

关键注意事项

  • 不同事件ID的UserData结构体字段可能存在差异,需对照微软官方ETW事件定义调整结构体声明。
  • 必须保证结构体的内存对齐与ETW事件数据结构一致,否则会出现解析错误。
  • 优先使用EventRecordGetString而非直接指针访问,因为ETW事件可能包含可变长度字段,该函数会自动处理内存偏移和字符串提取逻辑。

内容的提问来源于stack exchange,提问作者user846940

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 02:52:40