基本概念
WinVerifyTrust是Windows系统中用于验证数字签名、证书链和信任状态的核心API。它可以验证文件、目录(catalog)、证书、驱动程序等对象是否可信。
WinVerifyTrust是Windows提供的信任验证接口,位于wintrust.dll。
它的作用是:
验证文件是否有有效的数字签名
验证签名证书是否由受信任的CA颁发
检查证书是否被吊销
验证目录文件(.cat)中的文件哈希是否可信
验证驱动程序、安装包等是否符合Windows信任策略
基本语法
1 2 3 4 5
| LONG WinVerifyTrust( [in] HWND hwnd, [in] GUID *pgActionID, [in] LPVOID pWVTData );
|
返回值
返回值是LONG类型。
常见返回值:
ERROR_SUCCESS (0):验证成功
TRUST_E_NOSIGNATURE:文件没有签名
TRUST_E_EXPLICIT_DISTRUST:被显式标记为不信任
TRUST_E_SUBJECT_NOT_TRUSTED:主题不受信任
CRYPT_E_SECURITY_SETTINGS:系统安全策略阻止验证
TRUST_E_CERT_SIGNATURE:证书签名无效
TRUST_E_REVOCATION_FAILURE:吊销检查失败
TRUST_E_UNKNOWN_CA:未知证书颁发机构
数据类型
HWND:
本质是通过预编译宏将HWND定义为指向匿名结构体的指针类型,是Windows窗口句柄的类型声明。
GUID:
1 2 3 4 5 6
| typedef struct _GUID { unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[ 8 ]; } GUID;
|
这段代码是Windows系统中GUID(Globally Unique Identifier,全局唯一标识符)的官方结构体定义,用于存储一个128位的唯一标识。GUID的核心作用是在整个系统 / 网络中唯一标记某个对象(如接口、策略、组件、文件类型等),确保不会出现重复。
通常GUID会被格式化为字符串,比如:
{00000000-0000-0000-0000-000000000000}
对应字段拆分:
Data1 → 00000000(8 位十六进制)
Data2 → 0000(4 位十六进制)
Data3 → 0000(4 位十六进制)
Data4[0-1] → 0000(4 位十六进制)
Data4[2-7] → 000000000000(12 位十六进制)
参数pWVTData:
当强制转换为WINTRUST_DATA结构时,包含信任提供程序需要处理指定作标识符的信息。
WINTRUST_DATA是Windows信任验证体系中用于配置验证行为的核心结构体,你可以把它理解为给WinVerifyTrust API传递的 “验证指令集”:
告诉API要验证什么(文件 / 目录 / 证书);
告诉API怎么验证(是否显示UI、是否检查证书吊销);
告诉API验证后要做什么(是否保留验证状态)。
它的定义位于wintrust.h头文件中,是调用WinVerifyTrust时必须正确初始化的参数(尤其是cbStruct字段)。
以下是最核心的字段定义(省略了部分不常用字段)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| typedef struct _WINTRUST_DATA { DWORD cbStruct; LPVOID pPolicyCallbackData; LPVOID pSIPClientData; DWORD dwUIChoice; DWORD fdwRevocationChecks; DWORD dwUnionChoice; union { struct WINTRUST_FILE_INFO_ *pFile; struct WINTRUST_CATALOG_INFO_ *pCatalog; struct WINTRUST_BLOB_INFO_ *pBlob; struct WINTRUST_SIGNER_INFO_ *pSigner; struct WINTRUST_CERT_INFO_ *pCert; }; DWORD dwStateAction; HANDLE hWVTStateData; WCHAR *pwszURLReference; DWORD dwProvFlags; DWORD dwUIContext; struct WINTRUST_SIGNATURE_SETTINGS_ *pSignatureSettings; } WINTRUST_DATA, *PWINTRUST_DATA;
|
简单示例
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
| #include <windows.h> #include <wintrust.h> #include <stdio.h>
#pragma comment(lib, "wintrust.lib")
BOOL VerifyFileSignature(LPCWSTR filePath) { WINTRUST_FILE_INFO fileInfo = {0}; fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); fileInfo.pcwszFilePath = filePath; fileInfo.hFile = NULL;
WINTRUST_DATA wtd = {0}; wtd.cbStruct = sizeof(WINTRUST_DATA); wtd.dwUnionChoice = WTD_CHOICE_FILE; wtd.pFile = &fileInfo; wtd.dwUIChoice = WTD_UI_NONE; wtd.fdwRevocationChecks = WTD_REVOKE_NONE; wtd.dwProvFlags = WTD_REVOCATION_CHECK_NONE; wtd.dwStateAction = 0;
GUID policyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
LONG lStatus = WinVerifyTrust(NULL, &policyGUID, &wtd);
if (lStatus == ERROR_SUCCESS) { wprintf(L"文件 \"%s\" 签名验证通过!\n", filePath); return TRUE; } else { wprintf(L"文件 \"%s\" 签名验证失败!错误码:0x%08X\n", filePath, lStatus); switch (lStatus) { case TRUST_E_NOSIGNATURE: wprintf(L" 原因:文件没有数字签名\n"); break; case TRUST_E_EXPLICIT_DISTRUST: wprintf(L" 原因:签名被系统显式标记为不信任\n"); break; case TRUST_E_SUBJECT_NOT_TRUSTED: wprintf(L" 原因:签名证书不受信任\n"); break; case CRYPT_E_SECURITY_SETTINGS: wprintf(L" 原因:系统安全策略阻止了验证\n"); break; default: wprintf(L" 原因:其他验证错误(可参考 WinError.h 查看错误码含义)\n"); break; } return FALSE; } }
int wmain(int argc, wchar_t* argv[]) { if (argc != 2) { wprintf(L"使用方法:%s <要验证的文件路径>\n", argv[0]); wprintf(L"示例:%s C:\\Windows\\notepad.exe\n", argv[0]); return 1; }
VerifyFileSignature(argv[1]);
return 0; }
|