SilkETW e SilkService são wrappers C# flexíveis para ETW, destinados a abstrair as complexidades do ETW e fornecer às pessoas uma interface simples para realizar pesquisas e introspecção. Embora ambos os projectos tenham aplicações defensivas (e ofensivas) óbvias, devem ser considerados principalmente como ferramentas de investigação.
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 o PowerShell, armazenados no log de eventos do Windows ou enviados para infraestrutura de terceiros, como o Elasticsearch.
Para obter mais informações sobre o futuro do SilkETW e SilkService, consulte a seção Roteiro.
Para obter mais informações sobre SilkETW e SilkService, consulte os seguintes recursos.
SilkETW é construído em .Net v4.5 e usa várias bibliotecas de terceiros, conforme mostrado abaixo. Consulte LICENSE-3RD-PARTY para obter 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 simples 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 um grande número de pessoas queria executar o SilkETW sem cabeça e realizar a coleta de ETW para várias fontes ao mesmo tempo. Embora haja um apelo óbvio a isto, os seguintes pontos devem ser mantidos em mente.
Depois de compilar ou baixar o pacote de lançamento, você pode instalar o serviço emitindo o seguinte comando em um prompt elevado.
sc create SillkService binPath= "C:PathToSilkService.exe" start= demand
O SilkService ingere um arquivo de configuração XML, "SilkServiceConfig.xml", que deve ser colocado no mesmo diretório que o binário do serviço. Um exemplo de arquivo de configuração pode ser visto abaixo.
< SilkServiceConfig >
< 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:SomePathRuleFolder YaraScan >
< YaraOptions >Matches YaraOptions >
ETWCollector >
< ETWCollector >
< Guid >21ac2393-3bbb-4702-a01c-b593e21913dc Guid >
< CollectorType >kernel CollectorType >
< KernelKeywords >Process KernelKeywords >
< OutputType >file OutputType >
< Path >C:Usersb33fDesktopkproc.json Path >
ETWCollector >
SilkServiceConfig >
Observe que cada elemento ETWCollector deve ter um GUID aleatório, usado para fins de rastreamento e registro interno. Você pode gerar GUIDs no PowerShell usando o seguinte comando:
PS C: > [ guid ]::NewGuid()
Guid
----
eee52b87 - 3f32 - 4651 - b0c3 - e7bb9af334aa
No 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 pesquisar o estado do serviço, verificar a validação dos parâmetros do serviço e revisar informações de erro. O SilkService tem preferência de encerrar normalmente se encontrar qualquer tipo de erro, mesmo que tal erro não exija estritamente o encerramento. Esta decisão de projeto foi tomada propositalmente, pois não é uma boa estratégia ter coletores pendentes ou operabilidade parcial.
Sempre consulte o log de serviço se o serviço for encerrado!
É sempre possível que algo dê errado. Consulte o registro de serviço para obter mais detalhes. Embora o SilkService esteja configurado para encerrar e limpar coletores ETW ou erros, é possível que um coletor obsoleto permaneça registrado após o encerramento do processo. Para listar os coletores em execução, você pode usar o seguinte comando.
logman -ets
Se algum coletor obsoleto for identificado, ele poderá ser removido emitindo os comandos a seguir em 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 estrutura C# a seguir.
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 imagens 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:Usersb33fDesktopmimikatz.json
Com os dados em mãos é fácil classificar, usar grep e filtrar as propriedades que nos interessam.
SilkETW inclui funcionalidade Yara para filtrar ou marcar dados de eventos. Novamente, isso tem capacidades defensivas óbvias, mas pode ser facilmente usado para aumentar sua pesquisa ETW.
Neste exemplo, usaremos a seguinte regra Yara para detectar a execução do cinto de segurança na memória por meio 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 .Net ETW com o seguinte comando. A opção "-yo" aqui indica que devemos apenas gravar correspondências de Yara no disco!
SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -l verbose -y C:Usersb33fDesktopyara -yo matches -ot file -p C:Usersb33fDesktopyara.json
Podemos ver em tempo de execução que nossa regra Yara foi atingida.
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 comunitária do Visual Studio gratuitamente. Ou você pode obter a versão pré-construída mais recente dos lançamentos.
Para obter detalhes sobre alterações específicas de versão, consulte o Changelog.