PowerShell Forensics. Techniques to Gather the Evidence and Tricks

Do you ever consider PowerShell as the forensics tool? Learn how to use it to gather evidence in order to demonstrate what actually happened, even though hackers are doing their best to hide the traces. Tools and some extra step by step on how to recover files from the drive are included as a bonus, too.

Time to do some real forensics practice… again.

Attach a given VHD in your system as X: You need to start PowerShell ISE as an Administrator to perform these tasks.

The story goes like this… We have a disk from the attacked machine. Of course, you never should work on a real piece of evidence! If you have the physical disk you can use for example Sysinternals Disk2VHD utility and if you have a VHD file – just work on a copy keeping the original in a safe place.

Of course, the very first thing to be done is to attach the VHD to our machine.

$disk= Mount-VHD -Path $VHDPath  

Just to make sure everything works fine:

dir x:\  

It works but there is absolutely nothing on it. At this point, we have no idea what happened and why data is not where it should be but let’s ask the MFT.

Install-Module PowerForensics
Import-Module PowerForensics -Verbose
Get-ForensicFileRecord -VolumeName x: | Where-Object {$_.Deleted}

We have found something here! Let’s write down the RecordNumber property.

As you can see it was a mysterious p.exe file and it was deleted. Let’s try to figure out what this executable was about. As you can see the name is not really useful here. It is common practice to use very short names for tools used for attack because it keeps the scripts and commands more compact and easier to pack into some payloads.

Now instead of looking for deleted files we can ask about this particular one and store the result in $fr (like “file record”) variable:

$fr=Get-ForensicFileRecord -VolumeName x: -Index 38

Inside we have one very nice property. Let’s display all of them first:

$fr | select *

And now let’s focus on “Attribute”:


As you can see there is STANDARD_INFORMATION, FILE_NAME and DATA. Data has a property called “DataRun”. We all love DataRun and for a reason 😉

Let’s store DATA attribute in a new variable and let’s examine the DataRun property.

$fd=$fr.Attribute | Where-Object {$_.name –eq ‘DATA’}


Here we have an information about data kept on a disk for this file. File is not sparse (not being sparse is very normal for executable files), it starts in a cluster 8267, and it is 130 clusters long. The good news is it is kept on the disk in one piece, not split into multiple fragments. With fragmented files, it is not more complicated at all, but it requires more PowerShell commands which makes the process more error-prone.

So we have cluster numbers. Here we need one piece of information more: the cluster size in bytes. It may be different so instead of guessing we have to read it from the Boot Record of the disk:

Get-ForensicVolumeBootRecord -VolumeName x:

The interesting value here is (what a surprise!) BytesPerCluster equals here 4096. Let’s remember it.

The magic we have to do right now is: read X bytes from the device starting at some offset. Let’s do this:

Invoke-ForensicDDInFile \\.\X: -Offset (8267*4096) -BlockSize (130*4096) -Count 1 -OutFile c:\test.exe

Now we can go to the C:\ and see the file created! It has an icon, description etc now so it looks like a success. It even works. The only thing to mention is we have read entire clusters not the real amount of bytes of the original file. This does not affect how executable file works but for some other format may be significant.

But please do not forget that in Attributes we had the actual size so if we would like to be very strict we should truncate the file.

Trimming the flie

Let’s return to our variable:


As you can see the allocated size is larger than real size – only 531368 bytes. To make everything just perfect we can trim the file we have created on the disk.

$bytes = [System.IO.File]::ReadAllBytes(“c:\test.exe”)

$bytes = $bytes[0..531367]


And now we can open properties of the test2.exe file and you can see even the digital signature is valid!

My favorite forensic trick

Now comes one of my favorite forensic tricks. It is based on how NTFS filesystem works. Let’s do a small demonstration. I will create 10 small text files containg 10x “cqure” string inside.

for ($j=0; $j -lt 10; $j++) { for ($i=0;$i -lt 10;$i++) {“cqure” | Out-File -FilePath “x:\wipeme$j.txt” -Encoding ascii -Append}}

As you can see in this file there is 10 * cqure. No rocket science.

Let’s Shift+Delete these files. (F5 if necessary)

Is the real data left on the disk? Sure it is! So let’s wipe the free space.

cipher /w:x:\

Every single unused byte on the x:\ should be written with 00, then FF then some random value.

Do we have any file on this disk? Well. It depends on what do you mean by “file”. The most exciting one is x:\$MFT – Master File Table.

Get-ForensicFileRecord -VolumeName X: -Index 0


BTW it is pretty interesting because it has a parent with index 5.

Get-ForensicFileRecord -VolumeName X: -Index 5

This is a root directory indicated as a parent (which makes sense) but the root directory has an index equal to 5. So it means the file was created before the directory it stays in.

Digital forensics are even more exciting – try it for free with CQURE Forensics and Prevention Mastery Course FREE TRIAL.

Final thoughts

The time is the UTC time if you are interested why it is not just a couple of seconds old if we just played with the volume.

Let’s copy MFT from the X: drive to c:\xmft.txt using CopyFile() method.

(Get-ForensicFileRecord -VolumeName X: -Index 0).CopyFile(“c:\xmft.txt”)

Now we have an MFT structure saved into a txt file, we can open it using any editor and scroll a couple of lines down or just search for “cqure”. And what you can see here is the content of the files we have just deleted and wiped.

Why was the data not wiped? The answer is simple and it is an effect of NTFS filesystem architecture. If we recreate the file

for ($i=0;$i –lt 10;$i++) {“cqure” | Out-File -FilePath x:\wipeme.txt -Encoding ascii -Append}

Then right click it and select properties we can observe how much place it takes on the drive. Looks reasonable? Well, it depends on your understanding the NTFS. But at least one thing should be clear right now – if it takes zero bytes on the drive, even if you wipe the space couple of times it will not destroy the data, right?

Actually, the mystery here is pretty easy to explain: small files (up to approximately 700B) fit entirely into MFT record and sometimes referred as “resident” data. If we delete such file and then wipe unused space, the file stays in the MFT (of course marked as deleted) but the MFT occupies some space on the drive and this space is marked as used – obviously MFT remains on the disk even if we delete a couple of files. So the wipe operation does not wipe the real data of the file. Pretty nice thing to have if we are doing the forensics.

CQURE on Microsoft Ignite

This nice piece of forensics was presented by Paula J during Microsoft Ignite conference. We’re always happy to meet with you during all industry gatherings – online and face to face. It is a great opportunity to share our expertise and learn from other cybersecurity experts. See you on the next editions!

If you want to test our tools, download CQURE Toolkit for free.

Want to explore more adventures in the underland? Check slides from Microsoft Ignite and learn more about forensic techniques against hackers evading the hook.


*co-author Grzegorz Tworek