<?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: kql</title><description>Posts tagged kql.</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/kql/rss.xml" rel="self" type="application/rss+xml"/><item><title>One Event, Three Portals: How a Single Sysmon Line Becomes a Microsoft Defender XDR Incident</title><link>https://paragmali.com/blog/one-event-three-portals-how-a-single-sysmon-line-becomes-a-m/</link><guid isPermaLink="true">https://paragmali.com/blog/one-event-three-portals-how-a-single-sysmon-line-becomes-a-m/</guid><description>Trace a single Sysmon ProcessCreate event through six hops -- from Windows kernel emission to a unified Microsoft Defender XDR incident -- and where the convergence stops.</description><pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate><content:encoded>
A single Sysmon ProcessCreate event takes six observable hops to land in a Microsoft Defender XDR incident: kernel ETW emission, agent shipping through a Data Collection Rule, ingestion into a Log Analytics workspace, KQL detection in Microsoft Sentinel, optional alert correlation from Microsoft Defender for Cloud&apos;s CWPP plans, and finally entity-graph fan-in inside the unified Defender portal [@ms-learn-sysmon] [@ms-learn-ama-overview] [@ms-learn-mdc-xdr-concept] [@ms-learn-xdr-correlation]. Each hop adds latency, loses fidelity, or introduces a configuration cliff -- and one wrong word in a Data Collection Rule (`Microsoft-Event` instead of `Microsoft-WindowsEvent`) silently drops the entire pipeline [@ms-learn-ama-windows-events]. This article walks the full path with a concrete worked example, names where the convergence actually stops, and gives a six-step recipe to build the pipeline yourself.
&lt;h2&gt;1. One event, three portals, nine minutes&lt;/h2&gt;
&lt;p&gt;At 14:03:17 UTC on a Tuesday, &lt;code&gt;winword.exe&lt;/code&gt; on the host &lt;code&gt;MAL-CONTOSO-PRD-04&lt;/code&gt; spawns a child process: &lt;code&gt;powershell.exe -EncodedCommand JABwAD0AJwBoAHQAdABwADoALwAv...&lt;/code&gt;. Sysmon, which loads early in the boot sequence as a boot-start kernel driver, writes a single ProcessCreate record (Event ID 1) to the Windows event log channel &lt;code&gt;Microsoft-Windows-Sysmon/Operational&lt;/code&gt; [@ms-learn-sysmon]. The record is roughly two kilobytes of XML with a stable &lt;code&gt;ProcessGuid&lt;/code&gt; field that uniquely identifies the new process across the host&apos;s lifetime [@ms-learn-defrag-tools-sysmon].&lt;/p&gt;
&lt;p&gt;At 14:03:21 UTC, the same record appears in the &lt;code&gt;Event&lt;/code&gt; table of an Azure Log Analytics workspace named &lt;code&gt;law-contoso-secops&lt;/code&gt; [@ms-learn-event-table]. At 14:05:00 UTC, a Microsoft Sentinel scheduled analytics rule fires its five-minute KQL query, matches a parent-image heuristic (&lt;code&gt;winword.exe&lt;/code&gt; -&amp;gt; &lt;code&gt;powershell.exe -EncodedCommand&lt;/code&gt;), and produces a &lt;code&gt;SecurityAlert&lt;/code&gt; row whose &lt;code&gt;Entities&lt;/code&gt; JSON column names the host, the parent process, the child process, and the encoded command line [@ms-learn-sentinel-scheduled-rules] [@ms-learn-sentinel-entities]. At 14:07:42 UTC, a Microsoft Defender for Cloud (MDC) &lt;strong&gt;alert&lt;/strong&gt; -- emitted by the MDC for Servers cloud workload protection plan, which sits on top of the Microsoft Defender for Endpoint (MDE) sensor on that same host -- shows up in the workspace&apos;s &lt;code&gt;SecurityAlert&lt;/code&gt; table with the title &lt;code&gt;Suspicious PowerShell command line&lt;/code&gt; [@ms-learn-mdc-defender-servers] [@ms-learn-mdc-mde-integration]. And at 14:09:30 UTC -- nine minutes and thirteen seconds after the kernel call -- a single incident appears in the Microsoft Defender XDR portal at &lt;code&gt;security.microsoft.com&lt;/code&gt;. Its title: &lt;code&gt;Multi-stage incident on one endpoint&lt;/code&gt;. Its alert tab lists three rows: one from Sentinel, one from MDC, and (because MDE was also installed) one from Defender for Endpoint&apos;s native detection engine [@ms-learn-defender-xdr-incidents] [@ms-learn-xdr-correlation].&lt;/p&gt;
&lt;p&gt;Three independent detection systems, three different timestamps, three different alert grammars, one incident. How?&lt;/p&gt;
&lt;p&gt;That question is the spine of this article. It is not a marketing question -- &quot;look how unified it is&quot; -- because the convergence is partial and the seams are load-bearing. It is an engineering question: which hops happen where, what does each hop cost in latency and money, and where does the unification actually stop?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Microsoft Defender XDR is not a single product. It is a correlation surface that fans in three structurally different pipelines: Sentinel&apos;s KQL analytics rules over Log Analytics, Defender for Cloud&apos;s cloud-workload-protection (CWPP) alerts from MDC plans (servers, containers, SQL, storage, App Service), and the native Defender stack (Endpoint, Identity, Office, Cloud Apps). The fan-in is real but partial: Sentinel cross-workspace correlation, MDC posture findings, and most third-party connectors stay outside the unified incident graph [@ms-learn-defender-xdr-overview] [@ms-learn-mdc-xdr-concept].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here is the full path the Sysmon record takes from kernel to portal. Each numbered box is a real component with its own owner team, deployment lifecycle, and failure mode:&lt;/p&gt;

flowchart LR
  A[&quot;1 Sysmon kernel ETW provider on host&quot;]
  B[&quot;2 Azure Monitor Agent + Data Collection Rule&quot;]
  C[&quot;3 Log Analytics workspace Event/SecurityEvent tables&quot;]
  D[&quot;4 Sentinel scheduled or NRT analytics rule -- KQL&quot;]
  E[&quot;5 MDC alert via Defender for Servers + MDE sensor&quot;]
  F[&quot;6 Defender XDR correlation engine -- security.microsoft.com&quot;]
  A --&amp;gt; B --&amp;gt; C --&amp;gt; D --&amp;gt; F
  C --&amp;gt; E --&amp;gt; F
  classDef src fill:#e8f4ff,stroke:#2b6cb0,color:#1a365d
  classDef sink fill:#fffaf0,stroke:#dd6b20,color:#7b341e
  class A,B,C src
  class F sink
&lt;p&gt;The diagram understates how separate these hops are. Box 2 lives on the host. Box 3 is a multi-tenant Azure Data Explorer cluster [@ms-learn-adx-docs]. Box 4 runs on Sentinel&apos;s serverless query engine inside the workspace&apos;s home region. Box 5 is a Defender for Cloud plan with its own SKU, scoped to an Azure subscription. Box 6 is a separate web portal in a separate Microsoft 365 tenant scope. Each one rolled out at a different time, was renamed at least once, and absorbed a different earlier product. The next section recovers the lineage that explains why.&lt;/p&gt;
&lt;h2&gt;2. Three lineages that became one portal&lt;/h2&gt;
&lt;p&gt;The three pipelines that converge at hop 6 did not start as siblings. They started as three separate Microsoft product lines aimed at three different buyer personas: an Azure subscription owner who wanted posture scoring, a Windows engineer who wanted endpoint detection, and a SOC analyst who wanted a SIEM. Reading the path right-to-left -- from the unified portal back to its three roots -- is the only honest way to understand why the seams look the way they do.&lt;/p&gt;

A platform that ingests security-relevant logs from many sources, normalizes them into a queryable schema, runs correlation rules to produce alerts, and groups related alerts into incidents that a SOC analyst triages. Microsoft Sentinel is a SIEM [@ms-learn-sentinel-overview].

A platform (often packaged with a SIEM) that runs playbooks in response to alerts -- isolating a host, disabling an account, opening a ticket. In Microsoft&apos;s stack, SOAR is implemented as Azure Logic Apps invoked from Sentinel automation rules [@ms-learn-sentinel-soar].

A sensor that runs on a single endpoint, collects rich process / file / network / registry telemetry, applies behavioural detections locally and in the cloud, and exposes response actions (terminate process, isolate machine, collect investigation package). Microsoft Defender for Endpoint is an EDR [@ms-learn-mde-landing] [@ms-learn-mde-eda].

A correlation layer that fans in alerts and entities from multiple Microsoft-or-vendor detection products (endpoint, identity, email, cloud apps, cloud workloads) and merges related alerts into a single incident graph. Microsoft Defender XDR is Microsoft&apos;s XDR; the term was popularized by Palo Alto Networks in 2018 [@ms-learn-defender-xdr-overview] [@pan-blog-xdr-journey].
&lt;p&gt;The CSPM line started first. In &lt;strong&gt;December 2015&lt;/strong&gt;, Microsoft put Azure Security Center (ASC) into public preview as a per-subscription posture dashboard that scored Azure resources against a baseline of hardening recommendations [@azure-blog-asc-preview-2015]. ASC went generally available in &lt;strong&gt;July 2016&lt;/strong&gt; alongside JIT VM access [@ms-security-blog-asc-ga-2016]. Public sources frequently report ASC GA as &quot;October 2015&quot; or &quot;October 2016.&quot; The primary Azure blog from December 2015 explicitly says &quot;Azure Security Center -- now in public preview,&quot; and the July 2016 Microsoft Security blog announces the GA wave of new capabilities. The December 2015 preview / mid-2016 GA framing matches both authoritative announcements [@azure-blog-asc-preview-2015] [@ms-security-blog-asc-ga-2016]. Over the next five years ASC absorbed runtime protection plans -- Defender for Servers, SQL, Storage, App Service, Containers -- and was renamed &lt;strong&gt;Microsoft Defender for Cloud&lt;/strong&gt; at Ignite Fall 2021, the same wave that renamed Microsoft Cloud App Security to Microsoft Defender for Cloud Apps (MDCA) [@ms-learn-mdc-introduction] [@ms-learn-mdca-rename-2021].&lt;/p&gt;
&lt;p&gt;The SIEM line is much younger. Microsoft announced &lt;strong&gt;Azure Sentinel&lt;/strong&gt; in public preview on &lt;strong&gt;February 28, 2019&lt;/strong&gt; as the first cloud-native SIEM from a hyperscaler, built on top of Azure Log Analytics and the Kusto Query Language [@ms-blog-sentinel-preview-2019]. It went GA on &lt;strong&gt;September 24, 2019&lt;/strong&gt; [@ms-security-blog-sentinel-ga-2019]. It was renamed &lt;strong&gt;Microsoft Sentinel&lt;/strong&gt; in November 2021 (same Ignite wave). Sentinel inherited every Log Analytics integration that Azure Monitor already had, which meant it could ingest Windows event logs, syslog, Office 365 audit, Microsoft Entra ID sign-ins, and anything you could shove into a workspace with a custom collector [@ms-learn-sentinel-data-connectors-ref].&lt;/p&gt;
&lt;p&gt;The XDR line landed last. In &lt;strong&gt;September 2020&lt;/strong&gt; Microsoft announced &quot;Microsoft unified SIEM and XDR&quot; as a direction, and rolled the Office 365 ATP and Microsoft Defender ATP detection surfaces into a single portal called &lt;strong&gt;Microsoft 365 Defender&lt;/strong&gt; [@ms-security-blog-unified-siem-xdr-2020]. The portal was renamed &lt;strong&gt;Microsoft Defender XDR&lt;/strong&gt; in early 2024, and the SIEM and XDR portals were merged at Ignite November 2023, with the unified Microsoft security operations platform going generally available in July 2024 [@ms-blog-ignite-2023] [@ms-security-blog-unified-secops-2024]. The Sentinel experience inside the Azure portal will be &lt;strong&gt;retired on March 31, 2027&lt;/strong&gt; (a deadline extended from its original July 1, 2026 target); after that date, Sentinel lives only inside &lt;code&gt;security.microsoft.com&lt;/code&gt; [@ms-learn-sentinel-azure-portal-retiring] [@helpnetsec-sentinel-defender-timeline].&lt;/p&gt;

gantt
    title Three lineages converging at security.microsoft.com
    dateFormat YYYY-MM
    axisFormat %Y&lt;pre&gt;&lt;code&gt;section EDR line
Sysmon v1 (Sysinternals)         :done, 2014-08, 12M
Microsoft Defender ATP (EDR)     :done, 2016-03, 60M
Renamed Microsoft Defender for Endpoint :done, 2020-09, 24M

section CSPM and CWPP line
Azure Security Center preview    :done, 2015-12, 8M
Azure Security Center GA         :done, 2016-07, 64M
Renamed Microsoft Defender for Cloud :done, 2021-11, 36M

section SIEM line
Azure Sentinel preview           :done, 2019-02, 7M
Azure Sentinel GA                :done, 2019-09, 26M
Renamed Microsoft Sentinel       :done, 2021-11, 24M

