# ETW: Event Tracing for Windows 101

## ETW: Event Tracing for Windows 101

### Terminology

* `Event Tracing for Windows (ETW)` is a Windows OS logging mechanism for troubleshooting and diagnostics, that allows us to tap into an enormous number of events that are generated by the OS every second
* `Providers` are applications that can generate some event logs
* `Keywords` are event types the provider is able to serve the consumers with
* `Consumers` are applications that subscribe and listen to events emitted by providers
* `Tracing session` records events from one or more providers
* `Contollers` are applications that can start a trace session and enable or disable providers in that trace session

### Logman

Logman.exe is a native Windows command-line utility, which is considered to be a `Controller`. Below, some of the concepts mentioned earlier are explored.

#### Listing Providers

We can see all the providers registered to Windows like so:

```
logman query providers
```

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8dxrCjTL1jYIk1a86L%2F-M8e2TTtR1axgZ7edyJO%2Fimage.png?alt=media\&token=5cead8e4-9209-400c-a760-30331a0a676d)

#### Provider Information

We can get more information about the provider with `logman query $providerName|$provider`.

One of the many built-in interesting providers available to us in Windows is **Microsoft-Windows-Kernel-Process**, so let's check it out:

```
logman query providers Microsoft-Windows-Kernel-Process
logman query providers "{22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716}"
```

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8dxrCjTL1jYIk1a86L%2F-M8e368bZhGTcygzuRwA%2Fimage.png?alt=media\&token=9df07e52-fecc-440e-9fe6-2c7474288ff4)

As we can tell from the above `keywords`, this provider could provide us with some process, thread and image (load/unload as we will see later) related events.

{% hint style="info" %}
Use [ETWExplorer](https://github.com/zodiacon/EtwExplorer) for a deep provider inspection, and see what events and more importantly data it can provide.
{% endhint %}

Below shows Microsoft-Windows-Kernel-Process being inspected with ETWExplorer with some information, which looks like something Sysmon and other similar security monitoring oriented tools could use:

![ETWExplorer](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8dxrCjTL1jYIk1a86L%2F-M8e4bdpiXm-dzi6fCtc%2Fimage.png?alt=media\&token=ee886720-cd9c-4299-9be7-f6cef6b2bb28)

#### Creating a Tracing Session

Let's now try to create a trace session called `spotless-tracing`:

```
logman create trace spotless-tracing -ets
```

We can see our session is now created:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8dxrCjTL1jYIk1a86L%2F-M8e8Fi6ivbt47yJb9Mg%2Fimage.png?alt=media\&token=96a49d78-cd0e-4648-b84f-7adabf25fbea)

We can query the tracing session and see some information about it:

```
logman query spotless-tracing -ets
```

Note that at the moment, although the tracing session is running, it is not recording any events as we have not yet subscribed to any providers:

![Events will be saved to the output location](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8dxrCjTL1jYIk1a86L%2F-M8e8mFKFyMVsqaoZx8_%2Fimage.png?alt=media\&token=f4907fd3-9046-45cb-bc8c-aea9bc566bc8)

#### Subscribing to Microsoft-Windows-Kernel-Process

Inside the `spotless-tracing` tracing session, let's subscribe to events about `PROCESSES` and `IMAGES` provided by the provider `Microsoft-Windows-Kernel-Process` and see what they look like.

In order to subscribe to those events, we first need to refer back to `Microsoft-Windows-Kernel-Process` available `keywords` (event types of this provider) and add `0x10` (`WINEVENT_KEYWORD_PROCESS`) to `0x40` (`WINEVENT_KEYWORD_IMAGE`), which gives us the total of `0x50`:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8e9UjPJM2spl78ft3X%2F-M8eBSiUlxBDw4VQx2Vx%2Fimage.png?alt=media\&token=1b887507-c3e5-4a0c-a57a-e27ed665597f)

We can now register a provider to the tracing session and ask it to emit events that map back to events `WINEVENT_KEYWORD_PROCESS` and `WINEVENT_KEYWORD_IMAGE`:

```
logman update spotless-tracing -p Microsoft-Windows-Kernel-Process 0x50 -ets
```

If we query the tracing session again, we see it now has `Microsoft-Windows-Kernel-Process`provider registered and listening to the two event types pertaining to processes (start/exit) and images (load/unload):

```
logman query spotless-tracing -ets
```

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8e9UjPJM2spl78ft3X%2F-M8eDPfgyLouu5dJ_XMa%2Fimage.png?alt=media\&token=ca6164c0-cacc-4043-b626-c0c8266c94a2)

#### Checking the .etl Log

After the tracing session has run for some time, we can check the log file by opening it with the Windows Event Viewer.

We can see process creation events (event ID 1):

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8e9UjPJM2spl78ft3X%2F-M8eGAX5r2MbZdX_btaH%2Fimage.png?alt=media\&token=dea08958-3337-4d3d-8564-13cb91681f06)

Image load events (event ID 5):

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8e9UjPJM2spl78ft3X%2F-M8eGjBYyt83M2MOFrpt%2Fimage.png?alt=media\&token=3ad77d27-233b-4ef2-9ff4-d343a37c7ec7)

Image unload events (event ID 6):

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8e9UjPJM2spl78ft3X%2F-M8eJS0CspuFpMjtahp_%2Fimage.png?alt=media\&token=6ae1b00f-844a-4af3-86da-ea57b097097e)

