Build a Home SOC Lab with Wazuh SIEM

Deploy a SIEM, enroll endpoints, simulate attacks, and write detection rules.

Introduction

30 Second Summary

Every company with a network needs someone watching for threats. Security Operations Center analysts are those watchers, but breaking into the field requires proving you can actually do the work.

In this project, you will build a fully operational home SOC lab using Wazuh SIEM on your Windows machine. You will simulate real attacks, investigate alerts, and write custom detection rules mapped to the MITRE ATT&CK framework.

What You'll Build

A working Security Operations Center lab where Wazuh SIEM runs inside Docker containers, your Windows host acts as a monitored endpoint with Sysmon providing deep telemetry, and you simulate attacks to generate and investigate real alerts.

By the end of this project, you'll have:

  • A Wazuh SIEM stack (manager, indexer, dashboard) running locally in Docker containers.
  • Your Windows endpoint enrolled and reporting live telemetry via the Wazuh agent and Sysmon.
  • Custom detection rules you authored in XML that detect specific attacker behaviors and map to MITRE ATT&CK technique IDs.
  • Secret Mission: Write a high-severity detection rule for a defense evasion technique (disabling Windows Defender) and validate it fires correctly.

Are there any prerequisites?

You should have intermediate knowledge of cybersecurity concepts, familiarity with Windows, and basic comfort with the command line. You will need a Windows machine with at least 8GB of RAM.

Set Up Docker and Deploy Wazuh

A SOC lab needs a SIEM platform running somewhere you can access it. In production, that would be a dedicated server. For your home lab, you will run the entire Wazuh stack inside Docker containers on your Windows machine.

Docker lets you spin up Linux-based services without needing a separate virtual machine. The Wazuh project publishes official Docker images for its manager, indexer, and dashboard. In this step, you will install Docker Desktop, clone the Wazuh repository, and bring the full stack online.

In this step, get ready to:
  • Install Docker Desktop with WSL2 backend and Git.
  • Clone the Wazuh Docker repository and generate TLS certificates.
  • Start the Wazuh stack and verify the dashboard loads.
Install Docker Desktop with WSL2 backend

Wazuh's Docker images are Linux containers. On Windows, Docker Desktop uses WSL2 (Windows Subsystem for Linux 2) as its backend to run these containers natively.

  • Open PowerShell as administrator. Right-click the Start menu and select Terminal (Admin) or Windows PowerShell (Admin).
  • First, enable WSL2 by running this command:
wsl --install

What does this command do?

This single command enables the WSL and Virtual Machine Platform features, downloads the latest Linux kernel, sets WSL 2 as the default, and installs Ubuntu. A reboot may be required after it finishes.

  • If prompted, restart your machine and then reopen PowerShell as administrator.
  • Next, download and install Docker Desktop from the official Docker documentation page:

Docker Desktop for Windows

  • Double-click Docker Desktop Installer.exe to launch the installer.
  • On the Configuration page, ensure Use WSL 2 instead of Hyper-V is checked.
  • Complete the installer and launch Docker Desktop.
  • Docker Desktop may prompt you to log out or restart. Follow any prompts before continuing.

Once Docker Desktop is running, verify it in PowerShell by running these commands:

docker --version
docker compose version

✔️ I see version numbers for both

Docker is ready. You should see output like Docker version 27.x.x and Docker Compose version v2.x.x. The exact numbers do not matter as long as both commands succeed.

ⓧ Command not recognized or Docker daemon not running

If docker is not recognized, Docker Desktop may not have finished starting. Wait for the Docker Desktop icon in your system tray to show a steady green status, then try again.

If you see a message about the Docker daemon not running, open Docker Desktop from your Start menu and wait for it to finish initializing.

  • Now configure Docker Desktop to allocate enough memory for Wazuh. Click the gear icon in Docker Desktop to open Settings.
  • Select Resources in the left sidebar.
  • Under Advanced, set Memory to at least 4 GB.
  • Click Apply & restart.

Why 4 GB?

