Прочитать и проверить сертификат из исполняемого файла
Я хочу проверить сертификаты подписанных исполняемых образов (под проверкой я имею в виду, если подпись исходит от MS/Adobe/Oracle и т. Д.). Windows предоставляет API для этой задачи? Как мне это сделать, понятия не имею. Любая помощь будет оценена. Я использую Windows и C++. Я хочу проверить собственные исполняемые образы, а не сборки.NET или файлы jar Java.
ОБНОВИТЬ
Хорошо, я постараюсь описать, что я хочу в ближайшее время.
1) Подтвердить сертификат PE. Подпись действительна или нет. Это должно работать, когда подпись встроена в PE и когда подпись находится в каталоге безопасности. (Я нашел это на форуме sysinternals и работает нормально, поэтому он мне больше не нужен).
2) Сообщите, кто подписал / издал файл. Я знаю, что этого можно достичь с помощью CryptQueryObject (я нашел рабочий пример, хотя он не работает с каталогами безопасности), но не знаю, как использовать его с файлами каталога безопасности.
3 ответа
Есть много API и подходов, как вы можете получить и проверить подпись исполняемого файла и как вы можете получить другую дополнительную информацию, которая вам нужна. Проблема в том, какой уровень вы выбираете (высокий уровень, как WinVerifyTrust
)
Самым простым первым API, который можно использовать для получения контекста криптографии из файла CAT или EXE, является функция CryptQueryObject. Пример кода из KB323809 может дать вам основную идею, как декодировать информацию, что вам нужно. Основное отличие при работе с файлами CAT заключается в том, что вам следует изменить некоторые параметры CryptQueryObject. Я рекомендую вам просто использовать CERT_QUERY_CONTENT_FLAG_ALL
а также CERT_QUERY_FORMAT_FLAG_ALL
а также CryptQueryObject
сделаем все что нужно внутри:
BOOL bIsSuccess;
DWORD dwEncoding, dwContentType, dwFormatType;
HCERTSTORE hStore = NULL;
HCRYPTMSG hMsg = NULL;
PVOID pvContext = NULL;
// fill szFileName
...
// Get message handle and store handle from the signed file.
bIsSuccess = CryptQueryObject (CERT_QUERY_OBJECT_FILE,
szFileName,
CERT_QUERY_CONTENT_FLAG_ALL,
CERT_QUERY_FORMAT_FLAG_ALL,
0,
&dwEncoding,
&dwContentType,
&dwFormatType,
&hStore,
&hMsg,
&pvContext);
Значение dwContentType
устанавливается CryptQueryObject
получите базовую информацию о типе файла szFileName
, pvContext
будет PCCERT_CONTEXT
для большинства случаев, которые вам нужны, но это также может быть PCCRL_CONTEXT
или же PCCTL_CONTEXT
если вы используете.ctl или.crl файл в качестве входных данных. Вы получите hStore
заполнены все сертификаты из файла szFileName
, Так что в отношении pvContext
а также hStore
Вы можете просмотреть файл, содержащийся с CryptoAPI. Если вы предпочитаете низкоуровневый массаж API, вы можете использовать hMsg
который будет дополнительно установлен в случае некоторых dwContentType
(по крайней мере, для CERT_QUERY_CONTENT_PKCS7_SIGNED
, CERT_QUERY_CONTENT_PKCS7_UNSIGNED
, CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
).
Чтобы проверить подпись файла, я бы порекомендовал вам использовать CertGetCertificateChain и CertVerifyCertificateChainPolicy, чтобы проверить не только то, что сертификат действителен в целом, но и то, что он (или все его родители) действителен для authenticode (szOID_PKIX_KP_CODE_SIGNING
). CertGetCertificateChain может использоваться для различных сценариев отзыва. Вы должны сделать два отдельных звонка с CERT_CHAIN_POLICY_AUTHENTICODE
а также CERT_CHAIN_POLICY_AUTHENTICODE_TS
чтобы убедиться, что политика цепочки Authenticode и политика цепочки меток времени Authenticode являются действительными.
ОБНОВЛЕНО: я перечитал ваш текущий вопрос (обновленная часть). Ваша текущая проблема заключается в том, как получить подписавшего / издателя файла. Поэтому я отвечаю только на вопрос.
Если вы используете код от sysinternal для проверки подписи, вам нужно просто найти строку
if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )
Утверждение Sill установить поля InfoStruct
в случае, если этот файл является системным файлом Windows, подпись которого проверяется относительно некоторого файла.cat. Поле InfoStruct.wszCatalogFile даст вам имя файла.cat.
Например, на моем Windows 7, если я пытаюсь проверить цифровую подпись C:\Windows\explorer.exe
файл.cat, где можно найти его хэш C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat
,
Если вы используете код из KB323809 с описанными выше параметрами CryptQueryObject
вы расшифруете SPC_SP_OPUS_INFO_OBJID
("1.3.6.1.4.1.311.2.1.12") атрибута C:\Windows\system32\CatRoot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\Package_1_for_KB2515325~31bf3856ad364e35~amd64~~6.1.1.0.cat
(см. функцию GetProgAndPublisherInfo
) и ты узнаешь
pwszProgramName: "Windows Express Security Catalogs"
pPublisherInfo: NULL
pMoreInfo->dwLinkChoice: SPC_URL_LINK_CHOICE
pMoreInfo->pwszUrl "http://www.microsoft.com"
Таким образом, никакая специальная информация об издателе не включена в файл. Если вы осмотрите подписавшего каталог, вы обнаружите, что:
The signer of the .cat file: "Microsoft Windows"
The signer signed it with the certificate:
Serial Number: 0x6115230F00000000000A
Issuer Name: Microsoft Windows Verification PCA
Full Issuer Name:
CN = Microsoft Windows Verification PCA
O = Microsoft Corporation
L = Redmond
S = Washington
C = US
Subject Name: Microsoft Windows
Full Subject Name:
CN = Microsoft Windows
OU = MOPR
O = Microsoft Corporation
L = Redmond
S = Washington
C = US
The Date of TimeStamp : 28.02.2011 21:16:36
TimeStamp Certificate:
Serial Number: 0x6103DCF600000000000C
Issuer Name: Microsoft Time-Stamp PCA
Subject Name: Microsoft Time-Stamp Service
Таким образом, вы должны использовать только подписавшего файла.cat, потому что нет другого подписавшего explorer.exe
,
Функция WinVerifyTrust выполняет действие по проверке доверия для указанного объекта. Функция передает запрос поставщику доверия, который поддерживает идентификатор действия, если таковой существует.
Для проверки сертификата используйте функции CertGetCertificateChain и CertVerifyCertificateChainPolicy.
@ Давита Я внимательно прочитал вышеупомянутую проблему и попытался ее решить.
Мое предложение состоит в том, чтобы попробовать CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
вместо CERT_QUERY_CONTENT_FLAG_ALL
в третьем параметре CryptQueryObject()