高级PowerShell散列函数

时间:2014-05-30 00:48:02

标签: powershell hash

我需要在某些服务器上执行更改审核,因此需要查看特定的一组文件类型,为匹配这些类型的文件创建哈希值,然后在以后比较第一个哈希列表我创建了第二个哈希列表。

到目前为止,我已经创建了这个字符串:

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

这可以很好地找到我需要哈希的所有文件,并为这些文件创建哈希值。到目前为止,我有两个问题......

第一个问题,当我将结果输入" Get-Hash" cmdlet,我丢失了有关我正在散列的文件的大部分相关信息,例如上次修改日期,文件长度和其他时间戳。

我尝试首先将结果传递给Select-Object命令,然后传入Get-Hash cmdlet,但似乎来自Get-Hash输出的唯一信息是文件的路径和哈希字符串

示例:

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

第二个问题......所以我决定继续使用我现在拥有的东西,并运行以下命令来比较我从第一步创建的两个哈希文件。

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

此命令的问题是,它只显示不匹配的哈希值;它不会显示与哈希相关的文件名,这对我来说是没用的。我需要知道哪些文件正在被更改。

示例:

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

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

4 个答案:

答案 0 :(得分:1)

您可能希望在循环使用每个文件时使用ForEach-Object执行多项操作。自动变量$ _将允许您定位代码块中的每个文件。

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'
    }

我认为您希望将旧哈希值与当前哈希值进行比较,在这种情况下,您可以在执行步骤1时执行步骤2.如果不是,则可以拉出两个结果集变量并比较具有匹配文件名的各行。

答案 1 :(得分:1)

如果您使用的是PowerShell V4,则可以使用-PipelineVariable参数存储当前的FileInfo对象,以便在将$_重新定义到其他对象时在管道的下游使用:

$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

如果您不在V4上,则可以使用foreach-object cmdlet,如下所示:

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

答案 2 :(得分:0)

看起来您正在使用PSCX中的Get-Hash cmdlet ...您可以创建自己的脚本cmdlet,使用哈希输出所有原始对象信息(示例如下) -

为了进行比较,您可以在同一行创建文件路径和散列的文本文件 -

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

这是函数 -

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 *

答案 3 :(得分:0)

这是另一种解决方案。我会在循环中将hash添加到fileobject,然后我将导出到XML对象文件中。对我来说,使用Import-Clixml比较对象更简单(小心使用select只导出所需的属性,因为Export-Clixml消耗时间)

$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'