Вот решение PowerShell, предоставленное PowerShell MVP Vadims Podans. Get-AuthenticodeSignatureEx
добавляет свойство SigningTime к результату, значение представляет собой общее время даты (а не местное время), вы всегда можете вызвать ToLocalTime () для объекта datetime, чтобы получить результат в вашем часовом поясе. Вы можете использовать следующую команду для быстрого тестирования:
dir $pshome\*.ps1xml | Get-AuthenticodeSignatureEx | ft SignerCertificate,Status,SigningTime,Path
function Get-AuthenticodeSignatureEx
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[String[]]$FilePath
)
begin
{
$signature = @"
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptQueryObject(
int dwObjectType,
[MarshalAs(UnmanagedType.LPWStr)]string pvObject,
int dwExpectedContentTypeFlags,
int dwExpectedFormatTypeFlags,
int dwFlags,
ref int pdwMsgAndCertEncodingType,
ref int pdwContentType,
ref int pdwFormatType,
ref IntPtr phCertStore,
ref IntPtr phMsg,
ref IntPtr ppvContext
);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptMsgGetParam(
IntPtr hCryptMsg,
int dwParamType,
int dwIndex,
byte[] pvData,
ref int pcbData
);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptMsgClose(
IntPtr hCryptMsg
);
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CertCloseStore(
IntPtr hCertStore,
int dwFlags
);
"@
Add-Type -AssemblyName System.Security
Add-Type -MemberDefinition $signature -Namespace PKI -Name Crypt32
}
process
{
Get-AuthenticodeSignature @PSBoundParameters | ForEach-Object {
$Output = $_
if ($Output.SignerCertificate -ne $null) {
$pdwMsgAndCertEncodingType = 0
$pdwContentType = 0
$pdwFormatType = 0
[IntPtr]$phCertStore = [IntPtr]::Zero
[IntPtr]$phMsg = [IntPtr]::Zero
[IntPtr]$ppvContext = [IntPtr]::Zero
$return = [PKI.Crypt32]::CryptQueryObject(
1,
$_.Path,
16382,
14,
$null,
[ref]$pdwMsgAndCertEncodingType,
[ref]$pdwContentType,
[ref]$pdwFormatType,
[ref]$phCertStore,
[ref]$phMsg,
[ref]$ppvContext
)
$pcbData = 0
$return = [PKI.Crypt32]::CryptMsgGetParam($phMsg,29,0,$null,[ref]$pcbData)
$pvData = New-Object byte[] -ArgumentList $pcbData
$return = [PKI.Crypt32]::CryptMsgGetParam($phMsg,29,0,$pvData,[ref]$pcbData)
$SignedCms = New-Object Security.Cryptography.Pkcs.SignedCms
$SignedCms.Decode($pvData)
foreach ($Infos in $SignedCms.SignerInfos) {
foreach ($CounterSignerInfos in $Infos.CounterSignerInfos) {
$sTime = ($CounterSignerInfos.SignedAttributes | Where-Object {$_.Oid.Value -eq "1.2.840.113549.1.9.5"}).Values | Where-Object {$_.SigningTime -ne $null}
}
}
$Output | Add-Member -MemberType NoteProperty -Name SigningTime -Value $sTime.SigningTime -PassThru -Force
[void][PKI.Crypt32]::CryptMsgClose($phMsg)
[void][PKI.Crypt32]::CertCloseStore($phCertStore,0)
} else {
$Output
}
}
}
}