The Wazuh indexer alone reserves 1 GB for its JVM heap. Combined with the manager and dashboard containers, 4 GB is the minimum to avoid out-of-memory crashes on an 8 GB machine.

  • Finally, install Git so you can clone the Wazuh repository. Download Git for Windows from:

Git for Windows

  • Run the installer and accept all defaults.
  • Verify the install by running this in PowerShell:
git --version

You should see a version number like git version 2.x.x.

Git command not recognized?

Close PowerShell and reopen it. The Git installer adds itself to your PATH, but existing terminal sessions do not pick up the change until restarted.

help me troubleshoot why git is not recognized in PowerShell after installing Git for Windows

Clone the Wazuh repository and start the stack

Wazuh publishes a ready-made Docker Compose configuration. You will clone it at the v4.14.5 tag (the latest stable release) and use it to bring up the full stack.

  • In PowerShell, move to your Desktop by running this command:
cd ~/Desktop
  • Clone the Wazuh Docker repository at the v4.14.5 tag by running this command:
git clone https://github.com/wazuh/wazuh-docker.git -b v4.14.5
  • Move into the single-node deployment folder by running this command:
cd wazuh-docker/single-node/

You should now be inside the wazuh-docker/single-node/ directory.

  • Generate the TLS certificates required by the indexer by running this command:
docker compose -f generate-indexer-certs.yml run --rm generator

What does this command do?

This spins up a temporary container that generates self-signed TLS certificates for encrypted communication between the Wazuh components. The --rm flag deletes the container automatically once the certificates are written to a shared volume.

  • Start the entire Wazuh stack in detached mode by running this command:
docker compose up -d

What does this command do?

This pulls the Wazuh Docker images (manager, indexer, dashboard) and starts three containers in the background. The -d flag means "detached" so you get your terminal back immediately.

  • Confirm all three containers are running by executing:
docker compose ps

You should see three containers listed with a status of Up:

  • single-node-wazuh.manager-1
  • single-node-wazuh.indexer-1
  • single-node-wazuh.dashboard-1

Containers not starting or exiting immediately?

Make sure Docker Desktop is running (check the system tray icon). If a container shows Exited status, check its logs with docker compose logs <container_name>. The most common issue is insufficient memory. Verify Docker Desktop is allocated at least 4 GB under Settings > Resources > Advanced.

help me troubleshoot why my Wazuh Docker containers are exiting or not starting

Access the Wazuh dashboard

The Wazuh indexer takes about 1 minute to initialize after the containers start. Once ready, the dashboard becomes available on port 443.

  • Wait approximately 1 minute for the indexer to finish initializing.
  • Open your web browser and navigate to:
https://localhost
  • Your browser will show a certificate warning because the TLS certificate is self-signed. Click Advanced and then Proceed to localhost (or the equivalent in your browser) to continue.
  • Log in with the default credentials:
  • Username: admin
  • Password: SecretPassword

The Wazuh dashboard overview page loads. You should see the main navigation with modules for Security events, Integrity monitoring, and more. No agents are enrolled yet, so the agent count shows zero.

Why a self-signed certificate?

The certificate you generated earlier encrypts traffic between your browser and the dashboard. Because it was not issued by a public certificate authority, your browser cannot verify it automatically. For a local lab, this is expected and safe to proceed through.

Dashboard not loading?

If the page times out, the indexer may still be initializing. Run docker compose logs single-node-wazuh.indexer-1 and look for a line containing "started" or "green". Wait until you see it, then refresh your browser.

help me troubleshoot why the Wazuh dashboard is not loading at https://localhost

Your SIEM stack is live. Next up, you will enroll your Windows machine as a monitored endpoint so Wazuh can start collecting real security telemetry.

Enroll Your Windows Endpoint with Sysmon

Your Wazuh SIEM is running and ready to receive data. The next challenge is getting your Windows host to actually send telemetry to it.

In this step, you will install Sysmon for deep process-level visibility, then install the Wazuh agent to ship those logs to your SIEM. By the end, your Windows machine will be an actively monitored endpoint.

In this step, get ready to:
  • Install Sysmon with a community detection config for deep Windows telemetry.
  • Install and start the Wazuh agent pointing to your Docker host.
  • Verify your endpoint appears in the Wazuh dashboard with Sysmon events flowing.
Install Sysmon for deep Windows telemetry

Windows has basic event logging built in, but it misses critical details like which process spawned which child, what command-line arguments were used, and which network connections were made. Sysmon fills that gap by logging process creations, network connections, file changes, and more.

You will install Sysmon with the SwiftOnSecurity community config, a battle-tested ruleset that captures high-signal events without flooding your logs.

  • Navigate to the Sysmon folder by running:
cd C:\Sysmon
  • Install Sysmon with the SwiftOnSecurity configuration by running:
.\sysmon.exe -accepteula -i sysmonconfig-export.xml

What does this command do?

  • -accepteula automatically accepts the Sysinternals license agreement so the install proceeds without a prompt.
  • -i sysmonconfig-export.xml installs Sysmon as a system driver and applies the SwiftOnSecurity configuration file. This tells Sysmon exactly which events to log (process creation, network connections, file changes, registry modifications) and which noisy events to filter out.

You should see output confirming that Sysmon was installed successfully and the configuration was applied.

Seeing an access denied error?

Make sure you launched PowerShell with Run as administrator. Sysmon installs a kernel-mode driver and requires elevated privileges.

If you see an error about a file not being found, confirm that both sysmon.exe and sysmonconfig-export.xml are in the same folder and that you cd'd into it first.

Still stuck? Help me troubleshoot my Sysmon installation error.

Install the Wazuh agent and configure Sysmon log collection

Sysmon is now generating detailed telemetry, but that data stays local on your machine. The Wazuh agent picks up those events and ships them to the Wazuh manager running in Docker.

  • First, find your Windows host IP address. This is the IP address the Wazuh agent will use to reach the Wazuh manager in Docker. Open a new PowerShell window (still as Administrator) and run:
ipconfig
  • Look for your primary network adapter (usually Ethernet adapter or Wi-Fi) and note the IPv4 Address value. This is your Docker host IP.

Why not just use localhost?

The Wazuh agent communicates over port 1514 using the OSSEC protocol, not HTTP. While Docker Desktop maps web ports like 443 to localhost, the agent enrollment process works more reliably when pointed at the host machine's actual network IP address.

You can find this IP from the ipconfig output under your active network adapter.

msiexec.exe /i .\wazuh-agent-4.14.5-1.msi /q WAZUH_MANAGER="[[DOCKER_HOST_IP="your IPv4 address from ipconfig"]]"
  • Start the Wazuh agent service by running:
NET START WazuhSvc

What do these commands do?

  • msiexec.exe /i performs a silent installation of the Wazuh agent MSI package. The /q flag makes it quiet (no GUI prompts).
  • WAZUH_MANAGER tells the agent which IP to connect to for enrollment and log forwarding.
  • NET START WazuhSvc starts the Wazuh agent Windows service, which begins the enrollment process with the manager.

Now you need to tell the Wazuh agent to collect Sysmon logs specifically. The agent's configuration file controls which Windows Event Channels it monitors.

  • Open the Wazuh agent configuration file in Notepad by running:
notepad "C:\Program Files (x86)\ossec-agent\ossec.conf"
  • Scroll down to find the existing <localfile> entries (you will see entries for Security, System, and Application channels).
  • Add the following block below the existing <localfile> entries, inside the <ossec_config> tags:
<!-- Configure Wazuh agent to receive events from Sysmon -->
<localfile>
  <location>Microsoft-Windows-Sysmon/Operational</location>
  <log_format>eventchannel</log_format>
</localfile>

What does this configuration do?

This tells the Wazuh agent to subscribe to the Microsoft-Windows-Sysmon/Operational Windows Event Channel. Sysmon writes all its telemetry (process creation, network connections, file changes) to this channel.

The eventchannel log format tells Wazuh to use the modern Windows Event Channel API, which captures all event fields in JSON format for rich analysis.

  • Save and close ossec.conf in Notepad (Ctrl+S, then close the window).
  • Restart the Wazuh agent to apply the new configuration by running:
NET STOP WazuhSvc
NET START WazuhSvc

Agent won't start or shows a connection error?

Double check that your Docker containers are still running. Return to your original terminal and run docker compose ps from the wazuh-docker/single-node/ directory.

Verify the IP you used for WAZUH_MANAGER matches the IPv4 address shown by ipconfig. If you used the wrong IP, you can fix it by editing C:\Program Files (x86)\ossec-agent\ossec.conf and updating the <address> field under <client><server>.

Still stuck? Help me troubleshoot why my Wazuh agent can't connect to the manager.

Verify enrollment in the Wazuh dashboard

Your agent should now be enrolled and sending data. Time to confirm everything is working from the Wazuh dashboard.

  • Switch back to your browser with the Wazuh dashboard at https://localhost.
  • Click the menu icon in the upper left corner.
  • Navigate to Agents management, then select Summary.
  • Confirm your Windows host appears in the agents list with status Active.

What should I see?

You should see one agent listed with your computer's hostname, showing a green Active status. If the agent just enrolled, it may take 30-60 seconds to appear. Refresh the page if needed.

  • Now verify Sysmon events are flowing. Click on your agent's name to open its details.
  • Navigate to the Threat Hunting module from the menu.
  • Look for events from your agent. You should see Sysmon event data including Event IDs like 1 (Process Creation), 3 (Network Connection), 7 (Image Loaded), 11 (File Created), and 13 (Registry Value Set).

Agent shows Active but no Sysmon events appear?

Make sure you saved the ossec.conf change and restarted the agent service. Open C:\Program Files (x86)\ossec-agent\ossec.conf and confirm the Microsoft-Windows-Sysmon/Operational localfile entry is present inside the <ossec_config> tags.

Also verify Sysmon is running by checking Windows Event Viewer. Navigate to Applications and Services Logs > Microsoft > Windows > Sysmon > Operational. You should see events being logged there.

Still stuck? Help me figure out why Sysmon events aren't showing up in my Wazuh dashboard.

Your Windows endpoint is now fully enrolled and reporting detailed telemetry. Next up, you will simulate real attacks and investigate the alerts they generate.

Simulate Attacks and Investigate Alerts

Your SIEM is running and your endpoint is reporting telemetry. But a security tool is only as useful as the threats it detects.

In this step, you will simulate three real-world attack techniques on your own Windows host, then investigate the alerts each one generates in the Wazuh dashboard. This is the same workflow SOC analysts follow every day: detect, triage, and investigate.

In this step, get ready to:
  • Simulate encoded PowerShell execution (MITRE T1059.001).
  • Generate brute force login attempts (MITRE T1110).
  • Trigger suspicious process creation using a LOLBin technique (MITRE T1055/T1036).
Simulate encoded PowerShell execution

Attackers often encode their PowerShell commands in Base64 to evade basic detection. The -enc flag tells PowerShell to decode and execute a Base64 string. Wazuh's built-in rules flag this pattern because legitimate scripts rarely need encoding.

  • Open PowerShell as administrator on your Windows host.
  • Generate and execute a Base64-encoded command by running the following:
# Encode a harmless command in Base64 (UTF-16LE, as PowerShell expects)
$command = 'Write-Host "SOC Lab Test - Encoded Execution Detected"'
$encoded = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($command))

# Execute the encoded command (this triggers Wazuh detection)
powershell -enc $encoded

What does this code do?

The first two lines convert a simple Write-Host command into a Base64 string. The third line launches a new powershell.exe process with the -enc flag, which Sysmon captures as a Process Creation event (Event ID 1).

Wazuh's built-in rules in 0915-win-powershell_rules.xml detect encoded PowerShell execution and map it to MITRE ATT&CK technique T1059.001 (Command and Scripting Interpreter: PowerShell).

You should see the text "SOC Lab Test - Encoded Execution Detected" printed in your terminal. The command itself is harmless, but the encoded execution pattern is what triggers the alert.

  • Return to the Wazuh dashboard at https://localhost.
  • Click on the Threat Hunting module in the left sidebar.
  • In the search bar, filter by your agent name to scope results to your Windows host.
  • Look for an alert related to PowerShell encoded execution. It may take 30-60 seconds for the alert to appear.
  • Click on the alert to expand it. Note the rule.id, rule.level (severity), and rule.mitre.id fields.

What should I see in the alert?

Each alert in the Wazuh dashboard contains structured JSON data. The key fields to note are:

  • rule.id identifies which detection rule fired.
  • rule.level shows the severity on a scale of 0-15.
  • rule.mitre.id maps the alert to a specific MITRE ATT&CK technique (in this case, T1059.001).

Not seeing an alert after 60 seconds?

  • Make sure WazuhSvc is still running. Open Services on your Windows host and confirm the Wazuh service shows Running.
  • Check that the Sysmon EventChannel is configured in your agent's ossec.conf. Without it, Sysmon events won't reach Wazuh.
  • Try refreshing the Threat Hunting page or adjusting the time range filter to include the last 15 minutes.

Ask for help: Why isn't my PowerShell encoded command generating a Wazuh alert?

Simulate brute force login attempts

Brute force attacks flood a system with authentication attempts using wrong credentials. Wazuh correlates multiple failed login events and escalates them into a single high-severity alert when a frequency threshold is crossed.

  • In your administrator PowerShell window, generate multiple failed authentication attempts by running:
# Generate 6 failed login attempts against localhost
# Each attempt creates a Windows Security Event 4625 (failed logon)
net use \\localhost /user:fakeuser WrongPass1
net use \\localhost /user:fakeuser WrongPass2
net use \\localhost /user:fakeuser WrongPass3
net use \\localhost /user:fakeuser WrongPass4
net use \\localhost /user:fakeuser WrongPass5
net use \\localhost /user:fakeuser WrongPass6

What does this code do?

Each net use command attempts to connect to the local machine with an invalid username and password. Windows generates a Security Event ID 4625 (failed logon) for each attempt.

Wazuh's correlation engine counts these failed events within a time window. Once the threshold is crossed, it triggers a brute force alert mapped to MITRE T1110 (Brute Force).

Each command will display an error message about logon failure. This is expected and intentional.

  • Return to the Threat Hunting module in the Wazuh dashboard.
  • Wait 30-60 seconds, then look for alerts related to multiple authentication failures.
  • Expand the brute force alert. Note the rule.id, the rule.level, and the rule.mitre.id (should show T1110).
  • Observe the parent rule that the brute force alert chains from. This shows how Wazuh correlates individual events into a higher-level detection.

Why does Wazuh need multiple events to trigger?

A single failed login could be a typo. Wazuh's correlation rules require multiple failures within a time window before escalating to a brute force alert. This reduces false positives while still catching real attacks.

The alert shows both the frequency count and the time window. These are the thresholds a SOC analyst would tune for their environment.

No brute force alert appearing?

  • Make sure you ran all 6 commands in quick succession. If there's too much time between attempts, Wazuh's correlation window may not trigger.
  • Verify that your Wazuh agent is collecting Windows Security logs (Event ID 4625 requires the Security channel).
  • Try running the commands again quickly. Some environments need 8-10 failures to cross the default threshold.

Ask for help: Why isn't my brute force simulation triggering a Wazuh alert?

Simulate suspicious process creation with certutil

A LOLBin (Living Off the Land Binary) is a legitimate Windows tool that attackers abuse for malicious purposes. certutil.exe is a certificate management tool, but attackers commonly use it to download files from the internet because it bypasses many security controls.

  • Create a temp directory for the test by running:
mkdir C:\temp -Force
  • Simulate the LOLBin technique by running a certutil download command:
# Use certutil to download a file (common LOLBin technique)
# This triggers Sysmon Event ID 1 with the suspicious command line
certutil -urlcache -split -f http://example.com/test.txt C:\temp\test.txt

What does this command do?

The certutil -urlcache -split -f flags tell certutil to download a URL and save it to disk. This is a well-known attacker technique because certutil is a trusted, signed Windows binary that won't be blocked by application whitelisting.

Sysmon captures the full command line of this process (Event ID 1). Wazuh's rules detect the suspicious combination of certutil with download-related flags and map it to MITRE techniques T1055/T1036 (Process Injection / Masquerading).

The command may succeed or fail depending on network connectivity. Either way, Sysmon captures the process creation event and Wazuh generates the alert based on the command-line pattern.

  • Return to the Threat Hunting module in the Wazuh dashboard.
  • Look for a new alert related to certutil or suspicious process creation.
  • Expand the alert and note the rule.id, rule.level, and rule.mitre.id fields.
  • Click on the event data to see the full Sysmon log, including the win.eventdata.commandLine field showing the exact command you ran.

Investigate using MITRE ATT&CK view

For a consolidated view of all your attack simulations mapped to the MITRE framework, navigate to the MITRE ATT&CK module (under Threat Detection and Response in the sidebar). The Events tab lets you filter by specific technique IDs like T1059.001, T1110, or T1036.

Not seeing the certutil alert?

  • Verify that your Sysmon EventChannel is configured in the agent's ossec.conf. Certutil detection relies on Sysmon Event ID 1 (Process Creation).
  • Check that the C:\temp directory was created successfully. Some environments restrict directory creation.
  • Try adjusting the time range in the dashboard to the last 30 minutes.

Ask for help: Why isn't my certutil command generating a Wazuh alert?

You now have documented evidence of three real attack simulations and their corresponding SIEM alerts. Next up, you will write your own custom detection rules that catch specific attacker behaviors Wazuh does not detect out of the box.

Write Custom Detection Rules

In the previous step, you simulated attacks and investigated the alerts Wazuh's built-in rules generated. Those rules cover thousands of common patterns out of the box. Now it is time to engineer your own detection rules that target specific behaviors you care about.

Custom detection rules are what separate a SOC analyst from someone who just installed a SIEM. You will write XML rules that match command-line patterns captured by Sysmon, then map each rule to a MITRE ATT&CK technique ID so alerts are automatically categorized.

In this step, get ready to:
  • Write a custom detection rule for PowerShell download activity (MITRE T1105).
  • Write a second rule detecting certutil abuse for file downloads (MITRE T1140).
  • Trigger both rules and verify they fire in the Wazuh dashboard with correct MITRE mappings.
Access the Wazuh manager and write your first detection rule

Custom rules live in a file called local_rules.xml inside the Wazuh manager container. Rules use an if_sid element to chain off a parent rule. Your rules will chain off rule 92000, which is the built-in Sysmon Event ID 1 (Process Creation) rule.

  • Open a shell inside the Wazuh manager container by running this command in your terminal:
docker exec -it single-node-wazuh.manager-1 bash

What does this command do?

This opens an interactive Bash session inside the running Wazuh manager container. Your terminal prompt will change to show you are inside the container (usually showing root@ followed by a container ID).

  • Write your first custom rule to the local_rules.xml file by running this command:
cat > /var/ossec/etc/rules/local_rules.xml << 'EOF'
<group name="custom_soc_lab,windows,">
  <rule id="100100" level="10">
    <if_sid>92000</if_sid>
    <field name="win.eventdata.commandLine" type="pcre2">(?i)(Invoke-WebRequest|wget|curl|DownloadFile|DownloadString)</field>
    <description>PowerShell download activity detected on $(win.system.computer).</description>
    <mitre>
      <id>T1105</id>
    </mitre>
  </rule>
</group>
EOF

What does this rule do?

  • rule id="100100" assigns a unique ID in the custom range (100000 to 120000).
  • level="10" sets the severity to medium-high, meaning it generates a visible alert.
  • if_sid chains this rule off parent rule 92000 (Sysmon process creation events).
  • The field element uses a regex to match common download commands in the captured command line.
  • The mitre block maps this detection to T1105 (Ingress Tool Transfer) so it appears categorized in the dashboard.
  • Verify the file was written correctly by running:
cat /var/ossec/etc/rules/local_rules.xml

You should see the full XML rule with the group wrapper, rule ID 100100, and the MITRE T1105 mapping.

Seeing a file not found error?

Make sure you ran docker exec first and are inside the container shell. Your prompt should show root@ or similar. If you accidentally typed the cat command in your Windows terminal instead of inside the container, run the docker exec command again first.

Help me fix a file not found error when writing rules inside the Wazuh manager container

Add a certutil detection rule and restart the manager

Your second rule detects certutil being used for file downloads or decoding. Certutil is a legitimate Windows certificate utility that attackers frequently abuse as a living-off-the-land binary (LOLBin) to download malicious payloads.

  • Update the rules file to include both rules by running this command (still inside the container):
cat > /var/ossec/etc/rules/local_rules.xml << 'EOF'
<group name="custom_soc_lab,windows,">
  <rule id="100100" level="10">
    <if_sid>92000</if_sid>
    <field name="win.eventdata.commandLine" type="pcre2">(?i)(Invoke-WebRequest|wget|curl|DownloadFile|DownloadString)</field>
    <description>PowerShell download activity detected on $(win.system.computer).</description>
    <mitre>
      <id>T1105</id>
    </mitre>
  </rule>
  <rule id="100101" level="10">
    <if_sid>92000</if_sid>
    <field name="win.eventdata.commandLine" type="pcre2">(?i)certutil.*(-urlcache|-decode)</field>
    <description>Certutil used for download or decode on $(win.system.computer).</description>
    <mitre>
      <id>T1140</id>
    </mitre>
  </rule>
</group>
EOF

What does rule 100101 do?

This rule matches any command line containing certutil followed by either -urlcache (used to download files) or -decode (used to decode base64-encoded payloads).

It maps to MITRE T1140 (Deobfuscate/Decode Files or Information). Both of these certutil flags are heavily abused by threat actors because certutil is a trusted, signed Microsoft binary that often bypasses application whitelisting.

  • Restart the Wazuh manager to load the new rules by running:
systemctl restart wazuh-manager

Wait about 10 seconds for the manager to fully restart.

Manager not restarting?

If you see an error about invalid XML syntax, run cat /var/ossec/etc/rules/local_rules.xml to check for typos. Common issues include mismatched opening and closing tags or a missing closing group tag. Re-run the heredoc command from above to overwrite the file with the correct content.

Help me fix an XML syntax error in my Wazuh custom rules file

✔️ Awesome, I've got everything!

Great. Double check you see both rules (100100 and 100101) inside a single group element when you run cat /var/ossec/etc/rules/local_rules.xml.

ⓧ I'd like to double check the full code

Here is the complete local_rules.xml file as it should appear inside the container:

<group name="custom_soc_lab,windows,">
  <rule id="100100" level="10">
    <if_sid>92000</if_sid>
    <field name="win.eventdata.commandLine" type="pcre2">(?i)(Invoke-WebRequest|wget|curl|DownloadFile|DownloadString)</field>
    <description>PowerShell download activity detected on $(win.system.computer).</description>
    <mitre>
      <id>T1105</id>
    </mitre>
  </rule>
  <rule id="100101" level="10">
    <if_sid>92000</if_sid>
    <field name="win.eventdata.commandLine" type="pcre2">(?i)certutil.*(-urlcache|-decode)</field>
    <description>Certutil used for download or decode on $(win.system.computer).</description>
    <mitre>
      <id>T1140</id>
    </mitre>
  </rule>
</group>
Trigger and validate your custom rules

Your rules are loaded and watching for matching command-line patterns. Now you need to trigger them from your Windows host so the Wazuh agent sends matching Sysmon events to the manager.

  • Exit the manager container shell by running:
exit
  • On your Windows host, open PowerShell as administrator.
  • Create a temp directory so the test commands have somewhere to write by running:
mkdir C:\temp -Force
  • Trigger rule 100100 (PowerShell download detection) by running:
powershell -command "Invoke-WebRequest -Uri 'http://example.com/test.txt' -OutFile 'C:\temp\test.txt'"
  • Trigger rule 100101 (certutil detection) by running:
certutil -urlcache -split -f http://example.com/test.txt C:\temp\test2.txt

Do the downloads need to succeed?