#### Removing Providers from a Tracing Session

We can remove a provider from a tracing session like so:

```
logman update trace spotless-tracing --p Microsoft-Windows-Kernel-Process 0x50 -ets
```

Note that the kernel provider is no longer associated with the `spotless-tracing` tracing session:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8fQ9vXz8HhbSDI-y-1%2F-M8j1CqRltxIUbg-Lot_%2Fimage.png?alt=media\&token=9860eb47-567f-4d12-aa61-83c1e711d025)

#### Killing the Tracing Session

We can kill the entire tracing session like so:

```
logman stop spotless-tracing -ets
```

...and the tracing session is no longer present on the system:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8fQ9vXz8HhbSDI-y-1%2F-M8j1etW3trRcOQc0D7h%2Fimage.png?alt=media\&token=7b4e3401-d66d-406f-8b94-1ee26b77f19a)

#### Listing Providers a Process is Registered with

We can check what providers any currently running process is registered with, meaning that process will be writing events to those providers.

Below shows how we can check which providers our current powershell console is registered with (`$pid` gives the current powershell console process id):

```
logman query providers -pid $pid
```

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8jx9Z4H7dh5zbsaQCE%2F-M8jy2PGK-2wE19rGA52%2Fimage.png?alt=media\&token=2589bc94-852c-4f8f-988f-2a817c360da5)

### Consuming Events via Code

Thanks to [Pavel Yosifovich](https://github.com/zodiacon), we can use the below C# code to subscribe to a kernel provider, that will feed our console program with process related events:

```csharp
# code by Pavel Yosifovich, https://github.com/zodiacon/DotNextSP2019/blob/master/SimpleKernelConsumer/Program.cs
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Session;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SimpleKernelConsumer {
	class ProcessInfo {
		public int Id { get; set; }
		public string Name { get; set; }
	}

	class Program {
		static void Main(string[] args) {
			var processes = Process.GetProcesses().Select(p => new ProcessInfo {
				Name = p.ProcessName,
				Id = p.Id
			}).ToDictionary(p => p.Id);

			using (var session = new TraceEventSession(Environment.OSVersion.Version.Build >= 9200 ? "MyKernelSession" : KernelTraceEventParser.KernelSessionName)) {
				session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.ImageLoad);
				var parser = session.Source.Kernel;

				parser.ProcessStart += e => {
					Console.ForegroundColor = ConsoleColor.Green;
					Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Process {e.ProcessID} ({e.ProcessName}) Created by {e.ParentID}: {e.CommandLine}");
					processes.Add(e.ProcessID, new ProcessInfo { Id = e.ProcessID, Name = e.ProcessName });
				};
				parser.ProcessStop += e => {
					Console.ForegroundColor = ConsoleColor.Red;
					Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Process {e.ProcessID} {TryGetProcessName(e)} Exited");
				};

				parser.ImageLoad += e => {
					Console.ForegroundColor = ConsoleColor.Yellow;
					var name = TryGetProcessName(e);
					Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Image Loaded: {e.FileName} into process {e.ProcessID} ({name}) Size=0x{e.ImageSize:X}");
				};

				parser.ImageUnload += e => {
					Console.ForegroundColor = ConsoleColor.DarkYellow;
					var name = TryGetProcessName(e);
					Console.WriteLine($"{e.TimeStamp}.{e.TimeStamp.Millisecond:D3}: Image Unloaded: {e.FileName} from process {e.ProcessID} ({name})");
				};

				Task.Run(() => session.Source.Process());
				Thread.Sleep(TimeSpan.FromSeconds(60));
			}

			string TryGetProcessName(TraceEvent evt) {
				if (!string.IsNullOrEmpty(evt.ProcessName))
					return evt.ProcessName;
				return processes.TryGetValue(evt.ProcessID, out var info) ? info.Name : string.Empty;
			}
		}
	}
}
```

Don't forget to install the package:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8e9UjPJM2spl78ft3X%2F-M8eTxjK24YBFe1_YikU%2Fimage.png?alt=media\&token=5b76abf4-6983-439f-9395-55335f50cac6)

If we compile and run the code, we will now see events flowing in:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8e9UjPJM2spl78ft3X%2F-M8eUEej1H-3U2mf9HkD%2Fkernel-consumer.gif?alt=media\&token=778e2087-da11-4ca3-a86b-0a0a44a07c0f)

### Notes

From an attacker's perspective, if you are up against some EDR or logging capability, you may be able to blind the system by killing their tracing session or removing certain providers from their tracing session.

From a defender's perspective, you may want to:

* learn about the additional telemetry you could get from ETW
* think about detections that target attackers trying to tamper with your telemetry through ETW

### References

[Microsoft-Windows-Threat-Intelligence](https://pastebin.com/6VGHjGjH) Provider Manifest as [mentioned](https://twitter.com/FancyCyber/status/1267536407272345602) by @FancyCyber:

![](https://386337598-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LFEMnER3fywgFHoroYn%2F-M8jyWgzvN0_u6kSet9d%2F-M8lPy6I5dIfd9oNJ4rz%2Fimage.png?alt=media\&token=26abf49c-62bf-4d92-9639-1c822d79332f)
