2

I have a need to perform change audits on some servers, and as such need to look at a particular bunch of file types, create hashes for the files matching those types, and then at a later time, compare the first hash list with a second hash list I created.

So far, I have created this string:

Get-ChildItem -Path C:\Windows -Force -Recurse -Include "*.exe","*.dll","*.sqr","*.sqc","*.sql","*.dms","*.asps" -ErrorAction SilentlyContinue | Get-Hash | Out-File 'results.txt'

This does a great job of finding all files that I need hashed, and creating hashes for those files. I have two problems with what I have so far...

First problem, when I pipe my results into the "Get-Hash" cmdlet, I lose most of the relevant information about the files that I am hashing, such as the last modified date, file length, and other timestamps.

I tried first piping my results into a Select-Object command, and then into the Get-Hash cmdlet, but it seems that the only information from the Get-Hash output is the file's path and hashstring.

Example:

Path       : C:\Users\MM COS\Documents\results\changes.txt
HashString : 00C89D6C14E29A77DD52644F91E240DF

Second problem...So I decided to push on and work with what I had for the moment, and ran the following command to compare two hash files I created from my first step.

Compare-Object $(Get-Content .\results.txt) $(Get-Content '.\results2.txt')

The problem with this command, is it only displays the hashes that do not match; it does not display the file names associated with the hashes, which is pretty useless to me. I need to know what files are being changed.

Example:

Compare-Object (Get-Content .\hash1.txt) (Get-Content .\hash2.txt)

InputObject                                                 SideIndicator
-----------                                                 -------------
HashString : 1D90ADDE1194C8F1E60AF0BB0D725162               =>
HashString : D591529F73ADCB4ADAC8DD8B7AE58554               <=

4 Answers 4

1

You're probably going to want to use ForEach-Object to do multiple things with each file as you cycle through them. The automatic variable $_ will let you target each file within the code block.

Get-ChildItem -Path C:\Windows -Force -Recurse -Include "*.exe","*.dll","*.sqr","*.sqc","*.sql","*.dms","*.asps" -ErrorAction SilentlyContinue | ForEach-Object {
    Get-Hash $_.FullName | Out-File 'results.txt'
    }

I'd think you would want to compare the old hash to the current one, in which case you could perform step 2 while you're going through step 1. If not you could pull the two result sets into variables and compare individual lines with matching filenames.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks everyone! Answers were super helpful!
1

If you are on PowerShell V4, you can use the -PipelineVariable parameter to stash the current FileInfo object for use further down the pipeline when $_ has been redefined to a different object:

$ext = "*.exe","*.dll","*.sqr","*.sqc","*.sql","*.dms","*.asps"
Get-ChildItem C:\Windows -Force -Recurse -Include $ext -pv fileInfo -ErrorAction SilentlyContinue | 
    Get-Hash | Foreach {$_.HashString + " " + $fileInfo.Name} | 
    Out-File results.txt

If you're not on V4 you can use a foreach-object cmdlet like so:

Get-ChildItem C:\Windows -Force -Recurse -Include $ext -ErrorAction SilentlyContinue | 
    Foreach {$fileInfo = $_; $hash = $_ | Get-Hash; $hash.HashString + " " + $fileInfo.Name} |
    Out-File results.txt

2 Comments

@user3689582 Using PowerShell 4.0 you've got an integrated CmdLet Get-FileHash.
@JPBlanc Yeah, but it ditches the original FileInfo object as well. So you would still need to do one of the two approaches above to access things like the LastWriteTime, etc. PS thanks for fixing the "pv" typo. :-)
0

Here is another solution. I would add the hash to the fileobject in a loop, and then I would export in an XML object file. For me it's then more simple to compare objects using Import-Clixml (be careful to use a select to export only the properties you need because Export-Clixml consumes time)

$ext = "*.exe","*.dll","*.sqr","*.sqc","*.sql","*.dms","*.asps"
Get-ChildItem -Path C:\temp\Arielle -Force -Recurse -Include $ext -ErrorAction SilentlyContinue | % {$a=Get-FileHash $_; Add-Member -InputObject $_ -MemberType Noteproperty -name "Hash" -Value $a.Hash; $_} | Export-Clixml 'c:\temp\results.xml'

1 Comment

get-filehash came out in 4.0. adding a note property is the method i like
0

It looks like you are using the Get-Hash cmdlet from PSCX... You can make your own script cmdlet that outputs all the original object information with the hash (example below) -

For the comparison you can create text files with the file path and hash on the same line -

dir C:\ | Get-FileMd5 | % {$_.FullName + '=' + $_.HashMD5} | Set-Content results.txt

Here's the function -

function Get-FileMd5 {
    begin {
        Add-Type -AssemblyName System.Security
    }
    process {
        $input | % {
            try {
                $path = ($_ | Resolve-Path -ErrorAction SilentlyContinue).Path
                if ($path) {
                    $file = Get-Item -Path $path
                    if ($file -is [System.IO.FileInfo]) {
                        $stream = $file.Open([System.IO.FileMode]::Open)
                        $crypt_prov = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
                        $md5_hash = [System.BitConverter]::ToString($crypt_prov.ComputeHash($stream)).Replace('-', '')
                        $stream.Close()
                        $file | Add-Member -MemberType NoteProperty -Name HashMD5 -Value $md5_hash -PassThru
                    }
                }
            } catch {
                if ($stream) {$stream.Close()}
                Write-Error -ErrorRecord $_
            }
        }
    }
}

dir C:\ | Get-FileMd5 | Select *

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.