No. What matters is that Sysmon captures the command line when the process starts. Your Wazuh rules match on the command-line string, not on whether the download completed. Even if example.com returns a 404, the rule still fires.

  • Wait about 30 seconds for the events to flow from Sysmon to the Wazuh agent to the manager.
  • Return to the Wazuh dashboard in your browser at https://localhost.
  • Navigate to the Threat Hunting module.
  • Filter for your agent and look for alerts with rule IDs 100100 and 100101.
  • Expand each alert and confirm the MITRE ATT&CK technique shows T1105 for rule 100100 and T1140 for rule 100101.

Not seeing your custom rule alerts?

  • Confirm the manager restarted successfully. Run docker exec -it single-node-wazuh.manager-1 bash and then check /var/ossec/logs/ossec.log for rule-loading errors.
  • Make sure your Wazuh agent is still active. Check the agent status in the dashboard under Agents management > Summary.
  • Wait a full minute. Events sometimes take time to propagate through the pipeline.
  • Check that you ran the trigger commands in an elevated PowerShell window (Run as Administrator). Sysmon needs to capture the process creation event.

Help me troubleshoot why my custom Wazuh rules are not generating alerts

You just engineered two custom detection rules from scratch, mapped them to the MITRE ATT&CK framework, and validated them end-to-end. This is the exact workflow SOC analysts use to build detection coverage for their organizations.

Secret mission

Detect Defense Evasion (T1562.001)

Attackers who gain access to a system often try to disable security tools before doing anything else. Can you write a high-severity detection rule that catches an attacker disabling Windows Defender's real-time monitoring via PowerShell?

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally using open-source tools, so there are no ongoing financial costs.

Resources you used:

  • Docker containers (Wazuh manager, indexer, dashboard) consuming approximately 4GB RAM while running.
  • Wazuh agent installed on your Windows host at C:\Program Files (x86)\ossec-agent.
  • Sysmon installed as a system driver on your Windows host.
  • The wazuh-docker cloned repository folder on your machine.

Keep everything running

No action needed. Choose this if you are still actively experimenting with your SOC lab, writing more detection rules, or simulating additional attacks.

  • Your Docker containers remain running and continue collecting telemetry from your Windows host.
  • The Wazuh agent stays active and reports to the manager.
  • RAM usage stays at approximately 4GB for the containers.

Pause - I'll come back to this later

Shut down the Docker containers to free up approximately 4GB of RAM. Your data and configurations are preserved in Docker volumes so you can pick up right where you left off.

  • Open a terminal and navigate to the wazuh-docker/single-node/ directory.
  • Stop all containers by running:
docker compose stop
  • Your Wazuh agent will queue events locally and reconnect automatically when you restart the containers.
  • To resume later, navigate back to wazuh-docker/single-node/ and run:
docker compose start

Delete - I don't want to use this again

Remove all project resources completely. This deletes all indexed data, alert history, and custom rules stored in Docker volumes.

  • Open a terminal and navigate to the wazuh-docker/single-node/ directory.
  • Remove all containers and their associated volumes by running:
docker compose down -v
  • Uninstall the Wazuh agent. Open Settings, then go to Apps, then Installed apps. Find Wazuh Agent in the list and click Uninstall.
  • Uninstall Sysmon by opening PowerShell as administrator and running:
sysmon -u
  • Delete the cloned repository folder. In PowerShell, navigate to the parent directory containing wazuh-docker and run:
Remove-Item -Recurse -Force wazuh-docker

Nice Work!

Nice Work!

You just built a fully operational Security Operations Center lab on your own Windows machine. You now have hands-on experience with the exact workflow SOC analysts perform daily: deploying a SIEM, enrolling endpoints, investigating alerts, and engineering custom detections.

You've learned how to:

  • Deploy a full Wazuh SIEM stack (manager, indexer, dashboard) using Docker and enroll your Windows host as a monitored endpoint with Sysmon providing deep telemetry.
  • Simulate real-world attack techniques (PowerShell abuse, brute force, LOLBin usage) and investigate the alerts they generate in the Wazuh dashboard.
  • Author custom detection rules in XML with MITRE ATT&CK mapping that detect specific attacker behaviors on your endpoint.
  • Secret Mission: Created a high-severity detection rule for defense evasion (disabling Windows Defender via PowerShell) and validated it fires end-to-end.

Ready to quiz yourself?