Build Your Own Module
When the coverage tool identifies gaps in your Sysmon monitoring, you have two options: merge an existing module from the module library, or build your own. This guide walks through building a custom module from scratch.
When to Build vs. Extend
Build a new module when the library has no module for your vendor, protocol, or use case. Examples: a new OT vendor product, a site-specific application, a protocol not in the built-in catalog.
Extend an existing module when a module exists but is missing rules for your specific version, edition, or installation path. Fork the existing module and add your rules.
Do not build a module for noise that should be an exclusion in the base config. If a trusted process generates too many events, add an exclusion to the curated config header instead.
Step 1: Assess Your Coverage
Before writing rules, measure what you have. Run the coverage tool against your system:
.\Get-SysmonCoverage.ps1 -ConfigPath sysmonconfig-baseline-ot.xml
The gap report tells you what is unmonitored: unmatched processes, uncovered OT software, unmatched industrial ports. These gaps are your module candidates.
For locked-down systems, capture an inventory first:
.\Export-SystemInventory.ps1 -OutputPath my-system.json .\Get-SysmonCoverage.ps1 -ConfigPath sysmonconfig-baseline-ot.xml -InventoryPath my-system.json
Step 2: Module File Structure
A module is an XML fragment containing one or more <RuleGroup> elements. It has no <Sysmon> root element -- the merge tool handles that.
<!--
ICS Watch Dog Module: <Your Module Name>
Category: <vendor-ot|vendor-it|cloud-storage|sector|protocol|remote-access>
Version: v1.0
Schema: 4.90
Dependencies: none
ATT&CK: <technique IDs covered>
PURPOSE:
<What this module monitors and why>
WHEN TO USE:
<Which systems benefit from this module>
PROVENANCE:
Source: <Where the rule content came from>
Confidence: <vendor-documented|security-research|theoretical>
Last Validated: <date>
Validated By: <your name or handle>
Known Limitations: <What this module does not cover>
-->
<RuleGroup name="<EventType>-<ModuleName>" groupRelation="or">
<!-- Rules go here -->
</RuleGroup>
Save the file under sysmon-configs/modules/<category>/<module-name>.xml.
Step 3: Detection Pattern Cookbook
Each pattern below is a complete, working example you can adapt. All examples use the ATT&CK tagging convention.
Pattern 1: Process Monitoring (Binary Name)
Monitor when a specific binary runs. Use end with to match regardless of install path.
<RuleGroup name="ProcessCreate-MyVendor" groupRelation="or">
<ProcessCreate onmatch="include">
<Image name="technique_id=T1565.001,technique=Stored Data Manipulation,detection=MyVendor engineering tool launched"
condition="end with">\MyVendorTool.exe</Image>
</ProcessCreate>
</RuleGroup>
Pattern 2: File Creation (Extensions and Paths)
Monitor when project files or configuration files are created or modified.
<RuleGroup name="FileCreate-MyVendor" groupRelation="or">
<FileCreate onmatch="include">
<TargetFilename name="technique_id=T1565.001,technique=Stored Data Manipulation,detection=MyVendor project file created"
condition="end with">.mvproj</TargetFilename>
<TargetFilename name="technique_id=T1565.002,technique=Transmitted Data Manipulation,detection=File created in MyVendor directory"
condition="contains">\MyVendor\</TargetFilename>
</FileCreate>
</RuleGroup>
Pattern 3: Network Connection (Protocol Port)
Monitor connections to a specific industrial protocol port.
<RuleGroup name="NetworkConnect-MyProtocol" groupRelation="or">
<NetworkConnect onmatch="include">
<DestinationPort name="technique_id=T0830,technique=Adversary-in-the-Middle,detection=Connection to MyProtocol port 12345"
condition="is">12345</DestinationPort>
</NetworkConnect>
</RuleGroup>
Pattern 4: Composite Rule (Binary + Command Line)
Detect a specific binary only when its command line matches a suspicious pattern. Uses <Rule groupRelation="and"> to require both conditions. This reduces false positives compared to matching either condition alone.
<RuleGroup name="ProcessCreate-SuspiciousTool" groupRelation="or">
<ProcessCreate onmatch="include">
<Rule name="technique_id=T1105,technique=Ingress Tool Transfer,detection=MyTool downloading remote file"
groupRelation="and">
<Image condition="end with">\mytool.exe</Image>
<CommandLine condition="contains">--download</CommandLine>
</Rule>
</ProcessCreate>
</RuleGroup>
Pattern 5: Registry Persistence
Monitor registry keys used for persistence or configuration tampering.
<RuleGroup name="RegistryEvent-MyVendor" groupRelation="or">
<RegistryEvent onmatch="include">
<TargetObject name="technique_id=T1547.001,technique=Registry Run Keys,detection=MyVendor service registry modified"
condition="contains">\CurrentControlSet\Services\MyVendorSvc</TargetObject>
</RegistryEvent>
</RuleGroup>
Pattern 6: Named Pipe (C2 Detection)
Monitor named pipes associated with specific tools or C2 frameworks.
<RuleGroup name="PipeCreated-MyDetection" groupRelation="or">
<PipeEvent onmatch="include">
<PipeName name="technique_id=T1572,technique=Protocol Tunneling,detection=SuspiciousTool named pipe"
condition="begin with">\suspipe_</PipeName>
</PipeEvent>
</RuleGroup>
Pattern 7: Noise Exclusion (IT Software)
Exclude a trusted IT application that generates excessive events. Used in vendor-it category modules.
<RuleGroup name="ProcessCreate-Exclude-MyApp" groupRelation="or">
<ProcessCreate onmatch="exclude">
<Image name="exclude=MyApp updater noise"
condition="is">C:\Program Files\MyApp\Updater.exe</Image>
<Image name="exclude=MyApp helper noise"
condition="is">C:\Program Files\MyApp\Helper.exe</Image>
</ProcessCreate>
</RuleGroup>
Step 4: ATT&CK Tagging
Every include rule MUST have a name attribute following the ATT&CK tagging convention:
name="technique_id=T1234,technique=Technique Name,detection=What this rule detects"
Rules:
- The
nameattribute must not exceed 250 characters - No commas in field values (commas are field delimiters)
- Multiple technique IDs use pipe:
technique_id=T1105|T1140 - Exclude rules use
name="exclude=Reason"instead
See the ATT&CK Rule Tagging guide for the full specification and SIEM parsing examples.
Step 5: Validate Your Module
XML validation
The module must be well-formed XML (even though it has no root element, the merge tool wraps it for validation):
xmllint --noout your-module.xml
Merge test
Merge your module into a curated config and verify the output loads into Sysmon:
.\Merge-SysmonModules.ps1 `
-BaseConfig sysmonconfig-baseline-ot.xml `
-Modules @('your-module.xml') `
-OutputPath merged-test.xml
Sysmon64.exe -c merged-test.xml
Verify: "Configuration updated." appears and Sysmon64.exe -c shows your new RuleGroup in the rule list.
Coverage re-check
Verify your module closes the gaps you identified:
.\Get-SysmonCoverage.ps1 `
-ConfigPath sysmonconfig-baseline-ot.xml `
-AdditionalModules @('your-module.xml')
Step 6: Document Provenance
Add the provenance block to your module header (see the file structure in Step 2). Be honest about the confidence level:
| Level | Meaning | Use When |
|---|---|---|
| theoretical | Plausible but unverified | You wrote rules from general knowledge without checking vendor docs |
| security-research | Based on public security research | Rules derived from threat intel, LOLBAS Project, Sigma rules |
| vendor-documented | Based on vendor documentation | Process names and paths from vendor install guides or KB articles |
| verified-in-lab | Tested against a real installation | You ran the module in a lab and confirmed rules fire correctly |
Step 7: Create a Validation File
Create a .validation.md file alongside your module XML. This is the public record of what has been validated.
# Module Validation: Your Module Name **Module**: sysmon-configs/modules/vendor-ot/your-module.xml **Version**: v1.0 **Confidence**: vendor-documented **Last Validated**: 2026-04-11 **Validated By**: Your Name ## Evidence Source documentation: [link to vendor KB article] ## Checklist | Item | Status | Notes | |------|--------|-------| | XML well-formed | PASS | | | Merge test | PASS | Merged into baseline-ot | | Merged config loads | PASS | Tested on Win10, Sysmon 15.20 | ## Observations Your testing notes, false positive observations, version-specific behavior. ## History | Date | Change | By | |------|--------|----| | 2026-04-11 | Initial creation | Your Name |
Step 8: Contributing Back
Share your module with the community:
- Submit via GitHub: open a GitHub issue or pull request with your module XML, validation file, and (optionally) a sanitized system inventory JSON showing the gap your module fills.
- Sanitize before sharing: if including an inventory, export with
-Redactand review manually for site-specific details (project names, custom service names, license keys). - Include evidence: vendor documentation URLs, lab test results, or LOLBAS Project references. Higher-confidence contributions are more likely to be accepted into the main library.
See the Community Contributions page for the full intake process and acceptance levels.
Quick Reference: Sysmon Event Types for Modules
| Event ID | Type | Common Use in Modules |
|---|---|---|
| 1 | ProcessCreate | Vendor binary monitoring, LOLBAS detection |
| 3 | NetworkConnect | Protocol port monitoring (Modbus, OPC-UA, etc.) |
| 11 | FileCreate | Project files, config files, vendor directories |
| 12-14 | RegistryEvent | Service registry, persistence keys |
| 17-18 | PipeEvent | C2 pipe detection, vendor named pipes |
| 22 | DnsQuery | Vendor update/telemetry domains |
For the full event type list and Sysmon documentation, see Microsoft Sysinternals Sysmon.