let's continue to dissect ETW and consider one of the many usermode tracing structures - _TlgProvider_t. It is even officially documented in platform sdk in header TraceLoggingProvider.h (sample of using):
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:
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:
One obvious way is just zero LevelPlus1. Lets see inside TlgKeywordOn:
So perhaps we can also zero any of KeywordAll/KeywordAll fields. And finally we can just zero RegHandle. So if you have enough rights (or driver) you can disable tracing in any running process (for example services.exe, lsass, RPC Service, DCom Server etc)
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:
cmp _Tlgg_hCombaseTraceLoggingProviderProv.LevelPlus1, 5
jbe skip_logging
push useTimer ; keyword
push useTimer ; hProvider
call __TlgKeywordOn@12 ; _TlgKeywordOn(x,x,x)
test al, al
jz skip_logging
One obvious way is just zero LevelPlus1. Lets see inside TlgKeywordOn:
BOOLEAN _TlgKeywordOn(
TraceLoggingHProvider _In_ hProvider,
ULONGLONG keyword)
TLG_NOEXCEPT
{
return keyword == 0 || (
(keyword & hProvider->KeywordAny) &&
(keyword & hProvider->KeywordAll) == hProvider->KeywordAll);
}
So perhaps we can also zero any of KeywordAll/KeywordAll fields. And finally we can just zero RegHandle. So if you have enough rights (or driver) you can disable tracing in any running process (for example services.exe, lsass, RPC Service, DCom Server etc)