主要函数说明:
验证文件数字签名是否有效可以使用函数 WinVerifyTrust
取得文件数字签名证书信息需要使用函数 CryptQueryObject。
一、数字签名获取
// FileSign.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <stdio.h>
#include <tchar.h>
#pragma comment(lib, "crypt32.lib")
#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
typedef struct {
LPWSTR lpszProgramName;//程序名
LPWSTR lpszPublisherLink;//发布者链接
LPWSTR lpszMoreInfoLink;//更多信息链接
} SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO;
BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_PUBLISHERINFO Info);
//获取时间戳日期
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st);
//打印证书信息
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext);
//获取签名信息的时间戳
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo,
PCMSG_SIGNER_INFO *pCounterSignerInfo);
int _tmain(int argc, TCHAR *argv[])
{
WCHAR szFileName[MAX_PATH];
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PCCERT_CONTEXT pCertContext = NULL;
BOOL fResult;
DWORD dwEncoding, dwContentType, dwFormatType;
PCMSG_SIGNER_INFO pSignerInfo = NULL;
PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
DWORD dwSignerInfo;
CERT_INFO CertInfo;
SPROG_PUBLISHERINFO ProgPubInfo;
SYSTEMTIME st;
ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo));
__try
{
if (argc != 2)
{
_tprintf(_T("Usage: SignedFileInfo <filename>\n"));
//return 0;
}
#ifdef UNICODE
lstrcpynW(szFileName, argv[1], MAX_PATH);
#else
if (mbstowcs(szFileName, argv[1], MAX_PATH) == -1)
{
printf("Unable to convert to unicode.\n");
__leave;
}
#endif
// Get message handle and store handle from the signed file.
//查询签名信息
fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
CERT_QUERY_FORMAT_FLAG_BINARY,
0,
&dwEncoding,
&dwContentType,
&dwFormatType,
&hStore,
&hMsg,
NULL);
if (!fResult)
{
_tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError());
__leave;
}
// Get signer information size.
fResult = CryptMsgGetParam(hMsg,
CMSG_SIGNER_INFO_PARAM,
0,
NULL,
&dwSignerInfo);
if (!fResult)
{
_tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
__leave;
}
// Allocate memory for signer information.
pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
if (!pSignerInfo)
{
_tprintf(_T("Unable to allocate memory for Signer Info.\n"));
__leave;
}
// Get Signer Information.
fResult = CryptMsgGetParam(hMsg,
CMSG_SIGNER_INFO_PARAM,
0,
(PVOID)pSignerInfo,
&dwSignerInfo);
if (!fResult)
{
_tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError());
__leave;
}
// Get program name and publisher information from
// signer info structure.
//获取程序名和发布者信息
if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo))
{
if (ProgPubInfo.lpszProgramName != NULL)
{
wprintf(L"Program Name : %s\n",
ProgPubInfo.lpszProgramName);
}
if (ProgPubInfo.lpszPublisherLink != NULL)
{
wprintf(L"Publisher Link : %s\n",
ProgPubInfo.lpszPublisherLink);
}
if (ProgPubInfo.lpszMoreInfoLink != NULL)
{
wprintf(L"MoreInfo Link : %s\n",
ProgPubInfo.lpszMoreInfoLink);
}
}
_tprintf(_T("\n"));
// Search for the signer certificate in the temporary
// certificate store.
CertInfo.Issuer = pSignerInfo->Issuer;
CertInfo.SerialNumber = pSignerInfo->SerialNumber;
pCertContext = CertFindCertificateInStore(hStore,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&CertInfo,
NULL);
if (!pCertContext)
{
_tprintf(_T("CertFindCertificateInStore failed with %x\n"),
GetLastError());
__leave;
}
// Print Signer certificate information.
_tprintf(_T("Signer Certificate:\n\n"));
PrintCertificateInfo(pCertContext);
_tprintf(_T("\n"));
// Get the timestamp certificate signerinfo structure.
if (GetTimeStampSignerInfo(pSignerInfo, &pCounterSignerInfo))
{
// Search for Timestamp certificate in the temporary
// certificate store.
CertInfo.Issuer = pCounterSignerInfo->Issuer;
CertInfo.SerialNumber = pCounterSignerInfo->SerialNumber;
pCertContext = CertFindCertificateInStore(hStore,
ENCODING,
0,
CERT_FIND_SUBJECT_CERT,
(PVOID)&CertInfo,
NULL);
if (!pCertContext)
{
_tprintf(_T("CertFindCertificateInStore failed with %x\n"),
GetLastError());
__leave;
}
// Print timestamp certificate information.
_tprintf(_T("TimeStamp Certificate:\n\n"));
PrintCertificateInfo(pCertContext);
_tprintf(_T("\n"));
// Find Date of timestamp.
if (GetDateOfTimeStamp(pCounterSignerInfo, &st))
{
_tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"),
st.wMonth,
st.wDay,
st.wYear,
st.wHour,
st.wMinute);
}
_tprintf(_T("\n"));
}
}
__finally
{
// Clean up.
if (ProgPubInfo.lpszProgramName != NULL)
LocalFree(ProgPubInfo.lpszProgramName);
if (ProgPubInfo.lpszPublisherLink != NULL)
LocalFree(ProgPubInfo.lpszPublisherLink);
if (ProgPubInfo.lpszMoreInfoLink != NULL)
LocalFree(ProgPubInfo.lpszMoreInfoLink);
if (pSignerInfo != NULL) LocalFree(pSignerInfo);
if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo);
if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
if (hStore != NULL) CertCloseStore(hStore, 0);
if (hMsg != NULL) CryptMsgClose(hMsg);
}
return 0;
}
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext)
{
BOOL fReturn = FALSE;
LPTSTR szName = NULL;
DWORD dwData;
__try
{
// Print Serial Number.
_tprintf(_T("Serial Number: "));
dwData = pCertContext->pCertInfo->SerialNumber.cbData;
for (DWORD n = 0; n < dwData; n++)
{
_tprintf(_T("%02x "),
pCertContext->pCertInfo->SerialNumber.pbData[dwData - (n + 1)]);
}
_tprintf(_T("\n"));
// Get Issuer name size.
if (!(dwData = CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
NULL,
0)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Allocate memory for Issuer name.
szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
if (!szName)
{
_tprintf(_T("Unable to allocate memory for issuer name.\n"));
__leave;
}
// Get Issuer name.
if (!(CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
szName,
dwData)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// print Issuer name.
_tprintf(_T("Issuer Name: %s\n"), szName);
LocalFree(szName);
szName = NULL;
// Get Subject name size.
if (!(dwData = CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Allocate memory for subject name.
szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
if (!szName)
{
_tprintf(_T("Unable to allocate memory for subject name.\n"));
__leave;
}
// Get subject name.
if (!(CertGetNameString(pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
szName,
dwData)))
{
_tprintf(_T("CertGetNameString failed.\n"));
__leave;
}
// Print Subject Name.
_tprintf(_T("Subject Name: %s\n"), szName);
fReturn = TRUE;
}
__finally
{
if (szName != NULL) LocalFree(szName);
}
return fReturn;
}
LPWSTR AllocateAndCopyWideString(LPCWSTR inputString)
{
LPWSTR outputString = NULL;
outputString = (LPWSTR)LocalAlloc(LPTR,
(wcslen(inputString) + 1) * sizeof(WCHAR));
if (outputString != NULL)
{
lstrcpyW(outputString, inputString);
}
return outputString;
}
BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo,
PSPROG_PUBLISHERINFO Info)
{
BOOL fReturn = FALSE;
PSPC_SP_OPUS_INFO OpusInfo = NULL;
DWORD dwData;
BOOL fResult;
__try
{
// Loop through authenticated attributes and find
// SPC_SP_OPUS_INFO_OBJID OID.
for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
{
if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
{
// Get Size of SPC_SP_OPUS_INFO structure.
fResult = CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
NULL,
&dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Allocate memory for SPC_SP_OPUS_INFO structure.
OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData);
if (!OpusInfo)
{
_tprintf(_T("Unable to allocate memory for Publisher Info.\n"));
__leave;
}
// Decode and get SPC_SP_OPUS_INFO structure.
fResult = CryptDecodeObject(ENCODING,
SPC_SP_OPUS_INFO_OBJID,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
OpusInfo,
&dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Fill in Program Name if present.
if (OpusInfo->pwszProgramName)
{
Info->lpszProgramName =
AllocateAndCopyWideString(OpusInfo->pwszProgramName);
}
else
Info->lpszProgramName = NULL;
// Fill in Publisher Information if present.
if (OpusInfo->pPublisherInfo)
{
switch (OpusInfo->pPublisherInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
Info->lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
Info->lpszPublisherLink =
AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile);
break;
default:
Info->lpszPublisherLink = NULL;
break;
}
}
else
{
Info->lpszPublisherLink = NULL;
}
// Fill in More Info if present.
if (OpusInfo->pMoreInfo)
{
switch (OpusInfo->pMoreInfo->dwLinkChoice)
{
case SPC_URL_LINK_CHOICE:
Info->lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl);
break;
case SPC_FILE_LINK_CHOICE:
Info->lpszMoreInfoLink =
AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile);
break;
default:
Info->lpszMoreInfoLink = NULL;
break;
}
}
else
{
Info->lpszMoreInfoLink = NULL;
}
fReturn = TRUE;
break; // Break from for loop.
} // lstrcmp SPC_SP_OPUS_INFO_OBJID
} // for
}
__finally
{
if (OpusInfo != NULL) LocalFree(OpusInfo);
}
return fReturn;
}
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st)
{
BOOL fResult;
FILETIME lft, ft;
DWORD dwData;
BOOL fReturn = FALSE;
// Loop through authenticated attributes and find
// szOID_RSA_signingTime OID.
for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++)
{
if (lstrcmpA(szOID_RSA_signingTime,
pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0)
{
// Decode and get FILETIME structure.
dwData = sizeof(ft);
fResult = CryptDecodeObject(ENCODING,
szOID_RSA_signingTime,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData,
0,
(PVOID)&ft,
&dwData);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
break;
}
// Convert to local time.
FileTimeToLocalFileTime(&ft, &lft);
FileTimeToSystemTime(&lft, st);
fReturn = TRUE;
break; // Break from for loop.
} //lstrcmp szOID_RSA_signingTime
} // for
return fReturn;
}
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO *pCounterSignerInfo)
{
PCCERT_CONTEXT pCertContext = NULL;
BOOL fReturn = FALSE;
BOOL fResult;
DWORD dwSize;
__try
{
*pCounterSignerInfo = NULL;
// Loop through unathenticated attributes for
// szOID_RSA_counterSign OID.
for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
{
if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId,
szOID_RSA_counterSign) == 0)
{
// Get size of CMSG_SIGNER_INFO structure.
fResult = CryptDecodeObject(ENCODING,
PKCS7_SIGNER_INFO,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
0,
NULL,
&dwSize);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
// Allocate memory for CMSG_SIGNER_INFO.
*pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
if (!*pCounterSignerInfo)
{
_tprintf(_T("Unable to allocate memory for timestamp info.\n"));
__leave;
}
// Decode and get CMSG_SIGNER_INFO structure
// for timestamp certificate.
fResult = CryptDecodeObject(ENCODING,
PKCS7_SIGNER_INFO,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
0,
(PVOID)*pCounterSignerInfo,
&dwSize);
if (!fResult)
{
_tprintf(_T("CryptDecodeObject failed with %x\n"),
GetLastError());
__leave;
}
fReturn = TRUE;
break; // Break from for loop.
}
}
}
__finally
{
// Clean up.
if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
}
return fReturn;
}
二、数字签名认证
转载: https://blog.csdn.net/a33445621/article/details/54969846
// FileSign.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#define _WIN32_WINNT 0x0500
#define WINVER 0x0500
#include <windows.h>
#include <Softpub.h>
#include <Wincrypt.h>
#include <tchar.h>
#include <stdlib.h>
#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "Wintrust.lib")
LPTSTR GetCertificateDescription(PCCERT_CONTEXT pCertCtx)
{
DWORD dwStrType;
DWORD dwCount;
LPTSTR szSubjectRDN = NULL;
dwStrType = CERT_X500_NAME_STR;
dwCount = CertGetNameString(pCertCtx,
CERT_NAME_RDN_TYPE,
0,
&dwStrType,
NULL,
0);
if (dwCount)
{
szSubjectRDN = (LPTSTR)LocalAlloc(0, dwCount * sizeof(TCHAR));
CertGetNameString(pCertCtx,
CERT_NAME_RDN_TYPE,
0,
&dwStrType,
szSubjectRDN,
dwCount);
}
return szSubjectRDN;
}
int _tmain(int argc, _TCHAR* argv[])
{
GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_FILE_INFO sWintrustFileInfo;
WINTRUST_DATA sWintrustData;
HRESULT hr;
if (argc != 2)
{
_tprintf(_T("Usage: VerifyExeSignature file_name\n"));
return -1;
}
memset((void*)&sWintrustFileInfo, 0x00, sizeof(WINTRUST_FILE_INFO));
memset((void*)&sWintrustData, 0x00, sizeof(WINTRUST_DATA));
sWintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
sWintrustFileInfo.pcwszFilePath = argv[1];
sWintrustFileInfo.hFile = NULL;
sWintrustData.cbStruct = sizeof(WINTRUST_DATA);
sWintrustData.dwUIChoice = WTD_UI_NONE;
sWintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
sWintrustData.dwUnionChoice = WTD_CHOICE_FILE;
sWintrustData.pFile = &sWintrustFileInfo;
sWintrustData.dwStateAction = WTD_STATEACTION_VERIFY;
hr = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);
if (TRUST_E_NOSIGNATURE == hr)
{
_tprintf(_T("No signature found on the file.\n"));
}
else if (TRUST_E_BAD_DIGEST == hr)
{
_tprintf(_T("The signature of the file is invalid\n"));
}
else if (TRUST_E_PROVIDER_UNKNOWN == hr)
{
_tprintf(_T("No trust provider on this machine can verify this type of files.\n"));
}
else if (S_OK != hr)
{
_tprintf(_T("WinVerifyTrust failed with error 0x%.8X\n"), hr);
}
else
{
_tprintf(_T("File signature is OK.\n"));
// retreive the signer certificate and display its information
CRYPT_PROVIDER_DATA const *psProvData = NULL;
CRYPT_PROVIDER_SGNR *psProvSigner = NULL;
CRYPT_PROVIDER_CERT *psProvCert = NULL;
FILETIME localFt;
SYSTEMTIME sysTime;
psProvData = WTHelperProvDataFromStateData(sWintrustData.hWVTStateData);
if (psProvData)
{
psProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)psProvData, 0, FALSE, 0);
if (psProvSigner)
{
FileTimeToLocalFileTime(&psProvSigner->sftVerifyAsOf, &localFt);
FileTimeToSystemTime(&localFt, &sysTime);
_tprintf(_T("Signature Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"), sysTime.wDay, sysTime.wMonth, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
psProvCert = WTHelperGetProvCertFromChain(psProvSigner, 0);
if (psProvCert)
{
LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
if (szCertDesc)
{
_tprintf(_T("File Signer = %s\n"), szCertDesc);
LocalFree(szCertDesc);
}
}
if (psProvSigner->csCounterSigners)
{
_tprintf(_T("\n"));
// Timestamp information
FileTimeToLocalFileTime(&psProvSigner->pasCounterSigners[0].sftVerifyAsOf, &localFt);
FileTimeToSystemTime(&localFt, &sysTime);
_tprintf(_T("Timestamp Date = %.2d/%.2d/%.4d at %.2d:%2.d:%.2d\n"), sysTime.wDay, sysTime.wMonth, sysTime.wYear, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
psProvCert = WTHelperGetProvCertFromChain(&psProvSigner->pasCounterSigners[0], 0);
if (psProvCert)
{
LPTSTR szCertDesc = GetCertificateDescription(psProvCert->pCert);
if (szCertDesc)
{
_tprintf(_T("Timestamp Signer = %s\n"), szCertDesc);
LocalFree(szCertDesc);
}
}
}
}
}
}
sWintrustData.dwUIChoice = WTD_UI_NONE;
sWintrustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidAction, &sWintrustData);
return 0;
}
方法二、
#include <windows.h>
#include <Softpub.h>
#include <wincrypt.h>
#include <wintrust.h>
#include <mscat.h>
#include <wchar.h>
#pragma comment(lib, "wintrust")
BOOLEAN IsFileDigitallySigned(PWCHAR FilePath)
{
//Author: AD, 2009
PVOID Context;
HANDLE FileHandle;
DWORD HashSize = 0;
PBYTE Buffer;
PVOID CatalogContext;
CATALOG_INFO InfoStruct;
WINTRUST_DATA WintrustStructure;
WINTRUST_CATALOG_INFO WintrustCatalogStructure;
WINTRUST_FILE_INFO WintrustFileStructure;
PWCHAR MemberTag;
BOOLEAN ReturnFlag = FALSE;
ULONG ReturnVal;
GUID ActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
//Zero our structures.
memset(&InfoStruct, 0, sizeof(CATALOG_INFO));
InfoStruct.cbStruct = sizeof(CATALOG_INFO);
memset(&WintrustCatalogStructure, 0, sizeof(WINTRUST_CATALOG_INFO));
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
memset(&WintrustFileStructure, 0, sizeof(WINTRUST_FILE_INFO));
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
//Get a context for signature verification.
if (!CryptCATAdminAcquireContext(&Context, NULL, 0))
{
return FALSE;
}
//Open file.
FileHandle = CreateFileW(FilePath, GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == FileHandle)
{
CryptCATAdminReleaseContext(Context, 0);
return FALSE;
}
//Get the size we need for our hash.
CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, NULL, 0);
if (HashSize == 0)
{
//0-sized has means error!
CryptCATAdminReleaseContext(Context, 0);
CloseHandle(FileHandle);
return FALSE;
}
//Allocate memory.
Buffer = (PBYTE)calloc(HashSize, 1);
//Actually calculate the hash
if (!CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, Buffer, 0))
{
CryptCATAdminReleaseContext(Context, 0);
free(Buffer);
CloseHandle(FileHandle);
return FALSE;
}
//Convert the hash to a string.
MemberTag = (PWCHAR)calloc((HashSize * 2) + 1, sizeof(WCHAR));
for (unsigned int i = 0; i < HashSize; i++)
{
swprintf(&MemberTag[i * 2],100, L"%02X", Buffer[i]);
}
//Get catalog for our context.
CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, Buffer, HashSize, 0, NULL);
if (CatalogContext)
{
//If we couldn't get information
if (!CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0))
{
//Release the context and set the context to null so it gets picked up below.
CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
CatalogContext = NULL;
}
}
//If we have a valid context, we got our info.
//Otherwise, we attempt to verify the internal signature.
if (!CatalogContext)
{
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
WintrustFileStructure.pcwszFilePath = FilePath;
WintrustFileStructure.hFile = NULL;
WintrustFileStructure.pgKnownSubject = NULL;
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
WintrustStructure.dwUnionChoice = WTD_CHOICE_FILE;
WintrustStructure.pFile = &WintrustFileStructure;
WintrustStructure.dwUIChoice = WTD_UI_NONE;
WintrustStructure.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustStructure.dwStateAction = WTD_STATEACTION_IGNORE;
WintrustStructure.dwProvFlags = WTD_SAFER_FLAG;
WintrustStructure.hWVTStateData = NULL;
WintrustStructure.pwszURLReference = NULL;
}
else
{
//If we get here, we have catalog info! Verify it.
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
WintrustStructure.pPolicyCallbackData = 0;
WintrustStructure.pSIPClientData = 0;
WintrustStructure.dwUIChoice = WTD_UI_NONE;
WintrustStructure.fdwRevocationChecks = WTD_REVOKE_NONE;
WintrustStructure.dwUnionChoice = WTD_CHOICE_CATALOG;
WintrustStructure.pCatalog = &WintrustCatalogStructure;
WintrustStructure.dwStateAction = WTD_STATEACTION_VERIFY;
WintrustStructure.hWVTStateData = NULL;
WintrustStructure.pwszURLReference = NULL;
WintrustStructure.dwProvFlags = 0;
WintrustStructure.dwUIContext = WTD_UICONTEXT_EXECUTE;
//Fill in catalog info structure.
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
WintrustCatalogStructure.dwCatalogVersion = 0;
WintrustCatalogStructure.pcwszCatalogFilePath = InfoStruct.wszCatalogFile;
WintrustCatalogStructure.pcwszMemberTag = MemberTag;
WintrustCatalogStructure.pcwszMemberFilePath = FilePath;
WintrustCatalogStructure.hMemberFile = NULL;
}
//Call our verification function.
ReturnVal = WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
//Check return.
ReturnFlag = SUCCEEDED(ReturnVal);
//Free context.
if (CatalogContext)
CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
//If we successfully verified, we need to free.
if (ReturnFlag)
{
WintrustStructure.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
}
//Free memory.
free(MemberTag);
free(Buffer);
CloseHandle(FileHandle);
CryptCATAdminReleaseContext(Context, 0);
return ReturnFlag;
}
int _tmain(int argc, _TCHAR* argv[])
{
IsFileDigitallySigned(L"C:\\Windows\\System32\\svchost.exe");
}
方法三、
略
三、一种内核级的api
github地址: https://github.com/mstefanowich/IsFileSigned
C Win32 API code segment. Utilizes kernel level API calls to achieve similiar functionality to that of WinVerifyTrust.
Prerequisites
User must import NtReadFile, NtWaitForSingleObject, and Wdm.h.
An example of importing NtReadFile:
typedef NTSTATUS (NTAPI *NTREADFILE)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
HMODULE hMod = LoadLibrary(L"Ntdll.dll");
NTREADFILE NtReadFile = GetProcAddress(hMod, "NtReadFile");
代码:
/*
Prior to function call + function call
WCHAR *szPath = "C:\\Users\\...\\Desktop\\TestFile.exe";
DWORD dwCount = ERROR_SUCCESS;
HANDLE hHandle;
NTSTATUS Status;
OBJECT_ATTRIBUTES Attributes;
IO_STATUS_BLOCK IoBlock;
LARGE_INTEGER Integer;
UNICODE_STRING uString;
VxZeroMemory(&Attributes, sizeof(OBJECT_ATTRIBUTES));
VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
VxZeroMemory(&Integer, sizeof(LARGE_INTEGER));
Integer.QuadPart = 2048;
VxZeroMemory(&uString, sizeof(UNICODE_STRING));
if(szPath[0] != L'\\')
RtlDosPathNameToNtPathName_U(szPath, &uString, NULL, NULL);
else
RtlInitUnicodeString(&uString, szPath);
InitializeObjectAttributes(&Attributes, &uString, OBJ_CASE_INSENSITIVE, NULL, NULL);
if(NtCreateFile(&hHandle, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &Attributes, &IoBlock, &Integer, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
0, 0) != 0x00000000){ return; }
if((!VxIsTargetSigned(hHandle, CERT_SECTION_TYPE_ANY, &dwCount, NULL, 0)) && (dwCount == ERROR_SUCCESS))
return;
*/
BOOL VxIsTargetSigned(HANDLE FileHandle, DWORD TypeFilter, PDWORD CertificateCount, PDWORD Indices, DWORD IndexCount) //NOT
{
DWORD dwSize, dwCount, dwAddress, dwIndex, dwOffset;
WIN_CERTIFICATE Hdr;
BOOL bFlag;
IO_STATUS_BLOCK IoBlock;
NTSTATUS Status;
CONST SIZE_T CertHdrSize = sizeof(Hdr) - sizeof(Hdr.bCertificate);
if(!VxGetSecurityDirectoryOffsetEx(FileHandle, &dwAddress, &dwSize))
goto FAILURE;
dwOffset = ERROR_SUCCESS;
dwIndex = ERROR_SUCCESS;
*CertificateCount = ERROR_SUCCESS;
VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
while(dwOffset < dwSize)
{
if(VxSetFilePointer(FileHandle, dwAddress + dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
goto FAILURE;
Status = NtReadFile(FileHandle, NULL, NULL, NULL, &IoBlock, &Hdr, CertHdrSize, NULL, NULL);
if(Status == 0x00000103)
{
Status = NtWaitForSingleObject(FileHandle, FALSE, NULL);
if(Status == ERROR_SUCCESS)
Status = IoBlock.Status;
}
if(Status == ERROR_SUCCESS)
dwCount = IoBlock.Information;
else
goto FAILURE;
if((dwCount != CertHdrSize) || (Hdr.dwLength < CertHdrSize) || (Hdr.dwLength > (dwSize - dwOffset)))
goto FAILURE;
if((TypeFilter == CERT_SECTION_TYPE_ANY) || (TypeFilter == Hdr.wCertificateType))
{
(*CertificateCount)++;
if(Indices && *CertificateCount <= IndexCount)
*Indices++ = dwIndex;
}
dwOffset += Hdr.dwLength;
if(Hdr.dwLength % 0x08)
dwOffset += 8 - (Hdr.dwLength % 0x08);
dwIndex++;
}
return TRUE;
FAILURE:
return FALSE;
}
BOOL VxGetSecurityDirectoryOffsetEx(HANDLE hHandle, PDWORD dwOffset, PDWORD dwSize) //pi
{
IMAGE_NT_HEADERS32 Hdr32;
IMAGE_NT_HEADERS64 Hdr64;
PIMAGE_DATA_DIRECTORY Data;
INT dwReturn = VxGetCertificateNtHeaders(hHandle, NULL, &Hdr32, &Hdr64);
switch(dwReturn)
{
case -1:
return FALSE;
case 0:
Data = &Hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
break;
case 1:
Data = &Hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
}
*dwSize = Data->Size;
*dwOffset = Data->VirtualAddress;
return TRUE;
}
INT VxGetCertificateNtHeaders(HANDLE hHandle, PDWORD Offset, PIMAGE_NT_HEADERS32 Nt32, PIMAGE_NT_HEADERS64 Nt64) //pe
{
IMAGE_DOS_HEADER Dos;
DWORD dwCount = ERROR_SUCCESS;
IO_STATUS_BLOCK IoBlock;
VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
NTSTATUS Status;
if(VxSetFilePointer(hHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
goto FAILURE;
Status = NtReadFile(hHandle, NULL, NULL, NULL, &IoBlock, &Dos, sizeof(Dos), NULL, NULL);
if(Status == 0x00000103)
{
Status = NtWaitForSingleObject(hHandle, FALSE, NULL);
if(Status == ERROR_SUCCESS)
Status = IoBlock.Status;
}
if(Status == ERROR_SUCCESS)
dwCount = IoBlock.Information;
else
goto FAILURE;
if((dwCount != sizeof(Dos)) || (Dos.e_magic != IMAGE_DOS_SIGNATURE))
goto FAILURE;
if(VxSetFilePointer(hHandle, Dos.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
goto FAILURE;
dwCount = ERROR_SUCCESS;
if(Dos.e_magic != IMAGE_DOS_SIGNATURE)
*Offset = Dos.e_lfanew;
Status = ERROR_SUCCESS;
VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
Status = NtReadFile(hHandle, NULL, NULL, NULL, &IoBlock, Nt32, sizeof(IMAGE_NT_HEADERS32), NULL, NULL);
if(Status == 0x00000103)
{
Status = NtWaitForSingleObject(hHandle, FALSE, NULL);
if(Status == ERROR_SUCCESS)
Status = IoBlock.Status;
}
if(Status == ERROR_SUCCESS)
dwCount = IoBlock.Information;
else
goto FAILURE;
if((dwCount != sizeof(IMAGE_NT_HEADERS32)) || (Nt32->Signature != IMAGE_NT_SIGNATURE))
goto FAILURE;
switch(Nt32->OptionalHeader.Magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
return 0;
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
{
if(VxSetFilePointer(hHandle, Dos.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
goto FAILURE;
Status = ERROR_SUCCESS;
VxZeroMemory(&IoBlock, sizeof(IO_STATUS_BLOCK));
Status = NtReadFile(hHandle, NULL, NULL, NULL, &IoBlock, Nt64, sizeof(IMAGE_NT_HEADERS64), NULL, NULL);
if(Status == 0x00000103)
{
Status = NtWaitForSingleObject(hHandle, FALSE, NULL);
if(Status == ERROR_SUCCESS)
Status = IoBlock.Status;
}
if(Status == ERROR_SUCCESS)
dwCount = IoBlock.Information;
else
goto FAILURE;
if((dwCount != sizeof(IMAGE_NT_HEADERS64)) || (Nt64->Signature != IMAGE_NT_SIGNATURE))
goto FAILURE;
else
return 1;
}
default:
goto FAILURE;
}
FAILURE:
return -1;
}