用于ETW的C#封装器,将内核和用户模式事件数据序列化为JSON,用于威胁狩猎、恶意软件分析和事件响应,集成了Yara并支持发送至Elasticsearch。
SilkETW 与 SilkService 是用于 ETW 的灵活 C# 封装器,旨在抽象 ETW 的复杂性,为用户提供简单的接口以进行研究和内省。虽然这两个项目显然具有防御(以及攻击)用途,但主要应视为研究工具。
为便于使用,输出数据会被序列化为 JSON。JSON 数据既可以写入文件并在本地使用 PowerShell 分析,也可以存储在 Windows 事件日志中,或发送至第三方基础设施(如 Elasticsearch)。
有关 SilkETW 与 SilkService 未来发展的更多信息,请参阅路线图部分。
有关 SilkETW 和 SilkService 的更多背景,请查阅以下资源。
SilkETW 基于 .Net v4.5 构建,并使用了多个第三方库,如下所示。详细信息请参阅 LICENSE-3RD-PARTY。
ModuleId Version LicenseUrl
-------- ------- ----------
McMaster.Extensions.CommandLineUtils 2.3.2 https://licenses.nuget.org/Apache-2.0
Microsoft.Diagnostics.Tracing.TraceEvent 2.0.36 https://github.com/Microsoft/perfview/blob/master/LICENSE.TXT
Newtonsoft.Json 12.0.1 https://licenses.nuget.org/MIT
System.ValueTuple 4.4.0 https://github.com/dotnet/corefx/blob/master/LICENSE.TXT
YaraSharp 1.3.1 https://github.com/stellarbear/YaraSharp/blob/master/LICENSE
命令行用法相当直观,用户输入在执行序言阶段会经过验证。详情请参见下图。

SilkService 的创建是因为大量用户希望以无头模式运行 SilkETW,并同时从多个数据源进行 ETW 收集。虽然这显然很有吸引力,但应牢记以下几点。
在编译或下载发布包后,可以通过在提升的命令提示符下执行以下命令来安装服务。
sc create SillkService binPath= "C:\Path\To\SilkService.exe" start= demand
SilkService 读取 XML 配置文件 "SilkServiceConfig.xml",该文件应与服务二进制文件放在同一目录下。下面是一个示例配置文件。
<SilkServiceConfig>
<!--
这是一个用户态收集器
-> Microsoft-Windows-DotNETRuntime
-> 基于 GUID 或字符串的名称
-->
<ETWCollector>
<Guid>45c82358-c52d-4892-8237-ba001d396fb4</Guid>
<CollectorType>user</CollectorType>
<ProviderName>e13c0d23-ccbc-4e12-931b-d9cc2eee27e4</ProviderName>
<UserKeywords>0x2038</UserKeywords>
<OutputType>url</OutputType>
<Path>https://some.elk:9200/NetETW/_doc/</Path>
</ETWCollector>
<!--
这是一个用户态收集器
-->
<ETWCollector>
<Guid>6720babc-dedc-4906-86b9-d0bc0089ec50</Guid>
<CollectorType>user</CollectorType>
<ProviderName>Microsoft-Windows-DNS-Client</ProviderName>
<OutputType>eventlog</OutputType>
<YaraScan>C:\Some\Path\RuleFolder</YaraScan>
<YaraOptions>Matches</YaraOptions>
</ETWCollector>
<!--
这是一个内核态收集器
-->
<ETWCollector>
<Guid>21ac2393-3bbb-4702-a01c-b593e21913dc</Guid>
<CollectorType>kernel</CollectorType>
<KernelKeywords>Process</KernelKeywords>
<OutputType>file</OutputType>
<Path>C:\Users\b33f\Desktop\kproc.json</Path>
</ETWCollector>
</SilkServiceConfig>
请注意,每个 ETWCollector 元素应有一个随机 GUID,用于内部跟踪和日志记录。可以使用以下 PowerShell 命令生成 GUID:
PS C:\> [guid]::NewGuid()
Guid
----
eee52b87-3f32-4651-b0c3-e7bb9af334aa
在运行时,SilkService 会创建一个 "Logs" 子文件夹,用于记录服务运行时信息。这是查询服务状态、验证服务参数以及查看错误信息的宝贵资源。SilkService 倾向于在遇到任何类型错误时优雅关闭,即使该错误并不严格要求终止。此设计是有意为之,因为残留的收集器或部分可操作性并非稳妥的策略。
如果服务自行关闭,请务必查阅服务日志!
总是有可能出现问题。请查阅服务日志以获取更多详细信息。尽管 SilkService 配置为在遇到错误时终止并清理 ETW 收集器,但进程终止后仍有可能残留过期的收集器。要列出正在运行的收集器,可以使用以下命令。
logman -ets
如果发现任何过期的收集器,可以从提升的命令提示符下执行以下命令将其移除。
Get-EtwTraceProvider |Where-Object {$_.SessionName -like "SilkService*"} |ForEach-Object {Stop-EtwTraceSession -Name $_.SessionName}
Get-EtwTraceProvider |Where-Object {$_.SessionName -like "SilkService*"} |Remove-EtwTraceProvider
JSON 输出(序列化之前)按照以下 C# 结构进行格式化。
public struct EventRecordStruct
{
public Guid ProviderGuid;
public List<String> YaraMatch;
public string ProviderName;
public string EventName;
public TraceEventOpcode Opcode;
public string OpcodeName;
public DateTime TimeStamp;
public int ThreadID;
public int ProcessID;
public string ProcessName;
public int PointerSize;
public int EventDataLength;
public Hashtable XmlEventData;
}
请注意,根据提供程序和事件类型的不同,XmlEventData 哈希表中的数据会有所变化。以下是 "Microsoft-Windows-Kernel-Process" -> "ThreadStop/Stop" 的示例 JSON 输出。
{
"ProviderGuid":"22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716",
"YaraMatch":[
],
"ProviderName":"Microsoft-Windows-Kernel-Process",
"EventName":"ThreadStop/Stop",
"Opcode":2,
"OpcodeName":"Stop",
"TimeStamp":"2019-03-03T17:58:14.2862348+00:00",
"ThreadID":11996,
"ProcessID":8416,
"ProcessName":"N/A",
"PointerSize":8,
"EventDataLength":76,
"XmlEventData":{
"FormattedMessage":"Thread 11,996 (in Process 8,416) stopped. ",
"StartAddr":"0x7fffe299a110",
"ThreadID":"11,996",
"UserStackLimit":"0x3d632000",
"StackLimit":"0xfffff38632d39000",
"MSec":"560.5709",
"TebBase":"0x91c000",
"CycleTime":"4,266,270",
"ProcessID":"8,416",
"PID":"8416",
"StackBase":"0xfffff38632d40000",
"SubProcessTag":"0",
"TID":"11996",
"ProviderName":"Microsoft-Windows-Kernel-Process",
"PName":"",
"UserStackBase":"0x3d640000",
"EventName":"ThreadStop/Stop",
"Win32StartAddr":"0x7fffe299a110"
}
}
你可以使用以下简单的 PowerShell 函数导入 SilkETW 的 JSON 输出。
function Get-SilkData {
param($Path)
$JSONObject = @()
Get-Content $Path | ForEach-Object {
$JSONObject += $_ | ConvertFrom-Json
}
$JSONObject
}
在下面的示例中,我们将从内核提供程序收集进程事件数据,并使用映像加载来识别 Mimikatz 的执行。我们可以使用以下命令收集所需数据。
SilkETW.exe -t kernel -kk ImageLoad -ot file -p C:\Users\b33f\Desktop\mimikatz.json
拿到数据后,我们可以轻松地排序、筛选和查找我们感兴趣的属性。

SilkETW 包含 Yara 功能,可用于过滤或标记事件数据。同样,这具有明显的防御能力,但也可以轻松用于增强你的 ETW 研究。
在本示例中,我们将使用以下 Yara 规则检测通过 Cobalt Strike 的 execute-assembly 在内存中执行的 Seatbelt。
rule Seatbelt_GetTokenInformation
{
strings:
$s1 = "ManagedInteropMethodName=GetTokenInformation" ascii wide nocase
$s2 = "TOKEN_INFORMATION_CLASS" ascii wide nocase
$s3 = /bool\(native int,valuetype \w+\.\w+\/\w+,native int,int32,int32&/
$s4 = "locals (int32,int64,int64,int64,int64,int32& pinned,bool,int32)" ascii wide nocase
condition:
all of ($s*)
}
我们可以使用以下命令开始收集 .Net ETW 数据。这里的 "-yo" 选项表示只将 Yara 匹配结果写入磁盘!
SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -l verbose -y C:\Users\b33f\Desktop\yara -yo matches -ot file -p C:\Users\b33f\Desktop\yara.json
我们可以在运行时看到 Yara 规则被命中。

另请注意,我们只捕获了 "Microsoft-Windows-DotNETRuntime" 事件的一个子集(0x2038),具体包括:JitKeyword、InteropKeyword、LoaderKeyword 和 NGenKeyword。
你可以下载源码并在 Visual Studio 中编译。请注意,你可以免费获取 Visual Studio 社区版。或者,你也可以从 releases 获取最新的预编译版本。
有关各版本具体变更的详细信息,请参阅更新日志。