I’m a big proponent of Sysinternals Sysmon for shops that aren’t running a commercial endpoint detection and response (EDR) tool, like VMware’s Carbon Black or Crowdstrike’s Falcon. Sysmon is the “OG” tool for threat hunting and detailed activity logging on Windows systems, and has been embraced by cyber security practitioners so much that Microsoft’s Sysinternals team developed a version of Sysmon for Linux.
But Sysmon has one big disadvantage — it requires a lot of configuration and tuning to avoid collecting an excessive amount of events, and you’re not getting any official help from Microsoft on that front. That’s led to a cottage industry of canned Sysmon configuration files:
- https://github.com/SwiftOnSecurity/sysmon-config/
- https://github.com/Neo23x0/sysmon-config
- https://github.com/olafhartong/sysmon-modular
The last project, sysmon-modular, comes with canned rules but has the ability to produce custom Sysmon configuration files. With the amount of tuning required for Sysmon, sysmon-modular is an invaluable tool for quickly churning out custom Sysmon XML files. Rules are grouped by event code and type (include/exclude), and the sysmon-modular PowerShell script combines them into a single string of XML.
Working in those small bits of XML leads to the occasional mistake — in my experience, mismatched tags from a copy/paste job are the most common error. It’s a simple problem to fix, but usually I don’t catch it until running sysmon-modular. The error message will tell me where the invalid XML exists:
Cannot convert value "System.Object[]" to type "System.Xml.XmlDocument". Error: The "ParentImage" start tag on line 7 position 6 does not match the end tag of "Image", Line 7, position 116."
However, it won’t tell me the file name that contains the invalid XML, and I can easily be working with dozens of XML files in a custom deployment of sysmon-modular.
Finding the offending file is easy with a standalone bit of PowerShell. If you load the content of a file that purports to be XML and attempt to cast it as a XML object, the cast operation will fail if the content is malformed. Here’s an example where I iterate through all of the XML files in my custom copy of sysmon-modular, where I’ve added my own [malformed] custom XML modules:
PS C:\sysmon-modular-custom> Get-ChildItem -File -Recurse *.xml | % { [xml](Get-Content $_) | Out-Null; If ($? -eq $false) { Write-Error "Invalid XML in file $($_.FullName)" } }
For each XML file found (recursing through the relative base path), PowerShell reads in the content of the file and attempts to cast it as a XML object, then piping the content to a null output stream to suppress output of valid XML to the console. If the cast operation fails, PowerShell writes the full path of the file to the error stream. For readability, you could swap “Write-Error” with “Write-Host” because error messages are verbose, and it may be difficult to visually pick up the file path in a sea of red characters.
[A brief tech-heavy sidebar: PowerShell purists will note that a generic call to Get-Content is inefficient compared to other methods because it creates an object of arrays, with each array representing a line from the file. They’re correct: better to append “-Raw” or switch to the ReadAllLines method (a call to [System.IO.File]::ReadAllLines()) when dealing with long or large files, and once file sizes cross into the hundreds of megabytes, you have to switch to this method, otherwise PowerShell will eat all of your available RAM and never fully load the file’s content. That being said, in this specific case, most of the XML files are small, and the performance gain is negligible, so I prefer a shorter command requiring less typing.]
If you want a more compact version, you can run this instead:
gci -File -Recurse *.xml | % { [xml](gc $_) | Out-Null; If (!$?) { Write-Host "$($_.FullName)" } }
This technique is not limited to custom sysmon-modular rules. As long as your XML meets one of the supported standards for XML in .NET, you should be able to reuse the same cmdlets. You may need to dive into the .NET class [System.Xml] for more granular control over the processing and validation of XML.
Happy XML validating!