Skip to content

moligarch/LibETW

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LibETW

LibETW is a high-performance, concurrent-safe C library designed for consuming and controlling Event Tracing for Windows (ETW) events. Built for Cyber Security products (EDR/XDR) and high-throughput telemetry agents, it prioritizes ABI stability, low resource usage, and instruction cache locality.

Features

  • High Performance: Optimized hot path with internal TDH schema caching and zero-allocation property access where possible.
  • ABI Stable: Uses opaque handles (HETWCONSUMER, HETWCONTROLLER) and the PIMPL idiom to ensure binary compatibility.
  • Concurrency Safe: Thread-safe stopping mechanisms; designed for highly concurrent environments.
  • No Implicit Threading: The library does not spawn background threads. You control the threading model (1:1, Thread Pool, etc.).
  • Modern C: Written in standard C17.
  • Flexible Build: Supports both Static Library (.lib) and Dynamic Library (.dll) builds via a Shared Items Project structure.

Project Structure

The solution is organized to separate the public API from the internal implementation:

  • LibETWFiles (Shared Items): Contains the core source code and internal logic.
  • ETWStaticLib: Wrapper project to build a static library (.lib).
  • ETWDynamicLinkLib: Wrapper project to build a dynamic library (.dll).
  • Example/TestConsumer*: A sample console applications demonstrating usage of both static and dynamic linking.

Building

Prerequisites

  • Visual Studio 2022
  • Windows SDK 10.0+

Configurations

The project uses preprocessor definitions to control symbol visibility:

  • Building DLL: LIBETW_EXPORTS
  • Building/Using Static Lib: LIBETW_STATIC

Quick Start

1. Initialize a Session (Controller)

The Controller API manages the Kernel Trace Session. You must run as Administrator.

#include <libetw/controller.h>

ETW_CONTROLLER_CONFIG config = { 0 };
config.SessionName = L"MySecureSession";
config.Mode = ETW_MODE_REALTIME;
config.BufferSizeKB = 64; // 64KB buffers
config.MinimumBuffers = 2;
config.MaximumBuffers = 20;

HETWCONTROLLER hController;
ETW_RESULT hr = EtwControllerStart(&config, &hController);

// Enable "Microsoft-Windows-Kernel-Process"
static const GUID ProcessProvider = { 0x22FB2CD6, 0x0E7B, 0x422B, { 0xA0, 0xC7, 0x2F, 0xAD, 0x1F, 0xD0, 0xE7, 0x16 } };
EtwControllerEnableProvider(hController, &ProcessProvider, TRACE_LEVEL_INFORMATION, 0, 0);

2. Consume Events (Consumer)

The Consumer API reads events from the session. The EtwConsumerProcess function blocks the calling thread, allowing you to pin it to specific cores if needed.

#include <libetw/consumer.h>

void ETW_CALL MyEventCallback(HETWEVENT hEvent, PVOID pContext) {
    PEVENT_HEADER pHeader;
    EtwEventGetHeader(hEvent, &pHeader);

    // Filter for Process Start (Id 1)
    if (pHeader->EventDescriptor.Id == 1) {
        ULONG idxImage = 0;
        LPCWSTR imageName = NULL;

        // Retrieve cached property index (Fast)
        if (EtwEventGetPropertyIndex(hEvent, L"ImageName", &idxImage) == ETW_S_OK) {
             // Zero-copy extraction (returns pointer to internal buffer)
             EtwEventReadString(hEvent, idxImage, &imageName, NULL);
             printf("Process Started: %ls\n", imageName);
        }
    }
}

// In your worker thread:
HETWCONSUMER hConsumer;
EtwConsumerOpen(L"MySecureSession", ETW_MODE_REALTIME, MyEventCallback, NULL, NULL, &hConsumer);
EtwConsumerProcess(hConsumer); // Blocks until stopped

3. Cleanup

EtwConsumerStop(hConsumer);  // Signals loop to exit
EtwConsumerClose(hConsumer); // Frees memory

EtwControllerStop(hController);
EtwControllerClose(hController);

API Overview

Controller (controller.h)

  • EtwControllerStart: Starts a kernel trace session.
  • EtwControllerEnableProvider: Enables a provider via EnableTraceEx2.
  • EtwControllerStop: Flushes buffers and stops the session.

Consumer (consumer.h)

  • EtwConsumerOpen: Prepares a consumer handle for Realtime or File modes.
  • EtwConsumerProcess: Enters the blocking processing loop.
  • EtwEventGetPropertyIndex: Resolves a property name to an index (uses internal caching).
  • EtwEventReadString / EtwEventReadUInt32: High-performance data extraction.

Performance Notes

  • TDH Caching: LibETW implements a "Last-Seen" cache for TDH metadata. Bursts of identical event types (common in high-load scenarios) incur near-zero lookup overhead.
  • Scratch Buffers: String extraction uses thread-local scratch buffers to avoid malloc in the hot path.
  • Opaque Handles: Prevents users from accessing internal structures, allowing internal optimizations without breaking ABI.

License

MIT

About

C Library to work with Event Trace for Windows (ETW)

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages