struct _TlgProvider_t
{
UINT32 LevelPlus1;
UINT16 const UNALIGNED* ProviderMetadataPtr; // Points to the RemainingSize member of provider metadata.
ULONGLONG KeywordAny;
ULONGLONG KeywordAll;
REGHANDLE RegHandle;
TLG_PENABLECALLBACK EnableCallback;
PVOID CallbackContext;
};purpose of the fields is pretty obvious except RegHandle - it's not real HANDLE but some structure with address to ETW_REGISTRATION_ENTRY.
How we can find it? Field ProviderMetadataPtr is pointer to _TlgProviderMetadata_t:
struct _TlgProviderMetadata_t
{
UINT8 Type; // = _TlgBlobProvider3
GUID ProviderId;
#define _TLG_PROVIDER_METADATA_PREAMBLE 16 // = sizeof(ProviderId)
UINT16 RemainingSize; // = sizeof(RemainingSize + ProviderName)
/*
char ProviderName[sizeof("providerName")]; // UTF-8 nul-terminated provider name
for each additional chunk of metadata {
UINT16 ChunkSize;
UINT8 ChunkType;
UINT8 ChunkData[ChunkSize - 3];
}
*/
};actually it points to _TlgProviderMetadata_t.RemainingSize. Algo is simple - if you know provider GUID you can locate _TlgProviderMetadata_t.ProviderId by signature (usually located in .text or .rdata sections) and then find in .data section _TlgProvider_t whose ProviderMetadataPtr points to _TlgProviderMetadata_t.RemainingSize. I made simple PoC for arm64
How we can abuse it? Let`s see how this structures used for example in combase.dll: