Sysmon Event IDs 19, 20 and 21 all record WMI activity — which one shows persistence is armed?
answer
- three objects, one of them does the wiring
- a trigger with nothing attached does nothing
- filter, consumer, binding
- ConsumerToFilter is event ID 21
- registration is not execution
basics
~20 sEvent ID 21, the WmiEventConsumerToFilter binding. A filter (19) is a trigger with nothing attached and a consumer (20) is an action nothing calls; only the binding wires them together. Even then, 21 proves the subscription was registered, not that it has ever run.
solid answer
~50 sSysmon splits a WMI permanent event subscription across three records: **19** logs a `WmiEventFilter` — the WQL query that decides when to fire; **20** logs a `WmiEventConsumer` — the action, carrying its `Type` and `Destination`, which for a command-line consumer is the command it will run; and **21** logs the `WmiEventConsumerToFilter` binding that joins one to the other. Until the binding exists, the persistence is inert, so a rule promoted from a hunt should key on 21. The catch is that 21 names the consumer and filter but does not carry the consumer's command line — that lives on the 20 record — so a usable alert has to join or enrich across the two. And all three are registration events: a created binding tells you a subscription exists, never that its trigger has fired or that its payload has executed.
code
text · 14 linesEvent ID 20 - WmiEvent (WmiEventConsumer activity detected)
Operation: Created
User: CORP\svc-patch
Name: HealthCheckConsumer
Type: Command Line
Destination: wscript.exe //B C:\ProgramData\HealthCheck\hc.vbs
...
Event ID 21 - WmiEvent (WmiEventConsumerToFilter activity detected)
Operation: Created
User: CORP\svc-patch
Consumer: CommandLineEventConsumer.Name="HealthCheckConsumer"
Filter: __EventFilter.Name="HealthCheckFilter"
...go deeper
Know that a WMI event subscription needs three parts and that Sysmon logs them as separate records, with the binding being the one that makes it live. Be able to name filter, consumer and binding without mixing them up.
Explain the mechanics: which record carries the WQL query, which carries the command line, and why a rule anchored on the binding still has to reach the consumer record to produce a usable alert.
Show the discipline of separating what the records support from what they do not. A created binding is registration, not execution, and corroborating execution means going to process telemetry with the provider host as parent.
Weigh the maintenance cost of a correlated rule against a simpler anchor plus a documented pivot, and be explicit that a small team should choose the cheaper form deliberately rather than build a fragile correlation nobody can debug.
## What a WMI permanent event subscription is made of Windows Management Instrumentation supports subscriptions that survive reboots and run without a logged-on user, which is why attackers use them for persistence (ATT&CK technique `T1546.003`). Three objects are involved, normally in the `root\subscription` namespace: - an **event filter** (`__EventFilter`) — a WQL query describing the condition, for example a timer firing or a process starting; - an **event consumer** — the action, most commonly `CommandLineEventConsumer` (runs a command) or `ActiveScriptEventConsumer` (runs script text); - a **binding** (`__FilterToConsumerBinding`) — the object that says *when this filter fires, run that consumer*. A filter with no binding never triggers anything. A consumer with no binding is never invoked. **The binding is the moment the persistence becomes live.** ## How Sysmon reports each part Sysmon mirrors that structure across three event IDs: | Sysmon ID | What it records | Useful fields | |---|---|---| | 19 | WmiEventFilter activity | `Operation`, `User`, `EventNamespace`, `Name`, `Query` | | 20 | WmiEventConsumer activity | `Operation`, `User`, `Name`, `Type`, `Destination` | | 21 | WmiEventConsumerToFilter activity | `Operation`, `User`, `Consumer`, `Filter` | `Operation` is `Created` or `Deleted`, so deletions appear too — which matters, because a subscription that is planted, used and removed leaves a trail of 19/20/21 records and no surviving object on disk. ## Why the promoted rule keys on 21 When a hunt turns up hand-found WMI persistence and you are converting it into a maintainable rule, 21 is the highest-signal anchor: - it is the record that means *this thing can now run*, so it has the tightest relationship to the behaviour you care about; - it is comparatively rare in most estates, which matters when a small team is deciding whether it can afford another rule; - filters and consumers are created in bulk by legitimate tooling and, on their own, are not evidence of anything. A rule keyed on 19 alone will fire on every management agent that registers a query and tell you nothing about whether an action is attached. ## What the binding record does not tell you This is where candidates most often over-claim. A 21 record with `Operation: Created` proves that **a binding was registered**. It does not prove: - that the filter's condition has ever been satisfied; - that the consumer's command or script has ever executed; - that the subscription is malicious — approved software creates bindings constantly; - anything about subscriptions that already existed before Sysmon started reporting on that host. Execution, if it happened, shows up elsewhere: a process-creation record whose parent is `WmiPrvSE.exe` is the classic corroboration, since consumer-launched processes are spawned by the WMI provider host rather than by the original creator. ## The join problem the promotion has to solve The binding record identifies its two halves by name, in a form like `CommandLineEventConsumer.Name="HealthCheckConsumer"`. It does not repeat the consumer's `Destination`. So a rule that alerts purely on 21 produces an alert saying *a binding to a consumer called HealthCheckConsumer was created on HOST-1421* — accurate, and almost unusable, because the single most decision-relevant field, what the consumer actually runs, is on the 20 record. That gives you two workable shapes. Either the rule correlates 21 with the matching 20 by consumer name within a short window and carries the `Destination` into the alert, or it alerts on 21 and the triage note tells the analyst to pull the corresponding 20 record as the first pivot. The correlated form is a better alert and a heavier rule to maintain; the simpler form is cheaper and pushes one lookup onto the analyst. On a two-person detection team that trade is worth making consciously rather than by accident. ## Practical reading of a record pair Given a 20 and a 21 seconds apart under the same account, you can state: a subscription named X was fully assembled at time T by account A, and its action is command Y. You cannot state that Y ran, when it will run, or whether A intended harm. Keeping those two lists separate — what the records support and what they do not — is the difference between an escalation that holds up and one that collapses on the first question.
- Why is a Sysmon Event ID 21 record on its own a poor alert payload?Because it identifies the consumer only by name. The command or script the consumer will run lives on the Event ID 20 record, so an alert built from 21 alone omits the field that decides the verdict. Either correlate the two by consumer name within a short window and carry the `Destination` into the alert, or make pulling the 20 record the first documented pivot.
- What would corroborate that a WMI consumer actually executed?Process-creation telemetry, not the WMI records. A consumer-launched process is spawned by the WMI provider host, so a process-create record with `WmiPrvSE.exe` as the parent image, close in time and matching the consumer's command line, is the usual corroboration. Without it you can only claim a subscription exists.
- Sysmon logs Event ID 19 for a filter created by a monitoring agent. Is that a finding?No. A filter is a WQL condition with nothing attached; on its own it cannot cause anything to happen, and management tooling registers them routinely. It becomes interesting only when a binding attaches it to a consumer, or when the filter query itself is unusual enough to be worth a look during a hunt.
saying these in an interview costs you the question
- Treats a filter record alone as evidence of persistence
- Says a binding record proves the payload executed
- Cannot say which of 19, 20, 21 carries the command line
- Assumes the binding record repeats the consumer's destination
- Ignores that Operation can be Deleted as well as Created