public WinVerifyTrustResult GetSign(string filePath) { var result = new WinVerifyTrustResult(); var file = new WINTRUST_FILE_INFO { cbStruct = Marshal.SizeOf(typeof(WINTRUST_FILE_INFO)), pcwszFilePath = filePath }; var data = new WINTRUST_DATA { cbStruct = Marshal.SizeOf(typeof(WINTRUST_DATA)), dwUIChoice = NativeMethods.WTD_UI_NONE, dwUnionChoice = NativeMethods.WTD_CHOICE_FILE, fdwRevocationChecks = NativeMethods.WTD_REVOKE_NONE, dwStateAction = NativeMethods.WTD_STATEACTION_VERIFY, pFile = Marshal.AllocHGlobal(file.cbStruct) }; Marshal.StructureToPtr(file, data.pFile, false); try { var hr = NativeMethods.WinVerifyTrust(NativeMethods.INVALID_HANDLE_VALUE, NativeMethods.WINTRUST_ACTION_GENERIC_VERIFY_V2, ref data); result.HasSign = (hr == NativeMethods.TRUST_SUCCESS || hr == NativeMethods.TRUST_E_BAD_DIGEST); result.IsSignValid = hr == NativeMethods.TRUST_SUCCESS; if (result.HasSign) { IntPtr ptrProvData = NativeMethods.WTHelperProvDataFromStateData(data.hWVTStateData); var lastError = Marshal.GetLastWin32Error(); if (ptrProvData == IntPtr.Zero && result.IsSignValid) { throw new Win32Exception(lastError); } IntPtr ptrProvSigner = NativeMethods.WTHelperGetProvSignerFromChain(ptrProvData, 0, false, 0); lastError = Marshal.GetLastWin32Error(); if (ptrProvSigner == IntPtr.Zero) { throw new Win32Exception(lastError); } IntPtr ptrCert = NativeMethods.WTHelperGetProvCertFromChain(ptrProvSigner, 0); lastError = Marshal.GetLastWin32Error(); if (ptrCert == IntPtr.Zero) { throw new Win32Exception(lastError); } CRYPT_PROVIDER_CERT cert = (CRYPT_PROVIDER_CERT)Marshal.PtrToStructure(ptrCert, typeof(CRYPT_PROVIDER_CERT)); using (X509Certificate2 certificate = new X509Certificate2(cert.pCert)) { result.Publisher = GetPublisherName(certificate.Subject); } } } finally { data.dwStateAction = NativeMethods.WTD_STATEACTION_CLOSE; NativeMethods.WinVerifyTrust(NativeMethods.INVALID_HANDLE_VALUE, NativeMethods.WINTRUST_ACTION_GENERIC_VERIFY_V2, ref data); Marshal.FreeHGlobal(data.pFile); } return(result); }
internal static void Main(string[] args) { string fileName = args[0]; IntPtr hWind = IntPtr.Zero; Guid WINTRUST_ACTION_GENERIC_VERIFY_V2 = new Guid("{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}"); byte[] actionIdBytes = WINTRUST_ACTION_GENERIC_VERIFY_V2.ToByteArray(); IntPtr pcwszFilePath = Marshal.StringToHGlobalAuto(fileName); try { WINTRUST_FILE_INFO File = new WINTRUST_FILE_INFO() { cbStruct = Marshal.SizeOf(typeof(WINTRUST_FILE_INFO)), pcwszFilePath = pcwszFilePath, hFile = IntPtr.Zero, pgKnownSubject = IntPtr.Zero, }; IntPtr ptrFile = Marshal.AllocHGlobal(File.cbStruct); try { Marshal.StructureToPtr(File, ptrFile, false); WINTRUST_DATA WVTData = new WINTRUST_DATA() { cbStruct = Marshal.SizeOf(typeof(WINTRUST_DATA)), pPolicyCallbackData = IntPtr.Zero, pSIPClientData = IntPtr.Zero, dwUIChoice = WTD_UI_NONE, fdwRevocationChecks = WTD_REVOKE_NONE, dwUnionChoice = WTD_CHOICE_FILE, pFile = ptrFile, dwStateAction = WTD_STATEACTION_IGNORE, hWVTStateData = IntPtr.Zero, pwszURLReference = IntPtr.Zero, dwProvFlags = WTD_REVOCATION_CHECK_NONE, dwUIContext = WTD_UICONTEXT_EXECUTE, pSignatureSettings = IntPtr.Zero, }; // N.B. Use of this member is only supported on Windows 8 and Windows Server 2012 (and later) WINTRUST_SIGNATURE_SETTINGS signatureSettings = default(WINTRUST_SIGNATURE_SETTINGS); bool canUseSignatureSettings = Environment.OSVersion.Version > new Version(6, 2, 0, 0); IntPtr pSignatureSettings = IntPtr.Zero; if (canUseSignatureSettings) { // Setup WINTRUST_SIGNATURE_SETTINGS to get the number of signatures in the file signatureSettings = new WINTRUST_SIGNATURE_SETTINGS() { cbStruct = Marshal.SizeOf(typeof(WINTRUST_SIGNATURE_SETTINGS)), dwIndex = 0, dwFlags = WSS_GET_SECONDARY_SIG_COUNT, cSecondarySigs = 0, dwVerifiedSigIndex = 0, pCryptoPolicy = IntPtr.Zero, }; pSignatureSettings = Marshal.AllocHGlobal(signatureSettings.cbStruct); } try { if (pSignatureSettings != IntPtr.Zero) { Marshal.StructureToPtr(signatureSettings, pSignatureSettings, false); WVTData.pSignatureSettings = pSignatureSettings; } IntPtr pgActionID = Marshal.AllocHGlobal(actionIdBytes.Length); try { Marshal.Copy(actionIdBytes, 0, pgActionID, actionIdBytes.Length); IntPtr pWVTData = Marshal.AllocHGlobal(WVTData.cbStruct); try { Marshal.StructureToPtr(WVTData, pWVTData, false); int hRESULT = WinVerifyTrust(hWind, pgActionID, pWVTData); if (hRESULT == 0) { if (pSignatureSettings != IntPtr.Zero) { // Read back the signature settings signatureSettings = (WINTRUST_SIGNATURE_SETTINGS)Marshal.PtrToStructure(pSignatureSettings, typeof(WINTRUST_SIGNATURE_SETTINGS)); } int signatureCount = signatureSettings.cSecondarySigs + 1; Console.WriteLine("File: {0}", fileName); Console.WriteLine("Authenticode signatures: {0}", signatureCount); Console.WriteLine(); for (int dwIndex = 0; dwIndex < signatureCount; dwIndex++) { if (pSignatureSettings != IntPtr.Zero) { signatureSettings.dwIndex = dwIndex; signatureSettings.dwFlags = WSS_VERIFY_SPECIFIC; Marshal.StructureToPtr(signatureSettings, pSignatureSettings, false); } WVTData.dwStateAction = WTD_STATEACTION_VERIFY; WVTData.hWVTStateData = IntPtr.Zero; Marshal.StructureToPtr(WVTData, pWVTData, false); hRESULT = WinVerifyTrust(hWind, pgActionID, pWVTData); try { if (hRESULT == 0) { WVTData = (WINTRUST_DATA)Marshal.PtrToStructure(pWVTData, typeof(WINTRUST_DATA)); IntPtr ptrProvData = WTHelperProvDataFromStateData(WVTData.hWVTStateData); CRYPT_PROVIDER_DATA provData = (CRYPT_PROVIDER_DATA)Marshal.PtrToStructure(ptrProvData, typeof(CRYPT_PROVIDER_DATA)); for (int idxSigner = 0; idxSigner < provData.csSigners; idxSigner++) { IntPtr ptrProvSigner = WTHelperGetProvSignerFromChain(ptrProvData, idxSigner, false, 0); CRYPT_PROVIDER_SGNR ProvSigner = (CRYPT_PROVIDER_SGNR)Marshal.PtrToStructure(ptrProvSigner, typeof(CRYPT_PROVIDER_SGNR)); CMSG_SIGNER_INFO Signer = (CMSG_SIGNER_INFO)Marshal.PtrToStructure(ProvSigner.psSigner, typeof(CMSG_SIGNER_INFO)); if (Signer.HashAlgorithm.pszObjId != IntPtr.Zero) { string objId = Marshal.PtrToStringAnsi(Signer.HashAlgorithm.pszObjId); if (objId != null) { Oid hashOid = Oid.FromOidValue(objId, OidGroup.All); if (hashOid != null) { Console.WriteLine("Hash algorithm of signature {0}: {1}.", dwIndex + 1, hashOid.FriendlyName); } } } IntPtr ptrCert = WTHelperGetProvCertFromChain(ptrProvSigner, idxSigner); CRYPT_PROVIDER_CERT cert = (CRYPT_PROVIDER_CERT)Marshal.PtrToStructure(ptrCert, typeof(CRYPT_PROVIDER_CERT)); if (cert.cbStruct > 0) { X509Certificate2 certificate = new X509Certificate2(cert.pCert); Console.WriteLine("Certificate thumbprint of signature {0}: {1}", dwIndex + 1, certificate.Thumbprint); } if (ProvSigner.sftVerifyAsOf.dwHighDateTime != provData.sftSystemTime.dwHighDateTime && ProvSigner.sftVerifyAsOf.dwLowDateTime != provData.sftSystemTime.dwLowDateTime) { DateTime timestamp = DateTime.FromFileTimeUtc(((long)ProvSigner.sftVerifyAsOf.dwHighDateTime << 32) | (uint)ProvSigner.sftVerifyAsOf.dwLowDateTime); Console.WriteLine("Timestamp of signature {0}: {1}", dwIndex + 1, timestamp); } } } } finally { WVTData.dwStateAction = WTD_STATEACTION_CLOSE; Marshal.StructureToPtr(WVTData, pWVTData, false); hRESULT = WinVerifyTrust(hWind, pgActionID, pWVTData); } Console.WriteLine(); } } else if ((uint)hRESULT == 0x800b0100) { Console.WriteLine("{0} has no Authenticode signatures.", fileName); } } finally { Marshal.FreeHGlobal(pWVTData); } } finally { Marshal.FreeHGlobal(pgActionID); } } finally { if (pSignatureSettings != IntPtr.Zero) { Marshal.FreeHGlobal(pSignatureSettings); } } } finally { Marshal.FreeHGlobal(ptrFile); } } finally { Marshal.FreeHGlobal(pcwszFilePath); } Console.WriteLine("Press enter to exit."); Console.ReadLine(); }