Skip to content

Commit

Permalink
powershell
Browse files Browse the repository at this point in the history
Calculates a ToBeSigned hash of a certificate, producing the same uniquely identifying hash present in code integrity rule sets.
  • Loading branch information
AV1080p authored Dec 19, 2017
1 parent 9a9f660 commit f812eef
Showing 1 changed file with 123 additions and 0 deletions.
123 changes: 123 additions & 0 deletions CertTBSHash.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,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 ''
}

0 comments on commit f812eef

Please sign in to comment.