Find-PCBCrypto: Function to aid in finding CryptoLocker encrypted files

CryptoLocker is a nasty beast of a bug causing all manner of havoc.  If it's done nothing else, one positive impact it has had on IT is that we're making sure our backups aren't being ignored.

One of the hardest parts still, though, is finding what got hit, and who got hit, and in a timely enough manner to minimize the damage done.  Part of that problem is that there is no scanner that can definitively detect CryptoLocker encrypted files, specifically because they just look like any encrypted file; there is no virus fingerprint to be had.

So, how to scan for its fingerprints proactively?  It seemed like a nearly impossible task (I'm no malware expert, so figuring out how to detect something like this isn't my forte).  When I started digging in to the problem, though, I did learn a few key pieces to the puzzle.

The first piece is that, while the timestamps on files that are encrypted don't change, the NTFS MFT's entry change time does get modified.  I learned about this on Security Braindump; it's a good read, and you can find it here:

The second piece is a bit on how CryptoLocker functions: since it uses the logged in user account to encrypt files, and since it is literally replacing the files with encrypted copies, the newly encrypted files are being created by the logged in user.  This means that, no matter who owned them before, the logged in user will become the file owner.  This is hugely useful in tracking down the source of the encryption so that system can be taken offline (assuming the user was sitting at their usual workstation, that is).

Taken together, we have what I like to think of as a heuristic fingerprint for CryptoLocker.

With a good fingerprint, we should be able to script this and perform scans against network files, correct?  Unfortunately, this is where things come to a halt: there is no native way in PowerShell to look at the MFT change time on a file.  No WMI class to save the day, no .NET class will take a peak for you.  For this job, we need some more advanced coding chops, which are well beyond me at this point in time.

Enter Get-FileTimeStamp, written by PowerShell MVP Boe Prox.  With a bit of C# magic, Boe's function lists out a files creation, modified and last access times (which can all already be seen easily with Get-ChildItem) as well as the more elusive MFT change time (the all-important field for this fingerprinting).  You can find his function, which is required for mine to work, here:

So, with those two bits of information, and that excellent tool already built, I set out to build a tool for hunting down CryptoLocker encrypted files.  I'm not going to go deep into detail here about how each part works or why I did what I did, but I will explain the high level logic that I use: mainly, if the MFT change time doesn't match the create or modified times, then it is potentially been encrypted.  This is far from a perfect science, and if you run it, you will get false positives; this means you will need to use your judgement when using this to determine when you're actually looking at an infection.

There is one potential issue it might still have, and that is localization; anyone who's system date format default isn't set at the US standard of mm/dd/yyyy might have an issue with the comparison not working; I've not tested this against any systems that use a different date format yet, though, so keep that in mind when using this if this applies to you (and please, if it does, please let me know if you run into any issues).

Finally, you DO need to have Get-FileTimeStamp downloaded (from the link above) and sourced for this function to work.

UPDATE 5-9-2014: I've added some logic to reduce the number of false positives by removing seconds and milliseconds from being compared, as well as some logic for future deep scanning that I hope to add.  I'll call this version 1.1.

UPDATE 6-20-2014: I ran across a minor bug that causes the function to exit ungracefully if it has an issue connecting the folder path to the selected drive letter.  I added error handling to retry up to 3 more times with different drive letters if none were specified, then fail back to scanning directly using the shared folder path; if the drive letter was specified and it fails to map, it will throw an error and halt.

UPDATE 10-15-2014: Due to some changes in the output of Get-FileTimeStamp, I've changed "FileName" to "FullName" (edit: and also "CreationDate" to "CreationTime").  Note that I wasn't able to get the new Get-FileTimeStamp to work in PowerShell version 4, though it did work in version 2.  This change is untested at this point in time.

With all of that in mind, here is the function I came up with (it works in PowerShell version 2 and newer):

(UPDATE 7-30-2015: I've removed the directly embedded copy of the rather large function, and moved it to its new home in GitHub: )