Diving into Wazuh's File Integrity Monitoring: the syscheck module for watching important files, comparing realtime and scheduled monitoring, whitelisting directories and Windows registry, plus configuring intervals, checksums, and added, modified, and deleted file change reports.

In episode 6 you learned to assemble decoders and rules, understanding that all alerts are born from logs that are normalized and then evaluated. But there's a class of detection that doesn't depend on logs at all: monitoring the state of the files themselves. Small changes to important files are often an early sign of compromise, before an attacker has had time to write suspicious logs.
Episode 7 takes you into Wazuh's File Integrity Monitoring (FIM). We'll dissect the syscheck module, compare realtime and scheduled monitoring, learn about whitelists and the Windows registry, then build interval and checksum configurations for varied needs.
By the end of this episode you'll be able to answer a simple but crucial question: are the important files on your server still the same as yesterday?
FIM works by calculating file checksums, then comparing them against a stored baseline database of the last known state. When a checksum changes, Wazuh knows the file was modified and generates an alert. The module responsible in Wazuh is syscheck, which runs on the agent and is active by default on many operating systems.
syscheck's scope doesn't stop at file content. It also monitors metadata such as permissions, owner, group, size, and modification time. A permission change, for example, can happen without touching file content, yet it's still dangerous if it turns a secret file world-readable.
Info
FIM is not a replacement for log monitoring, but a complement. Logs tell you what happened on the system, while FIM tells you what changed on your assets. A clever attacker can turn off logging, but it's hard to erase traces of file changes without triggering FIM.
syscheck has two basic modes: realtime and scheduled. Realtime mode leverages kernel notifications, like inotify on Linux, so file changes are reported within seconds. Scheduled mode scans directories at a fixed interval and compares checksums against previous records.
Each has clear trade-offs. Realtime is responsive but consumes more resources, because the kernel must watch every file in the directory. Scheduled is lighter and suits large directories, but there's a window during which changes aren't yet detected. The best decision is usually a mix of both.
<syscheck>
<directories check_all="yes" realtime="yes">/etc</directories>
</syscheck>In the first block, the /etc directory is monitored in realtime so any change, however small, immediately becomes an event. The second block doesn't include the realtime attribute, so /var/www follows syscheck's default scan schedule. Small directories holding critical configuration deserve realtime, while large directories that change slowly can be handled by scheduling.
The syscheck configuration can be written directly in the agent's ossec.conf, or managed centrally via agent.conf on the manager for many agents at once. The centralized approach is far cleaner in large environments, because you can apply the same FIM policy to an entire fleet of servers.
<agent_config>
<syscheck>
<directories check_all="yes">/etc,/usr/bin</directories>
<frequency>3600</frequency>
<scan_on_start>yes</scan_on_start>
</syscheck>
</agent_config>The directories element defines the monitored locations, with multiple paths separated by commas. frequency sets the scan interval in seconds, and scan_on_start ensures the first scan runs as soon as the agent starts. This configuration is automatically synced to agents the next time they contact the manager.
Info
Save a baseline of files before adding directories to syscheck. Otherwise, the first scan can produce many false positive alerts because Wazuh treats every file it has never recorded as new. Give yourself observation time before deciding which directories really matter.
When a file changes, Wazuh emits a FIM alert categorized into three main types: added, modified, and deleted. The event attribute inside the alert details tells you the change type, and the alert level sits around 550 for all three categories.
{
"syscheck": {
"event": "modified",
"path": "/etc/passwd",
"attributes": {
"type": "file",
"uid": "0",
"gid": "0"
},
"previous_attributes": {
"checksum": "abc123"
}
}
}An alert like this stores both sides of the state: the current attributes and the previous attributes. By comparing the two, an analyst can immediately know what changed — whether it was only metadata or also the file content. The Wazuh FIM dashboard collects all these changes into a single table filterable by agent, by directory, and by event type.
When reviewing reports, remember that not every change is an attack. Package updates, application deployments, and routine backup jobs also modify files. The key is building a baseline of normal activity, then treating any change outside that list as a signal to investigate.
Not every file deserves monitoring, and not every change deserves reporting. The ignore element inside syscheck excludes certain files or directories from monitoring. This is very helpful for files that change constantly, like caches or lock files that will always generate noise.
On the other hand, Wazuh also monitors the Windows registry via the windows_registry element. The registry holds a lot of critical configuration, including keys executed at startup. Attackers often add registry values in Run keys so malware runs every time the machine boots, making this area very valuable to monitor in Windows environments.
<syscheck>
<ignore>/var/cache/apt/archives</ignore>
<ignore>/tmp</ignore>
<windows_registry>HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run</windows_registry>
<windows_registry>HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce</windows_registry>
</syscheck>Note that the realtime and check_all attributes can also be applied to windows_registry. When resources allow, monitor the Run and RunOnce keys in realtime because both are frequent entry points for malware persistence. The ignore element also applies to the registry, for example to exclude keys that change constantly due to telemetry.
One directory doesn't necessarily fit all needs. Wazuh allows different intervals per directory, as well as choosing which checksum attributes are computed. The more attributes computed, the more accurate the detection, but the heavier the CPU and I/O load on the agent.
<syscheck>
<directories check_sha256="yes" frequency="300">/etc/ssh</directories>
<directories check_md5="yes" frequency="43200">/var/log</directories>
<directories check_size="no" check_owner="no">/srv/app</directories>
<recursion_level>3</recursion_level>
</syscheck>In this example, the SSH configuration is monitored every 5 minutes with a strong SHA-256 checksum, while the log directory is scanned every 12 hours with the lighter MD5. The application directory is still checked but without the irrelevant size and owner attributes. recursion_level limits the subdirectory depth explored so the scan doesn't touch an unbounded directory tree.
This combination of interval and checksum is what determines FIM's cost in production. Start with conservative intervals, observe agent CPU usage, then lower the interval only for genuinely critical directories. This principle is far better than monitoring every file with super-tight intervals.
FIM complements log-based detection with a different lens: not what happened, but what changed. You now understand how syscheck works, when to use realtime and scheduled modes, how to read the added, modified, and deleted reports, and how to exclude unimportant files and monitor the Windows registry.
Key takeaways:
ignore to suppress noise and windows_registry to monitor Windows persistence areas.In episode 8 we stop merely reporting and start acting: active response to block IPs, kill processes, and quarantine files, plus malware detection through rootcheck, YARA, and the newest malware scan module. See you there!