'Share this page


Latest update:

September 16, 2013




Your Windows OS must be in english!



This Powershell script will let you take snapshots of your system and compare them with a new set of snapshots, then the script will write down the output from the comparison in html format. The script also enables you to do live file system changes monitoring of any directory and filter the output.

Powershell is very strong and if you take the time to understand the basics you can come up with a lot of crazy ideas. I decided to create this monitoring script to apply some of the functionalities I've learned by reading "Learn Windows PowerShell in a Month of Lunches"

The script can be use for different purpose but it is mainly useful to quickly find any changes made to the directories you are monitoring or to track down malwares activities within your system. Basically, its a good analysing script which run on Windows system that have PowerShell.

Features :

I broke down the script into 5 different parts;

[1]Create default snapshots
[2]Create custom snapshots
[3]Compare default snapshots
[4]Compare custom snapshots
[5]File Monitoring

|Create\compare default snapshots|

This option will take 11 snapshots of your system which are considered *critical* with high chances of being hit by infected files/configuration. The script will take the following default snapshots; _________________________________________________________________________

$env:allusersprofile + cd '.\Application data' (winxp)
$env:localappdata (win vista/7)
Get-WmiObject -Class Win32_NetworkAdapterConfiguration

The idea here is to take these snapshots when you are running a clean system so whenever something bad hit your computer, you can quickly take a new set of snapshots by using the option "Compare Default snapshots", the script will then run the diff command against both snapshots and write down the output in html format.

Here's how it works;


get-childitem c:\ >> diff.txt -force
diff $(Get-Content root.txt) $(Get-Content diff.txt) | Where-Object { $_.SideIndicator -eq '=>' } | ConvertTo-HTML | Out-File root.html

By using get-childitem we are listing all items and child items from the specified path. Since we need to compare the original snapshot of [c:\] against a new snapshot of the same location, we will be storing the items inside diff.txt Now that we have both snapshots, the original [root.txt] and the new one [diff.txt], we can run the diff command!

Diff command will compare both snapshots and list any differences found inside root.html

root.html output;

In this example, we can clearly see that something new reside inside [c:\] and yes its a nasty virus! The idea is to quickly analyse each critical directories against a clean snapshot so you can easily know what happened.

|Create\compare custom snapshots|

By using this option you can tell the script to take a snapshot of any directory from your system. The script will also ask you if you wish to run the recurse option (list all sub-folders) for deep analyzing.

This is how it work;


Write-Host "Would you like to use the -recurse option? (list all sub-folders)"
$q = Read-Host "y/n"
Write-Host "Creating snapshot of " -nonewline; Write-Host "$path" -foregroundcolor red
if ($q -eq "y") {
cd $path
$recurse = get-childitem -force -recurse
cd $p
$date >> $name
$recurse >> $name
else {
cd $p
$date >> $name
get-childitem -force $path >> $name

This is really basic stuff, gci will store the items inside $name which is the name of the snapshot given by the user. $path is the target of the snapshot given by the user.

Now that we have a custom snapshot, we can compare the items against another snapshot from the same target location.

Function cmp #compare custom snapshots
Write-Host "Enter the "-nonewline; Write-Host "full path " -foregroundcolor red -nonewline; Write-Host "of your snapshots directory"
$p = Read-Host "?"
Write-Host "Which snapshot would you like to compare? ; example snapshot.txt"
Write-Host "[extension is needed]" -foregroundcolor red
$name = Read-Host "?" #snapshot name is needed to parse the [path] with "gc"
cd $p #cd to snapshot directory so we can "gc" the selected snapshot
$gc = gc $name #storing the snapshot content inside $gc with get-content
$path = $gc -match "Directory" #only need "Directory" string from all the content and store this string inside $path
$target = "$path".substring(15) #now I only need the target itself without "Directory:" - substring will do the job
#$target will give us the full path of the original snapshot and we can now take a new snapshot of the exact same location and compare it!
Write-Host "Would you like to use the -recurse option? (list all sub-folders)"
$q = Read-Host "y/n"
Write-Host "Creating snapshot of " -nonewline; Write-Host "$target" -foregroundcolor red
if ($q -eq "y") {
cd $target
$recurse = get-childitem -force -recurse
cd $p
$date >> diff.txt
$recurse >> diff.txt
else {
cd $p
$date >> diff.txt
get-childitem -force $target >> diff.txt
Write-Host "Comparing [$name] snapshot with [$name] snapshot taken on $date" -foregroundcolor green
cd $p
$output = $name -replace ".txt", ".html" #switching extention so the output will be in html format with a custom name
diff $(Get-Content $name) $(Get-Content diff.txt) | Where-Object { $_.SideIndicator -eq '=>' } | ConvertTo-HTML | Out-File $output
remove-item diff.txt -force #removing diff snapshot because we only need the html output

This part was quite fun to code because in order to compare a snapshot the script has to take a new one. Since we are comparing custom snapshots, the script has no way to know what was the original target location of the snapshot. Lets say I took a snapshot of [C:\Downloads] and now I want to compare my original snapshot with the new one. There's two ways of doing this, the first one would be to ask the user to input the original target location of the snapshot, which would be [C:\Downloads] but lets face it that's not cool. Instead I used the informations already inside the original snapshot to harvest the target location and then insert it inside the script.

Each snapshot contain the following string : "Directory : c:\Downloads" <== target location!!!

The target is already written inside the snapshot so the only thing I had to do was to run gc & -match against it and from there trim the info I didnt need.

The only input needed from the user is the name of the snapshot he wish to compare. The name must contain the extention so we can use the variable in each commands.

Lets say the user input Downloads.txt as a snapshot name.

The script will then run the following command : $gc = gc $name #storing the snapshot content inside $gc with get-content

get-content will store the informations from $name (original snapshot) inside $gc

The problem now is that we do not need all of this informations, all we need is "Directory : c:\Downloads"

Now we need to extract the path from all this informations, the fastest way to do this is to do the following command : $path = $gc -match "Directory"

By using -match we are looking for a string which start with "Directory" and the harvested information will be stored inside $path

Now we know that $path = "Directory : c:\Downloads" but if we simply feed $path to get-childitem it won't work because its not a valid path

All we have to do now is to extract the target from "Directory : c:\Downloads" - we can easily do this by using $target = "$path".substring(15)

.substring(15) will return "c:\Downloads" and store the information inside $target, now we are in business and we can feed it to get-childitem!

get-childitem -force $target >> diff.txt BINGO!

|File monitoring|

If you wish to do some live file monitoring of any directories this is the option for you.
The current events supported by the watcher are;

"Changed | Created | Deleted | Renamed"

$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $searchPath
$watcher.Filter = $filter
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true

$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)"

The following events will monitor any file system changes from a given path and display the output inside the powershell console.
You can also filter out unwanted noise, you can find more informations here It is also possible to keep a log of the events.


The File Monitoring could be useful for analazing how malwares spread inside your system, you could set the watcher to monitor [c:\] and apply *.exe as filter, as a result you would see where the malware is dropping is executable. There are many more scenario where this kind of monitoring would be useful but that is up to you to find one.