使用C#解析Active Directory Domain Services: Core ETW事件遇Payload解析问题
关于"Active Directory Domain Services: Core" ETW提供程序的类型与Payload解析方案
嘿,刚好对AD相关的ETW提供程序有点经验,来帮你解决这个问题:
1. 提供程序类型:清单型ETW提供程序
"Active Directory Domain Services: Core"是清单型的ETW提供程序,它基于XML清单定义事件结构(而非经典型依赖的MOF文件)。这类提供程序会把事件的字段、类型等元数据嵌入到清单中,只要能正确加载这些元数据,就能解析出完整的Payload。
2. 解决Payload无法解析的方案
你目前只能解析时间戳,大概率是代码没有正确关联提供程序的清单元数据,或者用了不支持清单解析的原始ETW调用。这里给你几个可行的方向:
方法一:直接读取事件日志(适合已记录的事件)
如果是收集已经写入事件日志的AD DS Core事件,推荐用System.Diagnostics.Eventing.Reader命名空间下的API,它会自动加载提供程序的清单并解析Payload:
using System; using System.Diagnostics.Eventing.Reader; class AdEtwParser { static void Main() { // 目标提供程序的名称 string providerName = "Active Directory Domain Services: Core"; // 创建查询,指定读取该提供程序的事件 var eventQuery = new EventLogQuery(providerName, PathType.LogName); using (var reader = new EventLogReader(eventQuery)) { EventRecord eventRecord; while ((eventRecord = reader.ReadEvent()) != null) { Console.WriteLine($"=== 事件 {eventRecord.Id} ==="); Console.WriteLine($"时间戳: {eventRecord.TimeCreated?.ToString("yyyy-MM-dd HH:mm:ss.fff")}"); Console.WriteLine("Payload内容:"); // 遍历所有Payload属性,这些属性对应清单定义的字段 for (int i = 0; i < eventRecord.Properties.Count; i++) { // 可以通过eventRecord.PropertyNames[i]获取字段名称(如果清单加载成功) string fieldName = eventRecord.PropertyNames.Count > i ? eventRecord.PropertyNames[i] : $"字段{i}"; Console.WriteLine($"{fieldName}: {eventRecord.Properties[i].Value}"); } Console.WriteLine("\n"); } } } }
方法二:实时ETW跟踪(适合实时收集事件)
如果是通过ETW会话实时收集事件,需要确保代码加载了提供程序的清单。你可以先导出清单文件,再在代码中解析:
- 先用命令导出清单:
wevtutil gp "Active Directory Domain Services: Core" > ad_core_manifest.xml
- 在C#中加载清单并解析事件:
using System; using System.Diagnostics.Tracing; using System.IO; class AdRealTimeEtw { static void Main() { string manifestPath = "ad_core_manifest.xml"; // 解析清单 using var manifestStream = File.OpenRead(manifestPath); var manifestParser = new EventManifest.Parser(manifestStream); // 创建ETW会话 using var session = new EventTraceSession("AdCoreSession"); // 启用目标提供程序 session.EnableProvider("Active Directory Domain Services: Core"); // 注册事件回调 session.EventRecordWritten += (sender, e) => { if (e.EventRecord == null) return; Console.WriteLine($"=== 实时事件 {e.EventRecord.Id} ==="); Console.WriteLine($"时间戳: {e.EventRecord.TimeStamp:yyyy-MM-dd HH:mm:ss.fff}"); // 用清单解析Payload字段 var eventMetadata = manifestParser.TryGetEventMetadata(e.EventRecord.Id, e.EventRecord.Version); if (eventMetadata != null) { Console.WriteLine("Payload内容:"); var propertyValues = e.EventRecord.GetPropertyValues(eventMetadata); foreach (var prop in eventMetadata.Properties) { Console.WriteLine($"{prop.Name}: {propertyValues[prop.Name]}"); } } Console.WriteLine("\n"); }; Console.WriteLine("正在实时收集AD DS Core事件...按任意键退出"); Console.ReadKey(); } }
额外注意点
- 确保程序以管理员权限运行,ETW跟踪和读取部分AD事件需要权限。
- 如果
PropertyNames为空,说明清单没有正确加载,可以检查提供程序名称是否拼写完全正确(注意是"Active Directory Domain Services: Core",冒号和空格不能错)。 - 部分AD DS Core事件可能包含二进制Payload,需要根据清单定义的类型手动解析二进制数据。
内容的提问来源于stack exchange,提问作者ling7334
相关产品推荐
相关产品推荐

