Sometimes is useful to be able to look for the hash value of a file without using third party software. Since PowerShell comes installed by default with Windows and it has an specific cmdlet for this purpose, this process can be very simple.
Using Get-FileHash cmdlet
This cmdlet, according to Microsoft Documentation, “Computes the hash value for a file by using a specified hash algorithm” and by default it uses SHA256 algorithm. Hash values are useful since they can show even the smallest changes in the contents of a file. For instance, if you want to verify if a file is safe, you can compare the hash value of that file to see if it has been modified. That said, let’s review the basic syntax of the cmdlet:
PS C:> Get-FileHash “Path_of_the_file”
Where:
Path_of_the_file is the location of the file you want to check. For example, to check the hash value of notepad.exe, you can use the following instruction:
Get-FileHash "c:\windows\notepad.exe"
Let’s explore the parameters we can use with this cmdlet.
- -Algorithm: this parameter can take one of the following instructions SHA1, SHA256, SHA384, SHA512 and MD5. Those are different algorithms that can be used to calculate the hash value of a given file. As stated above, the default is SHA256. Using the same example as before, we can tell PS to use a different algorithm adding this parameter as is follows:
Get-FileHash "c:\windows\notepad.exe" -algorithm MD5
- -InputStream: with this parameter we can specify not only a file but an “input/output device, an inter-process communication pipe, or a TCP/IP socket”. A simple approach to this parameter could be checking the hash value of a .msi file located in my GitHub repository, using SHA512 algorithm:
Get-FileHash -InputStream ([System.Net.WebClient]::new()).OpenRead('https://github.com/chunchemontero/sdc/raw/main/FirefoxSetup94.0.2.msi') -Algorithm SHA512
-LiteralPath and -Path: the first one allows to specify the path of a file as it is and no characters are interpretated as wildcards while -Path does accept wildcards characters.
A practical use of Get-FileHash
Now, let’s do something a little bit more interesting. Let’s think in an application of this cmdlet that allow us to do the following:
- We want to check several files currently located in our computer. The path of these files is stored in hashFiles.csv.
- For every file path in hashFiles.csv we want to calculate the SHA256 hash value.
- Those values are going to be compared with the healthy hash values for the corresponding file. For that purpose, our .csv is going to have the headers: fileName, filePath and healthyHashValue.
- Within PS we want to see if the values match or not.
First, we have to create the hashValues.csv file with the following headers:
"fileName","filePath", "healthyHashValue"
Then we must fill the corresponding fields:
"fileName","filePath", "healthyHashValue"
"Text_File_One","C:\PS_example\One.txt","7692C3AD3540BB803C020B3AEE66CD8887123234EA0C6E7143C0ADD73FF431ED"
"Text_File_Two","C:\PS_example\Two.txt","3FC4CCFE745870E2C0D99F71F30FF0656C8DEDD41CC1D7D3D376B0DBE685E2F3"
"Text_File_Three","C:\PS_example\Three.txt","8B5B9DB0C13DB24256C829AA364AA90C6D2EBA318B9232A4AB9313B954D3555F"
As a test I have created three different .txt files inside C:\PS_example\. Inside of them I placed the words “one”, “two” and “three” respectively. After that, I calculated the hash value using Get-FileHash and placed it as “healthyHashValue” in hashValues.csv. We can check if PS is reading our .csv using the cmdlet Import-Csv -Path “INSERT_PATH_HERE”.
At this point, we want to check if the calculated hash value for a file is the same as the healthy one we placed in hashValues.csv:
#First we import the .csv where we stored the paths of the files we want to check
$hashToBeChecked= Import-Csv -Path "C:\PS_example\hashValues.csv"
#For each object in the csv we want to compare the hash value against the healthy one
$hashToBeChecked | ForEach-Object {
if((Get-FileHash ($_.filePath)).Hash -eq ($_.healthyHashValue))
{
Write-Host $env:COMPUTERNAME, "|" ,"File:", $_.fileName ,"|", "Match"
}
else
{
Write-Host $env:COMPUTERNAME, "|" ,"File:", $_.fileName ,"|", "No Match"
}
}
We get the following result after executing this code:
PS C:\Windows\system32> C:\Users\andre\Documents\matchHash.ps1
DESKTOP-ENMPEOG | File: Text_File_One | Match
DESKTOP-ENMPEOG | File: Text_File_Two | Match
DESKTOP-ENMPEOG | File: Text_File_Three | Match
If we modify the Text_File_One to add just one single space and run the code again, we get the following result:
PS C:\Windows\system32> C:\Users\andre\Documents\matchHash.ps1
DESKTOP-ENMPEOG | File: Text_File_One | No Match
DESKTOP-ENMPEOG | File: Text_File_Two | Match
DESKTOP-ENMPEOG | File: Text_File_Three | Match
This simple script can help you to quickly identify the hash value of several files. The results can be exported to a csv file and can also be executed on a remote computer with the cmdlet available in PS.
You can download the files used in this article here: