Secure ETW
more specifically the EtwTi
Kernel-Mode
event provider and learn to stealthily neutralize/revive it at demand.Microsoft-Windows-Threat-Intelligence ETW provider
(or EtwTi
in short) for detection of various TTP
s used by adversaries and this is partly owing to the fact that it presents a clear and present danger to operations since PSP
vendors started their exodus from User-Mode
hooks to Kernel-Mode
for API
interception and logging.Windows XP x64
, hooking the SSDT
quickly became a no-go because of KPP
and while that seemed to stop the majority of PSP
vendors from writing and deploying questionable code to the kernel, it also presented a looming problem to these vendors including Microsoft
themselves.PSP
vendors were forced to move their code into User-Mode
and use standard hooking techniques such as Inline Hooking
etc. for monitoring API
calls. In theory, this seems like a perfectly fine technique but the obvious disadvantage is that since the hooks are in Ring 3
, any User-Mode
malware may choose to tamper with it as and when they please even from a Medium-IL
context which is where most of the positive foothold occurs.Windows 10 20H1/2004
called PsAltSystemCallHandlers
albeit it is only registered by Microsoft Defender
).Memory Manager(Mm*)
and Asynchronous Procedure Call(APC)
routines/operations and there were already some huge investments made into Event Tracing for Windows(ETW)
so they decided to instrument the Nt Kernel
with some special functions that'd log these calls and thus was born the EtwTi
provider.Windows 10 RS2/1703
and has undergone several advancements over time. In this lab, we are going to be referring to Windows 10 20H2/2009
which is the latest public build at the time of this writing.Microsoft-Windows-Threat-Intelligence
ETW
provider happens to be one of two major data sources for MDATP/WDATP
, the other one being Microsoft-Windows-SEC
provider which is composed of the callback routines registered by mssecflt.sys
driver.ETW
provider exists, we can type the following command from an admin prompt:ETW
providers and their corresponding GUID
s and we can also see the Microsoft-Windows-Threat-Intelligence
provider highlighted and its binary manifest file(InstrumentationManifest
) located at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Publishers\<PROVIDER_GUID>
registry key since this is a Manifest-based ETW
provider.LOCAL
here indicates own process and REMOTE
indicates another process and logging of most LOCAL
events are suppressed by default due to the sheer volume of logs they'd produce had they been enabled.EtwExplorer
by Pavel Yosifovich and examine the provider.XML Manifest
file using this tool. This gives us a more detailed insight into the parameters that are logged by a specific EtwTi
event.KD
/LKD
and type the following command to discover all the EtwTi
routines in the kernel:PSP
s now have superior visibility over most of the API
s that are considered likely to be abused by CNO
tools such as:kernel32!VirtualAllocEx(or ntdll!NtAllocateVirtualMemory)
kernel32!VirtualProtectEx(or ntdll!NtProtectVirtualMemory)
kernel32!MapViewOfFile(or ntdll!NtMapViewOfSection)
kernel32!QueueUserAPC(or ntdll!NtQueueApcThread)
nt!KeInsertQueueApc
kernel32!SetThreadContext(or ntdll!NtSetContextThread)
kernel32!ReadProcessMemory(or ntdll!NtReadVirtualMemory)
kernel32!WriteProcessMemory(or ntdll!NtWriteVirtualMemory)
kernel32!SuspendThread(or ntdll!NtSuspendThread)
kernel32!ResumeThread(or ntdll!NtResumeThread)
kernel32!SuspendProcess(or ntdll!NtSuspendProcess)
kernel32!ResumeProcess(or ntdll!NtResumeProcess)
ntdll!NtLoadDriver
ntdll!NtUnloadDriver
nt!IoCreateDevice
nt!IoDeleteDevice
nt!IoCompleteRequest
and lots moreRing 0
implant without getting logged by these pesky sensors let alone issue commands to further covert access.EtwTi
, I would point the readers to an excellent blog post by 0x00dtm.WinDbg
and analyze the private subroutines with IDA Pro
:EtwTi
is restricted to Microsoft Virus Initiative(MVI)
partners only and under NDA
.EtwTi
events are a part of the so-called Secure ETW Channel
and are only available for consumption to Early Launch Anti Malware(ELAM) Signed
drivers, unlike normal ETW
providers which anyone could subscribe and get events from.EtwTi
events to services/processes running as SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT
/PS_PROTECTED_ANTIMALWARE_LIGHT
that have been signed by the Early Launch EKU
certificate which was also used to sign the corresponding ELAM
driver and installed using kernel32!InstallElamCertificateInfo
.Secure ETW
is supposed to be "tamper-proof" or at least from User-Mode
that is. We can verify these claims to an extent by trying to remove the provider from the trace session.logman
like so(or use sechost!EnableTraceEx2
with EVENT_CONTROL_CODE_DISABLE_PROVIDER
flag):EtwTi
events.Normal ETW
provider i.e. Microsoft-Windows-Kernel-Process
which is rather (in)famous for its ability to detect Parent Process ID(PPID) Spoofing
with kernel32!CreateProcessA/W + PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
. Note that we are able to disable the provider successfully, ergo stop further logging of this event by PSP
s even though it is a Kernel-Mode
provider.TelemetrySourcerer
against the EtwTi
provider.sechost!StopTraceA/W
in this specific scenario even though we weren't able to remove the provider.MD
.Microsoft-Windows-Threat-Intelligence
provider in order to get these events from the kernel.ELAM driver
and pre-generated Certificate and Private Key PFX
file from PPLRunner
repository.TiEtwAgent
repository.4
and 5
must be repeated after every reboot.injection_prototype.exe
- allocate +RWX
memory in remote process by PID
), we can take a look at agent/DetectionLogic.cpp
(we'll come back to this later if you can't figure this out yet). To save time on the demonstration, we will not be changing any of the default behaviour but is left as an exercise for the readers.Test Signing
mode which if not, can be enabled by running the following command from an elevated command prompt:WHQL Signed
code-signing certificate containing the Early Launch EKU
.EtwTi
provider instead of deploying custom code. However, extra care should be taken in that scenario to airgap the test machine from the internet and prevent accidental sample sharing with the vendor cloud.EtwTi
events, let's take a look at how we can disable the provider at will and ergo stop it from logging these events.VA
of a global non-exported nt
symbol known as EtwThreatIntProvRegHandle
. As the name suggests, it is used to store the Ring 0
event provider registration handle(or REGHANDLE
) of the EtwTi
provider as returned by nt!EtwRegister
routine after the target provider GUID
is supplied to it. This is not really a HANDLE
in the traditional sense(Object Manager HANDLE
) but rather an opaque structure that directly stores the 64-bit
address of the target event registration object in the kernel - nt!_ETW_REG_ENTRY
which is created after a call to nt!EtwRegister
in order to write events through it(Remember that Windows
is an object-based OS?).IDA
screenshot, this pseudo-handle along with other Kernel-Mode
REGHANDLE
s are initialized in nt!EtwpInitialize
routine.kernel32!GetProcAddress
to get its VA
so we need to employ pattern searching.nt!EtwThreatIntProvRegHandle
symbol in IDA Pro
.nt!KeInsertQueueApc
is the ideal start symbol for pattern searching nt!EtwThreatIntProvRegHandle
since it satisfies both points 1
and 2
.VA
. The only necessary condition in this step is that the target signature must be unique in our search range.KD/LKD
like so:nt!EtwThreatIntProvRegHandle VA
at the cost of increased maintenance efforts and low scalability all of which are not desirable qualities of mission-critical tools.VA
of the nt!_ETW_REG_ENTRY
structure associated with the EtwTi
provider.Step 1
, nt!EtwThreatIntProvRegHandle
is actually a pointer to its associated nt!_ETW_REG_ENTRY
structure and we could directly dereference the pointer to get its VA
but since it is a Ring 0
address and we are currently in CPL 3
we cannot do that and instead use previously obtained Arbitrary Ring 0 PM/VM R/W
primitive to read 8-bytes
at nt!EtwThreatIntProvRegHandle
to get our desired VA
.VA
of the nt!_ETW_GUID_ENTRY
structure associated with the EtwTi
provider.nt!_ETW_REG_ENTRY
, we know that the pointer to nt!_ETW_GUID_ENTRY
structure(member = GuidEntry
) is located at an offset of 0x20
.0x20
to nt!_ETW_REG_ENTRY
to obtain the pointer to nt!_ETW_GUID_ENTRY
structure and consequently dump 8-bytes
at that resultant VA
using Arbitrary Ring 0 PM/VM R/W
primitive to obtain our desired VA
.VA
of the nt!_TRACE_ENABLE_INFO
structure associated with the EtwTi
provider.nt!_ETW_GUID_ENTRY
, we know that the VA
of nt!_TRACE_ENABLE_INFO
structure(member = ProviderEnableInfo
) is located at an offset of 0x60
.0x60
to nt!_ETW_GUID_ENTRY
to obtain our desired VA
.EtwTi
provider, we simply utilize the Arbitrary Ring 0 PM/VM R/W
primitive to write a single byte(0x00
) at nt!_TRACE_ENABLE_INFO.IsEnabled VA
and ergo disable the provider over all sessions.EtwTi
provider, we once again utilize the Arbitrary Ring 0 PM/VM R/W
primitive to write a single byte(0x01
) at nt!_TRACE_ENABLE_INFO.IsEnabled VA
and ergo re-enable the provider over all sessions.KD/LKD
which is what we are going to do.WinDbg
command and result dump to disable the EtwTi
provider:EtwTi
sensors without disabling the provider altogether some of which will be disclosed in this blog at a later date.PPL
bit from lsass.exe
using a proxy driver to take a MiniDump
and then never bothering to turn it back on. This is especially prevalent in both public and private commercial Red Team tools. It is analogous to an amateur thief breaking into a building by hammering the locks and leaving a mess behind but also leaving the facility vulnerable to future attacks. Not only is this bad tradecraft but also extremely dangerous for the customer on so many levels but let me start by giving the two predominant ones: BOOL
flag in our code via which we can either disable the provider, if enabled or enable it if disabled and it is expected of the operator to call the routine with the FALSE
flag to revive the EtwTi
provider as soon as the tasking is completed. I hope the analogies made sense.EtwTi
provider such as tampering with the REGHANDLE
itself such that it points to the incorrect provider, hijacking it to a custom provider, tampering with nt!_TRACE_ENABLE_INFO.Level
, tampering with nt!_TRACE_ENABLE_INFO.MatchAnyKeyword/MatchAllKeyword
etc. In other words, this technique is meant as a PoC
and there are lots of room for improvement. Also, worth noting is the fact that this technique is provider agnostic and can be used to disable other kernel providers too with some slight modifications.HyperGuard
, HVCI
, KDP
can protect a target from this data corruption attack unlike locating and patching an EtwTi*
routine with a RET/0xC3
instruction. Nevertheless, if you're interested in the above technique, b4rtik has written a post which I would highly recommend the readers to check out.WinDbg/KD/LKD
or a custom driver. The way it'd work is by checking a couple of things: The Kernel-Mode
REGHANDLE
points to the correct nt!_ETW_REG_ENTRY
structure which in turn points to the correct nt!_ETW_GUID_ENTRY
structure and ultimately whether tracing has been disabled by tampering with the appropriate nt!_TRACE_ENABLE_INFO.IsEnabled
member which should always(almost) be set to TRUE
.VBS
features especially HVCI/Memory Integrity
AND Kernel-Mode
CI
policy using WDAC
OR Consider deploying a custom version of Driver-Collider
to block bad drivers from loading nt!PsSetLoadImageNotifyRoutine
callbacks alongwith nt!EtwTiLogDriverObjectLoad
and look for inconsistenciesKernel Mitigations
on this blog.Arbitrary Ring 0 VM R/W
primitive by exploiting a proxy driver.main.c
is the source of the injector_prototype.exe
program that is used to trigger an anomalous memory allocation detection via EtwTi
events.+RWX
memory allocation in notepad.exe
was caught since that was before our code was executed but the second one was not logged, thus verifying our results.