Skip to content

Instantly share code, notes, and snippets.

@Zhentar
Created July 3, 2019 19:22
Show Gist options
  • Save Zhentar/4958d3fef6e51fbeb07e8f7c96d315d7 to your computer and use it in GitHub Desktop.
Save Zhentar/4958d3fef6e51fbeb07e8f7c96d315d7 to your computer and use it in GitHub Desktop.
C# script for exploring ETW providers
using System.ComponentModel;
using System.Runtime.InteropServices;
public static unsafe ulong StartTraceHelper(string loggerName, string filename)
{
var trace_props = NewEventTraceProperties(false);
trace_props.LogFileMode = 0x08000000; //EVENT_TRACE_INDEPENDENT_SESSION_MODE
trace_props.BufferSize = 1024;
for (int i = 0; i < loggerName.Length; i++)
{
trace_props.LoggerName[i] = loggerName[i];
}
for (int i = 0; i < filename.Length; i++)
{
trace_props.LogFileName[i] = filename[i];
}
ulong handle = 0;
var error = StartTrace(ref handle, trace_props.LoggerName, &trace_props);
if (error != 0)
{
throw new Win32Exception(error);
}
return handle;
}
public static unsafe void StopTraceHelper(ulong handle)
{
var trace_props = NewEventTraceProperties(false);
var error = StopTrace(handle, null, &trace_props);
if (error != 0)
{
throw new Win32Exception(error);
}
}
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
private static extern unsafe int StartTrace(ref ulong SessionHandle, void* SessionName, void* Properties);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
private static extern unsafe int StopTrace(ulong SessionHandle, void* SessionName, void* Properties);
private static unsafe EVENT_TRACE_PROPERTIES NewEventTraceProperties(bool isRealtime)
{
var trace_props = new EVENT_TRACE_PROPERTIES();
trace_props.Wnode.BufferSize = (uint)sizeof(EVENT_TRACE_PROPERTIES);
trace_props.Wnode.Flags = 0x20000;
//system trace control guid - only needed for 'NT Kernel Logger', forbidden otherwise...
//trace_props.Wnode.Guid = new Guid(0x9E814AAD, 0x3204, 0x11D2, 0x9A, 0x82, 0x00, 0x60, 0x08, 0xA8, 0x69, 0x39);
trace_props.LoggerNameOffset = 0x78 /*offsetof(LoggerName)*/;
if (!isRealtime)
{ //Left at 0 for a real time session
trace_props.LogFileNameOffset = 0x280 /*offsetof(LogFileName)*/;
}
return trace_props;
}
[StructLayout(LayoutKind.Sequential)]
private unsafe struct EVENT_TRACE_PROPERTIES
{
public WNODE_HEADER Wnode;
public uint BufferSize;
public uint MinimumBuffers;
public uint MaximumBuffers;
public uint MaximumFileSize;
public uint LogFileMode;
public uint FlushTimer;
public uint EnableFlags;
public int AgeLimit;
public uint NumberOfBuffers;
public uint FreeBuffers;
public uint EventsLost;
public uint BuffersWritten;
public uint LogBuffersLost;
public uint RealTimeBuffersLost;
public ulong LoggerThreadId;
public uint LogFileNameOffset;
public uint LoggerNameOffset;
public fixed char LoggerName[260];
public fixed char LogFileName[260];
}
[StructLayout(LayoutKind.Sequential)]
private struct WNODE_HEADER
{
public uint BufferSize;
public uint ProviderId;
public ulong HistoricalContext;
public ulong TimeStamp;
public Guid Guid;
public uint ClientContext; // Determines the time stamp resolution
public uint Flags;
}
[DllImport("advapi32.dll")]
private static extern unsaf
e int TraceSetInformation(ulong TraceHandle, TRACE_QUERY_INFO_CLASS InformationClass, void* TraceInformation, int InformationLength);
private static unsafe void TurnOnProviderBinaryTracking(ulong handle)
{
bool enabled = true;
var error = TraceSetInformation(handle, TRACE_QUERY_INFO_CLASS.TraceProviderBinaryTracking, &enabled, sizeof(bool));
if (error != 0)
{
throw new Win32Exception(error);
}
}
[DllImport("advapi32.dll")]
internal static extern unsafe int EnumerateTraceGuidsEx(TRACE_QUERY_INFO_CLASS TraceQueryInfoClass, void* InBuffer, int InBufferSize, void* OutBuffer, int OutBufferSize, ref int ReturnLength);
internal enum TRACE_QUERY_INFO_CLASS
{
TraceGuidQueryList,
TraceGuidQueryInfo,
TraceGuidQueryProcess,
TraceStackTracingInfo,
TraceSystemTraceEnableFlagsInfo,
TraceSampledProfileIntervalInfo,
TraceProfileSourceConfigInfo,
TraceProfileSourceListInfo,
TracePmcEventListInfo,
TracePmcCounterListInfo,
TraceSetDisallowList,
TraceVersionInfo,
TraceGroupQueryList,
TraceGroupQueryInfo,
TraceDisallowListQuery,
TraceCompressionInfo,
TracePeriodicCaptureStateListInfo,
TracePeriodicCaptureStateInfo,
TraceProviderBinaryTracking,
TraceMaxLoggersQuery,
MaxTraceSetInfoClass
};
[DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
internal static extern unsafe int EnableTraceEx2(ulong TraceHandle, in Guid ProviderId, uint ControlCode, byte Level, ulong MatchAnyKeyword, ulong MatchAllKeyword, int Timeout, void* EnableParameters);
static unsafe Guid[] GetActiveProviderGuids()
{
int buffSize = 0;
var hr = EnumerateTraceGuidsEx(TRACE_QUERY_INFO_CLASS.TraceGuidQueryList, null, 0, null, 0, ref buffSize);
if (hr != 122 && hr != 0)
{
throw new Win32Exception(hr);
}
var buffer = new Guid[buffSize / sizeof(Guid)];
var bufferBytes = MemoryMarshal.AsBytes<Guid>(buffer);
fixed(byte* buffPtr = bufferBytes)
{
hr = EnumerateTraceGuidsEx(TRACE_QUERY_INFO_CLASS.TraceGuidQueryList, null, 0, buffPtr, buffSize, ref buffSize);
}
if (hr != 0)
{
throw new Win32Exception(hr);
}
return buffer;
}
static readonly Guid KernelEventTracing = new Guid("B675EC37-BDB6-4648-BC92-F3FDC74D3CA2");
var guids = GetActiveProviderGuids();
var handle = StartTraceHelper("BinaryTrackingTest", "test.etl");
TurnOnProviderBinaryTracking(handle);
unsafe
{
EnableTraceEx2(handle, in KernelEventTracing, 1, 0, 0 ,0, 100, null);
for (int i = 0; i < guids.Length; i++)
{
if(guids[i] == KernelEventTracing) { continue; }
//Setting level to 1 - TRACE_LEVEL_CRITICAL - because some providers have large runup/rundown events
//Also setting timeout so that providers are started synchronously - it seems if we stop before the
//start goes through, binary tracking doesn't log any event
//Enable
EnableTraceEx2(handle, in guids[i], 1, 1, 0, 0, 10, null);
//Capture State
EnableTraceEx2(handle, in guids[i], 2, 1, 0, 0, 10, null);
//Disable
EnableTraceEx2(handle, in guids[i], 0, 1, 0, 0, 0, null);
}
}
StopTraceHelper(handle);
Console.WriteLine("Job's Done");
@mattifestation
Copy link

Great stuff! Really cool to see others tapping in to event tracing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment