Как определить, есть ли у MSI метка времени или нет? - PullRequest
2 голосов
/ 31 января 2012

Я использую signtool для подписи файлов msi и setup.exe.

Для большинства сообщений MSI не удалось установить временную метку. Теперь я хотел бы отметить их отдельно.

Как найтиотметка времени отсутствует или нет?

Следующий командлет помогает мне узнать, подписан он или нет

$AuthStatus= (Get-AuthenticodeSignature $FILENAME)

    If ($AuthStatus.status -ne "Valid") {

               $SIGNTOOL sign /v /f $CERPFX /t $TimestampSRVR /p $PWD $FILENAME
        }

Теперь мне нужно проверить, отсутствует ли отметка времени msi или нет, Как это сделать?

Ответы [ 2 ]

1 голос
/ 13 февраля 2012

Вот решение 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
            }
        }    
    }
}
1 голос
/ 02 февраля 2012

Наконец я нашел ответ сам.Там есть свойство с именем TimeStamperCertificate.Ниже приведен фрагмент кода.

Если msi не подписан или не помечен временной меткой, он снова подпишет и отметит временную метку.

$MsiAuthInfo= (Get-AuthenticodeSignature $FILENAME)

    If ($MsiAuthInfo.status -ne "Valid" -or $MsiAuthInfo.TimeStamperCertificate -eq $Null) {

               $SIGNTOOL sign /v /f $CERPFX /t $TimestampSRVR /p $PWD $FILENAME
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...