Threat Hunting with ETW events and HELK โ€” Part 1: Installing SilkETW ๐Ÿ„โ€โ™€๐Ÿ„

Roberto Rodriguez
Open Threat Research
14 min readSep 19, 2019

One of my favorite things to do besides playing with Jupyter Notebooks ๐Ÿ˜† is to identify new data sources that could provide additional context to the analytics that I develop while performing research. From a Windows environment perspective, most of the time, the event logs generated after simulating an adversarial technique, come from sources that are simply enabled by pushing an audit policy or by running auditpol.exe . Even though Windows audit policies allow you to enable several useful events, remember that those are only a subset of all the telemetry available in Windows systems.

There are several other sources of data that are available, but they cannot be easily enabled via an audit policy. However, they are easy to explore interactively with the right tooling and a little bit of knowledge about the Event Tracing for Windows (ETW) concepts.

This post is part of a four-part series which will go over the basics of the ETW model, how to install SilkETW, consume and aggregate ETW events, and at the same time show you how you can leverage the additional telemetry for a few detection use cases with the Hunting ELK (HELK).

In this first post, I will go over the basics of ETW and the installation of an amazing project by Ruben Boonen (@FuzzySec) ๐Ÿป named SilkETW โš”๏ธ

The other three parts can be found in the following links:

Before we even start talking about SilkETW, I believe it is important to start from the basics, and refresh some of the key concepts of the ETW model. I also believe it is important to understand how you could manually enable event tracing for specific ETW providers to learn about the mechanics of it.

What is ETW?

Event Tracing for Windows (ETW) is an efficient kernel-level tracing facility that lets you log kernel or application-defined events to a log file. You can consume the events in real time or from a log file and use them to debug an application or to determine where performance issues are occurring in the application. ETW lets you enable or disable event tracing dynamically, allowing you to perform detailed tracing in a production environment without requiring computer or application restarts.

According to MS docs, the Event Tracing API is broken into three distinct components:

  • Controllers, which start and stop an event tracing session and enable providers
  • Providers, which provide the events
  • Consumers, which consume the events

The following diagram from the Microsoft Ntdebugging Blog helped me to understand how each component relates to each other.

Exploring ETW Components

Controllers

Tools such as Logman are good examples of a Controller in the ETW model since it creates and manages Event Trace Sessions and Performance logs. In addition, you can use it to query metadata of each component (i.e. Providers).

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/logman

Another way to create new event trace sessions and enable ETW providers is via the built-in Windows Performance System Tool located at Computer Management> System Tools > Performance . Iโ€™ll go over an example later.

List Event Trace Sessions

You can use logman to list running event trace sessions in your system

logman query -ets

You can also use the Windows Performance System Tool to see what Event Trace Sessions are enabled and the providers providing events to them.

If you also wanted to know what event providers a specific event trace session is subscribed to via logman, you can run the following command:

logman query "EventLog-System" -ets

List ETW Providers

Next, you can list all the available providers in your system with logman:

logman query providers

Query Specific ETW Providers

What if I wanted to look for specific ETW Providers ? You can filter the logman query providers results and look for specific strings. For example, we can look for providers with the word Security in their name as shown below:

$ETWProviders = logman query providers
$ETWProviders | Where-Object { $_ -Like "*Security*" }

We can select the Microsoft-Windows-Security-Auditing, and query its metadata to get more information about it.

logman query providers Microsoft-Windows-Security-Auditing

You could also get information about specific ETW providers via a tool named Windows Events Providers Explorer (WEPExplorer)

You could also use wevtutil.exe to retrieve information about event logs and publishers ( Thank you Marc Sherman)

> wevtutil.exe get-publisher Microsoft-Windows-Security-Auditing /getevents:true /getmessage:true

Windows Security Auditing ETW Provider Events ๐Ÿ’ฅ

We now know that there is an event tracing session subscribed to the Microsoft-Windows-Security-Auditing provider which uses the channel Security to allow ingestion of Security events via the event log.

Can I Consume Any ETW Event via the Event Log?

According to Matt Graeberโ€™s research, ONLY ETW provider events that have a Channel property applied to them can be consumed by the event log.

For example, this post from the Microsoft Ntdebugging blog has a great step-by-step tutorial on how to enable event tracing for the Microsoft-Windows-WinINet provider via the Analytic channel.

We can start by using the WEPExplorer tool to get more detailed information about the specific Channels applied to each ETW event. As you can see below, we can see the Microsoft-Windows-WinINet/Analytic channel applied to most of the events from the Microsoft-Windows-WinINet provider. Therefore, they are meant to be consumed by the event log in real-time.

Consume WinINet Events

Now that we know that we can consume events from the Microsoft-Windows-WinINet provider in real-time via the event log, we can start the process by enabling the Analytic and Debug Logs view.

You might have to restart the event viewer console. You will see a new event log folder named WinINet (Microsoft-Windows-WinINet) under Application and Service Logs > Microsoft > Windows. Click on it and you will see 3 channels. Right-click on the Analytic channel and select Enable Log.

Click Ok.

If you go to a website via Microsoft Edge, you will start seeing events populating the Analytic Channel as shown below:

You can validate that an event trace session for the WinINet provider was enabled by going to Computer Management > System Tools > Performance > Data Collector Sets > Startup Event Trace Sessions as shown below:

What about ETW Events Without a Property Channel?

What if I wanted to enable an event trace session for providers which events do not have a property Channel applied to them? For example, with adversaries dynamically loading custom .NET code for execution, I would like to enable event tracing for the Microsoft-Windows-DotNETRuntime {E13C0D23-CCBC-4E12โ€“931B-D9CC2EEE27E4} and explore the data.

We can use the Windows Events Providers Explorer (WEPExplorer) tool again and verify if we can consume those ETW events in real-time via the event log. Unfortunately, there are not Channel properties applied to the events.

So What Now?

You can still do it, but not in real-time to the event log. You will have to:

  • Create an event trace session (manually)
  • Subscribe to the ETW provider
  • Set location of the .etl file that will be created
  • Start the event trace session
  • .etl file is generated
  • Open .etl log via the event log as a saved log file

You can start by creating the event trace session via the Performance System Tool located at Computer Management > System Tools > Performance. You just have to create a new Data Collector Set as shown in the image below:

Give it a name and select Create Manually (Advanced)

Next, select the event trace provider Microsoft-Windows-DotNETRuntime

You are almost done! You can use the view below and modify the properties of the data collector set. For example, select Keywords and then Edit.

For example, you can collect a subset of events related to JitKeyword, InteropKeyword, LoaderKeyword and NGenKeyword for .NET activity. If you want to learn why I am interested in those events, you can read this blog post from the Countercept team. After selecting those values, you will get a bitmask: 0x2038 (Remember this! ๐Ÿ˜‰). Next, click Ok and Next.

Select the location of the .etl file. Keep the default location and click Next.

Keep the defaults and click Finish!

You can see the new event trace session available but with status Stopped. You can also double-click on it and check the location and name of the .etl file that will be created once the event trace session gets started.

Right-click on the new event trace session and select Start.

The event trace session is now running, but you wont see it in the event logs unless you grab a copy of the .etl file and open it as a saved log. You wont be able to have a continuous ingestion to the event log. To open the .etl file as a saved log, go to Event Viewer console and click on Action > Open Saved Log.

Select the .etl file associated with your event trace session, and click Open.

Click Yes after getting the prompt to create a copy of it

You can keep the default location to display the external log. Click Ok.

๐Ÿ’ฅThats it! That was easy right?

Even though I was able to get events from the Microsoft-Windows-DotNETRuntime provider, it is not a continuous real-time ingestion to the event log. By default those ETW events donโ€™t have a Channel applied to them. One way to accomplish the real-time ingestion to the event log would be by writing an applications leveraging ETW apis and enable that capability.

Enter SilkETW

Fortunately! The amazing Ruben Boonen figured out a way to do that and more via C# wrappers and developed a tool named SilkETW to provide a straightforward interface for ETW events collection, filtering and ingestion. The project provides 2 ways to interact with ETW components. One is via the command line, and the other one by running SilkETW headless as a service.

https://twitter.com/FuzzySec/status/1108398013960065024

My brother Jose Luis Rodriguez and I were so excited about this release that..

We decided to test it in our lab environment and used it to consume events from the Microsoft-Windows-LDAP-Client provider while executing some LDAP filters via Powerview by Will . I will walk through some examples in the next parts of this series. For now, I can show you how to install SilkETW โš”๏ธ

https://twitter.com/Cyb3rWard0g/status/1108592833349464064

Installation

Download the latest release package from https://github.com/fireeye/SilkETW/releases and unblock the compressed file (Version 0.8 was the latest when writing this post)

