A demo of how to collect information on basic .NET events from ETW.
#define AssemblyDCStart_V1 155 | |
#define MethodLoadVerbose_V1 143 | |
#include <windows.h> | |
#include <stdio.h> | |
#include <wbemidl.h> | |
#include <wmistr.h> | |
#include <evntrace.h> | |
#include <Evntcons.h> | |
static GUID ClrRuntimeProviderGuid = { 0xe13c0d23, 0xccbc, 0x4e12, { 0x93, 0x1b, 0xd9, 0xcc, 0x2e, 0xee, 0x27, 0xe4 } }; | |
// Can be stopped with 'logman stop "dotnet trace" -etw' | |
const char name[] = "dotnet trace\0"; | |
#pragma pack(1) | |
typedef struct _AssemblyLoadUnloadRundown_V1 | |
{ | |
ULONG64 AssemblyID; | |
ULONG64 AppDomainID; | |
ULONG64 BindingID; | |
ULONG AssemblyFlags; | |
WCHAR FullyQualifiedAssemblyName[1]; | |
} AssemblyLoadUnloadRundown_V1, *PAssemblyLoadUnloadRundown_V1; | |
typedef struct _MethodLoadVerbose_V1 | |
{ | |
ULONG64 MethodID; | |
ULONG64 ModuleID; | |
ULONG64 MethodStartAddress; | |
DWORD MethodSize; | |
DWORD MethodToken; | |
DWORD MethodFlags; | |
WCHAR MethodNameSpace[1]; | |
} MethodLoadUnloadVerbose_V1, *PMethodLoadUnloadVerbose_V1; | |
#pragma pack() | |
static void NTAPI ProcessEvent(PEVENT_RECORD EventRecord) { | |
PEVENT_HEADER eventHeader = &EventRecord->EventHeader; | |
PEVENT_DESCRIPTOR eventDescriptor = &eventHeader->EventDescriptor; | |
AssemblyLoadUnloadRundown_V1* assemblyUserData; | |
MethodLoadUnloadVerbose_V1* methodUserData; | |
switch (eventDescriptor->Id) { | |
case AssemblyDCStart_V1: | |
assemblyUserData = (AssemblyLoadUnloadRundown_V1*)EventRecord->UserData; | |
wprintf(L"[%d] - Assembly: %s\n", eventHeader->ProcessId, assemblyUserData->FullyQualifiedAssemblyName); | |
break; | |
case MethodLoadVerbose_V1: | |
methodUserData = (struct _MethodLoadVerbose_V1*)EventRecord->UserData; | |
WCHAR* MethodNameSpace = methodUserData->MethodNameSpace; | |
WCHAR* MethodName = (WCHAR*)(((char*)methodUserData->MethodNameSpace) + (lstrlenW(methodUserData->MethodNameSpace) * 2) + 2); | |
WCHAR* MethodSignature = (WCHAR*)(((char*)MethodName) + (lstrlenW(MethodName) * 2) + 2); | |
wprintf(L"[%d] - MethodNameSpace: %s\n", eventHeader->ProcessId, methodUserData->MethodNameSpace); | |
wprintf(L"[%d] - MethodName: %s\n", eventHeader->ProcessId, MethodName); | |
wprintf(L"[%d] - MethodSignature: %s\n", eventHeader->ProcessId, MethodSignature); | |
break; | |
} | |
} | |
int main(void) | |
{ | |
TRACEHANDLE hTrace = 0; | |
ULONG result, bufferSize; | |
EVENT_TRACE_LOGFILEA trace; | |
EVENT_TRACE_PROPERTIES *traceProp; | |
printf("ETW .NET Trace example - @_xpn_\n\n"); | |
memset(&trace, 0, sizeof(EVENT_TRACE_LOGFILEA)); | |
trace.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD; | |
trace.LoggerName = (LPSTR)name; | |
trace.EventRecordCallback = (PEVENT_RECORD_CALLBACK)ProcessEvent; | |
bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(name) + sizeof(WCHAR); | |
traceProp = (EVENT_TRACE_PROPERTIES*)LocalAlloc(LPTR, bufferSize); | |
traceProp->Wnode.BufferSize = bufferSize; | |
traceProp->Wnode.ClientContext = 2; | |
traceProp->Wnode.Flags = WNODE_FLAG_TRACED_GUID; | |
traceProp->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_PAGED_MEMORY; | |
traceProp->LogFileNameOffset = 0; | |
traceProp->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); | |
if ((result = StartTraceA(&hTrace, (LPCSTR)name, traceProp)) != ERROR_SUCCESS) { | |
printf("[!] Error starting trace: %d\n", result); | |
return 1; | |
} | |
if ((result = EnableTraceEx( | |
&ClrRuntimeProviderGuid, | |
NULL, | |
hTrace, | |
1, | |
TRACE_LEVEL_VERBOSE, | |
0x8 | 0x10, // LoaderKeyword | JITKeyword | |
0, | |
0, | |
NULL | |
)) != ERROR_SUCCESS) { | |
printf("[!] Error EnableTraceEx\n"); | |
return 2; | |
} | |
hTrace = OpenTrace(&trace); | |
if (hTrace == INVALID_PROCESSTRACE_HANDLE) { | |
printf("[!] Error OpenTrace\n"); | |
return 3; | |
} | |
result = ProcessTrace(&hTrace, 1, NULL, NULL); | |
if (result != ERROR_SUCCESS) { | |
printf("[!] Error ProcessTrace\n"); | |
return 4; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment