
Wrapper em C# para ETW que serializa dados de eventos do kernel e modo de usuário para JSON para caça a ameaças, análise de malware e resposta a incidentes, com integração Yara e envio para Elasticsearch.
SilkETW & SilkService são wrappers flexíveis em C# para ETW, criados para abstrair as complexidades do ETW e fornecer uma interface simples para pesquisa e introspecção. Embora ambos os projetos tenham aplicações defensivas (e ofensivas) óbvias, devem ser considerados principalmente como ferramentas de pesquisa.
Para facilitar o consumo, os dados de saída são serializados em JSON. Os dados JSON podem ser gravados em arquivo e analisados localmente usando PowerShell, armazenados no log de eventos do Windows ou enviados para infraestrutura de terceiros, como Elasticsearch.
Para mais informações sobre o futuro do SilkETW & SilkService, consulte a seção Roadmap.
Para mais contexto sobre o SilkETW e o SilkService, consulte os seguintes recursos.
SilkETW é construído em .Net v4.5 e utiliza várias bibliotecas de terceiros, conforme mostrado abaixo. Consulte LICENSE-3RD-PARTY para mais detalhes.
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
O uso da linha de comando é bastante direto e a entrada do usuário é validada no prólogo de execução. Veja a imagem abaixo para mais detalhes.

O SilkService foi criado porque muitas pessoas queriam executar o SilkETW sem interface gráfica e realizar a coleta de ETW de várias fontes simultaneamente. Embora isso tenha um apelo óbvio, os seguintes pontos devem ser considerados.
Após compilar ou baixar o pacote de release, você pode instalar o serviço emitindo o seguinte comando de um prompt elevado.
sc create SillkService binPath= "C:\Path\To\SilkService.exe" start= demand
SilkService ingere um arquivo de configuração XML, "SilkServiceConfig.xml", que deve ser colocado no mesmo diretório do binário do serviço. Um exemplo de arquivo de configuração pode ser visto abaixo.
<SilkServiceConfig>
<!--
Este é um coletor de usuário
-> Microsoft-Windows-DotNETRuntime
-> Nome baseado em GUID ou string
-->
<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>
<!--
Este é um coletor de usuário
-->
<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>
<!--
Este é um coletor de kernel
-->
<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>
Observe que cada elemento ETWCollector deve ter um GUID aleatório, usado para rastreamento interno e fins de registro. Você pode gerar GUIDs no PowerShell usando o seguinte comando:
PS C:\> [guid]::NewGuid()
Guid
----
eee52b87-3f32-4651-b0c3-e7bb9af334aa
Em tempo de execução, o SilkService criará uma subpasta "Logs" para registrar informações de tempo de execução do serviço. Este é um recurso inestimável para consultar o estado do serviço, verificar a validação dos parâmetros do serviço e revisar informações de erro. O SilkService prefere desligar-se graciosamente se encontrar qualquer tipo de erro, mesmo que tal erro não exija estritamente a interrupção. Essa decisão de design foi tomada propositalmente, pois não é uma estratégia sólida ter coletores pendentes ou operacionalidade parcial.
Consulte sempre o log do serviço se o serviço desligar sozinho!
É sempre possível que algo dê errado. Consulte o log do serviço para mais detalhes. Embora o SilkService seja configurado para encerrar e limpar coletores ETW em caso de erro, é possível que um coletor obsoleto permaneça registrado após o término do processo. Para listar os coletores em execução, você pode usar o seguinte comando.
logman -ets
Se algum coletor obsoleto for identificado, eles podem ser removidos emitindo os seguintes comandos de um prompt elevado.
Get-EtwTraceProvider |Where-Object {$.SessionName -like "SilkService*"} |ForEach-Object {Stop-EtwTraceSession -Name $.SessionName}
Get-EtwTraceProvider |Where-Object {$_.SessionName -like "SilkService*"} |Remove-EtwTraceProvider
A saída JSON, antes da serialização, é formatada de acordo com a seguinte struct 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;
}
Observe que, dependendo do provedor e do tipo de evento, você terá dados variáveis na tabela hash XmlEventData. Um exemplo de saída JSON pode ser visto abaixo para "Microsoft-Windows-Kernel-Process" -> "ThreadStop/Stop".
{
"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"
}
}
Você pode importar a saída JSON do SilkETW no PowerShell usando a seguinte função simples.
function Get-SilkData {
param($Path)
$JSONObject = @()
Get-Content $Path | ForEach-Object {
$JSONObject += $_ | ConvertFrom-Json
}
$JSONObject
}
No exemplo abaixo, coletaremos dados de eventos de processo do provedor Kernel e usaremos carregamentos de imagem para identificar a execução do Mimikatz. Podemos coletar os dados necessários com o seguinte comando.
SilkETW.exe -t kernel -kk ImageLoad -ot file -p C:\Users\b33f\Desktop\mimikatz.json
Com os dados em mãos, é fácil classificar, grep e filtrar as propriedades de interesse.

SilkETW inclui funcionalidade Yara para filtrar ou marcar dados de eventos. Novamente, isso tem capacidades defensivas óbvias, mas também pode ser usado para aprimorar sua pesquisa em ETW.
Neste exemplo, usaremos a seguinte regra Yara para detectar a execução do Seatbelt na memória através do execute-assembly do Cobalt Strike.
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*)
}
Podemos começar a coletar dados de ETW do .Net com o seguinte comando. A opção "-yo" aqui indica que devemos gravar apenas correspondências Yara no disco!
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
Podemos ver em tempo de execução que nossa regra Yara foi acionada.

Observe também que estamos capturando apenas um subconjunto dos eventos "Microsoft-Windows-DotNETRuntime" (0x2038), especificamente: JitKeyword, InteropKeyword, LoaderKeyword e NGenKeyword.
Você pode baixar o código-fonte e compilá-lo no Visual Studio. Observe que você pode obter a edição community do Visual Studio gratuitamente. Ou você pode pegar a versão pré-compilada mais recente em releases.
Para detalhes sobre mudanças específicas de versão, consulte o Changelog.