Win7、win10下利用ETW Trace跟踪用户的文件读写信息

       发表于freebuf :             http://www.freebuf.com/column/138862.html

                 Windows® 事件跟踪 (ETW) 是操作系统提供的一个高速通用的跟踪工具。ETW 使用内核中实现的缓冲和日志记录机制,提供对用户模式应用程序和内核模式设备驱动程序引发的事件的跟踪机制。自windows2000开始,各种核心的操作系统和服务器组件开始纷纷采用 ETW 对其活动进行检测。ETW 主要包含四种类型的组件:事件提供程序、控制器、使用者和事件跟踪会话。

TIM图片20170630165648.png

ETW主要包括3componentController, Provider, and Consumer,下面我就以文件读写为例进行讲解使用过程。

TIM图片20170630165836.png


一、        Controller

使用StartTrace在内存创建一个Event Session,这个时候session是没有关联任何Provider的。

 ULONG StartTrace(
  _      Out_   PTRACEHANDLE           SessionHandle,  
           _In_    LPCTSTR             SessionName,
         _Inout_ PEVENT_TRACE_PROPERTIES Properties
         );

看该函数的第三个参数类型PEVENT_TRACE_PROPERTIES,EVENT_TRACE_PROPERTIES的结构体定义如下:

typedef struct _EVENT_TRACE_PROPERTIES {
  WNODE_HEADER Wnode;
  ULONG        BufferSize;
  ULONG        MinimumBuffers;
  ULONG        MaximumBuffers;
  ULONG        MaximumFileSize;
  ULONG        LogFileMode;
  ULONG        FlushTimer;
  ULONG        EnableFlags;
  LONG         AgeLimit;
  ULONG        NumberOfBuffers;
  ULONG        FreeBuffers;
  ULONG        EventsLost;
  ULONG        BuffersWritten;
  ULONG        LogBuffersLost;
  ULONG        RealTimeBuffersLost;
  HANDLE       LoggerThreadId;
  ULONG        LogFileNameOffset;
  ULONG        LoggerNameOffset;
} EVENT_TRACE_PROPERTIES, *PEVENT_TRACE_PROPERTIES;

所以在创建调用StartTrace 之前需要分配一定的该结构内存,按照MSDN的介绍至少要填写该结构体的一下几个字段

TIM图片20170630170005.png


需要定义一个sessionname,即:

#define SESSION_NAME_FILE L”Test_FileTrace_Sample”

  ULONG uBufferSize = sizeof(EVENT_TRACE_PROPERTIES) + 20*MAX_PATH*sizeof(TCHAR);

 EVENT_TRACE_PROPERTIES     pTraceConfig  =  new char[uBufferSize];

ifpTraceConfig ){        

         ZeroMemory(pTraceConfiguBufferSize);

         pTraceConfig->Wnode.BufferSize = uBufferSize;

         pTraceConfig->Wnode.Flags = WNODE_FLAG_TRACED_GUID;

         pTraceConfig->Wnode.ClientContext = 3;

         pTraceConfig->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;

         pTraceConfig->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);

         pTraceConfig->FlushTimer = 1; 

wcsncpy((LPWSTR)((char*)pTraceConfig + pTraceConfig->LoggerNameOffset), SESSION_NAME_FILEwcslen(SESSION_NAME_FILE));

 

接下来就可以使用StartTrace去创建内存Session了,

TRACEHANDLE  hSessionHandle

HRESULT hr = ::StartTrace(

(PTRACEHANDLE)&hSessionHandle,

 SESSION_NAME_FILE,

pTraceConfig);

 

Controller的第二步是启动(API: EnableTrace)和停止(API: ControlTraceProvider(它是使用ProviderGUID来区分不同的provider的)。

如果StartTrace直接创建成功我们就可以直接调用EnableTrace去开启想要监控的事件Provider Guid,如果StartTrace创建失败过程中,如果返回的错误值是ERROR_ALREADY_EXISTS,就必须调用ControlTrace去停止当前已经的Sessions事件实例,如下

hr = ::StartTrace(

(PTRACEHANDLE)&hSessionHandle,

 SESSION_NAME_FILE,

 pTraceConfig);

 

  ifhr == ERROR_ALREADY_EXISTS )

{

                   hr = ::ControlTrace(

(TRACEHANDLE)NULL,

SESSION_NAME_FILE,

pTraceConfig,

EVENT_TRACE_CONTROL_STOP);

if (SUCCEEDED(hr)) {

 

hr = ::StartTrace(

(PTRACEHANDLE)&hSessionHandle,

SESSION_NAME_FILE,

pTraceConfig);

}

下面就是EnableTrace开启我们需要监控的事件Idwin7win10 我们一般使用的是EnableTraceEx,函数定义:

TIM图片20170630170106.png

注意第1345这几个参数,必须填写的参数

ProviderId [in]

GUID of the event trace provider that you want to enableor disable.

TraceHandle [in]

Handle of the event tracing session to which you want toenable or disable the provider. The StartTrace functionreturns this handle.

IsEnabled [in]

Set to 1 to receive events when the provider isregistered; otherwise, set to 0 to no longer receive events from the provider.

Level [in]

Provider-definedvalue that specifies the level of detail included in the event. Specify one ofthe following levels that are defined in Winmeta.h. Higher numbers imply thatyou get lower levels as well. For example, if you specify TRACE_LEVEL_WARNING,you also receive all warning, error,and critical events.

Value Meaning
TRACE_LEVEL_CRITICAL1 Abnormal exit or termination events
TRACE_LEVEL_ERROR2 Severe error events
TRACE_LEVEL_WARNING3 Warning events such as allocation failures
TRACE_LEVEL_INFORMATION4 Non-error events such as entry or exit events
TRACE_LEVEL_VERBOSE5 Detailed trace events

按照msdn的说明,我们监控的是文件读写,因为文件内核的ETW日志GUID

 

DEFINE_GUID/*90cbdc39-4a3e-11d1-84f4-0000f80464e3 */

         FileIoGuid,

         0x90cbdc39,

         0x4a3e,

         0x11d1,

         0×84, 0xf4, 0×00, 0×00, 0xf8, 0×04,0×64, 0xe3

         );

