将SHA1和SHA256添加到此命令和输出中.此外,如果文件已签名或未签名



我一直在尝试添加另一个命令,并将其输出以显示SHA1和SHA256。同时检查文件是否使用Get-AuthenticatedSignature进行了签名,但似乎无法确定。

Get-ChildItem C: -Recurse -File -Force -ea SilentlyContinue -ev errs | % { Get-FileHash $_.Fullname -Algorithm MD5 } | Select-Object Hash,Path,@{Name='Name';Expression={[System.IO.Path]::GetFileName($_.Path)}} | Out-File C:$env:COMPUTERNAME.csv -Encoding UTF8 -Force

例如。

Column1 Column2 Column3 Column4       Column5
MD5     SHA1    SHA256  Sign/Unsigned Path

您想要执行的操作将花费大量时间,因此我建议不要在完整的C:\驱动器上尝试,而是循序渐进。。

为了加快每个文件所需的3个不同文件哈希,我建议以字节数组的形式读取文件,并计算这些字节上的哈希,这样可以避免反复读取同一文件。

类似这样的东西:

# create the 3 different hasher objects
$md5Hasher    = [System.Security.Cryptography.MD5]::Create()
$sha1Hasher   = [System.Security.Cryptography.SHA1]::Create()
$sha256Hasher = [System.Security.Cryptography.SHA256]::Create()
# Loop through the files in the root path
Get-ChildItem -Path 'C:SomePath' -File -Recurse -Force -ErrorAction SilentlyContinue | 
ForEach-Object { 
# read the content of the file as byte array only once
$bytes  = [System.IO.File]::ReadAllBytes($_.FullName)
# output an object with all properties you need
[PsCustomObject]@{
MD5    = ($md5Hasher.ComputeHash($bytes) | ForEach-Object { '{0:X2}' -f $_ }) -join ''
SHA1   = ($sha1Hasher.ComputeHash($bytes) | ForEach-Object { '{0:X2}' -f $_ }) -join ''
SHA256 = ($sha256Hasher.ComputeHash($bytes) | ForEach-Object { '{0:X2}' -f $_ }) -join ''
Signed = (Get-AuthenticodeSignature -Content $bytes -SourcePathorExtension $_.FullName).Status
Path   = $_.FullName
}
} | Export-Csv -Path "D:Test$env:COMPUTERNAME.csv" -Encoding UTF8 -NoTypeInformation
# clean op the hasher objects when done
$md5Hasher.Dispose()
$sha1Hasher.Dispose()
$sha256Hasher.Dispose()

Theo的绝妙答案是:对大文件进行即时哈希是一项缓慢的操作,您可能需要优化从磁盘的读取操作。对于较小的文件,这将是最佳的,但它不适用于大于2GB的文件。

问题是[System.IO.File]::ReadAllBytes($_.FullName)需要将整个文件读取到内存中的字节数组中,而.NET中的数组最多只能容纳21亿个项目(~2GB(。

您可以通过将文件流传递给$hasher.ComputeHash()来绕过这个限制——唯一需要注意的是;再风";文件流,然后将其传递给下一个算法。

如果只期望文件的一小部分具有签名,另一个(不太重要的(优化是选择性地筛选调用Get-AuthenticodeSignature的扩展名:

function Get-FileMultiHash
{
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[System.IO.FileInfo]$InputObject,
[Parameter(Mandatory = $false)]
[string[]]$SignatureExtension
)
begin {
$hashers = @(
($md5Hasher = [System.Security.Cryptography.MD5]::Create())
($sha1Hasher = [System.Security.Cryptography.SHA1]::Create())
($sha256Hasher = [System.Security.Cryptography.SHA256]::Create())
)
# Prepend any extension filter with `.` if not already present
$SignatureExtensionFilter = $SignatureExtensionFilter -replace '^(?!.)','.'
}
process {
try{
$shouldCheckSignature = -not$PSBoundParameters.ContainsKey('SignatureExtensionFilter') -or $InputObject.Extension -in $SignatureExtensionFilter
# Open file stream, compute md5
$fs = $InputObject.OpenRead()
$md5sum = $md5Hasher.ComputeHash($fs)
# Rewind file stream, compute sha1
[void]$fs.Seek(0, [System.IO.SeekOrigin]::Begin)
$sha1sum = $sha1Hasher.ComputeHash($fs)
# Rewind file stream, compute sha256
[void]$fs.Seek(0, [System.IO.SeekOrigin]::Begin)
$sha256sum = $sha256Hasher.ComputeHash($fs)
}
finally{
# Dispose of file stream
if($fs){$fs.Dispose()}
}
# Output checksums and signature status
[pscustomobject]@{
MD5    = [BitConverter]::ToString($md5sum).Replace('-', '')
SHA1   = [BitConverter]::ToString($sha1sum).Replace('-', '')
SHA256 = [BitConverter]::ToString($sha256sum).Replace('-', '')
Signed = if($shouldCheckSignature){(Get-AuthenticodeSignature -LiteralPath $_.FullName).Status}else{'Skipped'}
Path = $_.FullName
}
}
end {
# Dispose of hash algo instances
$hashers |ForEach-Object Dispose
}
}

然后使用类似:

Get-ChildItem -Path C:pathtorootfolder -Recurse -File -Force -ea SilentlyContinue -ev errs |Get-FileMultiHash

或带有扩展过滤器:

Get-ChildItem C:WindowsSystem32 -File |Get-FileMultiHash -SignatureExtensionFilter exe,dll

相关内容

最新更新