工作中碰到需要判断一个PE文件是否是所确认的文件,而不是被替换过的。直接判断文件名的话有些不保险,别人只要修改下文件名,就可以以假乱真。
因而需要判断额外的信息;由于文件有数字签名,判断数字签名因而是一个比较好的方法,但是如果只是判断数字签名是否有效也不够,别人只要用自己的证书重新签名就可以了,所以需要判断证书签名者信息。
验证文件数字签名是否有效可以使用函数 WinVerifyTrust
取得文件数字签名证书信息需要使用函数 CryptQueryObject。
下面是一段从网上搜到的获得文件数字签名证书信息的代码:
- 1 #include <windows.h>
- 2 #include <wincrypt.h>
- 3 #include <wintrust.h>
- 4 #include <stdio.h>
- 5 #include <tchar.h>
- 6 #pragma comment(lib, "crypt32.lib")
- 7 #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
- 8 typedef struct {
- 9 LPWSTR lpszProgramName;
- 10 LPWSTR lpszPublisherLink;
- 11 LPWSTR lpszMoreInfoLink;
- 12 } SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO;
- 13 BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
- 14 PSPROG_PUBLISHERINFO Info);
- 15 BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st);
- 16 BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext);
- 17 BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo,
- 18 PCMSG_SIGNER_INFO *pCounterSignerInfo);
- 19 int _tmain(int argc, TCHAR *argv[])
- 20 {
- 21 WCHAR szFileName[MAX_PATH];
- 22 HCERTSTORE hStore = NULL;
- 23 HCRYPTMSG hMsg = NULL;
- 24 PCCERT_CONTEXT pCertContext = NULL;
- 25 BOOL fResult;
- 26 DWORD dwEncoding, dwContentType, dwFormatType;
- 27 PCMSG_SIGNER_INFO pSignerInfo = NULL;
- 28 PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
- 29 DWORD dwSignerInfo;
- 30 CERT_INFO CertInfo;
- 31 SPROG_PUBLISHERINFO ProgPubInfo;
- 32 SYSTEMTIME st;
- 33 ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo));
- 34 __try
- 35 {
- 36 if (argc != 2)
- 37 {
- 38 _tprintf(_T("Usage: SignedFileInfo <filename>\n"));
- 39 return 0;
- 40 }
- 41 #ifdef UNICODE
- 42 lstrcpynW(szFileName, argv[1], MAX_PATH);
- 43 #else
- 44 if (mbstowcs(szFileName, argv[1], MAX_PATH) == -1)
- 45 {
- 46 printf("Unable to convert to unicode.\n");
- 47 __leave;
- 48 }
- 49 #endif
- 50 // Get message handle and store handle from the signed file.
- 51 fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
- 52 szFileName,
- 53 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
- 54 CERT_QUERY_FORMAT_FLAG_BINARY,
- 55 0,
- 56 &dwEncoding,
- 57 &dwContentType,
- 58 &dwFormatType,
- 59 &hStore,
- 60 &hMsg,
- 61 NULL);
- 62 if (!fResult)
- 63 {
- 64 _tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError());
- 65 __leave;
- 66 }
- 67 // Get signer information size.
- 68 fResult = CryptMsgGetParam(hMsg,
- 69 CMSG_SIGNER_INFO_PARAM,
- 70 0,
- 71 NULL,
- 72 &dwSignerInfo);
- 73 if (!fResult)
- 74 {
- 75 _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
- 76 __leave;
- 77 }
- 78 // Allocate memory for signer information.
- 79 pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
- 80 if (!pSignerInfo)
- 81 {
- 82 _tprintf(_T("Unable to allocate memory for Signer Info.\n"));
- 83 __leave;
- 84 }
- 85 // Get Signer Information.
- 86 fResult = CryptMsgGetParam(hMsg,
- 87 CMSG_SIGNER_INFO_PARAM,
- 88 0,
- 89 (PVOID)pSignerInfo,
- 90 &dwSignerInfo);
- 91 if (!fResult)
- 92 {
- 93 _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
- 94 __leave;
- 95 }
- 96 // Get program name and publisher information from
- 97 // signer info structure.
- 98 if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo))
- 99 {
- 100 if (ProgPubInfo.lpszProgramName != NULL)
- 101 {
- 102 wprintf(L"Program Name : %s\n",
- 103 ProgPubInfo.lpszProgramName);
- 104 }
- 105 if (ProgPubInfo.lpszPublisherLink != NULL)
- 106 {
- 107 wprintf(L"Publisher Link : %s\n",
- 108 ProgPubInfo.lpszPublisherLink);
- 109 }
- 110 if (ProgPubInfo.lpszMoreInfoLink != NULL)
- 111 {
- 112 wprintf(L"MoreInfo Link : %s\n",
- 113 ProgPubInfo.lpszMoreInfoLink);
- 114 }
- 115 }
- 116 _tprintf(_T("\n"));
- 117 // Search for the signer certificate in the temporary
- 118 // certificate store.
- 119 CertInfo.Issuer = pSignerInfo->Issuer;
- 120 CertInfo.SerialNumber = pSignerInfo->SerialNumber;
- 121 pCertContext = CertFindCertificateInStore(hStore,
- 122 ENCODING,
- 123 0,
- 124 CERT_FIND_SUBJECT_CERT,
- 125 (PVOID)&CertInfo,
- 126 NULL);
- 127 if (!pCertContext)
- 128 {
- 129 _tprintf(_T("CertFindCertificateInStore failed with %x\n"),
- 130 GetLastError());
- 131 __leave;
- 132 }
- 133 // Print Signer certificate information.
- 134 _tprintf(_T("Signer Certificate:\n\n"));
- 135 PrintCertificateInfo(pCertContext);
- 136 _tprintf(_T("\n"));
- 137 // Get the timestamp certificate signerinfo structure.
- 138 if (GetTimeStampSignerInfo(pSignerInfo, &pCounterSignerInfo))
- 139 {
- 140 // Search for Timestamp certificate in the temporary
- 141 // certificate store.
- 142 CertInfo.Issuer = pCounterSignerInfo->Issuer;
- 143 CertInfo.SerialNumber = pCounterSignerInfo->SerialNumber;
- 144 pCertContext = CertFindCertificateInStore(hStore,
- 145 ENCODING,
- 146 0,
- 147 CERT_FIND_SUBJECT_CERT,
- 148 (PVOID)&CertInfo,
- 149 NULL);
- 150 if (!pCertContext)
- 151 {
- 152 _tprintf(_T("CertFindCertificateInStore failed with %x\n"),
- 153 GetLastError());
- 154 __leave;
- 155 }
- 156 // Print timestamp certificate information.
- 157 _tprintf(_T("TimeStamp Certificate:\n\n"));
- 158 PrintCertificateInfo(pCertContext);
- 159 _tprintf(_T("\n"));
- 160 // Find Date of timestamp.
- 161 if (GetDateOfTimeStamp(pCounterSignerInfo, &st))
- 162 {
- 163 _tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"),
- 164 st.wMonth,
- 165 st.wDay,
- 166 st.wYear,
- 167 st.wHour,
- 168 st.wMinute);
- 169 }
- 170 _tprintf(_T("\n"));
- 171 }
- 172 }
- 173 __finally
- 174 {
- 175 // Clean up.
- 176 if (ProgPubInfo.lpszProgramName != NULL)
- 177 LocalFree(ProgPubInfo.lpszProgramName);
- 178 if (ProgPubInfo.lpszPublisherLink != NULL)
- 179 LocalFree(ProgPubInfo.lpszPublisherLink);
- 180 if (ProgPubInfo.lpszMoreInfoLink != NULL)
- 181 LocalFree(ProgPubInfo.lpszMoreInfoLink);
- 182 if (pSignerInfo != NULL) LocalFree(pSignerInfo);
- 183 if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo);
- 184 if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
- 185 if (hStore != NULL) CertCloseStore(hStore, 0);
- 186 if (hMsg != NULL) CryptMsgClose(hMsg);
- 187 }
- 188 return 0;
- 189 }
- 190 BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext)
- 191 {
- 192 BOOL fReturn = FALSE;
- 193 LPTSTR szName = NULL;
- 194 DWORD dwData;
- 195 __try
- 196 {
- 197 // Print Serial Number.
- 198 _tprintf(_T("Serial Number: "));
- 199 dwData = pCertContext->pCertInfo->SerialNumber.cbData;
- 200 for (DWORD n = 0; n < dwData; n++)
- 201 {
- 202 _tprintf(_T("%02x "),
- 203 pCertContext->pCertInfo->SerialNumber.pbData[dwData - (n + 1)]);
- 204 }
- 205 _tprintf(_T("\n"));
- 206 // Get Issuer name size.
- 207 if (!(dwData = CertGetNameString(pCertContext,
- 208 CERT_NAME_SIMPLE_DISPLAY_TYPE,
- 209 CERT_NAME_ISSUER_FLAG,
- 210 NULL,
- 211 NULL,
- 212 0)))
- 213 {
- 214 _tprintf(_T("CertGetNameString failed.\n"));
- 215 __leave;
- 216 }
- 217 // Allocate memory for Issuer name.
- 218 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
- 219 if (!szName)
- 220 {
- 221 _tprintf(_T("Unable to allocate memory for issuer name.\n"));
- 222 __leave;
- 223 }
- 224 // Get Issuer name.
- 225 if (!(CertGetNameString(pCertContext,
- 226 CERT_NAME_SIMPLE_DISPLAY_TYPE,
- 227 CERT_NAME_ISSUER_FLAG,
- 228 NULL,
- 229 szName,
- 230 dwData)))
- 231 {
- 232 _tprintf(_T("CertGetNameString failed.\n"));
- 233 __leave;
- 234 }
- 235 // print Issuer name.
- 236 _tprintf(_T("Issuer Name: %s\n"), szName);
- 237 LocalFree(szName);
- 238 szName = NULL;
- 239 // Get Subject name size.
- 240 if (!(dwData = CertGetNameString(pCertContext,
- 241 CERT_NAME_SIMPLE_DISPLAY_TYPE,
- 242 0,
- 243 NULL,
- 244 NULL,
- 245 0)))
- 246 {
- 247 _tprintf(_T("CertGetNameString failed.\n"));
- 248 __leave;
- 249 }
- 250 // Allocate memory for subject name.
- 251 szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
- 252 if (!szName)
- 253 {
- 254 _tprintf(_T("Unable to allocate memory for subject name.\n"));
- 255 __leave;
- 256 }
- 257 // Get subject name.
- 258 if (!(CertGetNameString(pCertContext,
- 259 CERT_NAME_SIMPLE_DISPLAY_TYPE,
- 260 0,
- 261 NULL,
- 262 szName,
- 263 dwData)))
- 264 {
- 265 _tprintf(_T("CertGetNameString failed.\n"));
- 266 __leave;
- 267 }
- 268 // Print Subject Name.
- 269 _tprintf(_T("Subject Name: %s\n"), szName);
- 270 fReturn = TRUE;
- 271 }
- 272 __finally
- 273 {
- 274 if (szName != NULL) LocalFree(szName);
- 275 }
- 276 return fReturn;
- 277 }
- 278 LPWSTR AllocateAndCopyWideString(LPCWSTR inputString)
- 279 {
- 280 LPWSTR outputString = NULL;
- 281 outputString = (LPWSTR)LocalAlloc(LPTR,
- 282 (wcslen(inputString) + 1) * sizeof(WCHAR));
- 283 if (outputString != NULL)
- 284 {
- 285 lstrcpyW(outputString, inputString);
- 286 }
- 287 return outputString;
- 288 }
- 289 BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
- 290 PSPROG_PUBLISHERINFO Info)
- 291 {
- 292 BOOL fReturn = FALSE;
- 293 PSPC_SP_OPUS_INFO OpusInfo = NULL;
- 294 DWORD dwData;
- 295 BOOL fResult;
- 296 __try
- 297 {
- 298 // Loop through authenticated attributes and find
- 299 // SPC_SP_OPUS_INFO_OBJID OID.
- 300 for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
- 301 {
- 302 if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID,
- 303 pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
- 304 {
- 305 // Get Size of SPC_SP_OPUS_INFO structure.
- 306 fResult = CryptDecodeObject(ENCODING,
- 307 SPC_SP_OPUS_INFO_OBJID,
- 308 pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
- 309 pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
- 310 0,
- 311 NULL,
- 312 &dwData);
- 313 if (!fResult)
- 314 {
- 315 _tprintf(_T("CryptDecodeObject failed with %x\n"),
- 316 GetLastError());
- 317 __leave;
- 318 }
- 319 // Allocate memory for SPC_SP_OPUS_INFO structure.
- 320 OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData);
- 321 if (!OpusInfo)
- 322 {
- 323 _tprintf(_T("Unable to allocate memory for Publisher Info.\n"));
- 324 __leave;
- 325 }
- 326 // Decode and get SPC_SP_OPUS_INFO structure.
- 327 fResult = CryptDecodeObject(ENCODING,
- 328 SPC_SP_OPUS_INFO_OBJID,
- 329 pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
- 330 pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
- 331 0,
- 332 OpusInfo,
- 333 &dwData);
- 334 if (!fResult)
- 335 {
- 336 _tprintf(_T("CryptDecodeObject failed with %x\n"),
- 337 GetLastError());
- 338 __leave;
- 339 }
- 340 // Fill in Program Name if present.
- 341 if (OpusInfo->pwszProgramName)
- 342 {
- 343 Info->lpszProgramName =
- 344 AllocateAndCopyWideString(OpusInfo->pwszProgramName);
- 345 }
- 346 else
- 347 Info->lpszProgramName = NULL;
- 348 // Fill in Publisher Information if present.
- 349 if (OpusInfo->pPublisherInfo)
- 350 {
- 351 switch (OpusInfo->pPublisherInfo->dwLinkChoice)
- 352 {
- 353 case SPC_URL_LINK_CHOICE:
- 354 Info->lpszPublisherLink =
- 355 AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl);
- 356 break;
- 357 case SPC_FILE_LINK_CHOICE:
- 358 Info->lpszPublisherLink =
- 359 AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile);
- 360 break;
- 361 default:
- 362 Info->lpszPublisherLink = NULL;
- 363 break;
- 364 }
- 365 }
- 366 else
- 367 {
- 368 Info->lpszPublisherLink = NULL;
- 369 }
- 370 // Fill in More Info if present.
- 371 if (OpusInfo->pMoreInfo)
- 372 {
- 373 switch (OpusInfo->pMoreInfo->dwLinkChoice)
- 374 {
- 375 case SPC_URL_LINK_CHOICE:
- 376 Info->lpszMoreInfoLink =
- 377 AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl);
- 378 break;
- 379 case SPC_FILE_LINK_CHOICE:
- 380 Info->lpszMoreInfoLink =
- 381 AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile);
- 382 break;
- 383 default:
- 384 Info->lpszMoreInfoLink = NULL;
- 385 break;
- 386 }
- 387 }
- 388 else
- 389 {
- 390 Info->lpszMoreInfoLink = NULL;
- 391 }
- 392 fReturn = TRUE;
- 393 break; // Break from for loop.
- 394 } // lstrcmp SPC_SP_OPUS_INFO_OBJID
- 395 } // for
- 396 }
- 397 __finally
- 398 {
- 399 if (OpusInfo != NULL) LocalFree(OpusInfo);
- 400 }
- 401 return fReturn;
- 402 }
- 403 BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st)
- 404 {
- 405 BOOL fResult;
- 406 FILETIME lft, ft;
- 407 DWORD dwData;
- 408 BOOL fReturn = FALSE;
- 409 // Loop through authenticated attributes and find
- 410 // szOID_RSA_signingTime OID.
- 411 for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
- 412 {
- 413 if (lstrcmpA(szOID_RSA_signingTime,
- 414 pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
- 415 {
- 416 // Decode and get FILETIME structure.
- 417 dwData = sizeof(ft);
- 418 fResult = CryptDecodeObject(ENCODING,
- 419 szOID_RSA_signingTime,
- 420 pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
- 421 pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
- 422 0,
- 423 (PVOID)&ft,
- 424 &dwData);
- 425 if (!fResult)
- 426 {
- 427 _tprintf(_T("CryptDecodeObject failed with %x\n"),
- 428 GetLastError());
- 429 break;
- 430 }
- 431 // Convert to local time.
- 432 FileTimeToLocalFileTime(&ft, &lft);
- 433 FileTimeToSystemTime(&lft, st);
- 434 fReturn = TRUE;
- 435 break; // Break from for loop.
- 436 } //lstrcmp szOID_RSA_signingTime
- 437 } // for
- 438 return fReturn;
- 439 }
- 440 BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO *pCounterSignerInfo)
- 441 {
- 442 PCCERT_CONTEXT pCertContext = NULL;
- 443 BOOL fReturn = FALSE;
- 444 BOOL fResult;
- 445 DWORD dwSize;
- 446 __try
- 447 {
- 448 *pCounterSignerInfo = NULL;
- 449 // Loop through unathenticated attributes for
- 450 // szOID_RSA_counterSign OID.
- 451 for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
- 452 {
- 453 if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId,
- 454 szOID_RSA_counterSign) == 0)
- 455 {
- 456 // Get size of CMSG_SIGNER_INFO structure.
- 457 fResult = CryptDecodeObject(ENCODING,
- 458 PKCS7_SIGNER_INFO,
- 459 pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
- 460 pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
- 461 0,
- 462 NULL,
- 463 &dwSize);
- 464 if (!fResult)
- 465 {
- 466 _tprintf(_T("CryptDecodeObject failed with %x\n"),
- 467 GetLastError());
- 468 __leave;
- 469 }
- 470 // Allocate memory for CMSG_SIGNER_INFO.
- 471 *pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
- 472 if (!*pCounterSignerInfo)
- 473 {
- 474 _tprintf(_T("Unable to allocate memory for timestamp info.\n"));
- 475 __leave;
- 476 }
- 477 // Decode and get CMSG_SIGNER_INFO structure
- 478 // for timestamp certificate.
- 479 fResult = CryptDecodeObject(ENCODING,
- 480 PKCS7_SIGNER_INFO,
- 481 pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
- 482 pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
- 483 0,
- 484 (PVOID)*pCounterSignerInfo,
- 485 &dwSize);
- 486 if (!fResult)
- 487 {
- 488 _tprintf(_T("CryptDecodeObject failed with %x\n"),
- 489 GetLastError());
- 490 __leave;
- 491 }
- 492 fReturn = TRUE;
- 493 break; // Break from for loop.
- 494 }
- 495 }
- 496 }
- 497 __finally
- 498 {
- 499 // Clean up.
- 500 if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
- 501 }
- 502 return fReturn;
- 503 }