Прочитать и проверить сертификат из исполняемого файла - PullRequest
15 голосов
/ 30 августа 2011

Я хочу проверить сертификаты подписанных исполняемых образов (под проверкой я имею в виду, приходит ли подпись от MS / Adobe / Oracle и т. Д.).Windows предоставляет API для этой задачи?Как мне это сделать, понятия не имею.Любая помощь будет оценена.Я использую Windows и C ++.Я хочу проверить собственные исполняемые образы, а не сборки .NET или файлы jar Java.

ОБНОВЛЕНИЕ


Хорошо, я попытаюсь описать то, что я хочув ближайшее время.

1) Проверить сертификат PE.Подпись действительна или нет.Это должно работать, когда подпись встроена в PE и когда подпись находится в каталоге безопасности.( Я нашел это на форуме sysinternals и работает нормально, поэтому он мне больше не нужен ).

2) Скажите, кто подписал / издал файл.Я знаю, что этого можно достичь с помощью CryptQueryObject (я нашел рабочий пример, хотя он не работает с каталогами безопасности), но не знаю, как использовать его с файлами каталога безопасности.

Ответы [ 3 ]

23 голосов
/ 02 сентября 2011

Существует множество 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 , чтобы проверить не только то, что сертификат действителен в целом, но что он (или все его родителей) действует для аутентичного кода (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.

4 голосов
/ 30 августа 2011

Функция WinVerifyTrust выполняет действие проверки доверия для указанного объекта. Функция передает запрос поставщику доверия, который поддерживает идентификатор действия, если он существует.

Для проверки сертификата используйте функции CertGetCertificateChain и CertVerifyCertificateChainPolicy.

1 голос
/ 09 января 2015

@ Davita Я внимательно прочитал вышеупомянутую проблему и попытался ее решить.

Я предлагаю попробовать CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED вместо CERT_QUERY_CONTENT_FLAG_ALL в третьем параметре CryptQueryObject()

...