-
Notifications
You must be signed in to change notification settings - Fork 164
/
CertTBSHash.ps1
123 lines (97 loc) · 3.96 KB
/
CertTBSHash.ps1
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Example: ls 'C:\Windows\System32\*' -Include '*.dll' | Get-AuthenticodeSignature | Select -ExpandProperty SignerCertificate | Get-TBSHash
filter Get-TBSHash {
[OutputType([String])]
param (
[Parameter(Mandatory, ValueFromPipeline)]
[Security.Cryptography.X509Certificates.X509Certificate2]
$Certificate
)
Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
namespace Crypto {
public struct CRYPT_DATA_BLOB
{
public uint cbData;
public IntPtr pbData;
}
public struct CRYPT_OBJID_BLOB
{
public uint cbData;
public IntPtr pbData;
}
public struct CRYPT_ALGORITHM_IDENTIFIER
{
public string pszObjId;
public CRYPT_OBJID_BLOB Parameters;
}
public struct CRYPT_BIT_BLOB
{
public uint cbData;
public IntPtr pbData;
public uint cUnusedBits;
}
public struct CERT_SIGNED_CONTENT_INFO
{
public CRYPT_DATA_BLOB ToBeSigned;
public CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
public CRYPT_BIT_BLOB Signature;
}
public class NativeMethods {
[DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CryptDecodeObject(uint dwCertEncodingType, IntPtr lpszStructType, [In] byte[] pbEncoded, uint cbEncoded, uint dwFlags, [Out] IntPtr pvStructInto, ref uint pcbStructInfo);
}
}
'@
$HashOIDs = @{
'1.2.840.113549.1.1.4' = 'MD5'
'1.2.840.113549.1.1.5' = 'SHA1'
'1.3.14.3.2.29' = 'SHA1'
'1.2.840.113549.1.1.11' = 'SHA256'
'1.2.840.113549.1.1.12' = 'SHA384'
'1.2.840.113549.1.1.13' = 'SHA512'
}
$CertBytes = $Certificate.RawData
$X509_PKCS7_ENCODING = 65537
$X509_CERT = 1
$CRYPT_DECODE_TO_BE_SIGNED_FLAG = 2
$ErrorMoreData = 234
$TBSData = [IntPtr]::Zero
[UInt32] $TBSDataSize = 0
$Success = [Crypto.NativeMethods]::CryptDecodeObject(
$X509_PKCS7_ENCODING,
[IntPtr] $X509_CERT,
$CertBytes,
$CertBytes.Length,
$CRYPT_DECODE_TO_BE_SIGNED_FLAG,
$TBSData,
[ref] $TBSDataSize
); $LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
if((-not $Success) -and ($LastError -ne $ErrorMoreData))
{
throw "[CryptDecodeObject] Error: $(([ComponentModel.Win32Exception] $LastError).Message)"
}
$TBSData = [Runtime.InteropServices.Marshal]::AllocHGlobal($TBSDataSize)
$Success = [Crypto.NativeMethods]::CryptDecodeObject(
$X509_PKCS7_ENCODING,
[IntPtr] $X509_CERT,
$CertBytes,
$CertBytes.Length,
$CRYPT_DECODE_TO_BE_SIGNED_FLAG,
$TBSData,
[ref] $TBSDataSize
); $LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
if((-not $Success))
{
throw "[CryptDecodeObject] Error: $(([ComponentModel.Win32Exception] $LastError).Message)"
}
$SignedContentInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TBSData, [Type][Crypto.CERT_SIGNED_CONTENT_INFO])
$TBSBytes = New-Object Byte[]($SignedContentInfo.ToBeSigned.cbData)
[Runtime.InteropServices.Marshal]::Copy($SignedContentInfo.ToBeSigned.pbData, $TBSBytes, 0, $TBSBytes.Length)
[Runtime.InteropServices.Marshal]::FreeHGlobal($TBSData)
$HashAlgorithmStr = $HashOIDs[$SignedContentInfo.SignatureAlgorithm.pszObjId]
if (-not $HashAlgorithmStr) { throw 'Hash algorithm is not supported or it could not be retrieved.' }
$HashAlgorithm = [Security.Cryptography.HashAlgorithm]::Create($HashAlgorithmStr)
$TBSHashBytes = $HashAlgorithm.ComputeHash($TBSBytes)
($TBSHashBytes | % { $_.ToString('X2') }) -join ''
}