Monitoring file system changes with PowerShell

I recently returned from facilitating Lenny Zeltser‘s excellent Reverse Engineering Malware course at SANS Security West.  One of the utilities covered in the course is called CaptureBAT, which is a useful utility for monitoring a system for changes while performing malware analysis.  Of course, given my ongoing interest in PowerShell, I decided to see if I could emulate some of CaptureBAT’s file system monitoring functionality natively in a PS script.

There are several strategies that you can use to monitor the file system in PowerShell and I decided to use the .Net framework to help accomplish this task.  Here’s how I did it:

  1. Create a new System.IO.FileSystemWatcher object, and set appropriate settings:
    $watcher = New-Object System.IO.FileSystemWatcher
    $watcher.Path = $searchPath
    $watcher.IncludeSubdirectories = $true
    $watcher.EnableRaisingEvents = $true

    .Path is the path that will be monitored, .IncludeSubdirectories tells the FileSystemWatcher to monitor all subdirectories of .Path

  2. Now we need to define some events that will fire when $watcher detects a filesystem change, I’m going to define an event for Changed, Created, Deleted, and Renamed:
    $changed = Register-ObjectEvent $watcher "Changed" -Action {
       write-host "Changed: $($eventArgs.FullPath)"
    }
    $created = Register-ObjectEvent $watcher "Created" -Action {
       write-host "Created: $($eventArgs.FullPath)"
    }
    $deleted = Register-ObjectEvent $watcher "Deleted" -Action {
       write-host "Deleted: $($eventArgs.FullPath)"
    }
    $renamed = Register-ObjectEvent $watcher "Renamed" -Action {
       write-host "Renamed: $($eventArgs.FullPath)"
    }

    Within each event you can define code for what you want to happen when the event fires.  In this example I’m just directly outputting the type of action and the full path of the changed object on the filesystem.

  3. That’s pretty much it.  These events will hang around until you close your current PowerShell session or manually unregister the events.  You can unregister the events using the Unregister-Event command:
    Unregister-Event $changed.Id
    Unregister-Event $created.Id
    Unregister-Event $deleted.Id
    Unregister-Event $renamed.Id

As you can see – monitoring file system changes is actually quite easy with PowerShell.  You could easily take the output of this script and write it to a file (either using output redirection, or specifying output directly in the script) and with a little more code you could read in a CSV/structured file containing a list of exclusions (i.e. what CaptureBat does) and within each event filter out unwanted “noise.”

The great thing about this method is that it just *works* in Windows systems that have PowerShell.  No need to install any applications or run any third-party utilities – which the malware that you’re looking at may be looking for (i.e. anti-analysis measures built into some malware).  My goal is to build a complete replacement for CaptureBat within PowerShell in my spare time over the next few weeks.  Once done, I’ll post the complete script with explanations on my blog…

But for now, time to spend some quality time with the family.  Have a great weekend.