Last active
May 3, 2024 22:10
-
-
Save aaaddress1/4add6b873ae6ed70cb125a7587d2e1bc to your computer and use it in GitHub Desktop.
use ETW (Event Tracing for Windows) to get notification of loaded CLR modules
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ETW CLR Tracker, by aaaddress1@chroot.org | |
// rewrite from post "Hiding your .NET - ETW" | |
// URL: https://blog.xpnsec.com/hiding-your-dotnet-etw/ | |
#define AssemblyDCStart_V1 155 | |
#define AssemblyLoad_V1 154 | |
#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" -ets' | |
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 AssemblyLoad_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 = OpenTraceA(&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; | |
} |
Author
aaaddress1
commented
Jun 22, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment