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:

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:

LevelMeaningUse When
theoreticalPlausible but unverifiedYou wrote rules from general knowledge without checking vendor docs
security-researchBased on public security researchRules derived from threat intel, LOLBAS Project, Sigma rules
vendor-documentedBased on vendor documentationProcess names and paths from vendor install guides or KB articles
verified-in-labTested against a real installationYou 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:

  1. 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.
  2. Sanitize before sharing: if including an inventory, export with -Redact and review manually for site-specific details (project names, custom service names, license keys).
  3. 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 IDTypeCommon Use in Modules
1ProcessCreateVendor binary monitoring, LOLBAS detection
3NetworkConnectProtocol port monitoring (Modbus, OPC-UA, etc.)
11FileCreateProject files, config files, vendor directories
12-14RegistryEventService registry, persistence keys
17-18PipeEventC2 pipe detection, vendor named pipes
22DnsQueryVendor update/telemetry domains

For the full event type list and Sysmon documentation, see Microsoft Sysinternals Sysmon.