Security

Monitoring Windows Shadow Copies

Microsoft Windows has a great feature called Shadow Copies (or Restore Points in desktop OS versions) that performs local point-in-time snapshots of disks.

Brian Scheewe

Friday, August 11, 2023

Monitoring Windows Shadow Copies

Microsoft Windows has a great feature called Shadow Copies (or Restore Points in desktop OS versions) that performs local point-in-time snapshots of disks. These snapshots are "differential, block-level backups" which means that only changes are tracked, so they're fast and space-efficient. This feature is built on top of Volume Shadow Copy Service (VSS) which allows the OS to take disk-level snapshots without locking files or needing to worry about changes during a backup window.

A best practice for most Windows Servers (especially file servers) is to enable Shadow Copies in order to protect against unintentional deletion or modification of files. Restoring from a Shadow Copy can take just a few seconds and can even be initiated by an end-user (because it's built right into Explorer).

Restoring previous versions in Windows.
Restoring previous versions in Windows.

There are few gut-wrenching moments worse than realizing (after it's too late) that a backup has failed, and sometimes it's great to carry a secondary parachute. Shadow Copies can often act as this secondary parachute!

In order to monitor Shadow Copies in an automated way, the command "vssadmin" will give us what we need.

copy
PS C:\> vssadmin -? vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool (C) Copyright 2001-2013 Microsoft Corp. ---- Commands Supported ---- Delete Shadows - Delete volume shadow copies List Providers - List registered volume shadow copy providers List Shadows - List existing volume shadow copies List ShadowStorage - List volume shadow copy storage associations List Volumes - List volumes eligible for shadow copies List Writers - List subscribed volume shadow copy writers Resize ShadowStorage - Resize a volume shadow copy storage association

Unfortunately vssadmin is not a native PowerShell command, which means the output is not formatted in a manner that is easy to work with! The rest of this post will cover how we created a PowerShell script that Level can use to monitor Shadow Copies.

Regex parsing

First we look at some sample output of "vssadmin list shadowstorage". Yuck! We will need the drive letters and the timestamps in order to accurately report on Shadow Copy health.

copy
PS C:\> vssadmin list shadows vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool (C) Copyright 2001-2013 Microsoft Corp. Contents of shadow copy set ID: {84808a27-bd1d-404e-93f2-6b1720418615} Contained 1 shadow copies at creation time: 8/6/2023 5:15:41 PM Shadow Copy ID: {0454e1f0-44f5-4712-9ab5-fe905472f033} Original Volume: (C:)\\?\Volume{582d645a-4743-4ba5-af42-badc47ebbc83}\ Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy17 Originating Machine: MyComputer Service Machine: MyComputer Provider: 'Microsoft Software Shadow Copy provider 1.0' Type: ApplicationRollback Attributes: Persistent, No auto release, Differential, Auto recovered Contents of shadow copy set ID: {8e8938f7-b44c-4564-8c5f-e4004d4b168b} Contained 1 shadow copies at creation time: 8/7/2023 11:46:31 AM Shadow Copy ID: {18c681eb-edbc-4782-8b60-fdff1655caf2} Original Volume: (C:)\\?\Volume{582d645a-4743-4ba5-af42-badc47ebbc83}\ Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy20 Originating Machine: MyComputer Service Machine: MyComputer Provider: 'Microsoft Software Shadow Copy provider 1.0' Type: ApplicationRollback Attributes: Persistent, No auto release, Differential, Auto recovered Contents of shadow copy set ID: {ba45a428-4f84-459e-b382-d4a7dd16c235} Contained 2 shadow copies at creation time: 8/7/2023 11:39:26 PM Shadow Copy ID: {dd1eb6c4-f662-40fb-b3c2-726d5a02999d} Original Volume: (C:)\\?\Volume{582d645a-4743-4ba5-af42-badc47ebbc83}\ Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy24 Originating Machine: MyComputer Service Machine: MyComputer Provider: 'Microsoft Software Shadow Copy provider 1.0' Type: ClientAccessibleWriters Attributes: Persistent, Client-accessible, No auto release, Differential, Auto recovered Shadow Copy ID: {18aef9bd-9b35-49f4-b709-9f66a8a174da} Original Volume: (E:)\\?\Volume{bbec2460-cabf-48fa-9841-e6e26a440bc1}\ Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25 Originating Machine: MyComputer Service Machine: MyComputer Provider: 'Microsoft Software Shadow Copy provider 1.0' Type: ClientAccessibleWriters Attributes: Persistent, Client-accessible, No auto release, Differential, Auto recovered

Since none of this data is in a PowerShell object format, manually matching patterns in the text will be required. The following snippet demonstrates how we can match the text for the drive letters and timestamps in order to push them into a PowerShell custom object. In our case we only care about the latest snapshot, so we'll only store the newest point-in-time per drive. In the example output above, we'll have "C" and "E" drives with Shadow Copies, and the newest copies were both taken in a set on August 7th at 11:39:26 PM.

copy
# Run vssadmin to list all the shadow copies present $vssShadows = vssadmin list shadows # Create a custom object list to store the latest shadow copy creation time for each drive $latestShadowCopies = @() $currentTime = $null $currentDriveLetters = @() # Iterate through the vssadmin output to extract drive letters and creation times foreach ($line in $vssShadows) { # Regex to parse the vssadmin output for snapshot creation times if ($line -match 'Contained \d+ shadow copies at creation time: (.*)') { $currentTime = Get-Date $matches[1] } # Regex to parse the vssadmin output for drive letters elseif ($line -match 'Original Volume: \((\w):') { $currentDriveLetters = $currentDriveLetters + $matches[1] } elseif ($line -eq '') { if ($currentTime -ne $null) { # Update the custom object list with the latest creation time for each drive letter foreach ($driveLetter in $currentDriveLetters) { $existingCopyIndex = -1 for ($i = 0; $i -lt $latestShadowCopies.Count; $i++) { if ($latestShadowCopies[$i].DriveLetter -eq $driveLetter) { $existingCopyIndex = $i break } } if ($existingCopyIndex -ne -1) { if ($currentTime -gt $latestShadowCopies[$existingCopyIndex].CreationTime) { $latestShadowCopies[$existingCopyIndex].CreationTime = $currentTime } } else { $latestShadowCopy = [PSCustomObject]@{ DriveLetter = $driveLetter CreationTime = $currentTime } $latestShadowCopies += $latestShadowCopy } } } $currentDriveLetters = @() } }

This will create 2 entries in the custom object called "$latestShadowCopies" with the drive letters and the timestamps. The next step is to query all NTFS hard drives on the system so that we can enumerate all disks that should have Shadow Copy enabled.

copy
# List all the known volumes and filter on volumes with drive letters using NTFS. Server 2012 uses FileSystem, newer uses FileSystemType $knownDriveLetters = Get-Volume | Where-Object { $_.DriveLetter -ne $null -and ($_.FileSystemType -EQ 'NTFS' -or $_.FileSystem -EQ 'NTFS') } | Select-Object -ExpandProperty DriveLetter

Lastly, we put it all together by using our list of NTFS volumes and compare it against the list of Shadow Copy snapshots. This section is also where we validate that the snapshot is under a defined time threshold (for example a snapshot was taken within the past 24 hours.

copy
# Specify the maximum allowed hours since the last shadow copy before alerting $hoursSinceLastShadowCopy = 24 # Using the list of all known NTFS volumes, compare if there are shadow copies within the specified time period. foreach ($knownDriveLetter in $knownDriveLetters) { $matchingDrive = $latestShadowCopies | Where-Object { $_.DriveLetter -eq $knownDriveLetter } if ($matchingDrive) { $shadowCreationTime = $matchingDrive.CreationTime $timeDifference = (Get-Date) - $shadowCreationTime $maxAllowedTimeDifference = [TimeSpan]::FromHours($hoursSinceLastShadowCopy) if ($timeDifference -lt $maxAllowedTimeDifference) { Write-Host "Drive $knownDriveLetter has a recent Shadow Copy from $shadowCreationTime." } else { Write-Host "ALERT: Drive $knownDriveLetter has a Shadow Copy, but it's not within $hoursSinceLastShadowCopy hours." exit 1 } } else { Write-Host "ALERT: No Shadow Copies found for drive $knownDriveLetter!" exit 1 } }

There are three outcomes from this check.

  1. There is a current snapshot for a given NTFS volume. Good!
  2. There is a snapshot for the NTFS volume, but it's outside the time limit set. Bad!
  3. There is not a snapshot for the NTFS volume. Bad!

The latter two will generate a console message beginning with "ALERT" and that's what we will use in Level to trigger the alert.

The entire script can be found in our Github community repo.

Creating a Check Shadow Copies script.
Creating a Check Shadow Copies script.

Once the script has been added to Level, now it's time to add it to a monitor policy. We will give it a meaningful name (because that shows up in the alert), chose the script in Level, and then chose a triggering output of "Contains" and "ALERT".

Adding the script to a monitor policy.
Adding the script to a monitor policy.

Once the monitor is saved, it will start to query all the target machines. If there's a problem, you'll see an alert in Level, and if you enabled email notifications, you'll see that too. Below is an example alert, and when we open the payload of the alert, we can see that the C drive does not have Shadow Copy enabled! We better fix that!

Checking the results of the script output.
Checking the results of the script output.

Hopefully this will get your mental gears churning as you consider all the possibilities! What else would you like to monitor? Let us know, we'd love to hear from you!

Level: Simplify IT Management

At Level, we understand the modern challenges faced by IT professionals. That's why we've crafted a robust, browser-based Remote Monitoring and Management (RMM) platform that's as flexible as it is secure. Whether your team operates on Windows, Mac, or Linux, Level equips you with the tools to manage, monitor, and control your company's devices seamlessly from anywhere.

Ready to revolutionize how your IT team works? Experience the power of managing a thousand devices as effortlessly as one. Start with Level today—sign up for a free trial or book a demo to see Level in action.