那么第一参数就是&FileProvGuid我们第三个参数就是前面创建hSessionHandle,第四个参数就是TRUE,第五个参数根据日志Level填写,我们选择的是TRACE_LEVEL_INFORMATION,那么代码就可以写为:

 

rc = ::EnableTraceEx(

                                               &FileProvGuid,

                                               NULL,

                                               hSessionHandle,

                                               1,

                                               TRACE_LEVEL_INFORMATION,

                                               0,

                                               0,

                                               0,

                                               0); 

                  if (ERROR_SUCCESS != rc) {

                           LOG_F(LS_WARNING<< “Failed to set file trace callback,rc: “ << rc;

                  }

一、        Consumer

  使用OpenTrace 打开事件通道

TIM图片20170630170241.png

第一个参数结构体 EVENT_TRACE_LOGFILE ,该结构主要定义着事件接受事件的方式,可以是文件也可以是内存,也可以是通过设置回调接口去获得信息,本文主要是通过毁掉接口是获取信息,调用方式为:

EVENT_TRACE_LOGFILE trace;

                   ZeroMemory(&tracesizeof(EVENT_TRACE_LOGFILE));

                   trace.LoggerName = SESSION_NAME_FILE;

                   trace.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;

                   trace.EventRecordCallback = ProcessRecordEvents;

                   trace.LogFileMode |= 0x10000000u;

 

                   hTraceHandle = ::OpenTrace(&trace);

                   if (hTraceHandle == NULL) {

                            LOG_F(LS_WARNING<< ::GetLastError();

                   }

EVENT_TRACE_REAL_TIME_MODE 表示实时获取数据,ProcessRecordEvents接收信息的回调函数,定义如下:

Void ProcessRecordEvents2(PEVENT_RECORD EventRecord)

接下来就是使用processTrace去开启监控,调用如下

rc = ::ProcessTrace(&hTraceHandle, 1, 0, 0);

 

调用成功会有数据进入回调ProcessRecordEvents函数

 EVENT_RECORD结构里有很多信息,主要用于区别不同日志信息,结构定义如下:

typedef struct _EVENT_RECORD {
  EVENT_HEADER                     EventHeader;
  ETW_BUFFER_CONTEXT               BufferContext;
  USHORT                           ExtendedDataCount;
  USHORT                           UserDataLength;
  PEVENT_HEADER_EXTENDED_DATA_ITEM ExtendedData;
  PVOID                            UserData;
  PVOID                            UserContext;
} EVENT_RECORD, *PEVENT_RECORD;

 

EVENT_HEADER里有进程相关的信息,有文件操作码的信息:

typedef struct _EVENT_HEADER {
  USHORT           Size;
  USHORT           HeaderType;
  USHORT           Flags;
  USHORT           EventProperty;
  ULONG            ThreadId;   线程id
  ULONG           ProcessId;  进程id
  LARGE_INTEGER           TimeStamp;
  GUID            ProviderId;
  EVENT_DESCRIPTOR EventDescriptor; 操作码描述
  union {
    struct {
      ULONG KernelTime;
      ULONG UserTime;
    };
    ULONG64 ProcessorTime;
  };
  GUID             ActivityId;
} EVENT_HEADER, *PEVENT_HEADER;

比如本文监控文件读写信息:

EventRecord->EventHeader.EventDescriptor.Id == 0xA表示读文件

EventRecord->EventHeader.EventDescriptor.Id == 0xB表示写文件

还有一个重要的数据结构是EventRecord-> UserDataLength 和EventRecord-> UserData,这个就是我们想要的日志信息的数据大小和具体数据

TIM图片20170630170311.png

得到的文件名是:\Device\HarddiskVolume1\Windows\System32\LogFiles\WM.I\RtBackup\EtwRTWDC_8060FileTrace000-9878654.etl

你会发现获得的名字是带Nt Device符号链接的路径的名字,因为这个是直接从windows的文件系统内打印的出来日志,所以带Nt Device符号的名字,只需要私用QueryDosDevice去转换获取对应的盘符的Nt Device链接去取代这个就可以获得应用层的对应名字,即

c:\ \Windows\System32\LogFiles\WM.I\RtBackup\EtwRTWDC_8060FileTrace000-9878654.etl

至此我们获取了windows的文件读写操作。 

         通过本文的方法我们还能监控很多windows的相应事件信息,ETW诊断的目的就是方便windows软件开发者在正常情况下或者无法预料的情况下能够通过ETW事件去分析诊断软件或者系统的各种问题,也可以用来对软件的性能进行完整记录与分析,ETW 使软件开发者能够动态地启用和禁用日志记录,轻松地在实际生产环境下进行详细跟踪问题并快速分析与解决。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值