You will see two folders: SilkETW and SilkService. Thats how you differentiate how you will go about running SilkETW.

Also, in the Dependencies folder, you will find binaries that you need to run as pre-requirements ( Do NOT skip this step!)

SilkETW CLI

You do not need to do anything else to start working with the CLI version of it and the basic options. Open a a terminal as Administrator and just run the binary inside of the SilkETW folder to learn about the available options with the tool. (Downloads>SilkETW_SilkService_v8>v8>SilkETW)

Event Tracing for Microsoft-Windows-DotNETRuntime

Remember all the things that we needed to do to interact with ETW providers that did not have a property Channel applied to them? These are the arguments to consume ETW events from the Microsoft-Windows-DotNETRuntime provider with the same keyword filters via the event log:

  • -pn Microsoft-Windows-DotNETRuntime
  • -ot eventlog
  • -uk 0x2038
> SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -ot eventlog

Something important to point out in here is that the collection of events is continuous and pushed to the SilkETW-Log event log directly. However, as you can see in your cmd terminal, it is not a collection that will run headless in the background. This is perfect for debugging and analysis of ETW events generated by any execution of code during research. CTRL-C to stop collector!

SilkETW in Headless Mode = SilkService ๐Ÿ”ฅ

According to the setup instructions in the GitHub README, you can install the service by issuing the following command from an elevated prompt:

sc create SillkService binPath= "C:\Path\To\SilkService.exe" start= demand

Build Your SilkService XML Config

Before you even start the SilkService, you have to make your own SilkServiceConfig.xml file and place it in the same directory as the service binary (i.e. Downloads>SilkETW_Service_v8\v8\SilkService). This is a template that Ruben provided with several options:

Following our example for Microsoft-Windows-DotNETRuntime events consumed via the event log, you can use this basic config:

Remember that the <Guid> field is a random GUID that you generate. When I started to work with these configs, I thought it was the provider GUID ๐Ÿ˜†. Next, copy the DotNETRuntime config, rename it SilkServiceConfig.xml, and place it in the same directory as the service binary.

Start SilkService ๐Ÿคž

Open Services> Right-Click on SilkService> Start . A new folder named Logs will be created under the SilkService folder. There you will find a log file that will tell you more about the collector status and if the parameters you provided via the SilkServiceConfig.xml were validated successfully.

If you open Event Viewer again (restart it), you will see that there is a new event log named SilkService-Log. There you will be able to see a continuous real-time ingestion of ETW events from the Microsoft-Windows-DotNETRuntime provider ๐Ÿ”ฅ ๐Ÿš’

SilkService XML Config Elements

If you want to modify your SilkService config and add other XML elements, this is the list of options that you can play with on your configs. Ruben has a lot of examples in his repo and also several demos from BH Arsenal 2019

// Define XML elements            
XName CI = XName.Get("ETWCollector");
XName CG = XName.Get("Guid");
XName CT = XName.Get("CollectorType");
XName KK = XName.Get("KernelKeywords");
XName OT = XName.Get("OutputType");
XName P = XName.Get("Path");
XName PN = XName.Get("ProviderName");
XName UTEL = XName.Get("UserTraceEventLevel");
XName UK = XName.Get("UserKeywords");
XName FO = XName.Get("FilterOption");
XName FV = XName.Get("FilterValue");
XName YS = XName.Get("YaraScan");
XName YO = XName.Get("YaraOptions");

Also, check how others are playing with SilkETW for some ideas. This blog post by Mathias Jessen, shows you how to write events to a file (JSON).

SilkETW Event Types

It is important to also know what events are provided by SilkETW when looking at the event log. This is totally different from the events provided by each provider. According to Issue 1, the log has four event id types:

Event ID = 0 -> Collector start

{
"Collector": "Start",
"Data": {
"Type": "User",
"Provider": "Microsoft-Windows-DotNETRuntime",
"Keywords": "0x2038",
"FilterOption": "None",
"FilterValue": "",
"YaraPath": "",
"YaraOption": "None"
}
}

Event ID = 1 -> Collector terminated by user

{
"Collector": "Stop",
"Error": false
}

Event ID = 2 -> Collector terminated by error

{
"Collector": "Stop",
"Error": true,
"ErrorCode": 3
}

Event ID = 3 -> Event recorded
This is just the raw JSON for the event that was recorded by the collector.

--

--