mirror of
https://github.com/microsoft/krabsetw
synced 2026-06-06 16:14:32 +00:00
676d948235
Add support for reading EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY from ETW extended data items, enabled via EVENT_ENABLE_PROPERTY_PROCESS_START_KEY. The ProcessStartKey uniquely identifies a process instance across a boot session (unlike PID which can be recycled). Changes: - Native C++: schema::process_start_key() in schema.hpp - Managed .NET: TryGetProcessStartKey() on IEventRecordMetadata/EventRecordMetadata - Test support: extended_data_builder::add_process_start_key() - New example: UserTrace008_ProcessStartKey.cs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
74 lines
3.0 KiB
C#
74 lines
3.0 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
// This example demonstrates reading the ProcessStartKey from ETW extended data items.
|
|
// The ProcessStartKey uniquely identifies a process instance across a boot session
|
|
// (unlike PID which can be recycled).
|
|
|
|
using System;
|
|
using System.Security.Principal;
|
|
using System.Threading;
|
|
using Microsoft.O365.Security.ETW;
|
|
|
|
namespace ManagedExamples
|
|
{
|
|
public static class UserTrace008_ProcessStartKey
|
|
{
|
|
public static void Start()
|
|
{
|
|
if (!(new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator)))
|
|
{
|
|
Console.WriteLine("Microsoft-Windows-Kernel-Process provider requires Administrator privileges.");
|
|
return;
|
|
}
|
|
|
|
var trace = new UserTrace("UserTrace008_ProcessStartKey");
|
|
var provider = new Provider("Microsoft-Windows-Kernel-Process");
|
|
provider.Any = 0x10; // WINEVENT_KEYWORD_PROCESS
|
|
provider.TraceFlags |= TraceFlags.IncludeProcessStartKey;
|
|
|
|
int eventCount = 0;
|
|
int eventsWithKey = 0;
|
|
const int maxEvents = 10;
|
|
|
|
// Listen for ProcessStart (1) and ProcessStop (2)
|
|
var filter = new EventFilter(Filter.EventIdIs(1).Or(Filter.EventIdIs(2)));
|
|
filter.OnEvent += (record) =>
|
|
{
|
|
var pid = record.GetUInt32("ProcessID");
|
|
string imageName;
|
|
try { imageName = record.GetUnicodeString("ImageName"); }
|
|
catch { try { imageName = record.GetAnsiString("ImageName"); } catch { imageName = "<unknown>"; } }
|
|
|
|
ulong processStartKey = 0;
|
|
bool hasKey = record.TryGetProcessStartKey(out processStartKey);
|
|
|
|
if (hasKey && processStartKey != 0)
|
|
Interlocked.Increment(ref eventsWithKey);
|
|
|
|
int count = Interlocked.Increment(ref eventCount);
|
|
|
|
Console.WriteLine($"[{record.TaskName}] PID={pid} ImageName={imageName} " +
|
|
$"HasProcessStartKey={hasKey} ProcessStartKey=0x{processStartKey:X}");
|
|
|
|
if (count >= maxEvents)
|
|
{
|
|
Console.WriteLine($"\nReceived {count} events, {eventsWithKey} had a non-zero ProcessStartKey.");
|
|
if (eventsWithKey > 0)
|
|
Console.WriteLine("PASS: ProcessStartKey is being populated in extended data.");
|
|
else
|
|
Console.WriteLine("FAIL: No events had a ProcessStartKey set.");
|
|
trace.Stop();
|
|
}
|
|
};
|
|
|
|
provider.AddFilter(filter);
|
|
trace.Enable(provider);
|
|
|
|
Console.WriteLine("Listening for process start/stop events (will stop after 10 events)...");
|
|
Console.WriteLine("Tip: Start or stop some processes to generate events.\n");
|
|
trace.Start();
|
|
}
|
|
}
|
|
}
|