class/SigningTimeGetter.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
Function Get-AuthenticodeSigningTime {
    [CmdletBinding(HelpUri = 'https://www.sysadmins.lv/blog-en/retrieve-timestamp-attribute-from-digital-signature.aspx')]
    Param(
        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [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).Where({ $_.SignerCertificate }) |
        ForEach-Object {
            $PdwMsgAndCertEncodingType =  0
            $PdwContentType =  0
            $PdwFormatType =  0
            [IntPtr] $PhCertStore = [IntPtr]::Zero
            [IntPtr] $PhMsg = [IntPtr]::Zero
            [IntPtr] $PpvContext = [IntPtr]::Zero
            [void] [PKI.Crypt32]::CryptQueryObject(
                1,
                $_.Path,
                16382,
                14,
                $Null,
                [ref] $PdwMsgAndCertEncodingType,
                [ref] $PdwContentType,
                [ref] $PdwFormatType,
                [ref] $PhCertStore,
                [ref] $PhMsg,
                [ref] $PpvContext
            )
            $PcbData = 0
            [void] [PKI.Crypt32]::CryptMsgGetParam($PhMsg, 29, 0, $Null, [ref] $PcbData)
            $PvData = New-Object byte[] -ArgumentList $PcbData
            [void] [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 { $Null -ne $_.SigningTime }
                }
            }
            $STime.SigningTime
            [void][PKI.Crypt32]::CryptMsgClose($PhMsg)
            [void][PKI.Crypt32]::CertCloseStore($PhCertStore, 0)
        }
    }
    End { }
}