section XDR convergence
Microsoft 365 Defender portal    :done, 2020-09, 38M
Sentinel merged into Defender portal :done, 2023-11, 8M
Unified secops GA                :done, 2024-07, 24M
Sentinel Azure portal retires    :crit, 2027-03, 1M
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three things matter about this timeline for the rest of the article. First, the &lt;strong&gt;CSPM/CWPP line is older&lt;/strong&gt; than either SIEM or XDR -- which is why the Defender for Cloud team owns its own alert format, its own subscription-scoped permissions model, and its own portal at &lt;code&gt;portal.azure.com/#blade/Microsoft_Azure_Security&lt;/code&gt;, none of which fully merge into the unified Defender experience even today. Second, &lt;strong&gt;Sentinel inherited Log Analytics&lt;/strong&gt;, not the other way around -- so the storage substrate, the agent (Azure Monitor Agent), and the query language (KQL) all predate Sentinel by years and serve far more workloads than security. Third, &lt;strong&gt;the unified portal is the new arrival&lt;/strong&gt;, not the foundation. The convergence is grafted on top of three pre-existing pipelines, and that grafting -- not the products themselves -- is what makes the architecture interesting.&lt;/p&gt;
&lt;h2&gt;3. The pre-cloud SIEM bottleneck&lt;/h2&gt;
&lt;p&gt;To understand why Sentinel was built the way it was, hold the question in mind that every SIEM buyer asked their finance team between roughly 2008 and 2018: &lt;em&gt;&quot;Why does each new server cost me a license-tier upgrade?&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Classic on-premises SIEMs -- Splunk Enterprise, ArcSight, QRadar -- priced by &lt;strong&gt;ingested gigabytes per day&lt;/strong&gt;, billed as a perpetual or annual license tied to a tier. Crossing a tier boundary triggered a forklift purchase. Storage was on-prem disk, and retention was constrained by how much steel you bought; compute was on the same hardware, so peak query load contended with peak ingest. The cost shape was step-wise, and the constraint that bound it most painfully was peak ingest rate.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost dimension&lt;/th&gt;
&lt;th&gt;Classic on-prem SIEM&lt;/th&gt;
&lt;th&gt;Cloud-native SIEM (Sentinel)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Ingest billing unit&lt;/td&gt;
&lt;td&gt;License tier (GB/day, stepped)&lt;/td&gt;
&lt;td&gt;Per-GB ingest (continuous) [@ms-learn-sentinel-billing]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage billing unit&lt;/td&gt;
&lt;td&gt;Bundled with license tier&lt;/td&gt;
&lt;td&gt;Per-GB-month retention (continuous) [@ms-learn-sentinel-billing]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compute billing unit&lt;/td&gt;
&lt;td&gt;Bundled / hardware capex&lt;/td&gt;
&lt;td&gt;Per-query bytes scanned (serverless) [@ms-learn-adx-docs]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capacity planning&lt;/td&gt;
&lt;td&gt;Estimate peak GB/day a year out&lt;/td&gt;
&lt;td&gt;None -- pay for what you ingested last hour&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New data source onboarding&lt;/td&gt;
&lt;td&gt;Re-tier and order disks&lt;/td&gt;
&lt;td&gt;Add a Data Collection Rule [@ms-learn-dcr-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The reframe Sentinel proposed -- and that the Kusto/Log Analytics substrate enabled -- was to &lt;strong&gt;separate the three cost axes&lt;/strong&gt;: ingest, storage retention, and query compute. Each axis bills continuously and independently. There is no tier to cross. Adding a new data source is a Data Collection Rule edit, not a procurement event. Retaining last quarter&apos;s logs another year is a per-GB-month flag, not a disk purchase [@ms-learn-sentinel-billing].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;Aha #1 -- the economic reframe.&lt;/strong&gt; What looked like a &lt;em&gt;pricing&lt;/em&gt; change (&quot;SaaS billing&quot;) was actually an &lt;em&gt;architectural&lt;/em&gt; change. Classic SIEMs bundled ingest, storage, and compute because the hardware bundled them. Once each axis lives on a different cloud service (Event Hubs / DCR for ingest, ADX for storage, KQL serverless query for compute), there is no bundle to defend. The SaaS bill is downstream of the deconstructed architecture, not the cause of it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This deconstruction is what makes the Sentinel pipeline interesting upstream of the SOC. When ingest is a separately-billed continuous variable, the &lt;em&gt;Data Collection Rule&lt;/em&gt; becomes the most important security artifact in the deployment: it determines what flows in and therefore both what costs you incur and what you can possibly detect. (The accuracy-report follow-up that drives section 10 hinges on exactly one wrong word in a DCR.) When query compute is serverless and per-byte, a long-running threat hunt over a year of process-creation events is a question of dollars, not of capacity-plan slack. And when storage retention is a per-GB-month flag, the question &quot;should we retain this for compliance?&quot; decouples from &quot;do we have rack space?&quot;&lt;/p&gt;

Sentinel offers a flexible and predictable pricing model. Pay-as-you-go pricing lets you pay for what you use, while commitment tiers provide guaranteed discounts. [@ms-learn-sentinel-billing]
&lt;p&gt;That is the pricing-page sales line. The architectural truth underneath it is that the three pre-cloud bundles unbundled, and once they unbundled, the SIEM was free to grow horizontally with the rest of the cloud workload. That is exactly what happened with Sentinel between 2019 and 2024: it accumulated &lt;strong&gt;300+ data connectors&lt;/strong&gt; for every Azure service, every Microsoft 365 surface, every major SaaS log feed, and a long tail of third-party security tools [@ms-learn-sentinel-data-connectors-ref]. None of that catalog would have been economically sane on a per-GB/day license tier.&lt;/p&gt;
&lt;p&gt;But the unbundle was not free. The price of separately-billed continuous axes is that you have to &lt;em&gt;measure&lt;/em&gt; on all three axes. You now need to know your steady-state ingest rate, your retention policy, and your hunt query patterns. The next section steps inside the substrate that makes those measurements -- and the queries on top of them -- possible.&lt;/p&gt;
&lt;h2&gt;4. The cloud-native SIEM substrate: KQL on Log Analytics&lt;/h2&gt;
&lt;p&gt;Microsoft Sentinel is a thin layer over a much older substrate. That substrate is &lt;strong&gt;Azure Monitor Log Analytics&lt;/strong&gt;, which itself is a security-and-multitenancy wrapper around &lt;strong&gt;Azure Data Explorer (ADX)&lt;/strong&gt;, the cluster engine that runs &lt;strong&gt;Kusto Query Language (KQL)&lt;/strong&gt; [@ms-learn-adx-docs]. Understanding the stack matters because almost everything Sentinel can or cannot do is determined by what Log Analytics and KQL can or cannot do, not by anything Sentinel itself implements.&lt;/p&gt;

A multi-tenant namespace inside Azure Monitor that stores ingested telemetry in typed tables and exposes them for KQL query. Each workspace lives in a specific Azure region and Azure subscription, has its own access controls, and bills ingest and retention independently. Sentinel &quot;is enabled&quot; on a workspace; the workspace is the storage and query unit [@ms-learn-sentinel-overview].

A read-only, pipe-composed query language for time-series and tabular log data, originally developed for Azure Data Explorer. KQL is the lingua franca of Azure Monitor Logs, Microsoft Sentinel analytics, Microsoft Defender XDR advanced hunting, and several other Microsoft data services [@ms-learn-adx-docs] [@ms-learn-advanced-hunting].
&lt;p&gt;The layering is shown below. Notice that KQL itself spans &lt;strong&gt;four&lt;/strong&gt; Microsoft surfaces, of which Sentinel is just one. KQL&apos;s polymorphism -- one query language across Monitor, Sentinel, Defender XDR advanced hunting, and ADX itself -- is the single most under-appreciated decision in the Microsoft security stack. It is also the reason your KQL skills move across teams.&lt;/p&gt;

flowchart TB
  subgraph L1[&quot;Layer 1 -- storage cluster&quot;]
    ADX[&quot;Azure Data Explorer (Kusto engine)&quot;]
  end
  subgraph L2[&quot;Layer 2 -- managed namespace&quot;]
    LA[&quot;Log Analytics workspace -- typed tables, RBAC, regional&quot;]
  end
  subgraph L3[&quot;Layer 3 -- query surfaces&quot;]
    AZM[&quot;Azure Monitor logs -- ops + perf&quot;]
    SEN[&quot;Microsoft Sentinel -- SIEM analytics rules&quot;]
    XDR[&quot;Defender XDR -- advanced hunting&quot;]
    ADXQ[&quot;ADX direct -- analytics + BI&quot;]
  end
  ADX --&amp;gt; LA
  LA --&amp;gt; AZM
  LA --&amp;gt; SEN
  LA --&amp;gt; XDR
  ADX --&amp;gt; ADXQ
  classDef stor fill:#e8f4ff,stroke:#2b6cb0,color:#1a365d
  classDef ns fill:#fff5d6,stroke:#b7791f,color:#5f370e
  classDef ui fill:#e6fffa,stroke:#319795,color:#234e52
  class ADX stor
  class LA ns
  class AZM,SEN,XDR,ADXQ ui
&lt;p&gt;The substrate predates Sentinel by years. &lt;strong&gt;Log Analytics&lt;/strong&gt; was the rebranded form of &lt;em&gt;Operations Management Suite (OMS)&lt;/em&gt;, which Microsoft introduced in 2015 as a cloud companion to System Center Operations Manager. The agent that fed OMS -- the &lt;strong&gt;Microsoft Monitoring Agent (MMA)&lt;/strong&gt;, sometimes also called the &lt;em&gt;Log Analytics agent&lt;/em&gt; -- shared its agent lineage with the System Center Operations Manager agent and ran on Windows and Linux servers to ship event logs and performance counters to the workspace [@ms-learn-laa-deprecated] [@lunavi-oms-azure-monitor]. ADX (Kusto) was productised externally in 2018 after years of internal Microsoft use as the engine behind Bing telemetry, Office 365 ops, and Azure monitoring [@ms-learn-adx-docs].&lt;/p&gt;

The naming continuity is worth pausing on. *Log Analytics* (2016) replaced *OMS* (2015), which replaced *Application Insights workspaces* (2014), which absorbed parts of *Operations Manager* (2007). The data store underneath was *Kusto* the whole time. By the time Azure Sentinel launched in 2019 [@ms-blog-sentinel-preview-2019], the substrate had been hardened for four years at hyperscale, mostly for non-security workloads. Sentinel did not have to invent the storage; it inherited it. This is also why the same KQL skill maps onto application telemetry and infrastructure metrics, not just security.
&lt;p&gt;Two consequences of the substrate inheritance shape every hop downstream:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Schema is per-table, not per-product.&lt;/strong&gt; A Log Analytics workspace exposes typed tables like &lt;code&gt;Event&lt;/code&gt; (Windows event log records), &lt;code&gt;SecurityEvent&lt;/code&gt; (Windows Security channel), &lt;code&gt;Syslog&lt;/code&gt;, &lt;code&gt;Heartbeat&lt;/code&gt;, &lt;code&gt;SecurityAlert&lt;/code&gt;, &lt;code&gt;DeviceProcessEvents&lt;/code&gt; (mirrored from Defender XDR&apos;s advanced hunting schema), &lt;code&gt;Perf&lt;/code&gt;, and any number of &lt;code&gt;Custom_CL&lt;/code&gt; tables [@ms-learn-event-table] [@ms-learn-securityevent-table]. KQL queries are written against tables, not against products. A Sentinel analytics rule is just a saved KQL query that runs on a schedule and emits a row into &lt;code&gt;SecurityAlert&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-workspace and cross-table joins are first-class.&lt;/strong&gt; Because the substrate is a real query engine, you can &lt;code&gt;join&lt;/code&gt; between &lt;code&gt;SecurityEvent&lt;/code&gt; and &lt;code&gt;SigninLogs&lt;/code&gt; and &lt;code&gt;DeviceProcessEvents&lt;/code&gt; in a single rule. You can use &lt;code&gt;workspace(&quot;law-other&quot;).Event&lt;/code&gt; to reach into a separate workspace. You can call &lt;code&gt;externaldata()&lt;/code&gt; to read from a blob. This expressive power is the source of both Sentinel&apos;s flexibility and its operational complexity: the rule that worked in test stops working in prod because the test workspace did not have a &lt;code&gt;SigninLogs&lt;/code&gt; table or because the cross-workspace permission is missing [@ms-learn-sentinel-threat-detection].&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the Sysmon worked example: the kernel record will land in the &lt;code&gt;Event&lt;/code&gt; table (because Sysmon&apos;s channel is treated as a generic Windows event log, not as the &lt;code&gt;SecurityEvent&lt;/code&gt; Security channel). The detection KQL will live as a Sentinel scheduled analytics rule that reads from &lt;code&gt;Event&lt;/code&gt;, filters to &lt;code&gt;Source == &quot;Microsoft-Windows-Sysmon&quot;&lt;/code&gt; and &lt;code&gt;EventID == 1&lt;/code&gt;, parses the XML payload (the next section will show the exact pattern), and emits a &lt;code&gt;SecurityAlert&lt;/code&gt; row. That &lt;code&gt;SecurityAlert&lt;/code&gt; row is what hop 6 ultimately fans in. The substrate did all the heavy lifting; Sentinel just wrote the rule.&lt;/p&gt;
&lt;h2&gt;5. The XDR reframe: from per-product portals to a single incident graph&lt;/h2&gt;
&lt;p&gt;If the SIEM substrate is &quot;many tables, one query engine,&quot; the XDR reframe is &quot;many alert sources, one incident graph.&quot; Microsoft Defender XDR exists because by 2019 a typical Microsoft enterprise customer had four or five separate Microsoft security portals -- one for Office 365 ATP, one for Microsoft Defender ATP, one for Microsoft Cloud App Security, one for Azure AD Identity Protection, and the Azure Security Center / Sentinel pair. Each portal had its own alert grammar, its own console, and its own analyst workflow. &lt;strong&gt;The XDR reframe is to keep the alert sources but merge the analyst surface.&lt;/strong&gt;&lt;/p&gt;

A correlation surface at `security.microsoft.com` that fans in alerts and entity data from the Microsoft Defender product family (Endpoint, Identity, Office 365, Cloud Apps), Microsoft Sentinel, and Microsoft Defender for Cloud&apos;s runtime CWPP plans, then merges related alerts into incidents using shared entity identifiers (user, device, file hash, IP, URL) [@ms-learn-defender-xdr-overview] [@ms-learn-defender-xdr-incidents].
&lt;p&gt;The mechanism the merge uses is the entity graph. When any of the source pipelines emits an alert, it is required to attach a set of typed entities (e.g., &lt;code&gt;Host = MAL-CONTOSO-PRD-04&lt;/code&gt;, &lt;code&gt;Process = winword.exe&lt;/code&gt;, &lt;code&gt;Account = CONTOSO\\jdoe&lt;/code&gt;) to that alert [@ms-learn-sentinel-entities]. The Defender XDR correlation engine reads incoming alerts, normalizes the entity values, and groups alerts whose entities overlap in time and identity into a single incident [@ms-learn-xdr-correlation]. That is the entire trick. It is conceptually simple. Operationally it has many edge cases, which section 8 returns to.&lt;/p&gt;
&lt;p&gt;For the worked example, the three alert sources (Sentinel KQL rule, MDC for Servers, MDE) each emit a separate alert. Each alert lists &lt;code&gt;Host = MAL-CONTOSO-PRD-04&lt;/code&gt; and (for two of the three) &lt;code&gt;ProcessGuid = {abc-...}&lt;/code&gt;. The correlation engine merges them on the host entity within a sliding time window. Result: one incident with three correlated alerts, not three separate incidents. The temporal fan-out is shown below; the fan-in geometry returns in section 6.6.&lt;/p&gt;

sequenceDiagram
    autonumber
    participant K as Host kernel (Sysmon)
    participant LA as Log Analytics workspace
    participant SEN as Sentinel scheduled rule
    participant MDC as MDC for Servers alert
    participant MDE as MDE native detection
    participant XDR as Defender XDR correlation
    K-&amp;gt;&amp;gt;LA: 14:03:21 -- Event row (ProcessGuid abc)
    LA-&amp;gt;&amp;gt;SEN: 14:05:00 -- 5-min query fires
    SEN-&amp;gt;&amp;gt;XDR: 14:05:04 -- SecurityAlert from KQL
    K-&amp;gt;&amp;gt;MDE: 14:03:17 -- local EDR sensor signal
    MDE-&amp;gt;&amp;gt;MDC: 14:06:30 -- MDE telemetry surfaces MDC alert
    MDC-&amp;gt;&amp;gt;XDR: 14:07:42 -- SecurityAlert from MDC plan
    MDE-&amp;gt;&amp;gt;XDR: 14:08:11 -- DeviceAlertEvents direct
    XDR-&amp;gt;&amp;gt;XDR: 14:09:30 -- merge on host + ProcessGuid -&amp;gt; Incident I-7842
&lt;p&gt;Two things in the diagram deserve to be noticed. First, the three alerts arrive in a window that is small but not synchronous: about six minutes from earliest to latest, all gated by the slowest pipeline (Sentinel&apos;s five-minute scheduled query). Second, &lt;strong&gt;MDE shows up twice&lt;/strong&gt;: once as the source that feeds MDC&apos;s CWPP plan (hop 5 in the master diagram), and once as a native Defender XDR alert source. The two are the same sensor data routed through two different alert grammars to the same correlation surface. The fact that the correlation engine deduplicates them on &lt;code&gt;ProcessGuid&lt;/code&gt; is not accidental -- it is the load-bearing identifier that makes the unification work for endpoint events. For non-endpoint sources (cloud-control-plane alerts from MDC for Storage, for example), there is no equivalent shared identifier, and the deduplication has to fall back on weaker entity matches like account name or IP. That is where the convergence frays.&lt;/p&gt;
&lt;p&gt;The next section walks the six hops in order, naming the artifact at each hop and the failure mode that lives there. Hops 1 through 4 are the SIEM lineage. Hop 5 is the CWPP lineage. Hop 6 is the XDR fan-in.&lt;/p&gt;
&lt;h2&gt;6. Walking the six hops&lt;/h2&gt;
&lt;h3&gt;6.1 Hop 1 -- The kernel emission&lt;/h3&gt;
&lt;p&gt;The Sysmon driver -- &lt;code&gt;SysmonDrv.sys&lt;/code&gt; -- is registered as a Windows &lt;strong&gt;boot-start driver&lt;/strong&gt; under &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Services\SysmonDrv&lt;/code&gt; with &lt;code&gt;Start=0&lt;/code&gt;, which means the I/O manager loads it during the early-boot phase before the bulk of user-mode services start; it also registers as an event-tracing-for-Windows (ETW) provider. On every process creation, it hooks the kernel&apos;s &lt;code&gt;PsSetCreateProcessNotifyRoutineEx&lt;/code&gt; callback, builds an event record, and writes it to the Windows event log channel &lt;code&gt;Microsoft-Windows-Sysmon/Operational&lt;/code&gt; [@ms-learn-sysmon] [@ms-learn-defrag-tools-sysmon]. The record carries roughly thirty fields, including the parent and child image paths, the command lines, the user SID, the integrity level, the hashes (configurable: MD5, SHA1, SHA256, IMPHASH), the parent and child &lt;code&gt;ProcessGuid&lt;/code&gt; values, and the kernel-side timestamp.&lt;/p&gt;
&lt;p&gt;A common slip: Sysmon&apos;s driver is &lt;em&gt;not&lt;/em&gt; an Early Launch Anti-Malware (ELAM) driver. ELAM is a separate, stricter Windows category for anti-malware vendors whose drivers must be certified by Microsoft and registered under &lt;code&gt;HKLM\SYSTEM\CurrentControlSet\Control\EarlyLaunch&lt;/code&gt;. Sysmon ships as an ordinary boot-start driver (&lt;code&gt;Start=0&lt;/code&gt; under its &lt;code&gt;Services\SysmonDrv&lt;/code&gt; key); it loads early enough to observe most user-mode activity from the start, but it does not occupy the ELAM slot. A reader who internalizes the wrong classification will go looking for a &lt;code&gt;SysmonDrv&lt;/code&gt; entry under &lt;code&gt;EarlyLaunch&lt;/code&gt; and not find one [@ms-learn-sysmon].&lt;/p&gt;

A 128-bit identifier Sysmon assigns to every new process. Unlike the OS-assigned PID, which the kernel can recycle as processes exit, ProcessGuid is unique across the host&apos;s lifetime and lets downstream tooling reassemble a process tree even after PIDs have been reused. The Microsoft Sysmon page documents the property -- &quot;a unique value for this process across a domain to make event correlation easier&quot; -- but does not document how the GUID is constructed; downstream KQL queries and Defender XDR&apos;s advanced hunting schema rely only on its uniqueness, not on its internal composition [@ms-learn-sysmon].
&lt;p&gt;There is a subtle field nuance worth knowing. Sysmon also emits &lt;code&gt;LogonGuid&lt;/code&gt;, &lt;code&gt;LogonId&lt;/code&gt;, and &lt;code&gt;User&lt;/code&gt; on a ProcessCreate event. These three are &lt;em&gt;post-impersonation&lt;/em&gt; values -- they reflect the security context the new process was created under, which can differ from the token of the parent. For service-impersonation chains (a service spawning a child under a different account), ignoring this distinction will mislead an analyst on who &quot;owned&quot; the process. KQL detection queries should &lt;code&gt;project&lt;/code&gt; both parent and child user/SID and reconcile them explicitly.&lt;/p&gt;
&lt;p&gt;For the worked example, the kernel emission at 14:03:17 UTC contains, among other fields:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;EventID:       1
TimeCreated:   2026-06-02T14:03:17.412Z
Computer:      MAL-CONTOSO-PRD-04
ProcessGuid:   {62b9c5cf-7c64-67ab-2e00-000000003200}
ProcessId:     8124
Image:         C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
CommandLine:   powershell.exe -EncodedCommand JABwAD0AJwBoAHQAdABwADoALwAv...
ParentProcessGuid:   {62b9c5cf-7b21-67ab-2c00-000000003200}
ParentProcessId:     6210
ParentImage:   C:\Program Files\Microsoft Office\root\Office16\winword.exe
ParentCommandLine:   &quot;winword.exe&quot; /n &quot;C:\Users\jdoe\Downloads\invoice.docm&quot;
User:          CONTOSO\jdoe
IntegrityLevel: Medium
Hashes:        SHA256=04ED...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing further happens at hop 1 until someone reads the channel. The kernel will not push the event off the host; it will only sit in the local event log, rotating by size or age, until an agent picks it up. That is hop 2.&lt;/p&gt;
&lt;h3&gt;6.2 Hop 2 -- Azure Monitor Agent shipping via a Data Collection Rule&lt;/h3&gt;
&lt;p&gt;The agent that reads the Sysmon channel and ships it to the workspace is the &lt;strong&gt;Azure Monitor Agent (AMA)&lt;/strong&gt;. AMA replaced the older &lt;strong&gt;Microsoft Monitoring Agent (MMA)&lt;/strong&gt; / &lt;strong&gt;Log Analytics agent&lt;/strong&gt;, which Microsoft retired effective &lt;strong&gt;August 31, 2024&lt;/strong&gt; [@ms-learn-laa-deprecated]. Customers still running MMA past that date are in unsupported territory, and -- this is the critical operational fact -- AMA does &lt;strong&gt;not&lt;/strong&gt; automatically pick up where MMA left off. AMA requires explicit migration: a Data Collection Rule (DCR) describing which events to collect and which workspace to send them to [@ms-learn-ama-migration].&lt;/p&gt;

A modern Microsoft agent that runs on Windows and Linux servers (Azure VM, Arc-enabled, or on-prem) and ships event logs, performance counters, syslog, and custom text files to one or more Log Analytics workspaces, driven entirely by Data Collection Rule (DCR) configurations [@ms-learn-ama-overview].

An ARM-managed configuration object that names a data source type (e.g., `windowsEventLogs`), an XPath-based subscription (which channels and which event IDs), and one or more destinations (typically a `logAnalyticsWorkspace` + `streams` mapping such as `Microsoft-Event` for the generic `Event` table or `Microsoft-WindowsEvent` for the more recent typed Windows event ingestion path). DCRs are assigned to one or more agents via a Data Collection Rule Association (DCRA) [@ms-learn-dcr-overview] [@ms-learn-ama-windows-events].

flowchart LR
  CH[&quot;Windows event channels (XPath subscription)&quot;]
  AMA[&quot;Azure Monitor Agent process&quot;]
  DCR[&quot;Data Collection Rule (cached locally)&quot;]
  ING[&quot;Log Analytics ingestion endpoint -- regional HTTPS&quot;]
  TBL[&quot;Workspace table -- Event / SecurityEvent / WindowsEvent&quot;]
  CH --&amp;gt; AMA
  DCR --&amp;gt; AMA
  AMA --&amp;gt; ING
  ING --&amp;gt; TBL
  classDef cfg fill:#fff5d6,stroke:#b7791f,color:#5f370e
  classDef agent fill:#e8f4ff,stroke:#2b6cb0,color:#1a365d
  classDef sink fill:#e6fffa,stroke:#319795,color:#234e52
  class DCR cfg
  class AMA,CH agent
  class ING,TBL sink
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;The MMA-to-AMA silent-miss trap.&lt;/strong&gt; A workspace that is still in transition between MMA and AMA can have agents on the same host both running, both shipping the same &lt;code&gt;Event&lt;/code&gt; row, and producing double counts. Worse, a host that has had MMA uninstalled but a DCR mis-assigned will stop shipping entirely -- and because Sysmon writes to the local event log no matter what, no alert fires on the host itself. The first signal of the gap is silence in the &lt;code&gt;Event&lt;/code&gt; table for that &lt;code&gt;Computer&lt;/code&gt; value, which a Sentinel &quot;stale data source&quot; watchdog rule must explicitly detect. Microsoft retired MMA effective August 31, 2024 [@ms-learn-laa-deprecated].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For the Sysmon channel specifically, AMA needs a DCR whose &lt;code&gt;windowsEventLogs&lt;/code&gt; block names the XPath subscription &lt;code&gt;Microsoft-Windows-Sysmon/Operational!*[System[(EventID=1)]]&lt;/code&gt; (or a broader filter that includes EventIDs 1, 3, 7, 8, 10, 11). The stream name in the destination block determines which table the record lands in: a DCR that names &lt;code&gt;Microsoft-Event&lt;/code&gt; ships into the generic &lt;code&gt;Event&lt;/code&gt; table; one that names &lt;code&gt;Microsoft-WindowsEvent&lt;/code&gt; ships into the newer &lt;code&gt;WindowsEvent&lt;/code&gt; table; and naming anything else silently emits nothing [@ms-learn-ama-windows-events] [@ms-learn-sentinel-data-connectors-ref]. The AMA does not log a hard error in this case; the events simply never appear, and the analyst sees a dashboard that is missing the wave.&lt;/p&gt;
&lt;p&gt;Hop 2 finishes at about 14:03:19 UTC for the worked example -- two seconds after the kernel emission. The record is now in the workspace&apos;s ingest buffer.&lt;/p&gt;
&lt;h3&gt;6.3 Hop 3 -- Workspace ingestion and the table-choice question&lt;/h3&gt;
&lt;p&gt;The ingestion endpoint validates the record against the named stream&apos;s schema, applies any DCR-side transformations, and persists the row into the destination table. From here on the record is queryable via KQL with end-to-end ingestion latency typically in the low minutes [@ms-learn-event-table]. For the Sysmon channel the destination table is almost always &lt;code&gt;Event&lt;/code&gt;, because the &lt;code&gt;SecurityEvent&lt;/code&gt; table is the Windows &lt;em&gt;Security&lt;/em&gt; channel only (the AMA &lt;code&gt;securityEvents&lt;/code&gt; data source), and the Sysmon channel is a separate operational channel [@ms-learn-securityevent-table].&lt;/p&gt;
&lt;p&gt;The table choice matters because it changes the shape of the row and the cost of querying it. The two relevant tables for Windows event data behave as follows:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Event&lt;/code&gt; (Microsoft-Event stream)&lt;/th&gt;
&lt;th&gt;&lt;code&gt;WindowsEvent&lt;/code&gt; (Microsoft-WindowsEvent stream)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Source&lt;/td&gt;
&lt;td&gt;AMA &lt;code&gt;windowsEventLogs&lt;/code&gt; data source [@ms-learn-ama-windows-events]&lt;/td&gt;
&lt;td&gt;AMA &lt;code&gt;windowsEventLogs&lt;/code&gt; data source (newer typed path) [@ms-learn-ama-windows-events]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EventData shape&lt;/td&gt;
&lt;td&gt;XML in &lt;code&gt;EventData&lt;/code&gt; column (string)&lt;/td&gt;
&lt;td&gt;Pre-parsed JSON in &lt;code&gt;EventData&lt;/code&gt; (dynamic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost characteristic&lt;/td&gt;
&lt;td&gt;Standard ingest pricing [@ms-learn-sentinel-billing]&lt;/td&gt;
&lt;td&gt;Standard ingest pricing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Mixed sources, simple filters&lt;/td&gt;
&lt;td&gt;Channels with deep parsing needs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KQL parse pattern&lt;/td&gt;
&lt;td&gt;&lt;code&gt;parse_xml(EventData)&lt;/code&gt; per row&lt;/td&gt;
&lt;td&gt;Direct property access&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;In production, most Sysmon-on-Windows pipelines run on the older &lt;code&gt;Event&lt;/code&gt; table with a &lt;code&gt;parse_xml(EventData)&lt;/code&gt; shim. The parse is not cheap -- it allocates per row -- but it is the most common pattern because the older table predates the typed &lt;code&gt;WindowsEvent&lt;/code&gt; path and customer queries already exist against it. New deployments should consider the newer table if their detection logic touches many fields per row [@ms-learn-ama-windows-events].&lt;/p&gt;
&lt;p&gt;A representative KQL detection that runs against the older &lt;code&gt;Event&lt;/code&gt; table for the worked example looks like the snippet below. Show it to a SOC analyst and they will read it left-to-right; show it to a Kusto engineer and they will tell you the &lt;code&gt;parse_xml&lt;/code&gt; is the expensive part.&lt;/p&gt;
&lt;p&gt;The KQL that parses a Sysmon event out of the older &lt;code&gt;Event&lt;/code&gt; table follows a four-step idiom that is worth walking explicitly, because the same shape appears in every detection a SOC writes against XML-shaped Windows event data. &lt;strong&gt;Step one:&lt;/strong&gt; &lt;code&gt;parse_xml(EventData)&lt;/code&gt; reads the entire EventData payload (a string column) and returns a dynamic JSON tree whose root is &lt;code&gt;DataItem.EventData&lt;/code&gt; and whose interesting children are an array of &lt;code&gt;&amp;lt;Data Name=&quot;...&quot;&amp;gt;value&amp;lt;/Data&amp;gt;&lt;/code&gt; elements [@ms-learn-kusto-parse-xml]. &lt;strong&gt;Step two:&lt;/strong&gt; &lt;code&gt;mv-expand ev = ...DataItem.EventData.Data&lt;/code&gt; flattens that array so each &lt;code&gt;&amp;lt;Data&amp;gt;&lt;/code&gt; child becomes its own row -- a long-form representation where one event becomes thirty rows, one per field. &lt;strong&gt;Step three:&lt;/strong&gt; &lt;code&gt;extend Field = tostring(ev[&quot;@Name&quot;]), Value = tostring(ev[&quot;#text&quot;])&lt;/code&gt; projects the XML attribute and text payload into two typed columns named &lt;code&gt;Field&lt;/code&gt; and &lt;code&gt;Value&lt;/code&gt;. &lt;strong&gt;Step four:&lt;/strong&gt; &lt;code&gt;evaluate pivot(Field, take_any(Value), TimeGenerated, Computer)&lt;/code&gt; invokes the Kusto &lt;code&gt;pivot&lt;/code&gt; plugin, which rotates the long-form (Field, Value) rows back into a wide row with one column per field name -- so after the pivot, &lt;code&gt;CommandLine&lt;/code&gt;, &lt;code&gt;Image&lt;/code&gt;, &lt;code&gt;ParentImage&lt;/code&gt;, and &lt;code&gt;ProcessGuid&lt;/code&gt; become first-class columns the detection can filter on as if they had been typed all along [@ms-learn-kusto-pivot-plugin]. The same chain adapts to any other EventID (3 / NetworkConnect, 11 / FileCreate, etc.) and, with one less hop, to the typed &lt;code&gt;WindowsEvent&lt;/code&gt; table where &lt;code&gt;EventData&lt;/code&gt; is already pre-parsed JSON.&lt;/p&gt;
&lt;p&gt;Quick reference, in margin form: &lt;code&gt;parse_xml(EventData)&lt;/code&gt; -&amp;gt; dynamic JSON tree; &lt;code&gt;mv-expand ev = ...EventData.Data&lt;/code&gt; -&amp;gt; one row per &lt;code&gt;&amp;lt;Data&amp;gt;&lt;/code&gt; element; &lt;code&gt;extend Field/Value&lt;/code&gt; -&amp;gt; typed Field/Value columns; &lt;code&gt;evaluate pivot(Field, take_any(Value), ...)&lt;/code&gt; -&amp;gt; wide row, one column per field. The pivot step is what turns &quot;thirty long-form rows&quot; into &quot;one wide row with named columns&quot;; without it the detection has to filter on the Field/Value pairs directly, which is much harder to write and to read [@ms-learn-kusto-pivot-plugin].&lt;/p&gt;

```kql
Event
| where TimeGenerated &amp;gt; ago(5m)
| where Source == &quot;Microsoft-Windows-Sysmon&quot; and EventID == 1
| extend ev = parse_xml(EventData).DataItem.EventData.Data
| mv-expand ev
| extend Field = tostring(ev[&quot;@Name&quot;]), Value = tostring(ev[&quot;#text&quot;])
| evaluate pivot(Field, take_any(Value), TimeGenerated, Computer)
| where ParentImage endswith &quot;winword.exe&quot;
  and Image endswith &quot;powershell.exe&quot;
  and CommandLine contains &quot;-EncodedCommand&quot;
| project
    TimeGenerated, Computer, User,
    ParentImage, ParentProcessGuid,
    Image, ProcessGuid, CommandLine, Hashes
| extend
    HostCustomEntity = Computer,
    AccountCustomEntity = User,
    ProcessCustomEntity = ProcessGuid
```
&lt;p&gt;The five lines after the &lt;code&gt;pivot&lt;/code&gt; are the actual detection: an Office process spawning PowerShell with &lt;code&gt;-EncodedCommand&lt;/code&gt;. The three &lt;code&gt;*CustomEntity&lt;/code&gt; columns at the bottom are what wire this alert into the Defender XDR correlation engine at hop 6 -- they become typed entities on the resulting &lt;code&gt;SecurityAlert&lt;/code&gt; row [@ms-learn-sentinel-entities].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;Why the row of CustomEntity columns matters.&lt;/strong&gt; A Sentinel analytics rule that produces a &lt;code&gt;SecurityAlert&lt;/code&gt; without entity mappings will still alert -- and will still be readable by an analyst -- but it will &lt;em&gt;not&lt;/em&gt; participate in cross-pipeline correlation at hop 6. The XDR fan-in matches on entity values, and an alert with no entities has nothing to match on. This is a common oversight when migrating older queries into Sentinel from on-prem SIEMs that did not have an equivalent concept.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hop 3 finishes at about 14:03:21 UTC: four seconds after kernel emission, with the row written to the workspace&apos;s &lt;code&gt;Event&lt;/code&gt; table and indexed for KQL query.&lt;/p&gt;
&lt;h3&gt;6.4 Hop 4 -- Sentinel analytics rule emits a SecurityAlert&lt;/h3&gt;
&lt;p&gt;Microsoft Sentinel supports several detection-rule shapes. The five that matter for understanding the Sysmon pipeline are summarized below, with the timing characteristics that drive end-to-end latency for hop 4.&lt;/p&gt;

A KQL query that Sentinel runs on a fixed schedule (default 5 minutes, minimum 5 minutes). When the query returns rows, each row -- subject to grouping configuration -- becomes a `SecurityAlert` row in the workspace and an alert object in Sentinel and in Defender XDR [@ms-learn-sentinel-scheduled-rules].

The Sentinel-rule configuration that names which output columns of the KQL detection map to which typed entities (Account, Host, Process, IP, URL, FileHash, etc.). Without entity mappings, an alert is &quot;orphan&quot; with respect to the Defender XDR correlation engine [@ms-learn-sentinel-entities].
&lt;p&gt;The five rule shapes and where they fire in the Sysmon path:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule type&lt;/th&gt;
&lt;th&gt;Query cadence&lt;/th&gt;
&lt;th&gt;Typical end-to-end latency&lt;/th&gt;
&lt;th&gt;Sysmon use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Scheduled analytics [@ms-learn-sentinel-scheduled-rules]&lt;/td&gt;
&lt;td&gt;Every 5+ min&lt;/td&gt;
&lt;td&gt;5-8 min from ingest&lt;/td&gt;
&lt;td&gt;The default for ProcessCreate detections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Near-real-time (NRT) [@ms-learn-sentinel-nrt-rules]&lt;/td&gt;
&lt;td&gt;Every 1 min&lt;/td&gt;
&lt;td&gt;1-2 min from ingest&lt;/td&gt;
&lt;td&gt;High-priority single-event matches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft security (parent-product)&lt;/td&gt;
&lt;td&gt;Tied to source product&lt;/td&gt;
&lt;td&gt;Sub-minute&lt;/td&gt;
&lt;td&gt;Pass-through for MDE / MDC / MDCA alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fusion (multistage) [@ms-learn-sentinel-fusion]&lt;/td&gt;
&lt;td&gt;ML-driven, continuous&lt;/td&gt;
&lt;td&gt;Hours&lt;/td&gt;
&lt;td&gt;Cross-source attack-pattern detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Threat-intelligence map [@ms-learn-sentinel-threat-detection]&lt;/td&gt;
&lt;td&gt;Continuous&lt;/td&gt;
&lt;td&gt;Sub-minute&lt;/td&gt;
&lt;td&gt;IOC matching on &lt;code&gt;Event&lt;/code&gt;-derived hashes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;For the worked example, the detection runs as a &lt;strong&gt;scheduled analytics rule&lt;/strong&gt; at five-minute cadence. The rule fires at 14:05:00 UTC, the query returns one row matching &lt;code&gt;winword.exe -&amp;gt; powershell.exe -EncodedCommand&lt;/code&gt;, and a &lt;code&gt;SecurityAlert&lt;/code&gt; is emitted at 14:05:04 UTC. The alert carries the &lt;code&gt;HostCustomEntity&lt;/code&gt;, &lt;code&gt;AccountCustomEntity&lt;/code&gt;, and &lt;code&gt;ProcessCustomEntity&lt;/code&gt; mappings that the rule defined.&lt;/p&gt;

{`// Three alerts arriving from three pipelines, each with entities.
const sentinelAlert = {
  source: &apos;Sentinel&apos;,
  time: &apos;14:05:04Z&apos;,
  entities: { Host: &apos;MAL-CONTOSO-PRD-04&apos;,
              Process: &apos;{62b9c5cf-7c64-67ab-2e00-000000003200}&apos; }
};
const mdcAlert = {
  source: &apos;MDC for Servers (via MDE)&apos;,
  time: &apos;14:07:42Z&apos;,
  entities: { Host: &apos;MAL-CONTOSO-PRD-04&apos;,
              File: &apos;powershell.exe&apos; }
};
const mdeAlert = {
  source: &apos;MDE native&apos;,
  time: &apos;14:08:11Z&apos;,
  entities: { Host: &apos;MAL-CONTOSO-PRD-04&apos;,
              Process: &apos;{62b9c5cf-7c64-67ab-2e00-000000003200}&apos; }
};
function correlate(alerts, windowMin = 30) {
  const byHost = new Map();
  for (const a of alerts) {
    const k = a.entities.Host;
    if (!byHost.has(k)) byHost.set(k, []);
    byHost.get(k).push(a);
  }
  return [...byHost.entries()].map(([host, alts]) =&amp;gt; ({
    incidentKey: &apos;host:&apos; + host,
    alerts: alts.map(a =&amp;gt; a.source)
  }));
}
console.log(correlate([sentinelAlert, mdcAlert, mdeAlert]));
// -&amp;gt; [{ incidentKey: &apos;host:MAL-CONTOSO-PRD-04&apos;,
//        alerts: [&apos;Sentinel&apos;,&apos;MDC for Servers (via MDE)&apos;,&apos;MDE native&apos;] }]
`}
&lt;p&gt;The toy correlator above only keys on &lt;code&gt;Host&lt;/code&gt;. The real one also keys on &lt;code&gt;Process&lt;/code&gt; (ProcessGuid where present), &lt;code&gt;Account&lt;/code&gt;, &lt;code&gt;IP&lt;/code&gt;, &lt;code&gt;URL&lt;/code&gt;, and &lt;code&gt;FileHash&lt;/code&gt;, and uses a sliding window plus a confidence-weighted merge that allows weak entities (file name) to participate when strong entities (ProcessGuid) overlap [@ms-learn-xdr-correlation]. The result is the same: three alerts in, one incident out.&lt;/p&gt;
&lt;p&gt;Two other Sentinel detection paths deserve a mention even though they did not fire for this specific worked example. &lt;strong&gt;UEBA anomalies&lt;/strong&gt; -- when enabled, Sentinel writes per-user and per-host baselines into &lt;code&gt;BehaviorAnalytics&lt;/code&gt; and &lt;code&gt;IdentityInfo&lt;/code&gt; tables; analytics rules can &lt;code&gt;join&lt;/code&gt; these to flag a normally-quiet jdoe spawning encoded PowerShell as anomalous independent of any specific signature [@ms-learn-sentinel-threat-detection]. &lt;strong&gt;Fusion&lt;/strong&gt; is an ML-driven multistage detector that operates over the broader alert + event corpus and emits Fusion-named incidents when it sees a chain that resembles an attack pattern (e.g., a phishing alert followed by a credential-access alert followed by a process-spawn anomaly within an hour on the same identity) [@ms-learn-sentinel-fusion]. Fusion&apos;s strength is correlation across products you would not have thought to correlate manually; its weakness is opacity, which §9 returns to.&lt;/p&gt;
&lt;p&gt;There is one further detection family worth introducing here because §10&apos;s recipe will explicitly avoid it: &lt;strong&gt;Defender XDR Custom Detections&lt;/strong&gt;. These are KQL queries authored not in Sentinel but in the unified portal&apos;s advanced hunting surface, and they emit alerts directly into Defender XDR rather than via the SIEM analytics-rule pipeline [@ms-learn-sentinel-custom-detections]. Custom detections can read &lt;code&gt;DeviceProcessEvents&lt;/code&gt; and the rest of the Defender advanced hunting schema, which is fed by the MDE sensor independent of Sysmon. For the worked example, a Custom Detection equivalent to the Sentinel scheduled rule would also have fired -- but it would have fired against MDE&apos;s &lt;code&gt;DeviceProcessEvents&lt;/code&gt; table, not against Log Analytics &lt;code&gt;Event&lt;/code&gt;. The two paths are not interchangeable. Microsoft&apos;s documentation is explicit that custom detections operate over the Defender XDR-internal advanced hunting schema, not over arbitrary Log Analytics tables [@ms-learn-sentinel-custom-detections] [@ms-learn-advanced-hunting].&lt;/p&gt;

Custom detection rules are rules you can design and tweak using advanced hunting queries. These rules let you proactively monitor various events and system states, including suspected breach activity and misconfigured endpoints. [@ms-learn-sentinel-custom-detections]
&lt;p&gt;That is the policy line that decides where to put a new rule: if your query reads from &lt;code&gt;DeviceProcessEvents&lt;/code&gt; (MDE feed), it belongs as an advanced-hunting custom detection inside Defender XDR; if your query reads from Sentinel &lt;code&gt;Event&lt;/code&gt; or &lt;code&gt;SecurityEvent&lt;/code&gt; (Log Analytics feed), it belongs as a Sentinel analytics rule. The recipe in §10 picks the Sentinel side because the worked example begins in Sysmon, not in MDE -- and Sysmon flows to Log Analytics, not to the MDE advanced-hunting schema.&lt;/p&gt;
&lt;h3&gt;6.5 Hop 5 -- Microsoft Defender for Cloud as the CWPP alert source&lt;/h3&gt;
&lt;p&gt;This hop is the most architecturally interesting and the most operationally misunderstood. It is also where the previous iteration of this article had to be corrected on its single most load-bearing detail, so the framing here is deliberate.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; &lt;strong&gt;Only Microsoft Defender for Cloud&apos;s CWPP alerts flow into Defender XDR -- not its CSPM posture findings.&lt;/strong&gt; A Secure Score recommendation that &quot;VMs should have endpoint protection installed&quot; or &quot;Storage accounts should restrict public access&quot; is a &lt;em&gt;posture finding&lt;/em&gt;. A &quot;Suspicious PowerShell command line detected on MAL-CONTOSO-PRD-04&quot; emitted by the Defender for Servers runtime plan is an &lt;em&gt;alert&lt;/em&gt;. Defender XDR ingests the alerts; the posture findings stay in the MDC blade [@ms-learn-mdc-xdr-concept] [@ms-learn-mdc-xdr-ingest].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The vocabulary first, because everything in this section depends on it.&lt;/p&gt;

Continuous assessment of cloud-resource configuration against a baseline of best practices (Microsoft cloud security benchmark, CIS, NIST 800-53, etc.). Output is *recommendations* and a *Secure Score*. CSPM does not see runtime telemetry. In Microsoft&apos;s stack, CSPM is the foundational layer of Microsoft Defender for Cloud and is free to enable [@ms-learn-mdc-introduction] [@ms-learn-secure-score].

Runtime detection on a deployed cloud workload -- a VM, a container, a SQL database, a storage account, an App Service. CWPP sees actual events (process spawns, network connections, control-plane API calls) and emits *alerts*. In MDC, CWPP is delivered as paid plans: Defender for Servers, Containers, SQL, Storage, App Service [@ms-learn-mdc-introduction] [@ms-learn-mdc-cwpp-features].

The default CSPM control framework that ships with Microsoft Defender for Cloud. MCSB is Microsoft&apos;s interpretation of CIS, NIST 800-53, and PCI DSS controls mapped to Azure, AWS, and GCP resource types. Recommendations are scored against MCSB by default; other frameworks can be added [@ms-learn-mcsb-overview].
&lt;p&gt;The CSPM-versus-CWPP distinction has direct operational consequences for what shows up at hop 6:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What MDC emits&lt;/th&gt;
&lt;th&gt;Where it lives&lt;/th&gt;
&lt;th&gt;Flows to Defender XDR?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Recommendation&lt;/strong&gt; (CSPM) -- e.g., &quot;Endpoint protection should be installed&quot;&lt;/td&gt;
&lt;td&gt;Recommendations blade in MDC + &lt;code&gt;SecurityRecommendation&lt;/code&gt; table&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt; [@ms-learn-mdc-xdr-concept]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Secure Score&lt;/strong&gt; (CSPM) -- aggregate over recommendations&lt;/td&gt;
&lt;td&gt;Secure Score blade in MDC&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt; [@ms-learn-secure-score]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Compliance assessment&lt;/strong&gt; (CSPM) -- per-framework rollup&lt;/td&gt;
&lt;td&gt;Regulatory compliance blade&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alert&lt;/strong&gt; (CWPP) -- e.g., &quot;Suspicious PowerShell command line&quot;&lt;/td&gt;
&lt;td&gt;Alerts blade in MDC + &lt;code&gt;SecurityAlert&lt;/code&gt; table&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt; [@ms-learn-mdc-xdr-ingest]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Container runtime alert&lt;/strong&gt; -- e.g., &quot;Web shell detected in pod&quot;&lt;/td&gt;
&lt;td&gt;MDC Alerts + &lt;code&gt;SecurityAlert&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt; [@ms-learn-mdc-containers]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage runtime alert&lt;/strong&gt; -- e.g., &quot;Anomalous access from Tor IP&quot;&lt;/td&gt;
&lt;td&gt;MDC Alerts + &lt;code&gt;SecurityAlert&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt; [@ms-learn-mdc-storage]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The CWPP alerts come from MDC&apos;s five priced runtime plans. Each plan has its own data path, but they all converge on the same &lt;code&gt;SecurityAlert&lt;/code&gt; table in Log Analytics and on the same XDR ingestion path:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MDC plan&lt;/th&gt;
&lt;th&gt;Workload&lt;/th&gt;
&lt;th&gt;Data source&lt;/th&gt;
&lt;th&gt;Reference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Defender for Servers&lt;/td&gt;
&lt;td&gt;Windows / Linux VMs, Arc&lt;/td&gt;
&lt;td&gt;MDE sensor + agent telemetry&lt;/td&gt;
&lt;td&gt;[@ms-learn-mdc-defender-servers] [@ms-learn-mdc-mde-integration]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender for Containers&lt;/td&gt;
&lt;td&gt;AKS, EKS, GKE pods&lt;/td&gt;
&lt;td&gt;runtime sensor + Kubernetes audit&lt;/td&gt;
&lt;td&gt;[@ms-learn-mdc-containers]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender for SQL&lt;/td&gt;
&lt;td&gt;Azure SQL, Arc SQL&lt;/td&gt;
&lt;td&gt;Azure SQL Advanced Threat Protection signals&lt;/td&gt;
&lt;td&gt;[@ms-learn-mdc-sql] [@ms-learn-azuresql-atp]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender for Storage&lt;/td&gt;
&lt;td&gt;Storage accounts&lt;/td&gt;
&lt;td&gt;Control plane + blob access patterns&lt;/td&gt;
&lt;td&gt;[@ms-learn-mdc-storage]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender for App Service&lt;/td&gt;
&lt;td&gt;App Service apps&lt;/td&gt;
&lt;td&gt;Process + network signal from the worker&lt;/td&gt;
&lt;td&gt;[@ms-learn-mdc-appservice]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;For the worked example, the relevant plan is Defender for Servers. Because MDE is installed on the host (Defender for Servers Plan 2 includes the MDE license), the MDE sensor&apos;s runtime telemetry feeds into MDC&apos;s detection engine and emits the &lt;code&gt;Suspicious PowerShell command line&lt;/code&gt; MDC alert at 14:07:42 UTC [@ms-learn-mdc-mde-integration] [@ms-learn-mde-onboard-windows]. That alert flows to Defender XDR via the MDC-to-XDR alert-ingestion integration that reached general availability in &lt;strong&gt;March 2024&lt;/strong&gt; (specifically March 13, 2024) [@ms-learn-mdc-xdr-ingest] [@ms-learn-mdc-xdr-concept].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;Do not assume MDC posture findings will appear in your Defender XDR incident.&lt;/strong&gt; The MDC-to-XDR integration ingests &lt;strong&gt;alerts only&lt;/strong&gt;, not recommendations and not Secure Score deltas. If a SOC analyst wants posture context on an incident-affected host (e.g., &quot;was this host&apos;s endpoint protection missing per Secure Score?&quot;), they must pivot to the MDC blade or join &lt;code&gt;SecurityRecommendation&lt;/code&gt; from KQL. There is no automatic incident-side enrichment for posture findings as of the documented integration scope [@ms-learn-mdc-xdr-concept] [@ms-learn-mdc-xdr-ingest].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The CSPM/CWPP separation also explains the multi-cloud story. MDC&apos;s CSPM scope spans Azure, AWS, and GCP via cloud connectors -- you can onboard an AWS account with &lt;code&gt;aws-onboarding&lt;/code&gt; and see your S3 buckets in the Secure Score [@ms-learn-mdc-onboard-aws]. The CWPP plans for non-Azure clouds are narrower: Defender for Servers works on AWS EC2 and on-prem via Azure Arc, Defender for Containers works on EKS and GKE, but several plans (Storage, App Service) are Azure-only. The result is a posture surface that is genuinely multi-cloud and a runtime surface that is mostly Azure-plus-Arc -- which is the layer that actually flows to XDR at hop 6 [@ms-learn-mdc-introduction].&lt;/p&gt;
&lt;h3&gt;6.6 Hop 6 -- The Defender XDR correlation engine and the fan-in&lt;/h3&gt;
&lt;p&gt;The last hop is the merge. The Defender XDR correlation engine reads incoming alerts from all source pipelines, normalizes the entity values they carry, and groups alerts whose entities overlap within a sliding time window into a single incident. The grouping is asymmetric: a higher-confidence alert (e.g., an MDE process-tree alert with a strong &lt;code&gt;ProcessGuid&lt;/code&gt;) can pull in lower-confidence alerts (e.g., a Sentinel rule whose only entity is &lt;code&gt;Host&lt;/code&gt;), but not vice-versa [@ms-learn-xdr-correlation].&lt;/p&gt;

The server-side service that reads alerts from connected sources, computes entity overlap and temporal proximity, and merges related alerts into incidents. The engine is not user-configurable in detail; merge thresholds, time windows, and entity-priority rules are Microsoft-managed defaults [@ms-learn-xdr-correlation] [@ms-learn-defender-xdr-incidents].
&lt;p&gt;The geometry of the fan-in for the worked example is the mirror image of the fan-out in section 5. The same three alerts that arrived at three different timestamps now converge on a single incident object I-7842:&lt;/p&gt;

sequenceDiagram
    autonumber
    participant SEN as Sentinel SecurityAlert
    participant MDC as MDC SecurityAlert
    participant MDE as MDE DeviceAlertEvents
    participant COR as Defender XDR correlator
    participant INC as Incident I-7842
    SEN-&amp;gt;&amp;gt;COR: Host MAL-... ProcessGuid abc at 14:05:04
    MDC-&amp;gt;&amp;gt;COR: Host MAL-... File powershell.exe at 14:07:42
    MDE-&amp;gt;&amp;gt;COR: Host MAL-... ProcessGuid abc at 14:08:11
    Note over COR: match window ≤ 30 min
    COR-&amp;gt;&amp;gt;INC: open incident, attach Sentinel alert
    COR-&amp;gt;&amp;gt;INC: merge: MDE matches on ProcessGuid
    COR-&amp;gt;&amp;gt;INC: merge: MDC matches on Host within window
    INC--&amp;gt;&amp;gt;SEN: backlink to source alert
    INC--&amp;gt;&amp;gt;MDC: backlink to source alert
    INC--&amp;gt;&amp;gt;MDE: backlink to source alert
&lt;p&gt;Three things deserve explicit attention in this fan-in:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The strong-entity priority.&lt;/strong&gt; The MDE alert and the Sentinel alert share &lt;code&gt;ProcessGuid&lt;/code&gt;. Microsoft documents that field as a unique value designed to make event correlation easier across hosts and domains [@ms-learn-sysmon]. The merge between them is unambiguous. The MDC-from-Servers alert only carries &lt;code&gt;Host&lt;/code&gt; and &lt;code&gt;File&lt;/code&gt; -- the MDC plan&apos;s alert grammar does not necessarily emit &lt;code&gt;ProcessGuid&lt;/code&gt; even though the underlying MDE sensor knows it. The MDC alert merges into the incident on the weaker &lt;code&gt;Host&lt;/code&gt; match within the time window.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Microsoft-managed thresholds.&lt;/strong&gt; The correlation window, the entity-priority rules, and the merge logic are not exposed for customer tuning. They are documented at the policy level -- &quot;alerts that share entities within a time window&quot; -- but the exact heuristics are part of the Defender XDR service [@ms-learn-xdr-correlation]. §9 returns to this opacity as an open problem.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What does NOT merge.&lt;/strong&gt; Some categories of source data stay outside the incident graph even when they ought to: cross-workspace Sentinel rules (alerts in a workspace other than the Defender-XDR-connected &quot;primary&quot; one), third-party connector alerts that lack entity mappings, and -- as already underlined -- MDC posture findings of every kind [@ms-learn-mdc-xdr-concept].&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &quot;primary workspace&quot; constraint matters for multi-workspace customers. A Defender XDR tenant connects to exactly one Sentinel primary workspace for the unified secops experience. Sentinel alerts from secondary workspaces still exist as alerts, can still trigger automation rules, and are still queryable via cross-workspace KQL -- but they do not appear in the unified incident graph at security.microsoft.com [@ms-learn-unified-secops] [@ms-learn-move-to-defender]. Customers with regional workspace topologies (e.g., one per Azure region for data-residency reasons) need to plan which workspace is the XDR-connected one.&lt;/p&gt;
&lt;p&gt;For the worked example, hop 6 completes at 14:09:30 UTC: the SOC analyst sees a single incident in their queue, titled &lt;code&gt;Multi-stage incident on one endpoint&lt;/code&gt;, with three correlated alerts on its alerts tab, a unified entity graph showing the host, the user, the parent and child processes, the file hash, and the URL embedded in the encoded command line, and one-click pivots to the MDE timeline, the Sentinel investigation graph, and the MDC alert detail. Three pipelines, one analyst surface, nine minutes thirteen seconds end-to-end.&lt;/p&gt;
&lt;p&gt;That is the full path. The next three sections compare it to what other vendors do, name the theoretical limits any such pipeline has to live with, and walk the open problems that even the best-tuned version of this pipeline still faces.&lt;/p&gt;
&lt;h2&gt;7. Competing approaches: inside and outside the Microsoft fence&lt;/h2&gt;
&lt;p&gt;The architecture in §6 is one answer to &quot;how do I turn endpoint telemetry into a SOC incident.&quot; It is not the only answer. Other detection engines exist both inside Microsoft and outside, with materially different design choices that are useful to compare side-by-side.&lt;/p&gt;
&lt;p&gt;Inside Microsoft, six detection engines run on roughly the same data over the same workspace -- and an architect picking where to put a new detection has to know what each one optimizes for.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Engine&lt;/th&gt;
&lt;th&gt;Where the query runs&lt;/th&gt;
&lt;th&gt;Latency&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Sentinel scheduled rule&lt;/td&gt;
&lt;td&gt;Log Analytics KQL, every 5+ min&lt;/td&gt;
&lt;td&gt;5-8 min&lt;/td&gt;
&lt;td&gt;Cross-source SIEM detections, free-form KQL [@ms-learn-sentinel-scheduled-rules]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentinel NRT rule&lt;/td&gt;
&lt;td&gt;Log Analytics KQL, every 1 min&lt;/td&gt;
&lt;td&gt;1-2 min&lt;/td&gt;
&lt;td&gt;High-priority single-row detections [@ms-learn-sentinel-nrt-rules]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentinel Fusion&lt;/td&gt;
&lt;td&gt;ML, multi-source&lt;/td&gt;
&lt;td&gt;Hours&lt;/td&gt;
&lt;td&gt;Multistage attack patterns, low-signal corroboration [@ms-learn-sentinel-fusion]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defender XDR custom detection&lt;/td&gt;
&lt;td&gt;Advanced hunting KQL, periodic&lt;/td&gt;
&lt;td&gt;5-30 min&lt;/td&gt;
&lt;td&gt;Detections over &lt;code&gt;DeviceProcessEvents&lt;/code&gt; / MDE schema [@ms-learn-sentinel-custom-detections]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDE built-in detections&lt;/td&gt;
&lt;td&gt;In-product behavioural&lt;/td&gt;
&lt;td&gt;Seconds-to-minutes&lt;/td&gt;
&lt;td&gt;Endpoint-local process / file / network signatures [@ms-learn-mde-landing]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDC plan built-in detections&lt;/td&gt;
&lt;td&gt;Per-plan engines&lt;/td&gt;
&lt;td&gt;Seconds-to-minutes&lt;/td&gt;
&lt;td&gt;Per-workload runtime detection (containers, SQL, storage) [@ms-learn-mdc-introduction]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The takeaway is that &lt;strong&gt;Sentinel and Defender XDR custom detections are not interchangeable&lt;/strong&gt;. They read from different schemas (Log Analytics tables vs MDE advanced-hunting tables), they have different governance models (Azure RBAC vs Defender role-based access), and they emit alerts via different paths. The right engine depends on where your telemetry lives. For the worked example, Sysmon in &lt;code&gt;Event&lt;/code&gt; is reached by Sentinel, not by Custom Detections; MDE&apos;s &lt;code&gt;DeviceProcessEvents&lt;/code&gt; for the same host is reached by Custom Detections, not by Sentinel scheduled rules.&lt;/p&gt;
&lt;p&gt;Outside Microsoft, the six widely-deployed alternative stacks each make different trade-offs:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;th&gt;Storage&lt;/th&gt;
&lt;th&gt;Query language&lt;/th&gt;
&lt;th&gt;Strength&lt;/th&gt;
&lt;th&gt;Cost shape&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Splunk Enterprise Security&lt;/td&gt;
&lt;td&gt;Splunk indexers&lt;/td&gt;
&lt;td&gt;SPL&lt;/td&gt;
&lt;td&gt;Long-installed, deep app catalog, mature SOAR&lt;/td&gt;
&lt;td&gt;License-tier (GB/day) or workload-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Splunk Cloud + ES&lt;/td&gt;
&lt;td&gt;Splunk-managed cloud&lt;/td&gt;
&lt;td&gt;SPL&lt;/td&gt;
&lt;td&gt;Same SPL, SaaS-managed&lt;/td&gt;
&lt;td&gt;Per-ingest workload-priced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Elastic Security&lt;/td&gt;
&lt;td&gt;Elasticsearch&lt;/td&gt;
&lt;td&gt;EQL + ES&lt;/td&gt;
&lt;td&gt;QL&lt;/td&gt;
&lt;td&gt;Open-source community, full-text strength&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google SecOps (Chronicle)&lt;/td&gt;
&lt;td&gt;Google-internal columnar&lt;/td&gt;
&lt;td&gt;YARA-L 2 + UDM&lt;/td&gt;
&lt;td&gt;Petabyte-scale retention, fixed bytes-per-employee pricing&lt;/td&gt;
&lt;td&gt;Per-employee (no per-GB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Security Lake + Athena&lt;/td&gt;
&lt;td&gt;S3 + OCSF&lt;/td&gt;
&lt;td&gt;Athena SQL&lt;/td&gt;
&lt;td&gt;Open-schema, bring-your-own-detection&lt;/td&gt;
&lt;td&gt;Per-ingest + per-query&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sigma + open-source SIEM&lt;/td&gt;
&lt;td&gt;Vendor-neutral rule format, translates to many SIEMs&lt;/td&gt;
&lt;td&gt;Sigma YAML&lt;/td&gt;
&lt;td&gt;Portable detection rules&lt;/td&gt;
&lt;td&gt;Free format; SIEM cost varies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Sigma&lt;/strong&gt; deserves a special mention because it is a &lt;em&gt;rule format&lt;/em&gt;, not a SIEM. Sigma rules describe detections in a vendor-neutral YAML schema and are translated by a converter (&lt;code&gt;sigmac&lt;/code&gt;) into the target SIEM&apos;s native query language -- KQL for Sentinel, SPL for Splunk, ES|QL for Elastic, YARA-L for Google SecOps [@sigmahq-sigma]. The result is that a single Sigma rule for &quot;Office process spawns PowerShell with encoded command&quot; can be deployed across multiple SIEMs without rewriting. The trade-off is that Sigma compiles to the lowest common denominator of expressiveness; complex multi-table joins do not translate cleanly. Microsoft Sentinel supports Sigma rule import via the analytics-rule wizard [@sigmahq-sigma].&lt;/p&gt;
&lt;p&gt;The structural difference that matters most across these stacks is &lt;strong&gt;where the storage and query engine live&lt;/strong&gt;. Splunk on-prem owns its full stack and bills on ingest. Elastic gives you the stack and lets you self-host or buy SaaS. Google SecOps removes the per-GB axis entirely and bills per employee, betting that the value of the SOC is the analyst&apos;s time, not the byte count. AWS Security Lake decomposes further than Microsoft does, exposing S3 directly so you can bring any analytics engine. Microsoft&apos;s design point -- KQL over Log Analytics with grafted XDR correlation -- sits in the middle: more managed than AWS, more opinionated than Elastic, billed per-GB like Splunk but with separable axes.&lt;/p&gt;
&lt;p&gt;There is also a &lt;strong&gt;migration option&lt;/strong&gt; worth knowing about. Microsoft introduced a Sentinel SIEM migration experience in 2024 that uses generative AI to translate detection rules from Splunk SPL to KQL [@ms-learn-sentinel-siem-migration]. The tool is not a complete replacement for human review of every translated rule, but it materially shortens the migration spike that has historically blocked SOCs from switching SIEMs. The existence of such a tool is itself evidence that the SIEM market is becoming more substitutable than it once was -- a SOC&apos;s investment in detection logic is no longer locked to one vendor&apos;s query language.&lt;/p&gt;
&lt;p&gt;For the worked example specifically, every one of the alternative stacks could in principle deliver the same end result -- one incident for a parent-child process-spawn detection. The differences are in the operating model: who owns the storage, who owns the agent, who priced the ingest, and how easily the analyst can pivot from the incident into raw telemetry. Microsoft&apos;s pitch with the unified secops platform is that &quot;all of the above are in one portal.&quot; The honest reading is &quot;the Microsoft-side ones are in one portal, and the third-party feeds you stream into Sentinel still participate via the same &lt;code&gt;SecurityAlert&lt;/code&gt; table.&quot;&lt;/p&gt;
&lt;h2&gt;8. Theoretical limits&lt;/h2&gt;
&lt;p&gt;The six-hop pipeline is mostly an engineering object. But it inherits a few honestly theoretical limits that no amount of clever product design can defeat. Naming them sharply is the difference between an architect who knows what the system cannot do and a buyer who is surprised.&lt;/p&gt;

The general problem of deciding when two records in different data sources refer to the same real-world entity. In the SIEM context, the entities are users, hosts, files, processes, IPs, URLs, and email recipients. Strong identifiers (a hardware-rooted DeviceId, a Microsoft Entra ObjectId, a SHA256 hash) make the problem tractable; weak identifiers (an account name, an IP address, a file name) make it probabilistic [@ms-learn-sentinel-entities].
&lt;p&gt;The first hard limit is that &lt;strong&gt;entity resolution across pipelines is structurally probabilistic&lt;/strong&gt; whenever the strong identifiers are missing. The Defender XDR correlator depends on entity overlap; the worked example merged cleanly because &lt;code&gt;ProcessGuid&lt;/code&gt; was shared between MDE and Sentinel. Take that identifier away and the merge falls back on &lt;code&gt;Host&lt;/code&gt;, which is shared but ambiguous (hostnames are reused, machine accounts get recycled), and ultimately on weaker identifiers like file name or command-line substring. The table below names what identifiers each source pipeline can be relied upon to carry.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Entity type&lt;/th&gt;
&lt;th&gt;Strong identifier (when available)&lt;/th&gt;
&lt;th&gt;Weak fallback&lt;/th&gt;
&lt;th&gt;Pipelines that emit the strong form&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;DeviceId (MDE GUID), Azure resourceId&lt;/td&gt;
&lt;td&gt;Hostname, FQDN&lt;/td&gt;
&lt;td&gt;MDE, MDC for Servers, Sentinel (if mapped)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Process&lt;/td&gt;
&lt;td&gt;ProcessGuid (Sysmon/MDE)&lt;/td&gt;
&lt;td&gt;Image path + start time&lt;/td&gt;
&lt;td&gt;Sysmon, MDE, advanced hunting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account&lt;/td&gt;
&lt;td&gt;Microsoft Entra ObjectId&lt;/td&gt;
&lt;td&gt;UPN, samAccountName&lt;/td&gt;
&lt;td&gt;Microsoft Entra ID logs, MDI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;SHA256&lt;/td&gt;
&lt;td&gt;Filename, MD5&lt;/td&gt;
&lt;td&gt;MDE, Sentinel rules that include hash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IP&lt;/td&gt;
&lt;td&gt;n/a (probabilistic by definition)&lt;/td&gt;
&lt;td&gt;IP literal&lt;/td&gt;
&lt;td&gt;All&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;URL&lt;/td&gt;
&lt;td&gt;Normalized URL with scheme&lt;/td&gt;
&lt;td&gt;Bare host&lt;/td&gt;
&lt;td&gt;MDE, Defender for Office, threat-intel feeds&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; &lt;strong&gt;Aha #3 -- entity resolution is information-theoretic, not engineering.&lt;/strong&gt; Two records refer to the same entity if and only if their identifiers carry enough joint information to pick that entity out of the space of all entities. When the entity space is small (a few thousand hosts) and the identifier is strong (a DeviceId), the match is determined. When the entity space is large (every IP on the public internet) and the identifier is weak (the bare IP), the match is probabilistic and false-positives accumulate. No correlation engine, however clever, can manufacture information that the source pipeline did not record. The architectural lesson is to &lt;em&gt;invest in strong identifiers upstream&lt;/em&gt; -- in agents, in DCR schemas, in alert grammars -- not to lean on correlator cleverness downstream.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second hard limit is &lt;strong&gt;normalization lossiness&lt;/strong&gt;. ASIM (Advanced Security Information Model), Microsoft&apos;s effort to normalize Sentinel data into common schemas like &lt;code&gt;_Im_ProcessCreate&lt;/code&gt;, makes cross-source queries dramatically easier -- but the normalization is lossy. Fields that exist only in Sysmon (such as the Sysmon-specific &lt;code&gt;IntegrityLevel&lt;/code&gt; value, or the &lt;code&gt;OriginalFileName&lt;/code&gt; from the PE manifest) get dropped on the way into the normalized schema [@ms-learn-sentinel-asim-normalization]. The trade-off is honest and inescapable: a normalized schema is a projection from a richer per-source schema, and projections lose data by construction.&lt;/p&gt;
&lt;p&gt;We can sketch this formally. If $$S$$ is the per-source schema (a set of fields), $$N$$ is the normalized schema, and $$\pi: S \to N$$ is the projection (the ASIM mapping), then the information loss on a single record $$r$$ is&lt;/p&gt;
&lt;p&gt;$$
L(r) = H(r) - H(\pi(r))
$$&lt;/p&gt;
&lt;p&gt;where $$H$$ is the entropy (number of bits) of the record. For a Sysmon ProcessCreate row, $$H(r)$$ is roughly $$\log_2 |S|$$ bits over a thirty-field schema (call it ~150-200 bits of effective entropy after compression of correlated fields); $$H(\pi(r))$$ is around half that after mapping into the much smaller normalized &lt;code&gt;_Im_ProcessCreate&lt;/code&gt; schema. The dropped bits are exactly the fields you cannot query in the normalized form. ASIM is good for cross-source detections that need only common fields; per-source detections that need the long tail of source-specific fields must query the raw source table directly.&lt;/p&gt;
&lt;p&gt;The third limit is &lt;strong&gt;temporal alignment&lt;/strong&gt;. Each pipeline has its own clock: Sysmon timestamps come from the host kernel, MDC alerts from the MDC service back-end, Sentinel &lt;code&gt;TimeGenerated&lt;/code&gt; from the workspace ingestion. Within a single host these clocks are usually close (NTP-synced), but across hosts and across pipelines they can drift by seconds or minutes. The correlator&apos;s &quot;within a time window&quot; merge has to tolerate this drift, which means the window has to be larger than the worst-case clock skew. A larger window means more false-positive merges. There is no way out of this trade-off; only operational tuning between sensitivity and specificity.&lt;/p&gt;
&lt;p&gt;The fourth limit is &lt;strong&gt;rule expressiveness ceiling&lt;/strong&gt;. KQL is Turing-complete in the sense that any computable detection can be expressed if you are willing to write enough of it -- but Sentinel scheduled rules cap query duration, query result size, and join cardinality. Detections that conceptually want to scan a year of data and join against a separately-changing IOC list are &lt;em&gt;expressible&lt;/em&gt; in KQL but &lt;em&gt;not runnable&lt;/em&gt; under Sentinel rule limits. Custom ADX clusters or Spark-on-Synapse can run such queries, at the cost of leaving the unified portal entirely.&lt;/p&gt;
&lt;p&gt;These are the limits any honest architecture has to live with. The Microsoft pipeline does well on the first (when strong identifiers exist), is honest about the second (ASIM is documented as a normalization, not a transparent overlay), tolerates the third (windowed merge), and surfaces the fourth as a Sentinel pricing-and-scope conversation. None of them is a Microsoft-specific defect. They are properties of the problem.&lt;/p&gt;
&lt;h2&gt;9. Open problems&lt;/h2&gt;
&lt;p&gt;The pipeline is fast enough, accurate enough, and -- in the worked example -- correct. It is not finished. Seven open problems remain, in roughly decreasing order of how much they hurt a working SOC today.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. The Sentinel-Azure-portal cutover is on a hard date.&lt;/strong&gt; Microsoft has announced the retirement of the Microsoft Sentinel experience in the Azure portal effective &lt;strong&gt;March 31, 2027&lt;/strong&gt; (extended from the original July 1, 2026 target) [@ms-learn-sentinel-azure-portal-retiring] [@helpnetsec-sentinel-defender-timeline]. After that date, Sentinel can only be operated through the unified Defender portal at &lt;code&gt;security.microsoft.com&lt;/code&gt;. The cutover affects analytics-rule authoring (the Azure-portal rule wizard goes away), automation rules, watchlists, and the investigation graph. Customers with custom dashboards, ARM templates, or automation that targets the Azure-portal Sentinel surface must port them. This is the most concrete migration deadline in this article.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. CWPP-to-XDR coverage is still expanding.&lt;/strong&gt; As of the documented integration scope, MDC for Servers, Containers, SQL, Storage, and App Service alerts flow to Defender XDR [@ms-learn-mdc-xdr-concept] [@ms-learn-mdc-xdr-ingest]. New CWPP plans (e.g., Defender for APIs as it matures) tend to land first in the MDC blade and only later in the unified incident graph. Customers operationalizing a new MDC plan should check the integration documentation for that specific plan rather than assuming XDR ingestion is automatic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Posture-finding context still lives in a separate blade.&lt;/strong&gt; As §6.5 established, MDC posture findings do not flow to Defender XDR. A SOC analyst looking at an incident on a host has no incident-side way to see &quot;this host also has a CSPM finding for missing endpoint protection.&quot; The workaround is to &lt;code&gt;join&lt;/code&gt; &lt;code&gt;SecurityRecommendation&lt;/code&gt; against the incident-affected resources via KQL, or to pivot manually to the MDC blade. A first-class &quot;posture context on incident&quot; feature does not exist as of the documented surface area.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. The correlation engine&apos;s heuristics are not user-tunable.&lt;/strong&gt; The Defender XDR correlation engine merges alerts using a Microsoft-managed set of thresholds: time window, entity priority, confidence weighting [@ms-learn-xdr-correlation]. These are not exposed for customer override. A SOC that wants to widen the merge window (because their telemetry has long ingest tails) or tighten the entity-priority (because they distrust hostname matches for shared-name VMs) has no knob to turn. The correlation behaviour is whatever Microsoft ships; tuning happens by raising support cases against perceived false-merges or false-splits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Custom detection semantics are subtly different from Sentinel rule semantics.&lt;/strong&gt; A KQL detection authored as a Defender XDR Custom Detection runs over the advanced-hunting schema (&lt;code&gt;DeviceProcessEvents&lt;/code&gt;, &lt;code&gt;DeviceFileEvents&lt;/code&gt;, etc.), not over Log Analytics tables [@ms-learn-sentinel-custom-detections] [@ms-learn-advanced-hunting]. The two schemas overlap (you can write conceptually similar detections over both), but the field names, the freshness windows, and the result-size caps differ. An organization with parallel teams authoring detections in both surfaces can end up with two near-duplicate detections that drift apart over time. There is no first-class deduplication or &quot;promote this Sentinel rule to a Custom Detection&quot; workflow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6. Logic Apps write-back from Sentinel to MDC has rough edges.&lt;/strong&gt; Sentinel automation rules can invoke Logic Apps playbooks to take response actions [@ms-learn-sentinel-logic-apps-playbooks] [@ms-learn-sentinel-soar]. Writing back to MDC -- for example, suppressing an alert in MDC or creating a Defender for Cloud assessment programmatically -- is possible but requires the playbook to call the MDC REST API directly [@ms-learn-mdc-assessments-rest]. There is no native &quot;MDC action&quot; connector with the breadth of the MDE actions connector. Customers building bidirectional response automation between Sentinel and MDC end up writing HTTP-action playbooks by hand. The MDC REST API for assessments lets you create and update assessment results programmatically, but the surface area for &lt;em&gt;writing back&lt;/em&gt; to MDC (e.g., dismissing or recategorizing an alert) is smaller than the read API and is not symmetric with Sentinel&apos;s native alert-lifecycle actions [@ms-learn-mdc-assessments-rest] [@ms-learn-mdc-custom-recs]. Closing this gap with a first-class connector is on most enterprise customers&apos; wish lists.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7. Multi-workspace and multi-tenant topologies remain awkward.&lt;/strong&gt; The unified secops experience connects Defender XDR to exactly one Sentinel primary workspace per tenant. Customers with multiple workspaces -- common in regulated industries with data-residency boundaries -- must choose which workspace is the XDR-connected one, and accept that the other workspaces&apos; alerts are visible only inside Sentinel, not in the unified incident graph [@ms-learn-unified-secops] [@ms-learn-move-to-defender]. Multi-tenant MSSPs and customers with subsidiaries on separate Azure tenants face an even harder design problem: there is no single pane across tenants in the unified portal, only the cross-workspace KQL pattern from §4.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;8. Multicloud entity resolution: the EC2-on-AWS case.&lt;/strong&gt; A Windows VM running as an AWS EC2 instance can be brought into Microsoft&apos;s stack through two layers, neither of which produces a single shared identifier. Defender for Cloud&apos;s multicloud connector ingests AWS CloudTrail and EC2 metadata into MDC&apos;s posture surface (CSPM coverage) [@ms-learn-mdc-onboard-multicloud]; Defender for Servers&apos; Arc-based provisioning then installs Azure Monitor Agent and Microsoft Defender for Endpoint on the EC2 host, projecting the box into the Azure tenant&apos;s resource graph as an &lt;code&gt;Microsoft.HybridCompute/machines&lt;/code&gt; Arc resource. Three identifiers therefore describe the same physical workload but never coincide on a single strong identifier: (1) the EC2 ARN &lt;code&gt;arn:aws:ec2:&amp;lt;region&amp;gt;:&amp;lt;account&amp;gt;:instance/&amp;lt;instance-id&amp;gt;&lt;/code&gt;, which is what AWS CloudTrail and the AWS console use; (2) the Arc machine resource ID &lt;code&gt;/subscriptions/&amp;lt;sub&amp;gt;/resourceGroups/&amp;lt;rg&amp;gt;/providers/Microsoft.HybridCompute/machines/&amp;lt;arc-machine-name&amp;gt;&lt;/code&gt;, which is what the Log Analytics &lt;code&gt;_ResourceId&lt;/code&gt; column carries when AMA forwards the Sysmon event; (3) the MDE &lt;code&gt;DeviceId&lt;/code&gt;, a GUID assigned at MDE first-onboarding, which is what the Defender for Servers CWPP alert and the &lt;code&gt;DeviceInfo&lt;/code&gt; advanced-hunting table key on. Bridging the three at query time requires bespoke KQL: lift the Arc machine name from &lt;code&gt;_ResourceId&lt;/code&gt; via &lt;code&gt;extend ArcMachine = tostring(split(_ResourceId, &quot;/&quot;)[-1])&lt;/code&gt;, look up the corresponding &lt;code&gt;DeviceId&lt;/code&gt; in &lt;code&gt;DeviceInfo&lt;/code&gt; keyed by &lt;code&gt;DeviceName&lt;/code&gt;, and &lt;code&gt;join&lt;/code&gt; to a customer-maintained &lt;code&gt;Watchlist&lt;/code&gt; (or external CMDB) that maps Arc machine name -&amp;gt; EC2 instance-id -&amp;gt; EC2 ARN. The pattern works, but every join is a place where the inventory can drift; a renamed EC2 instance or a reimaged host that picks up a new MDE &lt;code&gt;DeviceId&lt;/code&gt; will silently break correlation until the watchlist is refreshed.&lt;/p&gt;

The EC2 sub-example above is the tip of the iceberg. Multi-cloud is its own open problem and worth a separate article. MDC&apos;s CSPM and parts of the CWPP plans (Servers, Containers) cover AWS and GCP via Azure Arc and cloud connectors, but the depth of integration for non-Azure workloads in the unified XDR experience is less than for native Azure workloads. The honest summary is &quot;Azure-first, AWS/GCP-supported, on-prem via Arc.&quot; Designs that are AWS-primary should evaluate AWS Security Lake + a SIEM (Sentinel, Splunk, or Athena) against MDC-on-AWS specifically; the choice is not obvious.
&lt;p&gt;None of these problems is fatal to the architecture. Each is the kind of structural friction that comes from grafting three pre-existing pipelines into one analyst surface in fewer than three years. The cutover date is the only one with a deadline; the rest are roadmap items.&lt;/p&gt;
&lt;h2&gt;10. Recipe: building the pipeline yourself in six steps&lt;/h2&gt;
&lt;p&gt;This section walks the six setup steps that produce the worked example end-to-end, in the order an engineer should actually do them. Each step names the artifact, the documentation reference, and the single most common mistake that will silently break the step.&lt;/p&gt;
&lt;h3&gt;Step 1 -- Install Sysmon with a curated configuration&lt;/h3&gt;
&lt;p&gt;Install Sysmon on the host (Azure VM, Arc-enabled server, or on-prem Windows) with a configuration that emits the events you actually need [@ms-learn-sysmon]. The default Sysmon config is essentially empty; a curated config is what makes it useful. Many teams start with the SwiftOnSecurity &lt;code&gt;sysmon-config&lt;/code&gt; or Olaf Hartong &lt;code&gt;sysmon-modular&lt;/code&gt; public baselines and prune from there [@swiftonsecurity-sysmon-config] [@hartong-sysmon-modular].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;Don&apos;t reinvent the Sysmon config.&lt;/strong&gt; Two community-maintained baselines do most of the work: the SwiftOnSecurity &lt;code&gt;sysmon-config&lt;/code&gt; template (&quot;a Sysmon configuration file for everybody to fork...with default high-quality event tracing&quot;) and Olaf Hartong&apos;s &lt;code&gt;sysmon-modular&lt;/code&gt; framework (&quot;a Sysmon configuration repository for everybody to customise&quot;) cover the common cases with years of community tuning [@swiftonsecurity-sysmon-config] [@hartong-sysmon-modular]. Pick one, version-control it in your config-management tool (DSC, Ansible, Chef), and ship it via your existing host-config pipeline. The single most common mistake is shipping a default Sysmon install and then wondering why detections fire on noise.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Validate that Sysmon is emitting by reading the local event log on the host: &lt;code&gt;Get-WinEvent -LogName &quot;Microsoft-Windows-Sysmon/Operational&quot; -MaxEvents 5&lt;/code&gt;. If you see ProcessCreate (Event ID 1) records, hop 1 works.&lt;/p&gt;
&lt;h3&gt;Step 2 -- Deploy the Azure Monitor Agent with a Data Collection Rule&lt;/h3&gt;
&lt;p&gt;Install AMA on the host (via Azure Policy for Azure VMs, the Arc agent for non-Azure, or the standalone installer) [@ms-learn-ama-overview]. Then create a Data Collection Rule that names the Sysmon channel and ships it to your Sentinel-enabled workspace. The ARM snippet below is the load-bearing artifact: the &lt;code&gt;streams&lt;/code&gt; value must be exactly &lt;code&gt;Microsoft-WindowsEvent&lt;/code&gt; (or, for the older &lt;code&gt;Event&lt;/code&gt; table path, &lt;code&gt;Microsoft-Event&lt;/code&gt;), not a variant. &lt;strong&gt;This is the silent-failure cliff §6.2 named: get this string wrong and the agent ships nothing, returning no error.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;type&quot;: &quot;Microsoft.Insights/dataCollectionRules&quot;,
  &quot;apiVersion&quot;: &quot;2022-06-01&quot;,
  &quot;name&quot;: &quot;dcr-sysmon-to-sentinel&quot;,
  &quot;location&quot;: &quot;eastus&quot;,
  &quot;properties&quot;: {
    &quot;dataSources&quot;: {
      &quot;windowsEventLogs&quot;: [
        {
          &quot;name&quot;: &quot;sysmonOperational&quot;,
          &quot;streams&quot;: [&quot;Microsoft-WindowsEvent&quot;],
          &quot;xPathQueries&quot;: [
            &quot;Microsoft-Windows-Sysmon/Operational!*[System[(EventID=1 or EventID=3 or EventID=7 or EventID=10 or EventID=11)]]&quot;
          ]
        }
      ]
    },
    &quot;destinations&quot;: {
      &quot;logAnalytics&quot;: [
        { &quot;name&quot;: &quot;lawDest&quot;,
          &quot;workspaceResourceId&quot;:
            &quot;/subscriptions/&amp;lt;sub&amp;gt;/resourceGroups/&amp;lt;rg&amp;gt;/providers/Microsoft.OperationalInsights/workspaces/law-contoso-secops&quot; }
      ]
    },
    &quot;dataFlows&quot;: [
      { &quot;streams&quot;: [&quot;Microsoft-WindowsEvent&quot;],
        &quot;destinations&quot;: [&quot;lawDest&quot;] }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The silent-miss bug is real: a DCR that names &lt;code&gt;&quot;Microsoft-Event&quot;&lt;/code&gt; ships into the older &lt;code&gt;Event&lt;/code&gt; table; a DCR that names &lt;code&gt;&quot;Microsoft-WindowsEvent&quot;&lt;/code&gt; ships into the newer typed &lt;code&gt;WindowsEvent&lt;/code&gt; table; &lt;strong&gt;a DCR that names anything else (typo, copy-paste from another data source, or a name that does not exist) emits nothing, returns no validation error at deploy time, and produces a silent dashboard hole&lt;/strong&gt; [@ms-learn-ama-windows-events] [@ms-learn-sentinel-data-connectors-ref]. The fix is to validate post-deploy by checking that rows are arriving in the destination table within ~5 minutes.&lt;/p&gt;
&lt;p&gt;Validation KQL to run in the workspace:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kql&quot;&gt;Event
| where TimeGenerated &amp;gt; ago(10m)
| where Source == &quot;Microsoft-Windows-Sysmon&quot; and EventID == 1
| summarize count() by Computer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you see a row per Sysmon-emitting host, hop 2 and hop 3 work.&lt;/p&gt;
&lt;h3&gt;Step 3 -- Author the Sentinel scheduled analytics rule&lt;/h3&gt;
&lt;p&gt;Inside the Defender portal&apos;s Sentinel section (or the Azure-portal Sentinel blade until the March 31, 2027 cutover), create a new scheduled analytics rule [@ms-learn-sentinel-scheduled-rules] [@ms-learn-sentinel-azure-portal-retiring]. Paste the KQL from the Spoiler in §6.3. Configure entity mappings: &lt;code&gt;Host&lt;/code&gt; from &lt;code&gt;Computer&lt;/code&gt;, &lt;code&gt;Account&lt;/code&gt; from &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Process&lt;/code&gt; from &lt;code&gt;ProcessGuid&lt;/code&gt;. Schedule: run every 5 minutes over the last 5 minutes. Severity: Medium. Tactic: &lt;code&gt;Execution&lt;/code&gt; (MITRE ATT&amp;amp;CK T1059.001).&lt;/p&gt;
&lt;p&gt;The single most common mistake at this step is &lt;strong&gt;omitting the entity mappings&lt;/strong&gt;. The rule will fire and produce a &lt;code&gt;SecurityAlert&lt;/code&gt; row, but the alert will not participate in cross-pipeline correlation at hop 6 because there are no entities to merge on. Always configure at least Host, Account, and -- when available -- Process or FileHash entity mappings on a Sentinel rule.&lt;/p&gt;

This recipe sets up the Sysmon-to-Sentinel-to-XDR path only. Adjacent surfaces -- Microsoft Defender for Office 365 for email alerts, Microsoft Defender for Identity for on-prem AD signals, Microsoft Defender for Cloud Apps (MDCA) for SaaS-app signals -- have their own onboarding paths and are out of scope for this six-step recipe. The convergence point in Defender XDR is the same; the upstream setup differs per source.&lt;p&gt;Five other adjacent surfaces are worth knowing about as a map of the broader Microsoft SecOps surface, even though this article does not walk any of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sentinel watchlists&lt;/strong&gt; -- name-value reference tables (e.g., critical-asset inventory, terminated-user list, custom IOC list) stored in the &lt;code&gt;Watchlist&lt;/code&gt; table and cached for low-latency enrichment joins in KQL analytics rules and hunts [@ms-learn-sentinel-watchlists].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sentinel threat intelligence integration&lt;/strong&gt; -- ingest IOCs from TAXII feeds, Microsoft Defender Threat Intelligence, MISP, or platform connectors into the &lt;code&gt;ThreatIntelligenceIndicator&lt;/code&gt; table, and use the built-in TI map rule type to fire on matches against your telemetry [@ms-learn-sentinel-threat-intel].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MSTICPy + Sentinel Jupyter notebooks&lt;/strong&gt; -- the Microsoft-maintained MSTICPy Python library plus Sentinel&apos;s notebook integration give hunters a programmable workspace for incident investigation, IOC pivoting, and ML-driven analysis on Sentinel data outside the rule-authoring surface [@ms-learn-sentinel-notebooks].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sentinel Content Hub and the solutions marketplace&lt;/strong&gt; -- the in-product distribution surface for prepackaged detections, parsers, workbooks, hunting queries, and playbooks delivered as Microsoft-signed or partner-signed solutions [@ms-learn-sentinel-solutions].&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Microsoft Defender External Attack Surface Management (Defender EASM)&lt;/strong&gt; -- the adjacent posture surface that discovers and maps an organization&apos;s internet-facing assets from the outside-in; explicitly out of scope for this article&apos;s CSPM/CWPP/SIEM/XDR spine, but worth knowing exists [@ms-learn-defender-easm].&lt;/li&gt;&lt;/ul&gt;

&lt;h3&gt;Step 4 -- Enable Defender for Servers (Plan 2) for MDC alerts&lt;/h3&gt;
&lt;p&gt;On the Azure subscription that owns the VM (or the Arc-enabled resource group), enable Microsoft Defender for Cloud&apos;s Defender for Servers Plan 2 [@ms-learn-mdc-defender-servers]. Plan 2 includes the MDE license and the runtime detection engine that emits the MDC alert at hop 5. Enabling the plan automatically deploys MDE to the in-scope hosts and configures the MDC-to-XDR alert-ingestion integration that reached general availability in March 2024 [@ms-learn-mdc-mde-integration] [@ms-learn-mdc-xdr-ingest].&lt;/p&gt;
&lt;p&gt;Validation: trigger a benign test pattern (e.g., &lt;code&gt;powershell -EncodedCommand&lt;/code&gt; of a harmless script) on a test host. Within ~5 minutes, you should see an MDC alert in the MDC Alerts blade titled &lt;code&gt;Suspicious PowerShell command line&lt;/code&gt; (or similar), and a corresponding alert in &lt;code&gt;security.microsoft.com&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Step 5 -- Connect Sentinel to the unified Defender portal&lt;/h3&gt;
&lt;p&gt;Inside the Defender portal, enable the Sentinel connection that designates your Log Analytics workspace as the &lt;strong&gt;primary workspace&lt;/strong&gt; for the unified secops experience [@ms-learn-sentinel-defender-portal] [@ms-learn-move-to-defender]. This step is what makes the Sentinel &lt;code&gt;SecurityAlert&lt;/code&gt; rows flow into the Defender XDR incident graph at hop 6 and become merge candidates with the MDC and MDE alerts.&lt;/p&gt;
&lt;p&gt;One-tenant, one-primary-workspace constraint: as §6.6 noted, a Defender XDR tenant has exactly one primary Sentinel workspace. If you have multiple workspaces (regional residency reasons, MSSP topology, etc.), choose deliberately which one is the XDR-connected one. Alerts in secondary workspaces remain queryable via Sentinel but do not participate in the unified incident graph.&lt;/p&gt;
&lt;h3&gt;Step 6 -- Write a watchdog rule that fires on telemetry silence&lt;/h3&gt;
&lt;p&gt;The pipeline can fail silently in multiple places: AMA stops on a host, the DCR is removed or mis-edited, Sysmon is uninstalled, the workspace fills its daily cap. None of these failures produce an alert by themselves. Write a Sentinel scheduled rule that fires when &lt;strong&gt;expected&lt;/strong&gt; telemetry is &lt;em&gt;absent&lt;/em&gt;: for each host in your inventory, alert if &lt;code&gt;Event&lt;/code&gt; table rows from that host stop appearing for more than N minutes.&lt;/p&gt;

{`# Run via Azure Monitor REST API or the az monitor cli; here we simulate
# the comparison logic that an analytics rule would express in KQL.&lt;p&gt;EXPECTED_INVENTORY = {
    &apos;MAL-CONTOSO-PRD-01&apos;,
    &apos;MAL-CONTOSO-PRD-02&apos;,
    &apos;MAL-CONTOSO-PRD-03&apos;,
    &apos;MAL-CONTOSO-PRD-04&apos;,
    &apos;MAL-CONTOSO-PRD-05&apos;,
}&lt;/p&gt;
In a real deployment this list comes from KQL against the Event table:
Event | where TimeGenerated &amp;gt; ago(24h)
| summarize by Computer
&lt;p&gt;RECENTLY_EMITTING_HOSTS = {
    &apos;MAL-CONTOSO-PRD-01&apos;,
    &apos;MAL-CONTOSO-PRD-02&apos;,
    # PRD-03 absent: agent down? DCR removed?
    &apos;MAL-CONTOSO-PRD-04&apos;,
    &apos;MAL-CONTOSO-PRD-05&apos;,
}&lt;/p&gt;
&lt;p&gt;silent_hosts = EXPECTED_INVENTORY - RECENTLY_EMITTING_HOSTS
if silent_hosts:
    print(f&quot;ALERT: telemetry silence on {len(silent_hosts)} host(s):&quot;)
    for h in sorted(silent_hosts):
        print(f&quot;  - {h}&quot;)
else:
    print(&quot;OK: all expected hosts emitted Sysmon events in the last 24h.&quot;)
`}
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The equivalent in Sentinel is a scheduled rule that joins a static &lt;code&gt;Watchlist&lt;/code&gt; of expected hosts against &lt;code&gt;Event | summarize by Computer&lt;/code&gt; over the last 24 hours and alerts on the set difference. This watchdog is the only thing standing between an architectural diagram of perfect convergence and the operational reality of one host&apos;s silent agent.&lt;/p&gt;

This recipe addresses detection-and-response only. Compliance framing -- mapping detections to MITRE ATT&amp;amp;CK tactics, mapping posture findings to MCSB controls, reporting against PCI-DSS or NIST 800-53 -- is a separate concern handled by MCSB and the MDC regulatory-compliance blade [@ms-learn-mcsb-overview]. Most enterprise SOCs end up doing both, but a working detection pipeline can ship without the compliance layer attached.
&lt;p&gt;With these six steps the Sysmon record from §1 reaches &lt;code&gt;security.microsoft.com&lt;/code&gt; in roughly nine minutes, three alerts merged into one incident. The pipeline is real. The next section addresses the questions that show up in every architecture-review meeting once the pipeline is built.&lt;/p&gt;
&lt;h2&gt;11. FAQ&lt;/h2&gt;

  
It depends on whether you need a SIEM. MDE alone gives you endpoint detection, response actions on the endpoint, and a native incident view inside Defender XDR. It does not give you a place to ingest non-endpoint log sources (firewall, identity provider that is not Microsoft Entra, custom application logs) and run cross-source correlation against them. Sentinel is the SIEM substrate that does that [@ms-learn-mde-landing] [@ms-learn-sentinel-overview]. A small organization whose telemetry is entirely MDE-and-Microsoft-365 can run without Sentinel; one whose threat model includes anything outside that envelope generally needs it.
    
No. As §6.5 established and as the Microsoft documentation is explicit about, only MDC&apos;s **CWPP alerts** (from Defender for Servers, Containers, SQL, Storage, App Service plans) flow into the Defender XDR incident graph [@ms-learn-mdc-xdr-concept] [@ms-learn-mdc-xdr-ingest]. CSPM-side artifacts -- recommendations, Secure Score deltas, regulatory-compliance findings -- stay in the Microsoft Defender for Cloud blade. If you want posture context attached to an incident, you have to pivot manually to MDC or join `SecurityRecommendation` against the incident&apos;s affected resources via KQL.
    
For the documented Sysmon-to-Sentinel-to-XDR path: roughly 5 to 10 minutes typical. The dominant factor is the Sentinel scheduled-rule cadence (minimum 5 minutes) [@ms-learn-sentinel-scheduled-rules]. NRT rules cut it to 1-2 minutes for single-row matches [@ms-learn-sentinel-nrt-rules]. MDE&apos;s native path through Defender XDR is sub-minute for the endpoint detection itself; the cross-pipeline merge happens in the correlation engine within a sliding window after the slowest pipeline reports. Don&apos;t promise sub-minute for the SIEM path; do promise sub-minute for the EDR-direct path.
    
Because each pipeline names hosts in its own grammar. MDE uses a `DeviceId` (a Microsoft-generated GUID). Sentinel uses `Computer` (the hostname as Windows reports it). MDC uses the Azure `resourceId` for the underlying VM. Microsoft Entra ID uses a directory `ObjectId`. The Defender XDR correlation engine normalizes these where it can [@ms-learn-xdr-correlation] [@ms-learn-sentinel-entities], but in raw KQL queries you have to `join` across the identifier spaces explicitly. The `IdentityInfo` and `DeviceInfo` tables are the join helpers; the entity-resolution problem from §8 is what makes this non-trivial.
    
**March 31, 2027** (extended from the original July 1, 2026 target). After that date, Microsoft Sentinel can only be accessed via the unified Defender portal at `security.microsoft.com` [@ms-learn-sentinel-azure-portal-retiring] [@helpnetsec-sentinel-defender-timeline]. Customers with custom dashboards, automation, or ARM templates targeting the Azure-portal Sentinel surface need to plan migration. The underlying Log Analytics workspace and KQL queries do not change; the analyst UI does.
    
It depends on where your telemetry lives. **Sentinel scheduled rules** read from Log Analytics tables (`Event`, `SecurityEvent`, `Syslog`, custom tables) and are the right answer when your detection covers data ingested via DCRs or Sentinel connectors. **Defender XDR Custom Detections** read from the advanced-hunting schema (`DeviceProcessEvents`, `DeviceFileEvents`, `EmailEvents`, etc.) and are the right answer when your detection covers MDE / Defender for Office / Defender for Identity-native telemetry [@ms-learn-sentinel-custom-detections] [@ms-learn-advanced-hunting]. The two are not interchangeable; the field names and result-size caps differ. A common operational pattern is &quot;Sentinel for everything Sysmon and third-party, Custom Detections for everything MDE-native.&quot;
    
Partially, and only by hand. Sentinel automation rules invoke Azure Logic Apps playbooks, and those playbooks can call the Microsoft Defender for Cloud REST API directly to take actions like creating an assessment or (with limited surface area) acknowledging an alert [@ms-learn-sentinel-logic-apps-playbooks] [@ms-learn-mdc-assessments-rest] [@ms-learn-mdc-custom-recs]. There is no first-class &quot;MDC alert action&quot; Logic Apps connector with the same breadth as the MDE connector. Customers building bidirectional Sentinel-MDC response automation write HTTP-action playbooks against the MDC REST API and accept that the integration is less native than the MDE side.
  
&lt;p&gt;&amp;lt;StudyGuide
  terms={[
    &apos;SIEM&apos;,
    &apos;SOAR&apos;,
    &apos;EDR&apos;,
    &apos;XDR&apos;,
    &apos;CSPM&apos;,
    &apos;CWPP&apos;,
    &apos;MCSB&apos;,
    &apos;KQL&apos;,
    &apos;Log Analytics workspace&apos;,
    &apos;Azure Monitor Agent (AMA)&apos;,
    &apos;Data Collection Rule (DCR)&apos;,
    &apos;ProcessGuid&apos;,
    &apos;Sentinel scheduled analytics rule&apos;,
    &apos;Entity mapping&apos;,
    &apos;Defender XDR correlation engine&apos;,
  ]}
  questions={[
    &apos;Trace a single Sysmon ProcessCreate event through the six hops named in §6. At each hop, state the artifact that does the work and the most common silent-failure mode.&apos;,
    &apos;Why do MDC posture findings not appear in Defender XDR incidents, while MDC CWPP alerts do? Cite the architectural reason, not just the documented behaviour.&apos;,
    &apos;You inherit a Sentinel deployment whose Sysmon detections &quot;used to work.&quot; The Event table is empty for half the inventory. Name three places to check, in priority order.&apos;,
    &apos;Compare Sentinel scheduled rules and Defender XDR Custom Detections along three axes: schema read, latency, governance. When would you choose each?&apos;,
    &apos;A SOC analyst says &quot;the unified incident graph is missing alerts from our European workspace.&quot; What is the most likely cause, and what is the workaround?&apos;,
    &apos;Explain why the AMA DCR streams value &quot;Microsoft-Event&quot; vs &quot;Microsoft-WindowsEvent&quot; vs a typo all produce different outcomes, and what validation step catches the silent miss.&apos;,
  ]}
/&amp;gt;&lt;/p&gt;
</content:encoded><category>microsoft-sentinel</category><category>defender-for-cloud</category><category>defender-xdr</category><category>sysmon</category><category>kql</category><category>soc-architecture</category><category>cspm</category><category>cwpp</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></channel></rss>