Created
April 28, 2022 01:50
-
-
Save ahmedosama007/87bbfe4ee3b10fee12c02ac111e1794a to your computer and use it in GitHub Desktop.
Verifies the file digital signature embedded in the file or located in a Windows security catalog using WinVerifyTrust API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Copyright (c) Smart PC Utilities, Ltd. | |
'All rights reserved. | |
Imports System.Runtime.InteropServices | |
Namespace OsUtils.WinTrust | |
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> | |
Public Structure CatalogInfo | |
Public cbStruct As Integer | |
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> Public wszCatalogFile As String | |
End Structure | |
End Namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Copyright (c) Smart PC Utilities, Ltd. | |
'All rights reserved. | |
Namespace OsUtils.WinTrust | |
#Disable Warning BC40032 ' Underlying type of Enum is not CLS-compliant | |
''' <summary> | |
''' Certificate revocation check options | |
''' </summary> | |
Public Enum WinTrustDataRevocationCheck As UInteger | |
#Enable Warning BC40032 ' Underlying type of Enum is not CLS-compliant | |
''' <summary> | |
''' No revocation check | |
''' </summary> | |
None = &H0 | |
''' <summary> | |
''' Revocation check will be done on the whole chain | |
''' </summary> | |
WholeChain = &H1 | |
End Enum | |
#Disable Warning BC40032 ' Underlying type of Enum is not CLS-compliant | |
Public Enum WinVerifyTrustResult As UInteger | |
#Enable Warning BC40032 ' Underlying type of Enum is not CLS-compliant | |
''' <summary> | |
''' SUCCESS | |
''' </summary> | |
Success = 0 | |
''' <summary> | |
''' Trust provider is not recognized on this system | |
''' </summary> | |
ProviderUnknown = 2148204545 | |
''' <summary> | |
''' Trust provider does not support the specified action | |
''' </summary> | |
ActionUnknown = 2148204546 | |
''' <summary> | |
''' Trust provider does not support the subject's form | |
''' </summary> | |
SubjectFormUnknown = 2148204547 | |
''' <summary> | |
''' Subject failed the specified verification action | |
''' </summary> | |
SubjectNotTrusted = 2148204548 | |
''' <summary> | |
''' File is not signed. (TRUST_E_NOSIGNATURE) | |
''' </summary> | |
FileNotSigned = 2148204800 | |
''' <summary> | |
''' Signer's certificate is in the Untrusted Publishers store | |
''' </summary> | |
SubjectExplicitlyDistrusted = 2148204817 | |
''' <summary> | |
''' File is probably corrupt. (TRUST_E_BAD_DIGEST) | |
''' </summary> | |
SignatureOrFileCorrupt = 2148098064 | |
''' <summary> | |
''' Signer's certificate was expired. (CERT_E_EXPIRED) | |
''' </summary> | |
SubjectCertExpired = 2148204801 | |
''' <summary> | |
''' Subject's certificate was revoked. (CERT_E_REVOKED) | |
''' </summary> | |
SubjectCertificateRevoked = 2148204812 | |
''' <summary> | |
''' A certification chain processed correctly but terminated in a root certificate that is not trusted by the trust provider. (CERT_E_UNTRUSTEDROOT) | |
''' </summary> | |
UntrustedRoot = 2148204809 | |
End Enum | |
Friend Enum WinTrustDataUIChoice As UInteger | |
''' <summary> | |
''' Display all UI (WTD_UI_ALL) | |
''' </summary> | |
All = 1 | |
''' <summary> | |
''' Display no UI (WTD_UI_NONE) | |
''' </summary> | |
None = 2 | |
''' <summary> | |
''' Do not display any negative UI. (WTD_UI_NOBAD) | |
''' </summary> | |
NoBad = 3 | |
''' <summary> | |
''' Do not display any positive UI. (WTD_UI_NOGOOD) | |
''' </summary> | |
NoGood = 4 | |
End Enum | |
''' <summary> | |
''' Specifies the union member to be used and, thus, the type of object for which trust will be verified. | |
''' </summary> | |
Friend Enum WinTrustDataUnionChoice As UInteger | |
''' <summary> | |
''' File (WTD_CHOICE_FILE) | |
''' </summary> | |
File = 1 | |
''' <summary> | |
''' Windows Security Catalog (WTD_CHOICE_CATALOG) | |
''' </summary> | |
Catalog = 2 | |
''' <summary> | |
''' Blob (WTD_CHOICE_BLOB) | |
''' </summary> | |
Blob = 3 | |
''' <summary> | |
''' Use the WINTRUST_SGNR_INFO structure pointed to by pSgnr. (WTD_CHOICE_SIGNER) | |
''' </summary> | |
Signer = 4 | |
''' <summary> | |
''' Certificate (WTD_CHOICE_CERT) | |
''' </summary> | |
Certificate = 5 | |
End Enum | |
''' <summary> | |
''' Specifies the action to be taken | |
''' </summary> | |
Friend Enum WinTrustDataStateAction As UInteger | |
''' <summary> | |
''' Ignore the hWVTStateData member. (WTD_STATEACTION_IGNORE) | |
''' </summary> | |
Ignore = &H0 | |
''' <summary> | |
''' WTD_STATEACTION_VERIFY <br /> | |
''' Verify the trust of the object (typically a file) that is specified by the dwUnionChoice member. <br /> | |
''' The hWVTStateData member will receive a handle to the state data. This handle must be freed by specifying the WTD_STATEACTION_CLOSE action in a subsequent call. | |
''' </summary> | |
Verify = &H1 | |
''' <summary> | |
''' WTD_STATEACTION_CLOSE <br /> | |
''' Free the hWVTStateData member previously allocated with the WTD_STATEACTION_VERIFY action.<br /> | |
''' This action must be specified for every use of the WTD_STATEACTION_VERIFY action. | |
''' </summary> | |
Close = &H2 | |
''' <summary> | |
''' WTD_STATEACTION_AUTO_CACHE <br /> | |
''' Write the catalog data to a WINTRUST_DATA structure and then cache that structure. <br /> | |
''' This action only applies when the dwUnionChoice member contains WTD_CHOICE_CATALOG. | |
''' </summary> | |
AutoCache = &H3 | |
''' <summary> | |
''' WTD_STATEACTION_AUTO_CACHE_FLUSH <br /> | |
''' Flush any cached catalog data. This action only applies when the dwUnionChoice member contains WTD_CHOICE_CATALOG. | |
''' </summary> | |
AutoCacheFlush = &H4 | |
End Enum | |
''' <summary> | |
''' Trust provider settings | |
''' </summary> | |
<Flags> Friend Enum WinTrustDataProvFlags As UInteger | |
UseIe4TrustFlag = &H1 | |
NoIe4ChainFlag = &H2 | |
NoPolicyUsageFlag = &H4 | |
''' <summary> | |
''' Revocation checking is not performed. | |
''' </summary> | |
RevocationCheckNone = &H10 | |
''' <summary> | |
''' Revocation checking is performed on the end certificate only. | |
''' </summary> | |
RevocationCheckEndCert = &H20 | |
''' <summary> | |
''' Revocation checking is performed on the entire certificate chain. | |
''' </summary> | |
RevocationCheckChain = &H40 | |
''' <summary> | |
''' Revocation checking is performed on the entire certificate chain, excluding the root certificate. | |
''' </summary> | |
RevocationCheckChainExcludeRoot = &H80 | |
SaferFlag = &H100 | |
''' <summary> | |
''' Only the hash is verified. | |
''' </summary> | |
HashOnlyFlag = &H200 | |
''' <summary> | |
''' The default operating system version checking is performed. This flag is only used for verifying catalog-signed files. | |
''' </summary> | |
UseDefaultOsverCheck = &H400 | |
LifetimeSigningFlag = &H800 | |
''' <summary> | |
''' Use only the local cache for revocation checks. Prevents revocation checks over the network. it affects CRL retrieval and AIA retrieval | |
''' </summary> | |
CacheOnlyUrlRetrieval = &H1000 | |
End Enum | |
''' <summary> | |
''' Specifies the user interface context for the WinVerifyTrust function. | |
''' </summary> | |
Friend Enum WinTrustDataUIContext As UInteger | |
''' <summary> | |
''' Use when calling WinVerifyTrust for a file that is to be run. This is the default value. (WTD_UICONTEXT_EXECUTE) | |
''' </summary> | |
Execute = 0 | |
''' <summary> | |
''' Use when calling WinVerifyTrust for a file that is to be installed. (WTD_UICONTEXT_INSTALL) | |
''' </summary> | |
Install = 1 | |
End Enum | |
End Namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Copyright (c) Smart PC Utilities, Ltd. | |
'All rights reserved. | |
Imports System.Runtime.InteropServices | |
Imports SmartPCUtilities.ServicesOptimizer.Core.OsUtils.WinTrust | |
Friend Class NativeMethods | |
<DllImport("wintrust.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Unicode, EntryPoint:="WinVerifyTrustEx")> | |
Friend Shared Function WinVerifyTrustEx(<[In]> hwnd As IntPtr, <[In]> <MarshalAs(UnmanagedType.LPStruct)> pgActionID As Guid, <[In]> pWVTData As WinTrustData) As WinVerifyTrustResult | |
End Function | |
<DllImport("wintrust.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> | |
Friend Shared Function CryptCATAdminAcquireContext2(ByRef phCatAdmin As IntPtr, pgSubsystem As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> pwszHashAlgorithm As String, pStrongHashPolicy As IntPtr, dwFlags As Long) As <MarshalAs(UnmanagedType.Bool)> Boolean | |
End Function | |
<DllImport("wintrust.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> | |
Friend Shared Function CryptCATAdminCalcHashFromFileHandle2(hCatAdmin As IntPtr, hFile As IntPtr, <[In], Out> ByRef pcbHash As Integer, pbHash As Byte(), dwFlags As Long) As <MarshalAs(UnmanagedType.Bool)> Boolean | |
End Function | |
<DllImport("wintrust.dll", SetLastError:=True)> | |
Public Shared Function CryptCATAdminEnumCatalogFromHash(<[In]> hCatAdmin As IntPtr, <[In]> pbHash As Byte(), <[In]> cbHash As Integer, <[In]> dwFlags As Integer, <[In]> phPrevCatInfo As IntPtr) As IntPtr | |
End Function | |
<DllImport("wintrust.dll", SetLastError:=True)> | |
Public Shared Function CryptCATAdminReleaseContext(<[In]> hCatAdmin As IntPtr, <[In]> dwFlags As Integer) As Boolean | |
End Function | |
<DllImport("wintrust.dll", SetLastError:=True)> | |
Public Shared Function CryptCATAdminReleaseCatalogContext(<[In]> hCatAdmin As IntPtr, <[In]> hCatInfo As IntPtr, <[In]> dwFlags As Integer) As Boolean | |
End Function | |
<DllImport("wintrust.dll", SetLastError:=True)> | |
Public Shared Function CryptCATCatalogInfoFromContext(<[In]> hCatInfo As IntPtr, <Out> ByRef psCatInfo As CatalogInfo, <[In]> dwFlags As Integer) As Boolean | |
End Function | |
End Class |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Copyright (c) Smart PC Utilities, Ltd. | |
'All rights reserved. | |
Imports System.IO | |
Imports System.Text | |
Imports System.ComponentModel | |
Imports System.Runtime.InteropServices | |
Imports System.Security.Cryptography.X509Certificates | |
Namespace OsUtils.WinTrust | |
Public NotInheritable Class SignVerify | |
''' <summary> | |
''' Verify a file or object using the Authenticode policy provider | |
''' </summary> | |
Private Shared ReadOnly WinTrustActionGenericVerifyV2 As New Guid("{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}") | |
Private Shared ReadOnly InvalidHandleValue As New IntPtr(-1) | |
''' <summary> | |
''' Verifies the file digital signature embedded in the file or located in a Windows security catalog | |
''' </summary> | |
''' <param name="filePath">The target file path</param> | |
''' <param name="revokeCheck">Whether to check certificate revocation</param> | |
''' <param name="errInfo">Returns error info if any</param> | |
Public Shared Function VerifyFileSignature(filePath As String, revokeCheck As WinTrustDataRevocationCheck, ByRef errInfo As Exception) As WinVerifyTrustResult | |
Dim fs As FileStream = Nothing | |
Dim pCatAdmin = IntPtr.Zero | |
Dim pCatInfo = IntPtr.Zero | |
Dim signResult As WinVerifyTrustResult = WinVerifyTrustResult.FileNotSigned | |
Try | |
If Not File.Exists(filePath) Then Throw New FileNotFoundException("The specified file does not exist.", filePath) | |
Dim wtdFile = New WinTrustData(filePath) With {.fdwRevocationChecks = revokeCheck} | |
signResult = NativeMethods.WinVerifyTrustEx(InvalidHandleValue, WinTrustActionGenericVerifyV2, wtdFile) | |
If signResult <> WinVerifyTrustResult.FileNotSigned Then Return signResult | |
fs = Utils.CreateFileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, errInfo) | |
If fs Is Nothing Then Throw errInfo | |
If Not NativeMethods.CryptCATAdminAcquireContext2(pCatAdmin, Nothing, "SHA256", Nothing, 0) Then | |
Throw New Win32Exception(Marshal.GetLastWin32Error) | |
End If | |
Dim fileHandle As IntPtr = fs.SafeFileHandle.DangerousGetHandle | |
Dim hashLength As Integer = 256 | |
Dim hash As Byte() = New Byte(256) {} | |
If Not NativeMethods.CryptCATAdminCalcHashFromFileHandle2(pCatAdmin, fileHandle, hashLength, hash, 0) Then | |
Throw New Win32Exception(Marshal.GetLastWin32Error) | |
End If | |
Dim memberTag = New StringBuilder(hashLength * 2) | |
For i As Integer = 0 To hashLength - 1 | |
memberTag.Append(hash(i).ToString("X2")) | |
Next | |
pCatInfo = NativeMethods.CryptCATAdminEnumCatalogFromHash(pCatAdmin, hash, hashLength, 0, Nothing) | |
If pCatInfo = IntPtr.Zero Then Throw New Win32Exception(Marshal.GetLastWin32Error) | |
Dim catInfo As CatalogInfo = Nothing | |
If Not NativeMethods.CryptCATCatalogInfoFromContext(pCatInfo, catInfo, 0) Then | |
Throw New Win32Exception(Marshal.GetLastWin32Error) | |
End If | |
Dim wtCatInfo As New WintrustCatalogInfo With { | |
.pcwszCatalogFilePath = catInfo.wszCatalogFile, | |
.pcwszMemberFilePath = filePath, | |
.pcwszMemberTag = memberTag.ToString(), | |
.hMemberFile = fileHandle, | |
.hCatAdmin = pCatAdmin | |
} | |
Dim wtdCat As New WinTrustData() With { | |
.dwUnionChoice = WinTrustDataUnionChoice.Catalog, | |
.fdwRevocationChecks = revokeCheck} | |
wtdCat.dwProvFlags = wtdCat.dwProvFlags Or WinTrustDataProvFlags.UseDefaultOsverCheck | |
wtdCat.unionData = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(WintrustCatalogInfo))) | |
Marshal.StructureToPtr(wtCatInfo, wtdCat.unionData, False) | |
signResult = NativeMethods.WinVerifyTrustEx(InvalidHandleValue, WinTrustActionGenericVerifyV2, wtdCat) | |
Return signResult | |
Catch ex As Exception | |
errInfo = ex | |
Return signResult | |
Finally | |
If pCatAdmin <> IntPtr.Zero Then | |
If pCatInfo <> IntPtr.Zero Then NativeMethods.CryptCATAdminReleaseCatalogContext(pCatAdmin, pCatInfo, 0) | |
NativeMethods.CryptCATAdminReleaseContext(pCatAdmin, 0) | |
End If | |
If fs IsNot Nothing Then fs.Close() | |
End Try | |
End Function | |
End Class | |
End Namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Copyright (c) Smart PC Utilities, Ltd. | |
'All rights reserved. | |
Imports System.Runtime.InteropServices | |
Namespace OsUtils.WinTrust | |
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> | |
Friend Class WintrustCatalogInfo | |
''' <summary> | |
''' Size, in bytes, of this structure. | |
''' </summary> | |
Public cbStruct As Integer | |
''' <summary> | |
''' Optional. Catalog version number. | |
''' </summary> | |
Public dwCatalogVersion As Integer | |
''' <summary> | |
''' The full path and file name of the catalog file that contains the member to be verified. | |
''' </summary> | |
Public pcwszCatalogFilePath As String | |
''' <summary> | |
''' Tag of a member file to be verified. | |
''' </summary> | |
Public pcwszMemberTag As String | |
''' <summary> | |
''' The full path and file name of the catalog member file to be verified. | |
''' </summary> | |
Public pcwszMemberFilePath As String | |
''' <summary> | |
''' Optional. Handle of the open catalog member file to be verified. The handle must be to a file with at least read permissions. | |
''' </summary> | |
Public hMemberFile As IntPtr | |
''' <summary> | |
''' Optional. The calculated hash of the file that contains the file to be verified. | |
''' </summary> | |
Public pbCalculatedFileHash As Byte() | |
''' <summary> | |
''' The size, in bytes, of the value passed in the pbCalculatedFileHash member. cbCalculatedFileHash is used only if the calculated hash is being passed. | |
''' </summary> | |
Public cbCalculatedFileHash As Integer | |
''' <summary> | |
''' A pointer to a CTL_CONTEXT structure that represents a catalog context to be used instead of a catalog file. | |
''' </summary> | |
Public pcCatalogContext As IntPtr | |
''' <summary> | |
''' Handle to the catalog administrator context that was used when calculating the hash of the file. This value can be zero only for a SHA1 file hash.Windows 8 and Windows Server 2012: Support for this member begins. | |
''' </summary> | |
Public hCatAdmin As IntPtr | |
Public Sub New() | |
cbStruct = Marshal.SizeOf(GetType(WintrustCatalogInfo)) | |
End Sub | |
End Class | |
End Namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Copyright (c) Smart PC Utilities, Ltd. | |
'All rights reserved. | |
Imports System.Runtime.InteropServices | |
Namespace OsUtils.WinTrust | |
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> | |
Friend NotInheritable Class WinTrustData | |
Public cbStruct As Integer | |
Public pPolicyCallbackData As IntPtr = IntPtr.Zero | |
Public pSIPClientData As IntPtr = IntPtr.Zero | |
Public dwUIChoice As WinTrustDataUIChoice = WinTrustDataUIChoice.None | |
Public fdwRevocationChecks As WinTrustDataRevocationCheck = WinTrustDataRevocationCheck.WholeChain | |
Public dwUnionChoice As WinTrustDataUnionChoice | |
Public unionData As IntPtr | |
Public dwStateAction As WinTrustDataStateAction = WinTrustDataStateAction.Ignore | |
Public hWVTStateData As IntPtr = IntPtr.Zero | |
Public pwszURLReference As String = Nothing | |
Public dwProvFlags As WinTrustDataProvFlags = WinTrustDataProvFlags.CacheOnlyUrlRetrieval | |
Public dwUIContext As WinTrustDataUIContext = WinTrustDataUIContext.Execute | |
Public pSignatureSettings As Integer | |
Public Sub New() | |
cbStruct = Marshal.SizeOf(GetType(WinTrustData)) | |
End Sub | |
Public Sub New(fileName As String) | |
cbStruct = Marshal.SizeOf(GetType(WinTrustData)) | |
dwUnionChoice = WinTrustDataUnionChoice.File | |
Dim fileInfo = New WinTrustFileInfo(fileName) | |
unionData = Marshal.AllocCoTaskMem(Marshal.SizeOf(fileInfo)) | |
Marshal.StructureToPtr(fileInfo, unionData, False) | |
End Sub | |
Protected Overrides Sub Finalize() | |
Marshal.FreeCoTaskMem(unionData) | |
End Sub | |
End Class | |
End Namespace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'Copyright (c) Smart PC Utilities, Ltd. | |
'All rights reserved. | |
Imports System.Runtime.InteropServices | |
Namespace OsUtils.WinTrust | |
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> | |
Friend NotInheritable Class WinTrustFileInfo | |
''' <summary> | |
''' Count of bytes in this structure. | |
''' </summary> | |
Private ReadOnly cbStruct As Integer = Marshal.SizeOf(GetType(WinTrustFileInfo)) | |
''' <summary> | |
''' Full path and file name of the file to be verified. This parameter cannot be NULL. | |
''' </summary> | |
Private ReadOnly pcwszFilePath As IntPtr | |
''' <summary> | |
''' Optional. File handle to the open file to be verified. This handle must be to a file that has at least read permission. This member can be set to NULL. | |
''' </summary> | |
Private ReadOnly hFile As IntPtr = IntPtr.Zero | |
''' <summary> | |
''' Optional. Pointer to a GUID structure that specifies the subject type. This member can be set to NULL. | |
''' </summary> | |
Private ReadOnly pgKnownSubject As IntPtr = IntPtr.Zero | |
Public Sub New(filePath As String) | |
pcwszFilePath = Marshal.StringToCoTaskMemAuto(filePath) | |
End Sub | |
Protected Overrides Sub Finalize() | |
Marshal.FreeCoTaskMem(pcwszFilePath) | |
End Sub | |
End Class | |
End Namespace |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment