Skip to content
ADMIN
FUTURE
Главная страница » Sysmon + WEF + Wazuh: From Windows Events to Compromise Signals
FIELD NOTES / 23.10.2026

Sysmon + WEF + Wazuh: From Windows Events to Compromise Signals

Maksim Shapovalov21 min read
Sysmon, WEF and Wazuh: events, delivery validation and investigation

Build an investigation route, not another archive

A suspicious process runs, Windows records it, yet the administrator sees nothing. Let’s build Sysmon → WEF → Wazuh and validate every stage rather than the agent’s green status.

Hello, colleagues. I’m Maksim, a systems administrator. I want signals that answer specific questions: who launched remote management, why rphost created a shell, what accessed LSASS and who changed the sensor itself. Another question matters just as much: will the record reach us after its source has been temporarily disconnected?

We will start with a small pilot, not a promise to detect everything: one or two domain computers, a dedicated Windows Event Collector, its Wazuh agent and eight local rules extending the stock ruleset. We will retain process context, collect selected connections and evidence of logging interference, then trace a harmless command to the manager.

The example targets Windows Server 2022 and Windows PowerShell 5.1, Sysmon15.22 and rule parents from Wazuh4.14.0 source. These are selected versions, not a latest-version claim. Check schema acceptance with the installed Sysmon binary and record Windows patches and the actual ruleset before piloting. References checked23October2026.

Download the configuration and validation kit: Sysmon XML, two WEF subscriptions, an ossec.conf fragment, eight rules, two PowerShell helpers and a local validator. The configuration and expected outcomes are explained below.

Architecture: where events and source identity can disappear

Sysmon writes Microsoft-Windows-Sysmon/Operational at the source; Windows produces Security and System events. WEF selects records and delivers them into ForwardedEvents on WEC. A Wazuh agent reads that channel as eventchannel; the manager decodes records and applies rules. Indexing and notification are further stages requiring validation.

Sysmon, WEF and Wazuh chain with separate source and delivery checks
Three distinct validation stages. Preserve original computer identity separately from the WEC agent identity.

Keep three identities distinct: the source computer authenticating to WEC, the source-side service context reading logs, and the Wazuh agent identifying the collector. Consequently, agent.name is not every original host’s name. Rules use win.system.computer; indexed documents expose data.win.system.computer. The ForwardedEvents destination must not replace the event’s original System/Channel value.

Inspect actual XML and decoder Phase2. Otherwise hundreds of source hosts can be attributed to one WEC, and apparent cross-host repetition becomes repetition from one agent. The providerName, channel and computer fields come from the event’s system section: Wazuh v4.14.0 decoder.

One collector agent replaces this forwarded-event ingestion path only. It does not install endpoint FIM, SCA, inventory, vulnerability detection or active response on remote sources. Consider endpoint agents separately when those capabilities are required. WEC itself is critical infrastructure: observe availability, queues and disk capacity too.

The minimum includes context, not just existing alerts

The obvious solution collects everything. The opposite extreme retains only records already producing alerts. That leaves little process ancestry to investigate: useful predecessors were discarded before the incident.

I distinguish detection signals from investigation context. This pilot retains process creation and narrows more expensive classes by purpose. Expand scope and choose retention after measuring the workload. The selection does not cover every ATT&CK technique or establish sufficient protection.

Source / IDPurposeInference limit
Sysmon1Process tree, command, image, ProcessGuidA command can be legitimate; one record is not compromise
Sysmon3, selected imagesProcess-to-destination context, including internal trafficNo content decryption or RMM ownership verdict
Sysmon10 → lsass.exeIdentify access to a sensitive processAccess does not prove memory reading or stolen passwords
Sysmon4,16,255Sensor stop, configuration change and errorsThe final event may never leave the source
Security4698,4702Task creation and modificationNeeds advanced auditing; tasks can be legitimate
Security5136AD object changes on a DCNeeds auditing/SACL; not complete SYSVOL file auditing
Security1102; System104,7045Security/other-log clearing and service installationRequires actor and maintenance context

An RMM launch does not establish unauthorized management; LSASS access does not establish stolen passwords; a new service is not necessarily malicious. A useful detection produces an investigation queue with source, process, actor and maintenance context rather than an automatic verdict.

Wazuh already ships detections. A level0 Sysmon classifier does not make the entire ruleset alert-free: rule61620, for example, has level12. Our rules extend rather than replace that coverage. Inspect the Sysmon ruleset Wazuh v4.14.0 instead of relying on IDs from someone else’s installation.

Level1. Sysmon: keep ancestry and internal-network visibility

Start with one workstation and one application server. Collect process creation across that pilot to retain parent, command and ProcessGuid context. Select network events for AnyDesk, TeamViewer, client32 and rphost, and LSASS access for source/GrantedAccess investigation. These names are neither a complete RMM inventory nor protection against every renamed binary.

Do not globally exclude internal addresses. Lateral activity and RMM using an internal intermediary would disappear with RFC1918 exclusions. Reduce volume through pilot scope and process selection first, then evidence-backed exceptions.

<Sysmon schemaversion="4.82">
  <HashAlgorithms>SHA256</HashAlgorithms>
  <EventFiltering>
    <!-- All process creation on the PILOT; retain parent/command-line context. -->
    <RuleGroup name="Process context" groupRelation="or">
      <ProcessCreate onmatch="exclude" />
    </RuleGroup>
    <!-- Internal connections deliberately remain visible. -->
    <RuleGroup name="Selected network" groupRelation="or">
      <NetworkConnect onmatch="include">
        <Image condition="end with">\AnyDesk.exe</Image>
        <Image condition="end with">\TeamViewer.exe</Image>
        <Image condition="end with">\client32.exe</Image>
        <Image condition="end with">\rphost.exe</Image>
      </NetworkConnect>
    </RuleGroup>
    <RuleGroup name="LSASS access context" groupRelation="or">
      <ProcessAccess onmatch="include">
        <TargetImage condition="end with">\lsass.exe</TargetImage>
      </ProcessAccess>
    </RuleGroup>
    <!-- Explicitly disable selected high-volume/unneeded classes in this pilot. -->
    <ProcessTerminate onmatch="include" />
    <ImageLoad onmatch="include" />
    <DriverLoad onmatch="include" />
    <CreateRemoteThread onmatch="include" />
    <RawAccessRead onmatch="include" />
    <FileCreate onmatch="include" />
    <RegistryEvent onmatch="include" />
    <FileCreateStreamHash onmatch="include" />
    <PipeEvent onmatch="include" />
    <WmiEvent onmatch="include" />
    <DnsQuery onmatch="include" />
  </EventFiltering>
</Sysmon>

Schema4.82 comes from Microsoft’s published example. Schema and binary versions are distinct: -? config displays installed configuration information and -s displays its schema. Generic XML parsing does not establish Sysmon acceptance. Explicit groupRelation avoids relying on implicit grouping, but verify mixed-field and nested-rule behavior in the actual version. Sysmon — Microsoft Learn.

Warning: installation adds a service/driver; replacing XML can remove existing coverage. Preserve the original deployment file, binary signature/version and service state. The -c display is useful inspection, not an assured replacement for the original rollback XML. Use an official binary only on the approved pilot.

# Windows Server 2022 / Windows PowerShell 5.1, approved elevated pilot console.
# Inspect first. Keep the exact previous deployment XML before applying a change.
.\Sysmon64.exe -? config
.\Sysmon64.exe -s
.\Sysmon64.exe -c
# First installation ONLY after approval and review of the supplied XML:
.\Sysmon64.exe -accepteula -i .\sysmon-minimal.xml
# Existing deployment: use -c instead of -i, with a preserved rollback config.
# .\Sysmon64.exe -c .\sysmon-minimal.xml
Get-Service Sysmon64
wevtutil.exe qe Microsoft-Windows-Sysmon/Operational /c:3 /rd:true /f:xml

Expect accepted configuration, a running service and Operational records. ID16 concerns configuration changes and ID4 service state; both are not guaranteed after every invocation. Preserve configuration and observed output with the pilot version. Roll back an update using the previous XML and -c. Uninstalling a pre-existing sensor is not a universal rollback.

Level2. WEF starts with source identities and reading authority

Use source-initiated subscriptions within a working domain. A dedicated pilot-OU GPO supplies the collector FQDN. Configure Computer Configuration → Administrative Templates → Windows Components → Event Forwarding → Configure target Subscription Manager with Server=http://wec01.example.com:5985/wsman/SubscriptionManager/WEC,Refresh=60. Replace the example FQDN with the approved collector.

Refresh=60 concerns subscription-configuration refresh, not guaranteed one-minute event delivery. The XML uses MinLatency; Microsoft describes a30-second batch timeout for that mode. Queues and outages add their own delays. WEF performance guidance.

With domain Kerberos authentication, WinRM HTTP can protect message content without TLS. That is not permission to enable Basic or AllowUnencrypted. Check naming, time, trust and actual authentication independently. Non-domain or different-trust deployments need their own HTTPS/certificate design rather than a mechanical copy of this pilot.

Security reading authority belongs at the source. For a member server, inspect NETWORK SERVICE membership in Event Log Readers or approved channel access. Adding that identity only on WEC cannot repair remote Security access. Treat DCs separately; do not apply local-group automation to them. Microsoft source-initiated setup.

Inspect-WefPilot.ps1 reads state using Source/Collector roles. New-WefPilotFiles.ps1 only generates SID-specific XML and supports -WhatIf. Neither silently enables auditing, changes ACLs or opens firewall exposure. Inspection and mutation deliberately remain separate.

Collector and subscriptions: authorize only the pilot computers

Before WEC setup, record existing listeners, services, firewall and log settings. Restrict collector WinRM exposure to approved sources. Quickconfig changes services and may affect listeners/firewall; it is not read-only inspection. Run from an approved pilot-WEC administrative console with a prepared return path.

# Isolated, approved WEC pilot; elevated Windows PowerShell 5.1.
# Save existing WinRM/WEC/firewall state and limit the listener to pilot sources FIRST.
winrm.exe quickconfig -q
if ($LASTEXITCODE -ne 0) { throw 'WinRM setup failed' }
wecutil.exe qc /q
if ($LASTEXITCODE -ne 0) { throw 'WEC setup failed' }
.\Inspect-WefPilot.ps1 -Role Collector
# Save exact old log settings before resizing; 1 GiB is a PILOT assumption.
wevtutil.exe gl ForwardedEvents
wevtutil.exe sl ForwardedEvents /ms:1073741824
if ($LASTEXITCODE -ne 0) { throw 'Log resizing failed' }

One GiB of ForwardedEvents is an initial assumption, not a capacity calculation. Never shrink an existing larger log merely to match the example. Preserve its original setting and assess retention before any size-reducing rollback.

The main subscription follows. Do not import it with the SID placeholder intact:

<Subscription xmlns="http://schemas.microsoft.com/2006/03/windows/events/subscription">
  <SubscriptionId>AF-Sysmon-Pilot</SubscriptionId>
  <SubscriptionType>SourceInitiated</SubscriptionType>
  <Description>Admin Future pilot: process, selected network, LSASS and sensor state</Description>
  <Enabled>true</Enabled>
  <Uri>http://schemas.microsoft.com/wbem/wsman/1/windows/EventLog</Uri>
  <ConfigurationMode>MinLatency</ConfigurationMode>
  <Query><![CDATA[
    <QueryList><Query Id="0" Path="Microsoft-Windows-Sysmon/Operational">
      <Select Path="Microsoft-Windows-Sysmon/Operational">*[System[(EventID=1 or EventID=3 or EventID=4 or EventID=10 or EventID=16 or EventID=255)]]</Select>
    </Query></QueryList>
  ]]></Query>
  <ReadExistingEvents>false</ReadExistingEvents>
  <TransportName>http</TransportName>
  <ContentFormat>RenderedText</ContentFormat>
  <Locale Language="en-US" />
  <LogFile>ForwardedEvents</LogFile>
  <AllowedSourceDomainComputers>O:NSG:NSD:(A;;GA;;;__PILOT_GROUP_SID__)</AllowedSourceDomainComputers>
</Subscription>

The second downloadable subscription selects Security4698,4702,5136,1102 and System7045,104. Both use ReadExistingEvents=false to start with new records rather than uncontrolled historical replay. RenderedText is an initial pilot choice. Events is more compact but is not a mandatory Wazuh decoder format; validate either across the complete route.

Create an AD group of authorized computer accounts and obtain its real SID. The helper requires a domain SID and a new output directory, but cannot validate the group’s membership for you. A syntactically valid SID does not repair a group containing the wrong principals.

# Replace the SID with YOUR approved AD group of pilot computer accounts.
.\New-WefPilotFiles.ps1 -PilotGroupSid 'S-1-5-21-111-222-333-4444' -OutputDirectory C:\WEF-Pilot-Generated -WhatIf
.\New-WefPilotFiles.ps1 -PilotGroupSid 'S-1-5-21-111-222-333-4444' -OutputDirectory C:\WEF-Pilot-Generated
wecutil.exe es
# Import only if these IDs do NOT already exist; never overwrite another subscription.
wecutil.exe cs C:\WEF-Pilot-Generated\wef-sysmon.xml
if ($LASTEXITCODE -ne 0) { throw 'Sysmon subscription import failed' }
wecutil.exe cs C:\WEF-Pilot-Generated\wef-security-system.xml
if ($LASTEXITCODE -ne 0) { throw 'Security subscription import failed' }
wecutil.exe gs AF-Sysmon-Pilot
wecutil.exe gr AF-Sysmon-Pilot
wecutil.exe gr AF-Security-Pilot

Before cs, use es to establish that these subscription IDs are absent. Following import, gs describes configuration and gr reports source status after GPO application and connection. Subscription existence does not establish access to every selected channel. Syntax: wecutil.

Security events cannot be enabled by XPath alone

WEF does not generate missing audit records. Events4698/4702 require Other Object Access Events with appropriate success auditing. Read auditpol /get /category:* first, then approve a precise pilot-policy change. Auditpol names are localized; enabling every category is not required.

Event5136 concerns AD object changes on a DC and requires Directory Service Changes plus appropriate object SACLs. A directory GPC modification and a GPT file change in SYSVOL are distinct audit surfaces. Do not describe a5136 subscription as comprehensive GPO monitoring. Add appropriate file/permission auditing and evidence of client application when that investigation requires it.

Security clearing produces1102; System104 does not replace it. Wazuh4.14.0 contains stock rule60117 for1102,60228 for4698 and60229 for5136. Use the real installed branch rather than assuming every release shares an ID list. Wazuh4.14.0 Security rules, task auditing, directory-change auditing.

Start with member computers. Add DCs after reviewing volume, channel permissions and the approved SACL policy, not as interchangeable Windows hosts. Absence of5136 on an ordinary member server does not establish WEF failure.

Level3. Wazuh: read ForwardedEvents and observe the queue

The collector needs an already enrolled, healthy Wazuh agent. Add the ForwardedEvents localfile to its existing ossec.conf and merge client_buffer with the existing section. Never replace the complete configuration with this fragment: connection, groups and other settings would disappear. Avoid duplicate sections and duplicate collection of the same channel.

<!-- MERGE into existing ossec_config on the WEC agent. Do not replace the file. -->
<ossec_config>
  <localfile>
    <location>ForwardedEvents</location>
    <log_format>eventchannel</log_format>
  </localfile>
  <client_buffer>
    <disabled>no</disabled>
    <queue_size>20000</queue_size>
    <events_per_second>500</events_per_second>
  </client_buffer>
</ossec_config>

queue_size is measured in events; events_per_second in events per second. Documented defaults are5000 and500. The example raises queue capacity to20000 but retains500EPS. This does not “speed up the SIEM.” The collector agent has other inputs and the manager has additional queues and limits. client_buffer, agent queue and antiflooding.

Apply changes in an approved window with the original ossec.conf retained and post-restart service verification. Eventchannel names a Windows channel; it is not an instruction to submit an arbitrary XML file. Validate WEF format and decoded fields separately. Wazuh Windows eventchannel collection.

A larger queue absorbs a finite burst. Sustained input above output still fills it. Observe antiflooding signals and delivery cessation; otherwise increasing capacity merely postpones loss.

Eight local rules with explicit parents

Install adminfuture_rules.xml as a separate custom file under /var/ossec/etc/rules/ on the manager. Preserve local_rules.xml and vendor rules. The100000–120000 custom range does not guarantee these particular1105xx IDs are unused locally.

RuleWazuh4.14.0 parentSignal meaning
110501 / 110502sysmon_event1 → 110501RMM name / higher-priority execution path; verify owner
110510sysmon_event1Server process spawned an interpreter/tool
110511sysmon_event3Selected-connection context, not a verdict
110520sysmon_event_10LSASS access requiring investigation, not proven dumping
11054260117Raise priority of the stock Security-clear signal
110543sysmon_event4Sysmon stopped
11054461644 (sysmon_event_16)Sysmon configuration changed

Notice the underscores: sysmon_event_10 and sysmon_event_16 differ from sysmon_event1 and sysmon_event3. Event16 uses the actual61644 parent. A plausible but nonexistent group name can break detection even when its regex is correct. Parents are pinned to tag4.14.0, not moving master.

<!-- Wazuh 4.14.0 parents. Check IDs against the INSTALLED complete ruleset. -->
<group name="adminfuture,windows,">
  <rule id="110501" level="7">
    <if_group>sysmon_event1</if_group>
    <field name="win.eventdata.image" type="pcre2">(?i)\\(?:AnyDesk|TeamViewer|client32)\.exe$</field>
    <description>AF: RMM process on $(win.system.computer); verify deployment and management owner</description>
    <mitre><id>T1219</id></mitre>
  </rule>
  <rule id="110502" level="9">
    <if_sid>110501</if_sid>
    <field name="win.eventdata.image" type="pcre2">(?i)^[A-Z]:\\(?:Users\\|ProgramData\\|Windows\\Temp\\|PerfLogs\\|\$Recycle\.Bin\\)</field>
    <description>AF: RMM from a review-priority path on $(win.system.computer); establish actual ACLs</description>
  </rule>
  <rule id="110510" level="12">
    <if_group>sysmon_event1</if_group>
    <field name="win.eventdata.parentImage" type="pcre2">(?i)\\(?:rphost|ragent|rmngr|w3wp|httpd|nginx|sqlservr|php-cgi)\.exe$</field>
    <field name="win.eventdata.image" type="pcre2">(?i)\\(?:cmd|powershell|pwsh|certutil|mshta|wscript|cscript)\.exe$</field>
    <description>AF: server process spawned an interpreter/tool on $(win.system.computer); investigate integration versus abuse</description>
  </rule>
  <rule id="110511" level="5">
    <if_group>sysmon_event3</if_group>
    <field name="win.eventdata.image" type="pcre2">(?i)\\(?:AnyDesk|TeamViewer|client32|rphost)\.exe$</field>
    <description>AF: selected-process connection on $(win.system.computer); context, not compromise proof</description>
  </rule>
  <rule id="110520" level="7">
    <if_group>sysmon_event_10</if_group>
    <field name="win.eventdata.targetImage" type="pcre2">(?i)\\lsass\.exe$</field>
    <description>AF: process accessed LSASS on $(win.system.computer); inspect source, access mask and call trace</description>
  </rule>
  <rule id="110542" level="12">
    <if_sid>60117</if_sid>
    <description>AF: Security log cleared on $(win.system.computer); preserve available evidence</description>
  </rule>
  <rule id="110543" level="10">
    <if_group>sysmon_event4</if_group>
    <field name="win.eventdata.state" type="pcre2">(?i)^Stopped$</field>
    <description>AF: Sysmon stopped on $(win.system.computer); distinguish maintenance and interference</description>
  </rule>
  <rule id="110544" level="5">
    <if_sid>61644</if_sid>
    <description>AF: Sysmon configuration changed on $(win.system.computer); verify approved change</description>
  </rule>
</group>

PCRE2 sees decoded field values. Two backslashes in an XML regex represent one Windows-path separator; displayed JSON escaping belongs to another layer. Do not replace separators with arbitrary punctuation just to match a UI copy: that broadens the predicate to unrelated strings.

We checked field predicates independently. Validate actual parent hierarchy, competing-rule order and final alerts on the installed Wazuh live-event route. XML parsing, PCRE2 and logtest over transformed JSON do not substitute for an end-to-end eventchannel test. Reference: Wazuh rule syntax.

Investigate signals without creating exception-shaped gaps

Rule110510 means a server process spawned an interpreter or tool. Review the child command, identity, ParentProcessGuid/ProcessGuid, timing and integration context. For rphost, investigate external processing and application authority; for w3wp, examine publication and web evidence. “Servers never launch cmd” is false: legitimate integrations may do so and need identification.

Rule110501 identifies an RMM-like filename, not ownership of its management plane. Program Files does not establish authorization, a vendor signature does not identify the tenant owner, and an attacker may use the same legitimate binary hash. Therefore this kit has no global “approved hash, ignore everything” suppression. Scope exceptions by purpose, hosts, deployment, management owner and review date.

Rule110502 prioritizes selected Users/ProgramData/Temp-style paths. They are review candidates, not proof that every user can write there; actual ACLs vary. For110520, inspect sourceImage, GrantedAccess and available CallTrace. Security software and approved maintenance can also access LSASS.

Do not describe different_field=win.system.computer as a count of ten distinct hosts. Many events from A plus one from B are not ten different computers. If the requirement is distinct hosts by taskName, implement and test an explicit unique-value aggregation and time window. Otherwise the proposed mass-GPO detection rests on incorrect counting.

Install rules: validate before restarting

Preserve current custom manager configuration. The next block requires Bash, systemd and ripgrep; missing rg stops it rather than skipping ID review. Check conflicts across the complete installed ruleset and confirm real groups/parents. An example ID is not a compatibility guarantee for another release or an already customized installation.

Warning: restarting the Wazuh manager affects event processing. Use an approved window and validate first. On error, restore prior custom-file state rather than repairing syntax while the service is down. Match approved custom-rule ownership/permissions; never use chmod777.

# Linux Wazuh MANAGER only. Separate custom rule file; retain original configuration.
command -v rg >/dev/null || { printf '%s\n' 'ripgrep is required for these review commands; stop here.' >&2; exit 2; }
# Review all installed IDs, not just local_rules.xml.
rg -n 'id="(110501|110502|110510|110511|110520|110542|110543|110544)"' /var/ossec/etc/rules /var/ossec/ruleset/rules
# No matches before installation is expected. Check the pinned parents on YOUR version:
rg -n 'sysmon_event_10|sysmon_event_16|id="60117"|id="61644"' /var/ossec/ruleset/rules
# Place the reviewed kit file at /var/ossec/etc/rules/adminfuture_rules.xml.
# Match approved ownership/permissions of existing custom rules; do not use chmod 777.
# Only after successful validation AND a scheduled change with rollback:
if /var/ossec/bin/wazuh-analysisd -t; then
    systemctl restart wazuh-manager && systemctl is-active wazuh-manager
else
    printf '%s\n' 'Validation failed. Restore the previous custom rule state; DO NOT restart.' >&2
fi

Successful analysisd -t establishes configuration/loading validation, not every behavioral scenario. Following restart, inspect service state, ossec.log, real ingestion and decoding. Where active response exists, separate new rules from automatic actions initially: a diagnostic pilot must not isolate a server merely because of a filename match.

Stock and custom rules may compete for the final branch. Check the final rule for positive and negative actual events rather than merely finding the desired ID in XML.

A harmless canary checks delivery, not compromise

Activate subscriptions first. ReadExistingEvents=false is not intended to replay records created before connection. On the source, launch a harmless nested command; it creates no task, installs no RMM and does not access LSASS.

# SOURCE, Windows PowerShell 5.1: harmless process-creation canary; no scheduled task.
cmd.exe /d /c "powershell.exe -NoProfile -NonInteractive -Command Write-Output 'AF-WEF-CANARY'"
$Since = (Get-Date).AddMinutes(-10)
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Sysmon/Operational'; Id=1; StartTime=$Since} | Where-Object { $_.ToXml().Contains('AF-WEF-CANARY') } | Select-Object -First 3 TimeCreated, Id, MachineName, RecordId

On WEC, perform this separate read check; do not launch the canary again on the collector:

# COLLECTOR only, Windows PowerShell 5.1; read after source canary and delivery.
$Since = (Get-Date).AddMinutes(-10)
Get-WinEvent -FilterHashtable @{LogName='ForwardedEvents'; Id=1; StartTime=$Since} | Where-Object { $_.ToXml().Contains('AF-WEF-CANARY') } | Select-Object -First 3 TimeCreated, Id, MachineName, RecordId

Find ID1 with the marker in CommandLine at the source, then trace the same chain at WEC. Compare original computer, time and ProcessGuid, not event number alone. RecordId helps local inspection but is not a global identifier and can reset following a cleared log.

This canary has no dedicated rule among the eight. No1105xx alert is required, and its absence does not establish delivery loss. Observe raw manager events in a constrained test window. Temporarily enabling logall_json in the existing global section requires disk/access/retention review; restore its prior value afterward and verify the service. Do not create an indefinite archive of sensitive commands for one check. Wazuh event logging.

# Wazuh manager, approved temporary raw-event capture window; jq must be installed.
# Replace the source name. Use the real full_log string, not the entire archive wrapper.
jq -r 'select(.data.win.system.computer == "LAB-WS01.example.com") | select(.data.win.system.eventID == "1") | select(.full_log | contains("AF-WEF-CANARY")) | .full_log' /var/ossec/logs/archives/archives.json
/var/ossec/bin/wazuh-logtest
# Paste ONE actual full_log line and inspect Phase 2: normalized JSON may use decoder json.
# This is NOT native Windows eventchannel replay or proof of stock-parent matching.
# Do NOT change rule 60000 on production to force a logtest match.
# This canary has NO dedicated custom detection rule: no 1105xx alert is required.

Important boundary: archived full_log may already contain normalized JSON. Ordinary logtest can then report decoder json rather than reproduce the special Windows eventchannel processing used by stock parents. Fields and matching predicates do not prove the same rule will fire on the live route. Wazuh maintainers discuss this limitation; tag4.14.0 exposes the separate path in winevtchannel.c. Never change production rule60000 merely to obtain a successful logtest result. Establish final rule IDs and negative outcomes through an isolated real agent route, not attacks on production.

Capacity: a buffer is not a sizing or observability plan

Size logs from measured ingress and the delivery interruption you must tolerate. WEF uses the source log as its outage buffer. When records are overwritten before delivery, the collector receives no notification identifying that gap. This does not mean all WEF errors are silent: its Operational channel records states, warnings and failures. Microsoft: WEF для обнаружения вторжений.

For example,256MiB at a source and1GiB at WEC are pilot assumptions, not blanket assignments. Assuming2kB/event and100EPS gives720MB/hour before overhead, representation differences and other channels. This is arithmetic, not a measured collector result.

A20000-event queue with900EPS ingress and500EPS egress would theoretically fill in50seconds from empty. Different rates invalidate that interval. More capacity cannot repair sustained throughput deficit.

Measure source, WEC, agent and manager separately: events/bytes per window, actual latency, occupancy, reconnect and catch-up. There is no universal3000EPS collector guarantee here. Test delayed delivery and retention separately after interruption; a healthy-network canary cannot establish them.

What was checked, and how to locate a gap

The kit includes reproducible local validation: five XML files and embedded QueryList documents parse; eight IDs are unique; fourteen positive/negative field-predicate checks run using real PCRE2 through ripgrep. Those checks were actually performed while preparing this article.

# LOCAL validation machine: Python 3 and ripgrep built with PCRE2 are required.
python3 validate-kit.py
# Expected: 5 XML files + embedded queries; 8 unique IDs; 14 PCRE2 checks passed.
# This is NOT a Wazuh, WEF, PowerShell or Sysmon runtime test.

A complete Windows/WEF/Wazuh lab, Sysmon’s own XML acceptance, PowerShell execution, full rule-tree testing and load testing were not performed. Local validation does not make this a production-validated detection package. Deployment requires your pilot and end-to-end evidence.

SymptomInspectAvoid
No source canaryConfig acceptance, ID1, time window and reading authorityDo not fix Wazuh before the source event exists
Source event, no WEC eventSubscriptionManager, runtime status, channel access, Kerberos/WinRMDo not enable TrustedHosts=* or AllowUnencrypted
WEC event, no manager recordAgent, localfile, queue, connection and raw captureDo not confuse no alert with no received event
Received event, missing rulePhase2, fields, group/parent and competing rulesDo not tune regex against UI-escaped strings
Everything attributed to WECdata.win.system.computer and source XMLDo not substitute agent.name for source identity
Event flow disappearsExpected activity, heartbeat, delivery logs and queuesDo not depend only on a sensor-stop event

Sensor stop and configuration changes are useful signals, but the final record may never leave. Independently observe expected event flow, source state and delivery. A WEF heartbeat concerns subscription connectivity, not complete application-event ingestion. Silence cannot automatically mean no attacks.

Pilot, rollback and the next level

Start with a dedicated OU, restricted computer group and two sources with understandable workloads. Preserve Sysmon, agent and manager configuration, original log settings and affected policy/permissions. Define a window, operator, abort condition and post-rollback check.

Remove only confirmed-owned AF-Sysmon-Pilot and AF-Security-Pilot subscriptions using wecutil ds; restore previous configuration and validate collection. Preserve logs. Never broadly disable WinRM, firewall or Event Log Readers: other services may depend on them. Shrinking a log is not an automatically safe reverse operation. To unload the new custom-rule file, preserve it outside the included directory and restore known-good configuration before restarting.

Pilot success is not a rule count. It is several demonstrated routes: the record exists, arrives with correct source identity, follows the intended decoder and produces an explainable signal, plus understood behavior during outage, capacity pressure and maintenance.

Next I would add PowerShell4104, DNS22, ProcessTampering25, SYSVOL file changes and a dedicated correlation scenario one at a time, measuring volume and negative cases. Investigation context has purpose and cost even without an immediate alert.

How do you establish legitimate RMM management ownership and detect a lost flow after the sensor stops reporting? Share approaches without secrets or customer data. Download the pilot kit here; begin with its README and checks rather than mass deployment.

МШ

Maksim Shapovalov

Systems administrator. 17+ years working with infrastructure.

Discuss your project ↗

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top