/** * Verifies a file's digital signature. * * \param FileName A file name. * \param SignerName A variable which receives a pointer * to a string containing the signer name. You must free * the string using PhDereferenceObject() when you no * longer need it. Note that the signer name may be NULL * if it is not valid. * * \return A VERIFY_RESULT value. */ VERIFY_RESULT PhVerifyFile( __in PWSTR FileName, __out_opt PPH_STRING *SignerName ) { VERIFY_RESULT result; if (PhBeginInitOnce(&PhpVerifyInitOnce)) { PhpVerifyInitialization(); PhEndInitOnce(&PhpVerifyInitOnce); } // Make sure we have successfully imported // the required functions. if ( !CryptCATAdminCalcHashFromFileHandle || !CryptCATAdminAcquireContext || !CryptCATAdminEnumCatalogFromHash || !CryptCATCatalogInfoFromContext || !CryptCATAdminReleaseCatalogContext || !CryptCATAdminReleaseContext || !WinVerifyTrust_I || !WTHelperProvDataFromStateData_I || !WTHelperGetProvSignerFromChain_I || !CertNameToStr_I ) return VrUnknown; result = PhpVerifyFileBasic(FileName, SignerName); if (result == VrNoSignature) result = PhpVerifyFileFromCatalog(FileName, SignerName); return result; }
NTSTATUS PhVerifyFileEx( _In_ PPH_VERIFY_FILE_INFO Information, _Out_ VERIFY_RESULT *VerifyResult, _Out_opt_ PCERT_CONTEXT **Signatures, _Out_opt_ PULONG NumberOfSignatures ) { NTSTATUS status; HANDLE fileHandle; VERIFY_RESULT verifyResult; PCERT_CONTEXT *signatures; ULONG numberOfSignatures; WINTRUST_FILE_INFO fileInfo = { 0 }; if (PhBeginInitOnce(&PhpVerifyInitOnce)) { PhpVerifyInitialization(); PhEndInitOnce(&PhpVerifyInitOnce); } // Make sure we have successfully imported // the required functions. if ( !CryptCATAdminCalcHashFromFileHandle || !CryptCATAdminAcquireContext || !CryptCATAdminEnumCatalogFromHash || !CryptCATCatalogInfoFromContext || !CryptCATAdminReleaseCatalogContext || !CryptCATAdminReleaseContext || !WinVerifyTrust_I || !WTHelperProvDataFromStateData_I || !WTHelperGetProvSignerFromChain_I || !CertNameToStr_I || !CertDuplicateCertificateContext_I || !CertFreeCertificateContext_I ) return STATUS_NOT_SUPPORTED; if (!NT_SUCCESS(status = PhCreateFileWin32( &fileHandle, Information->FileName, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) return status; fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); fileInfo.pcwszFilePath = Information->FileName; fileInfo.hFile = fileHandle; verifyResult = PhpVerifyFile(Information, fileHandle, WTD_CHOICE_FILE, &fileInfo, &WinTrustActionGenericVerifyV2, NULL, &signatures, &numberOfSignatures); if (verifyResult == VrNoSignature) { if (CryptCATAdminAcquireContext2 && CryptCATAdminCalcHashFromFileHandle2) { PhFreeVerifySignatures(signatures, numberOfSignatures); verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, BCRYPT_SHA256_ALGORITHM, &signatures, &numberOfSignatures); } if (verifyResult != VrTrusted) { PhFreeVerifySignatures(signatures, numberOfSignatures); verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, NULL, &signatures, &numberOfSignatures); } } *VerifyResult = verifyResult; if (Signatures) *Signatures = signatures; else PhFreeVerifySignatures(signatures, numberOfSignatures); if (NumberOfSignatures) *NumberOfSignatures = numberOfSignatures; NtClose(fileHandle); return STATUS_SUCCESS; }