A Primer On Event Tracing For Windows (ETW)
他太懒了
A Primer On Event Tracing For Windows (ETW) | by Nasreddine Bencherchali | Aug, 2021 | Medium
What’s ETW
ETW 是一个多用途、高速的追踪设施,使用内核中实现的缓存和日志机制。ETW 提供了追踪事件的机制,这些事件可以由用户模式应用程序或者内核模式设备驱动产生。 ——MSDN 杂志
换句话说,ETW 为应用程序和驱动提供了写和发布事件的能力。早期它的设计目标是用于性能监控和解决问题,近年来变为了防御者的检测源。
Architecture
假设有一个程序 A 执行了一些代码,并且希望记录它的操作。一种方式是使用 ETW 注册一个 Provider,这个 Provider 可以向查询它的人提供日志。为了与 Provider 交互,Consumer 必须启动一个 Trace Session。这个 session 会捕捉 Provider 发送的事件。Controller 负责管理这些事情,例如启动和停止一个 session。
Controllers
顾名思义,Controllser 负责控制关于 ETW 的一切内容,包括启动和停止 trace sessions 来启用或禁用 providers。一个常用的 controller 是内置的工具logman.exe
。
Providers
Providers 生成日志并写入 ETW sessions。应用程序可以注册为 ETW providers 来写入事件。ETW 支持四种 providers:
- MOF providers
- WPP providers
- Mainfest-based providers
- TraceLogging providers
本文将重点介绍 Mainfest-based providers,其他 proivders 可以参考About Event Tracing - Win32 apps。
一个 provider 写入事件之前,它需要描述事件是如何组织的。对 Mainfest-Based provider 来说,这些内容记录在 Instrumentation Mainfest 中,它包含了关于事件的所有信息,包括如何过滤,它们的值、ID和描述等等。这些细节可以参考 MSDN Writing an Instrumentation Mainfest - Win32 apps。
虽然存在一些解析器,但是理解每个字段的含义仍是有帮助的。首先,Instrumentation Mainfest 是一个 XML 格式的文件,所有内容都是 XML 元素,包括
<provider>
第一个元素是 provider,是必须的,通常具有以下属性:
- name,表示 provider 的名称,使用类似于 logman 的工具时会显示名称
- resourceFilteName / messageFileName,分别是包含了元数据/消息资源的 EXE 或 DLL 文件
- parameterFilePath,包含字符串资源的 EXE / DLL 文件
这个元素实际上提供的是 provider 的标识和必须的元数据和字符串,想要消费这个 provider 的工具使用这些来获取事件。
<channels>
如果熟悉 Event Viewer 的话可能对 channels 比较熟悉。
共有四种 channel:
- Admin
- Operational
- Analytic
- Debug
当我们想向特定 channels 写入事件时可以使用 channels 元素,它包含以下属性:
- child,唯一标识符,可以在其他元素中引用
- name,channel 名,通常使用 provider 名后加
/
和 channel 类型,例如Microsoft-Windows-Windows Defender/Operational
- type,上面四种类型之一
MSDN 上的一个例子:
1 | <channel |
<levels>
level 元素用于定义不同的日志级别,基于这些级别可以将事件分组。根据 MSDN,常用的日志级别如下:
win:Critical(1)
win:Error(2)
win:Warning(3)
win:Informational(4)
win:Verbose(5)
如上图,还存在其他一些预定义的和保留的级别。Providers 也可以定义级别,例如 Powershell provider 定义了 20 用于 debug
Consumer 可以使用这些级别作为一种过滤机制来获取指定级别的事件。
<tasks> & <opcodes>
这两个元素用于将事件按照 任务 或者 操作 分组。例如Microsoft-Windows-Kernel-Process
provider 定义了如下的 tasks
1 | ... |
Consumer 同样可以使用这些自解释的 tasks 来过滤出想要的事件。Tasks 一般包含 name,message 和 value 属性。
类似 tasks,opcodes 用于描述特定的操作,例如Microsoft-Windows-Powershell
provider 为 task connetct
定义了如下的 opcodes:
1 | <task name="Connect" message="Connect" value="1"> |
Windows SDK 中的 winmeta.xml 文件包含了一些预定义的 opcodes,也可以在 OpcodeType Complex Type -Win32 apps中找到。
<keywords>
类似于 level 和 task,keyword 也是一种分组机制,包括以下属性:
- message,描述 keyword 的字符串
- name,唯一的名称,例如
ProcessStart
- mask,只有一个 1 的二进制掩码
例如Microsoft-Windows-Kernel-Process
provider:
1 | ... |
<maps>
maps 定义了一个值和字符串之间的关系,在解析事件数据时作为一个转换机制。例如一个事件可能返回一些值,这些值与特定字符串对应,可以在 maps 中找到,```Microsoft-Windows-DNS-Client`` provider 中:
1 | <maps> |
<templates>
如果事件生成的信息是自解释的,就不需要额外信息描述事件。但当事件包含特殊信息时,就需要定义 template 来描述增加的字段。
例如我们有一些操作会生成一个事件,这个事件包括了一些动态数据需要映射
1 | Message : Correlating activity id's. %n %t CurrentActivityId: %1 %n %t ParentActivityId: %2 |
Consumer 需要用合适的值来替换其中的%1
和%2
,这时需要定义的模板如下:
1 | <template tid="T_CorrelationEvent"> |
其中%1
代表 currentActivityId,%2
代表 parentActivityId。template 的属性包括类型信息和它是否呗映射到类似于 maps 的元素。
<event>
类似于写程序时定义变量、定义函数和类的过程,以上的元素也是在做类似的事情。定义了事件如何组织后,接下来就是定义事件本身。
对于每个事件都必须定义 event 元素,这个元素必须包含一个标识符或者唯一的值(这个值通常称为 Event ID 或 EID)。
例如Microsoft-Windows-Kernel-Process
provider:
1 | <event value="1" symbol="ProcessStart" version="0" task="ProcessStart" opcode="win:Start" level="win:Informational" keywords="WINEVENT_KEYWORD_PROCESS" template="ProcessStartArgs"/> |
这里包含了必须的 value 属性,意味着如果我们想捕捉这个事件我们可以搜索Event Id = 1
。另外外门也可以看见前面提到的各种属性,它们引用了之前的定义。这些可以用于 consumer 的过滤。
<localization>
例如以下 task 元素中:
1 | <task name="ProcessStart" message="$(string.task_ProcessStart)" value="1"/> |
message 的值时一个变量,引用了定义在 localization 元素中的字符串:
1 | <localization> |
使用 provider mainfest 的例子可以更好了解这些,例如ETW-Resources/Microsoft-Windows-Kernel-Process.mainfest.xml at main masbench/ETW-Resources。
Trace Sessions / Trace Files (.etl)
Trace sessions 只是一种启动/预定一组 providers 的机制,可以包含一些配置。这些配置包含 session 是否是实时的还是写入 trace files (.etl) 等。
Trace sessions 有两种 keyword 掩码类型来启用 providers(稍后解释):
- Keyword(Any):可以指定一个 8 字节的十六进制掩码表示一个或多个 keywords
- Keyword(All):一个可选的 8 字节的十六进制掩码,进一步限制 ETW providers 写入的事件类别
假如存在以下三个关键字:
- READ: 001
- LOCAL Events: 010
- REMOTE Events: 100
和两个事件:
- 事件 1,使用 READ 和 LOCAL keywords (011)
- 事件 2,使用 READ 和 REMOTE keyword (101)
Keyword(Any) 让我们可以指定一个掩码来过滤出掩码符合的事件。
比如我们想要读取事件,我们可以将 Keyword(Any) 设置为 001,这样就可以获取所有掩码最后一位设置为 1 的事件,即事件 1 和事件 2。如果我们需要更精确地过滤事件,可以将 Keyword(All) 设置为 101 来获取事件 2 或者设置为 011 获取事件 1。
换句话说,Any 过滤器匹配的事件掩码至少包含了指定的位。而 All 过滤器要求事件掩码所有的位都符合。这可以帮助我们了解捕捉了哪些事件。
Consumers
Consumers 时读取或监听 Trace Files / Sessions 的一个程序。一个常见的 consumer 时 Event Viewer。
Interacting With ETW
Logman
logman 是一个 Windows 内置的工具,作为 controller。
Windows 中默认有超过 100 个已注册的 providers 和至少 20 个 trace sessions。使用 logman 可以列出它们:
1 | > logman query providers |
也可以查询指定的 provider
1 | > logman query providers "Microsoft-Windows-WMI-Activity" |
其中 keyword 和 levels 在上面已经提到,PID 和 Image 包含了正在使用这个 provider 发送信息的进程。
也可以查询 trace sessions:
1 | > logman.exe query -ets |
查询具体某个 trace session 的 type 和 providers 的消息:
1 | > logman.exe query "EventLog-System" -ets |
使用这些命令,我们可以:
- 获取可用的 provider 的列表,可以对比来发现 Windows 新版本中新增的 provider
- 获取 provider 的重要信息,例如 keyword 和 levels
- 列出 trace sessions,或许可以检测出安装的一些软件(EDR 或者 AV)
Performance Monitor
虽然使用 logman 可以创建、开始、停止和更新 trace sessions,但是更快速的方法是使用 Performance Monitor。
双击会话可以看到相关的所有信息,也可以修改这些 sessions,添加或删除 providers 和通过 User Defined 菜单创建新 session。
Powershell (.NET)
使用 Powershell(.NET) 中的命名空间System.Diagnostics.Eventing.Reader
,System.Diagnostics.Eventing.Reader Namespace。
列出所有 providers
1 | [System.Diagnostics.Eventing.Reader.EventLogSession]::GlobalSession.GetProviderNames() |
列出特定 Provider 的属性
1 | # [System.Diagnostics.Eventing.Reader.ProviderMetadata]("Microsoft-Windows-Powershell") |
查询特定的对象
1 | # [System.Diagnostics.Eventing.Reader.ProviderMetadata]("Microsoft-Windows-Powershell") | Select-Object -ExpandProperty Opcodes |
Message Analyzer
微软已停止维护,并且不提供下载。
Extracting ETW Providers
我们有了一些与 ETW 交互的方法,但是有时我们只是想获得 provider mainfest,一个文件而不是对象的属性,这时我们有一些方法提取这些 mainfest。
ETW Explorer / Perfview
这两者实际上使用了相同的底层 API 来提取 provider mainfest:
1 | RegisteredTraceEventParser.GetManifestForRegisteredProvider |
zodiacon/EtwExplorer: View ETW Provider manifest (github.com)
类似可以使用 perfview dump provider mainfest,选择 File -> User Command 或者 Alt + U,使用以下命令:
1 | DumpRegisteredManifest providerName |
Dump mainfest 时需要注意文件有时不会包括所有的 XML 元素,这是 dumping 功能实现方式决定的。perfview/RegisteredTraceEventParser.cs at 6b4771eecba5ed00555a34d70e19a8742af4ee0a · microsoft/perfview (github.com)
WEPExplorer
类似于 ETW Explorer,WEPExplorer 可以用来查看 ETW provider mainfests,WinTools/WEPExplorer at master · lallousx86/WinTools (github.com)。
这个工具使用了Getting a Provider’s Metadata - Win32 apps | Microsoft Docs中的概念和 winevt API。这个工具中的信息包括了 mainfest 中可用的元素,并且当双击一个 provider 时会自动生成对应的 XML 文件,保存在启动目录下。
Script ETW
通过编程方式与 ETW 交互的选项有以下几种:
- KrabsETW
- SilkETW
- PyWintrace
- Powershell(.NET)
- WinAPI (Tdh.dll, Wevtapi.dll)
More ETW
Visualizing “Analytic” / “Debug” Channels
使用 WEPExplorer 时,可以看到许多 ETW providers 输出到到 Debug 或者 Ananlytic channels。默认情况下这些 channel 不会显示,但是可以在 Event Viewer 点击 View 来启用。
显示了之后,需要右键相应的日志来启用。
这时系统将为这个 provider 创建一个新的 trace session。
Regist(ry)ered ETW Providers
注册表中的下列位置保存了注册的 ETW providers
1 | HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Publishers\ |
可以看到 ResourceFileName 和 MessageFileName 是同一个位置,这个文件的二进制结构中包含了 Mainfest 定义,下图是使用 resource hacker 的情况。
Providers for detection and forensic
以下事件使用 python 库 pywintrace 捕捉。
Microsoft-Windows-Kernel-Process
Event | EID | CHANNEL | Description | Example |
---|---|---|---|---|
Process Creation | 1 | Microsoft-Windows-Kernel-Process/Analytic | Capture process creation | |
Thread Start | 3 | Microsoft-Windows-Kernel-Process/Analytic | Capture thread start in a process | |
Image Load | 5 | Microsoft-Windows-Kernel-Process/Analytic | Capture when an Image is being loaded into a process | |
Process termination(Stop) | 2 | |||
Image unload | 6 |
Microsoft-Windows-Kernel-FIle
Event | EID | CHANNEL | Description | Example |
---|---|---|---|---|
File Creation | 10 / 30 | Microsoft-Windows-Kernel-File/Analytic | Capture file creation event | |
File Deletion | 11 | Microsoft-Windows-Kernel-File/Analytic | Capture file deletion |
Microsoft-Windows-Kernel-Network
Event | EID | CHANNEL | Description | Example |
---|---|---|---|---|
Attemped Connectio | 12 | Microsoft-Windows-Kernel-Network/Analytic | Capture attempts of initial connection to an IP | |
Established Connection | 15 | Microsoft-Windows-Kernel-Network/Analytic | ||
N° of Bytes Transmitted / Received | 10 / 11 | Microsoft-Windows-Kernel-Netword/Analytic | Capture the number of bytes transmitted and received |
以上所有 event 都会捕捉 TCPv4 数据,N° of Bytes Transmitted / Received 也会捕捉 TCPv6,UDPv4 和 v6。
Microsoft-Windows-Kernel-Registry
Event | EID |
---|---|
CreateKey | 1 |
OpenKey | 2 |
DeleteKey | 3 |
QueryKey | 4 |
SetValueKey | 5 |
DeleteValueKey | 6 |
QueryValueKey | 7 |
EnumerateKey | 8 |
EnumerateValueKey | 9 |
这些 event 都在 Microsoft-WIndows-Kernel-Registry/Analytic 中。
Microsoft-Windows-Services-Svchost
Event | EID | Channel | Example |
---|---|---|---|
Svchost Process Start | 101 | Microsoft-Windows-Services-Svchost/Diagnostic | |
Svchost Process Stop | 102 | Microsoft-Windows-Services-Svchost-Diagnostic |
Microsoft-Windows-LDAP-Client
Evnet | EID | Channel | Description | Example |
---|---|---|---|---|
LDAP Search | 30 | Microsoft-Windows-LDAP-Client/Debug | Captures ldap search from different LDAP clients |
日过使用了类似于 MMC console Active Directory Users and Computers 也会得到相同结果。Event 由 wldap32.dll 处理,每个加载了它的进程都会生成这些事件。
Microsoft-Windows-COMRuntime
Event | EID | Channel | Example |
---|---|---|---|
COM Interface Usage / Call | 2 | Microsoft-Windows-COMRuntime/Tracing |
Microsoft-Windows-Winlogon
除了包括 Operational channel 中的 event 以外,还包括一些 Diagnostic 的:
- Fail 和 Succesful 的 Lock 和 Unlock 尝试
- Succesful 和 Failed 的登录
下面展示了锁定和解锁的情况:
1 | TimeStamp: 2021-08-25 22:27:10 |
Microsoft-Windows-TerminalServices-ClientActiveXCore
这个 provider 通过 Microsoft-Windows-TerminalServices-RDPClient 的 operational 和 analytic 导出了一些事件。
EID 1001 和 EID 1102 需要注意,它们当一个用户初始化 RDP 连接时出现。例如使用 mstsc.exe 链接服务器:
Microsoft-Windows-RPC
Event | EID | Channel | Example |
---|---|---|---|
Server RPC Call Start | 5 | Debug | |
Client RPC Call Start | 6 | Debug |
Conclusion
推荐阅读:Tampering with Windows Event Tracing: Background, Offense, and Defense | by Palantir | Palantir Blog
Github 仓库:nasbench/ETW-Resources: Event Tracing For Windows (ETW) Resources (github.com)
下一篇文章(已经发出来了,上面的 Providers 一段):Finding Detection and Forensic Goodness In ETW Providers | by Nasreddine Bencherchali | Aug, 2021 | Medium
Windows 11 中的新 provider Windows 11 “New” ETW Providers — Overview | by Nasreddine Bencherchali | Medium
补充
logman
1 | # 查询感兴趣的 Provider |
A Primer On Event Tracing For Windows (ETW)