### Enable Provider and Start Listening for Events Source: https://github.com/microsoft/krabsetw/blob/master/docs/LobstersExample.md Enable a configured provider for a specific trace. Start the trace listening for events, which blocks the current thread. For non-blocking operation, start the trace on a separate thread. ```csharp namedTrace.Enable(provider); void startListening() { namedTrace.Start(); } var task = await Task.Factory.StartNew(() => startListening(), TaskCreationOptions.LongRunning); sleep(1000); namedTrace.Stop(); task.Wait(); ``` -------------------------------- ### Kernel Trace Example Source: https://context7.com/microsoft/krabsetw/llms.txt Shows how to set up a kernel trace using built-in providers for process, image load, and network events. Requires administrator privileges to run. ```csharp using System; using Microsoft.O365.Security.ETW; using Kernel = Microsoft.O365.Security.ETW.Kernel; using Testing = Microsoft.O365.Security.ETW.Testing; // Kernel trace example public class KernelTraceExample { public static void Start() { var trace = new KernelTrace("My Kernel Trace"); // Use built-in kernel providers var processProvider = new Kernel.ProcessProvider(); var imageProvider = new Kernel.ImageLoadProvider(); var networkProvider = new Kernel.NetworkTcpipProvider(); processProvider.OnEvent += (record) => { if (record.Opcode == 0x01) // Process start { var image = record.GetAnsiString("ImageFileName", "Unknown"); var pid = record.GetUInt32("ProcessId", 0); Console.WriteLine($"{image} started with PID {pid}"); } }; trace.Enable(processProvider); trace.Start(); // Requires administrator privileges } } ``` -------------------------------- ### Start a Kernel Trace with Event Callbacks Source: https://context7.com/microsoft/krabsetw/llms.txt Initializes a kernel trace, enables image load and process providers, and sets up callbacks to process specific events. Requires administrator privileges. ```cpp #include "krabs.hpp" void start_kernel_trace() { // Kernel traces can be named, but on Windows 7 the name may be overridden krabs::kernel_trace trace(L"My Kernel Trace"); // Krabs provides convenience providers for common kernel events // These map to Windows ETW kernel provider flags krabs::kernel::image_load_provider imageProvider; krabs::kernel::process_provider processProvider; krabs::kernel::network_tcpip_provider networkProvider; krabs::kernel::registry_provider registryProvider; krabs::kernel::thread_provider threadProvider; krabs::kernel::disk_io_provider diskProvider; // Add callback to handle image load events imageProvider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &trace_context) { krabs::schema schema(record, trace_context.schema_locator); // Filter by opcode (10 = image load per MSDN documentation) if (schema.event_opcode() == 10) { krabs::parser parser(schema); std::wstring filename = parser.parse(L"FileName"); std::wcout << L"Loaded image: " << filename << std::endl; } }); // Add callback for process events processProvider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &trace_context) { krabs::schema schema(record, trace_context.schema_locator); // Opcode 1 = process start, 2 = process end if (schema.event_opcode() == 1) { krabs::parser parser(schema); std::wstring imageName = parser.parse(L"ImageFileName"); auto pid = parser.parse(L"ProcessId"); std::wcout << L"Process started: " << imageName << L" (PID: " << pid << L")" << std::endl; } }); // Enable providers on the trace (can enable multiple) trace.enable(imageProvider); trace.enable(processProvider); // Requires administrator privileges to start trace.start(); } // Available kernel providers: // - krabs::kernel::alpc_provider (ALPC events) // - krabs::kernel::context_switch_provider (context switches) // - krabs::kernel::disk_io_provider (disk I/O completion) // - krabs::kernel::file_io_provider (file I/O completion) // - krabs::kernel::image_load_provider (DLL/EXE loads) // - krabs::kernel::memory_page_fault_provider (page faults) // - krabs::kernel::network_tcpip_provider (TCP/IP events) // - krabs::kernel::process_provider (process start/stop) // - krabs::kernel::registry_provider (registry operations) // - krabs::kernel::thread_provider (thread start/stop) // - krabs::kernel::virtual_alloc_provider (VirtualAlloc/Free) ``` -------------------------------- ### Define and Configure Provider Source: https://github.com/microsoft/krabsetw/blob/master/docs/KrabsExample.md Create a provider instance identified by a GUID. Use the 'any' and 'all' flags for event filtering. Register a callback function to handle events. ```cpp void mycallbackFunction(const EVENT_RECORD &, const trace_context &) {} provider<> powershellProvider(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}"); powershellProvider.any(0x10); powershellProvider.any(0x01); // augment the any flag powershellProvider.add_on_event_callback(mycallbackFunction); ``` -------------------------------- ### Start ETW Trace Listening Source: https://github.com/microsoft/krabsetw/blob/master/Microsoft.O365.Security.Native.ETW/README.md Begin listening for ETW events on a trace. The Start() method blocks, so it's recommended to run it on a separate thread for concurrent operations. ```csharp var t = Task.Run(() => namedTrace.Start()); ``` -------------------------------- ### Basic User Trace Example Source: https://context7.com/microsoft/krabsetw/llms.txt Demonstrates creating a user trace, registering a provider with specific flags, and handling incoming events. Use this for general ETW event consumption in .NET. ```csharp using System; using Microsoft.O365.Security.ETW; using Kernel = Microsoft.O365.Security.ETW.Kernel; using Testing = Microsoft.O365.Security.ETW.Testing; // Basic user trace example public class UserTraceExample { public static void Start() { // Create a user trace (named or unnamed) var trace = new UserTrace(); var namedTrace = new UserTrace("My Trace Name"); // Create provider with GUID var provider = new Provider(Guid.Parse("{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); // Set any/all flags provider.Any = Provider.AllBitsSet; provider.All = 0x10; // Register event handler provider.OnEvent += (record) => { Console.WriteLine($"Event {record.Id} ({record.Name}) received"); if (record.Id == 7937) { // Parse properties with default fallback var context = record.GetUnicodeString("ContextInfo", "None"); var pid = record.GetUInt32("ProcessId", 0); Console.WriteLine($"Context: {context}, PID: {pid}"); } }; // Enable provider and start (blocks until Stop() is called) trace.Enable(provider); trace.Start(); } } ``` -------------------------------- ### Start and Stop Trace Listening Source: https://github.com/microsoft/krabsetw/blob/master/docs/KrabsExample.md Start listening for events on a trace. The start method blocks, so it's often called on a separate thread for concurrent operations. Ensure to stop the trace and join the thread afterwards. ```cpp void startListening() { namedTrace.start(); } std::thread t(startListening); sleep(1000); namedTrace.stop(); t.join(); ``` -------------------------------- ### Start a User Trace Source: https://context7.com/microsoft/krabsetw/llms.txt Demonstrates how to create and configure a user-mode ETW trace session. Includes setting up providers, filtering events, and registering callbacks for event handling. Use this to capture events from user-mode applications or Windows components. ```cpp #include "krabs.hpp" void start_user_trace() { // Create a user trace - can be unnamed or named krabs::user_trace trace; // unnamed trace (random GUID name) krabs::user_trace namedTrace(L"My Named Trace"); // named trace // Create a provider using its GUID (PowerShell provider in this example) krabs::provider<> provider(krabs::guid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); // Set the "any" flag to filter which events to receive // The meaning of these flags is provider-specific provider.any(0xf0010000000003ff); // Register a callback to handle events provider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &trace_context) { // Create a schema to interpret the event krabs::schema schema(record, trace_context.schema_locator); std::wcout << L"Event " << schema.event_id(); std::wcout << L" (" << schema.event_name() << L") received." << std::endl; // Parse specific event data if (schema.event_id() == 7937) { krabs::parser parser(schema); std::wstring context = parser.parse(L"ContextInfo"); std::wcout << L"\tContext: " << context << std::endl; } }); // Enable the provider on the trace trace.enable(provider); // Start listening - this call BLOCKS until trace.stop() is called // Run on separate thread if you need to do other work trace.start(); } // To run trace on separate thread: void run_trace_async() { krabs::user_trace trace(L"Async Trace"); // ... setup providers ... std::thread t([&trace]() { trace.start(); }); // Do other work... std::this_thread::sleep_for(std::chrono::seconds(10)); trace.stop(); // Signal the trace to stop t.join(); // Wait for thread to complete } ``` -------------------------------- ### Parse Process Start Event Details Source: https://context7.com/microsoft/krabsetw/llms.txt Parses specific details from a process start event, including Process ID, Parent ID, Session ID, Image File Name, and Command Line. It checks the event opcode to ensure it's a process start event before parsing. ```cpp // Example: Parsing a process start event void parse_process_event(const EVENT_RECORD &record, const krabs::trace_context &ctx) { krabs::schema schema(record, ctx.schema_locator); if (schema.event_opcode() == 1) { // Process start krabs::parser parser(schema); auto pid = parser.parse(L"ProcessId"); auto ppid = parser.parse(L"ParentId"); auto sessionId = parser.parse(L"SessionId"); std::string imageName; std::wstring commandLine; parser.try_parse(L"ImageFileName", imageName); parser.try_parse(L"CommandLine", commandLine); std::wcout << L"Process: " << imageName.c_str() << L" PID: " << pid << L" PPID: " << ppid << std::endl; } } ``` -------------------------------- ### Enable Provider for Trace Source: https://github.com/microsoft/krabsetw/blob/master/docs/KrabsExample.md Enable a configured provider for a specific trace instance. This must be done before starting the trace. ```cpp namedTrace.enable(powershellProvider); ``` -------------------------------- ### Configure and Enable ETW Provider Source: https://github.com/microsoft/krabsetw/blob/master/Microsoft.O365.Security.Native.ETW/README.md Create a Provider instance using its GUID, set filtering flags (Any/All), and register a callback function. Providers must be enabled on a trace to capture events. ```csharp Provider powershellProvider = new Provider(Guid.Parse("{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); powershellProvider.Any = 0x10; powershellProvider.OnEvent += MyCallbackFunction; ``` -------------------------------- ### Setup Error Handling and Callbacks in Krabs Source: https://context7.com/microsoft/krabsetw/llms.txt Configure provider-level, event-level, and filter-level error callbacks. Also demonstrates setting a default callback for unhandled events and safe event parsing. ```cpp #include "krabs.hpp" void setup_error_handling() { krabs::user_trace trace; krabs::provider<> provider(krabs::guid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); provider.any(0xf0010000000003ff); // Provider-level error callback provider.add_on_error_callback([](const EVENT_RECORD &record, const std::string &errorMessage) { std::cerr << "Provider error for event " << record.EventHeader.EventDescriptor.Id << ": " << errorMessage << std::endl; }); // Event callback provider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { try { krabs::schema schema(record, ctx.schema_locator); krabs::parser parser(schema); // Safe parsing with try_parse std::wstring value; if (!parser.try_parse(L"SomeProperty", value)) { std::wcerr << L"Property not found" << std::endl; return; } std::wcout << L"Value: " << value << std::endl; } catch (const std::exception &e) { std::cerr << "Error processing event: " << e.what() << std::endl; } }); // Filter-level error callback krabs::event_filter filter(krabs::predicates::id_is(7937)); filter.add_on_error_callback([](const EVENT_RECORD &record, const std::string &errorMessage) { std::cerr << "Filter error: " << errorMessage << std::endl; }); filter.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { // Handle filtered events }); provider.add_filter(filter); trace.enable(provider); // Default callback for events with no matching provider trace.set_default_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { std::wcout << L"Unhandled event from provider: " << record.EventHeader.ProviderId.Data1 << std::endl; }); trace.start(); } ``` -------------------------------- ### Event Filtering Example Source: https://context7.com/microsoft/krabsetw/llms.txt Illustrates how to filter ETW events using a predicate defined in native code for performance. Includes error handling for filters and providers. ```csharp using System; using Microsoft.O365.Security.ETW; using Kernel = Microsoft.O365.Security.ETW.Kernel; using Testing = Microsoft.O365.Security.ETW.Testing; // Event filtering example public class FilterExample { public static void Start() { var trace = new UserTrace("Filtered Trace"); var provider = new Provider(Guid.Parse("{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); provider.Any = Provider.AllBitsSet; // Create filter with predicate (filters in native code for performance) var filter = new EventFilter(Filter.EventIdIs(7937)); filter.OnEvent += (record) => { System.Diagnostics.Debug.Assert(record.Id == 7937); Console.WriteLine("Filtered event received"); }; // Error handling filter.OnError += (error) => { Console.WriteLine($"Filter error: {error.Message}"); }; provider.OnError += (error) => { Console.WriteLine($"Provider error: {error.Message}"); }; provider.AddFilter(filter); trace.Enable(provider); trace.Start(); } } ``` -------------------------------- ### Enable Rundown Events for Process Enumeration Source: https://context7.com/microsoft/krabsetw/llms.txt Enables rundown events for the Microsoft-Windows-Kernel-Process provider to capture existing processes when a trace starts. Parses and prints image names and PIDs. ```cpp #include "krabs.hpp" void enable_rundown_events() { krabs::user_trace trace; // Microsoft-Windows-Kernel-Process provider for process enumeration krabs::provider<> processProvider(L"Microsoft-Windows-Kernel-Process"); processProvider.any(0x10); // WINEVENT_KEYWORD_PROCESS // Enable rundown events to get existing processes processProvider.enable_rundown_events(); processProvider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { krabs::schema schema(record, ctx.schema_locator); krabs::parser parser(schema); // Rundown events have the same schema as regular events auto pid = parser.parse(L"ProcessId"); std::wstring imageName; parser.try_parse(L"ImageName", imageName); std::wcout << L"Process: " << imageName << L" (PID: " << pid << L")" << std::endl; }); trace.enable(processProvider); trace.start(); } ``` -------------------------------- ### Configure and Attach Event Handler to Provider Source: https://github.com/microsoft/krabsetw/blob/master/docs/LobstersExample.md Define a provider with a specific GUID and configure its Any/All filtering flags. Register an event handler to be called when events matching the provider's criteria are received. ```csharp void OnEventRecord(IEventRecord record) {} var trace = new UserTrace(); var provider = new Provider(Guid.Parse("{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); provider.All = 0x10; provider.Any = 0x01; // augment the Any flag. provider.OnEvent += OnEventRecord; ``` -------------------------------- ### Test Event Handling with Synthetic Events Source: https://context7.com/microsoft/krabsetw/llms.txt Demonstrates setting up a trace, provider, and callback to process synthetic events. Use this to unit test event handler logic. ```cpp #include "krabs.hpp" void test_event_handling() { // Setup the trace and provider as normal krabs::user_trace trace(L"Test Trace"); krabs::guid powershellGuid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}"); krabs::provider<> provider(powershellGuid); provider.any(0xf0010000000003ff); std::wstring capturedContext; provider.add_on_event_callback([&capturedContext](const EVENT_RECORD &record, const krabs::trace_context &ctx) { krabs::schema schema(record, ctx.schema_locator); krabs::parser parser(schema); capturedContext = parser.parse(L"ContextInfo"); std::wcout << L"Received context: " << capturedContext << std::endl; }); trace.enable(provider); // Create a proxy to push synthetic events (instead of calling trace.start()) krabs::testing::user_trace_proxy proxy(trace); // Build a synthetic event using record_builder krabs::testing::record_builder builder(powershellGuid, krabs::id(7937), krabs::version(1)); // Add properties to the synthetic event builder.add_properties() (L"ContextInfo", L"Test context value") (L"Data", L"Test data value") (L"UserData", L"Additional test data"); // For some events, you may need to set header flags // builder.header().Flags = EVENT_HEADER_FLAG_CLASSIC_HEADER // | EVENT_HEADER_FLAG_64_BIT_HEADER; // Pack the event (validates all required properties are set) // Use pack_incomplete() to allow missing properties with defaults auto record = builder.pack_incomplete(); // Push the synthetic event through the trace proxy.push_event(record); // Verify the callback processed the event correctly assert(capturedContext == L"Test context value"); } ``` -------------------------------- ### Configure Trace Properties in C++ Source: https://context7.com/microsoft/krabsetw/llms.txt Set buffer sizes, minimum/maximum buffers, flush timers, and log file modes for an ETW trace. Ensure buffer size is within 1024 KB and minimum buffers are at least 2 per processor. ```cpp #include "krabs.hpp" void configure_trace_properties() { krabs::user_trace trace(L"Configured Trace"); // Configure trace properties before starting EVENT_TRACE_PROPERTIES properties = { 0 }; properties.BufferSize = 256; // Buffer size in KB (max 1024) properties.MinimumBuffers = 12; // Minimum buffers (at least 2 per processor) properties.MaximumBuffers = 48; // Maximum buffers properties.FlushTimer = 1; // Flush interval in seconds properties.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; trace.set_trace_properties(&properties); // Setup provider krabs::provider<> provider(krabs::guid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); provider.any(0xf0010000000003ff); provider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { // Handle event }); trace.enable(provider); trace.start(); } ``` -------------------------------- ### Create User Trace Source: https://github.com/microsoft/krabsetw/blob/master/docs/KrabsExample.md Instantiate a user trace. An unnamed trace will have a generated name, while a named trace can be given an arbitrary name. ```cpp user_trace trace(); // unnamed trace user_trace namedTrace(L"Muffins McGoo"); ``` -------------------------------- ### Create UserTrace Instance Source: https://github.com/microsoft/krabsetw/blob/master/Microsoft.O365.Security.Native.ETW/README.md Instantiate a UserTrace, either with a custom name or an auto-generated one. User traces represent streams of events from user-mode applications. ```csharp UserTrace trace = new UserTrace(); // unnamed trace UserTrace namedTrace = new UserTrace("Muffins McGoo"); ``` -------------------------------- ### Create UserTrace Instance Source: https://github.com/microsoft/krabsetw/blob/master/docs/LobstersExample.md Instantiate a UserTrace. An unnamed trace will have a generated name, while a named trace can be given an arbitrary identifier. ```csharp var trace = new UserTrace(); // unnamed trace var namedTrace = new UserTrace("Muffins McGoo"); ``` -------------------------------- ### Async Trace with Threading Source: https://context7.com/microsoft/krabsetw/llms.txt Demonstrates running an ETW trace on a background thread using Task.Factory.StartNew for long-running operations. Useful for non-blocking trace collection. ```csharp using System; using Microsoft.O365.Security.ETW; using Kernel = Microsoft.O365.Security.ETW.Kernel; using Testing = Microsoft.O365.Security.ETW.Testing; // Async trace with threading public class AsyncTraceExample { public static async Task RunAsync() { var trace = new UserTrace(); // ... setup providers ... // Run trace on background thread var task = Task.Factory.StartNew( () => trace.Start(), TaskCreationOptions.LongRunning); // Do other work... await Task.Delay(10000); trace.Stop(); await task; } } ``` -------------------------------- ### Testing with Synthetic Events Source: https://context7.com/microsoft/krabsetw/llms.txt Shows how to test ETW event handling by creating and pushing synthetic events using the Testing.Proxy and Testing.RecordBuilder. Verifies event data capture. ```csharp using System; using Microsoft.O365.Security.ETW; using Kernel = Microsoft.O365.Security.ETW.Kernel; using Testing = Microsoft.O365.Security.ETW.Testing; // Testing with synthetic events public class TestingExample { public static void TestEventHandler() { var trace = new UserTrace("Test Trace"); var guid = Guid.Parse("{A0C1853B-5C40-4B15-8766-3CF1C58F985A}"); var provider = new Provider(guid); provider.Any = Provider.AllBitsSet; string capturedValue = null; provider.OnEvent += (record) => { foreach (Property prop in record.Properties) { Console.WriteLine($"Property: {prop.Name}"); } capturedValue = record.GetUnicodeString("ContextInfo", null); }; trace.Enable(provider); // Create proxy for testing var proxy = new Testing.Proxy(trace); // Build synthetic event var builder = new Testing.RecordBuilder(guid, 7937, 1); builder.AddUnicodeString("ContextInfo", "Test value"); builder.AddUnicodeString("Data", "More test data"); // Pack and push event var packed = builder.PackIncomplete(); proxy.PushEvent(packed); Debug.Assert(capturedValue == "Test value"); } } ``` -------------------------------- ### Kernel Rundown for Loaded Modules Source: https://context7.com/microsoft/krabsetw/llms.txt Captures kernel rundown events for loaded modules using the image load provider. Filters for load or DCStart opcodes and prints module file names. ```cpp // Kernel rundown for loaded modules void kernel_rundown() { krabs::kernel_trace trace(L"Rundown Trace"); krabs::kernel::image_load_provider imageProvider; // Set rundown flags for kernel provider imageProvider.set_rundown_flags(EVENT_TRACE_FLAG_IMAGE_LOAD); imageProvider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { krabs::schema schema(record, ctx.schema_locator); if (schema.event_opcode() == 10 || schema.event_opcode() == 3) { // Load or DCStart krabs::parser parser(schema); auto fileName = parser.parse(L"FileName"); std::wcout << L"Module: " << fileName << std::endl; } }); trace.enable(imageProvider); trace.start(); } ``` -------------------------------- ### Test Event Filtering Logic Source: https://context7.com/microsoft/krabsetw/llms.txt Illustrates how to set up event filters to selectively process events based on criteria like event ID. This is useful for testing filtering mechanisms. ```cpp // Test filtering logic void test_event_filters() { krabs::user_trace trace; krabs::guid testGuid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}"); krabs::provider<> provider(testGuid); int filteredCount = 0; int unfilteredCount = 0; // Filter for specific event ID krabs::event_filter filter(krabs::predicates::id_is(7937)); filter.add_on_event_callback([&filteredCount](const EVENT_RECORD &record, const krabs::trace_context &ctx) { filteredCount++; }); // Direct provider callback receives all events provider.add_on_event_callback([&unfilteredCount](const EVENT_RECORD &record, const krabs::trace_context &ctx) { unfilteredCount++; }); provider.add_filter(filter); trace.enable(provider); krabs::testing::user_trace_proxy proxy(trace); // Push event with ID 7937 (should trigger both callbacks) krabs::testing::record_builder builder1(testGuid, krabs::id(7937), krabs::version(1)); proxy.push_event(builder1.pack_incomplete()); // Push event with ID 1000 (should only trigger provider callback) krabs::testing::record_builder builder2(testGuid, krabs::id(1000), krabs::version(1)); proxy.push_event(builder2.pack_incomplete()); assert(filteredCount == 1); assert(unfilteredCount == 2); } ``` -------------------------------- ### Monitor Trace Statistics in C++ Source: https://context7.com/microsoft/krabsetw/llms.txt Query and display ETW trace statistics such as buffer counts, free buffers, written buffers, lost buffers, total events, handled events, and lost events. This is useful for performance analysis after a trace has been running. ```cpp // Query trace statistics void monitor_trace_stats() { krabs::user_trace trace; // ... setup and start trace ... // After running for a while, query stats krabs::trace_stats stats = trace.query_stats(); std::wcout << L"Buffers: " << stats.buffersCount << std::endl; std::wcout << L"Buffers Free: " << stats.buffersFree << std::endl; std::wcout << L"Buffers Written: " << stats.buffersWritten << std::endl; std::wcout << L"Buffers Lost: " << stats.buffersLost << std::endl; std::wcout << L"Events Total: " << stats.eventsTotal << std::endl; std::wcout << L"Events Handled: " << stats.eventsHandled << std::endl; std::wcout << L"Events Lost: " << stats.eventsLost << std::endl; } ``` -------------------------------- ### Iterate Over All Event Properties Source: https://context7.com/microsoft/krabsetw/llms.txt Demonstrates how to iterate through all properties of an ETW event using the `parser.properties()` method. This is useful for inspecting all available data within an event when specific property names are unknown. ```cpp // Iterate over all properties in the event for (auto& prop : parser.properties()) { std::wcout << L"Property: " << prop.name() << std::endl; } ``` -------------------------------- ### Enable Provider on Trace Source: https://github.com/microsoft/krabsetw/blob/master/Microsoft.O365.Security.Native.ETW/README.md Associate an enabled Provider with a specific UserTrace instance. This step is necessary for the trace to begin capturing events from the provider. ```csharp namedTrace.Enable(powershellProvider); ``` -------------------------------- ### Advanced Event Filtering with Multiple Predicates in Krabs Source: https://context7.com/microsoft/krabsetw/llms.txt Demonstrates advanced filtering techniques using a combination of predicates, including AND, OR, and NOT logic, as well as property-based filtering for strings. ```cpp // Advanced filtering with multiple predicates void advanced_filtering() { krabs::user_trace trace; krabs::provider<> provider(krabs::guid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); // Filter by event ID auto idFilter = krabs::predicates::id_is(7937); // Filter by opcode auto opcodeFilter = krabs::predicates::opcode_is(10); // Filter by process ID auto pidFilter = krabs::predicates::process_id_is(1234); // Filter by event version auto versionFilter = krabs::predicates::version_is(1); // Filter by property value auto propFilter = krabs::predicates::property_is(L"FileName", L"notepad.exe"); // Combine filters with AND auto combinedAnd = krabs::predicates::and_filter(idFilter, opcodeFilter); // Combine filters with OR auto combinedOr = krabs::predicates::or_filter(idFilter, opcodeFilter); // Negate a filter auto notFilter = krabs::predicates::not_filter(idFilter); // String property predicates auto containsFilter = krabs::predicates::property_contains(L"CommandLine", std::wstring(L"powershell")); auto startsWithFilter = krabs::predicates::property_starts_with(L"Path", std::wstring(L"C:\\Windows")); auto endsWithFilter = krabs::predicates::property_ends_with(L"FileName", std::wstring(L".exe")); // Case-insensitive variants auto icontainsFilter = krabs::predicates::property_icontains(L"CommandLine", std::wstring(L"POWERSHELL")); auto iequalsFilter = krabs::predicates::property_iequals(L"Name", std::wstring(L"TEST")); // Create filter with combined predicate krabs::event_filter filter(combinedAnd); filter.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { std::wcout << L"Event matched combined filter!" << std::endl; }); provider.add_filter(filter); trace.enable(provider); trace.start(); } ``` -------------------------------- ### Read ETW Trace Data from File in C++ Source: https://context7.com/microsoft/krabsetw/llms.txt Configure Krabs to read trace events from a specified ETL file instead of a real-time session. Use `trace.process()` to parse the file contents. ```cpp // Read from an ETL file instead of real-time void read_from_file() { krabs::user_trace trace; // Set the trace to read from file trace.set_trace_filename(L"C:\\logs\\trace.etl"); krabs::provider<> provider(krabs::guid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); provider.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { // Process event from file }); trace.enable(provider); trace.process(); // Process file contents } ``` -------------------------------- ### Parse Specialized Data Types Source: https://context7.com/microsoft/krabsetw/llms.txt Shows how to parse specialized data types like IP addresses, socket addresses, SIDs, binary data, and pointers from ETW events. These parsers handle the specific formats and provide convenient methods for accessing the data. ```cpp // Parse IP addresses (supports both IPv4 and IPv6) krabs::ip_address ipAddr = parser.parse(L"SourceAddress"); if (ipAddr.is_ipv4()) { std::wcout << L"IPv4: " << ipAddr.to_string() << std::endl; } // Parse socket addresses krabs::socket_address sockAddr = parser.parse(L"LocalAddress"); // Parse Security Identifiers (SIDs) krabs::sid userSid = parser.parse(L"UserSid"); std::wstring sidString = userSid.to_string(); // Parse binary data krabs::binary blob = parser.parse(L"BinaryData"); const uint8_t* data = blob.bytes(); size_t length = blob.length(); // Parse pointers (handles 32-bit and 64-bit automatically) krabs::pointer ptr = parser.parse(L"ObjectPointer"); uint64_t address = ptr.address; ``` -------------------------------- ### Register Event Callback Source: https://github.com/microsoft/krabsetw/blob/master/Microsoft.O365.Security.Native.ETW/README.md Define a callback function to handle incoming ETW events. This function will be invoked when events matching the provider's filter criteria are received. ```csharp void MyCallbackFunction(EventRecord) { } ``` -------------------------------- ### Safely Parse Event Properties with try_parse Source: https://context7.com/microsoft/krabsetw/llms.txt Illustrates safe parsing of optional event properties using `try_parse`. This method returns `false` if the property does not exist, preventing exceptions. Useful for fields that may or may not be present in an event. ```cpp // Safe parsing with try_parse - returns false if property doesn't exist std::wstring value; if (parser.try_parse(L"OptionalField", value)) { std::wcout << L"Optional field: " << value << std::endl; } ``` -------------------------------- ### Parse Event Properties with Explicit Types Source: https://context7.com/microsoft/krabsetw/llms.txt Demonstrates parsing various data types from ETW events using explicit type casting with the `parser` class. Ensure the property names and types match the event schema. Throws an exception if a property is not found. ```cpp #include "krabs.hpp" void parse_event_properties(const EVENT_RECORD &record, const krabs::trace_context &trace_context) { // Create schema and parser krabs::schema schema(record, trace_context.schema_locator); krabs::parser parser(schema); // Get basic event information from schema auto eventId = schema.event_id(); auto eventName = schema.event_name(); auto opcode = schema.event_opcode(); auto providerId = schema.provider_id(); auto processId = schema.process_id(); auto threadId = schema.thread_id(); auto timestamp = schema.timestamp(); // Parse properties by name with explicit type // Throws exception if property doesn't exist std::wstring unicodeStr = parser.parse(L"CommandLine"); std::string ansiStr = parser.parse(L"ImageFileName"); uint32_t dword = parser.parse(L"ProcessId"); uint64_t qword = parser.parse(L"Address"); int32_t signedInt = parser.parse(L"ReturnCode"); bool flag = parser.parse(L"Success"); // Safe parsing with try_parse - returns false if property doesn't exist std::wstring value; if (parser.try_parse(L"OptionalField", value)) { std::wcout << L"Optional field: " << value << std::endl; } // Parse IP addresses (supports both IPv4 and IPv6) krabs::ip_address ipAddr = parser.parse(L"SourceAddress"); if (ipAddr.is_ipv4()) { std::wcout << L"IPv4: " << ipAddr.to_string() << std::endl; } // Parse socket addresses krabs::socket_address sockAddr = parser.parse(L"LocalAddress"); // Parse Security Identifiers (SIDs) krabs::sid userSid = parser.parse(L"UserSid"); std::wstring sidString = userSid.to_string(); // Parse binary data krabs::binary blob = parser.parse(L"BinaryData"); const uint8_t* data = blob.bytes(); size_t length = blob.length(); // Parse pointers (handles 32-bit and 64-bit automatically) krabs::pointer ptr = parser.parse(L"ObjectPointer"); uint64_t address = ptr.address; // Iterate over all properties in the event for (auto& prop : parser.properties()) { std::wcout << L"Property: " << prop.name() << std::endl; } } ``` -------------------------------- ### Filter Events by ID using Krabs Source: https://context7.com/microsoft/krabsetw/llms.txt Create a filter that only passes events with a specific ID. Callbacks attached to this filter will only receive events that match the predicate. ```cpp #include "krabs.hpp" void filtered_trace() { krabs::user_trace trace(L"Filtered Trace"); krabs::provider<> provider(krabs::guid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); provider.any(0xf0010000000003ff); // Create a filter that only passes events with ID 7937 krabs::event_filter filter(krabs::predicates::id_is(7937)); // Callbacks on the filter only receive events that pass the predicate filter.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &trace_context) { krabs::schema schema(record, trace_context.schema_locator); std::wcout << L"Filtered event 7937 received!" << std::endl; }); // Attach filter to provider provider.add_filter(filter); trace.enable(provider); trace.start(); } ``` -------------------------------- ### Efficient Event ID Filtering at ETW API Level in Krabs Source: https://context7.com/microsoft/krabsetw/llms.txt Utilize Krabs to filter events directly at the ETW API level by providing event IDs. This method offers better performance compared to in-memory filtering. ```cpp // ETW API-level filtering by event ID (more efficient) void efficient_id_filtering() { krabs::user_trace trace; krabs::provider<> provider(krabs::guid(L"{A0C1853B-5C40-4B15-8766-3CF1C58F985A}")); // Pass event IDs directly - filtered at ETW API level for better performance krabs::event_filter filter(7937); // Single event ID // Or multiple event IDs krabs::event_filter multiFilter(std::vector{7937, 7938, 7939}); filter.add_on_event_callback([](const EVENT_RECORD &record, const krabs::trace_context &ctx) { // Only receives events with ID 7937 }); provider.add_filter(filter); trace.enable(provider); trace.start(); } ``` -------------------------------- ### Define PowerShell Function Source: https://github.com/microsoft/krabsetw/blob/master/docs/UsingMessageAnalyzerToFindETWSources.md Define a simple PowerShell function to trigger ETW events. This is used to generate sample data for analysis in Message Analyzer. ```powershell function invoke-mimikatz {} invoke-mimikatz ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.