Как определить что подпись файла не валидна?
От: Losar Россия  
Дата: 18.05.12 13:53
Оценка:
Привет.

Есть подписанный файл, если изменить его контент,
то при просмотре информации о сертификате есть сообщение "This digital signature is not valid"

Как определить программно, что сигнатура не валидна?

Спасибо.
Re: Как определить что подпись файла не валидна?
От: okman Беларусь  
Дата: 18.05.12 14:02
Оценка: 4 (1)
Здравствуйте, Losar, Вы писали:

L>Есть подписанный файл, если изменить его контент,

L>то при просмотре информации о сертификате есть сообщение "This digital signature is not valid"

L>Как определить программно, что сигнатура не валидна?


Я делал так.
Сначала определял наличие Certificate Table в исполняемом файле (ImageEnumerateCertificates) и
проверял, возвращает ли ImageGetCertificateHeader значение WIN_CERT_TYPE_PKCS_SIGNED_DATA.
Если хотя бы одно из условий не выполняется, значит, файл не подписан.
Дальше зовем WinVerifyTrust (флаги могут отличаться, в зависимости от условий задачи).
Если возвращает код, отличный от ERROR_SUCCESS, значит, подпись невалидна.
Re[2]: Как определить что подпись файла не валидна?
От: Losar Россия  
Дата: 18.05.12 14:16
Оценка:
Спасибо за совет.

Дело в том что сейчас на такой файл WinVerifyTrust возвращает OK.

Код как я работаю с WinVerifyTrust:


GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA wintrustdata;
WINTRUST_FILE_INFO fileinfo;
 
memset(&fileinfo, 0, sizeof(fileinfo));
fileinfo.cbStruct          = sizeof(fileinfo);
fileinfo.pcwszFilePath     = pszFileName;
fileinfo.pgKnownSubject    = NULL;
fileinfo.hFile             = NULL;
 
memset(&wintrustdata, 0, sizeof(wintrustdata));

wintrustdata.cbStruct            = sizeof(wintrustdata);
wintrustdata.fdwRevocationChecks = WTD_REVOKE_NONE;
wintrustdata.dwStateAction       = WTD_STATEACTION_CLOSE;
wintrustdata.hWVTStateData       = NULL;
wintrustdata.pwszURLReference    = NULL;
wintrustdata.dwUIChoice          = WTD_UI_NONE;
wintrustdata.dwProvFlags         = 0;
wintrustdata.dwUnionChoice       = WTD_CHOICE_FILE;
wintrustdata.pFile               = &fileinfo;
HRESULT hr = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidPublishedSoftware, &wintrustdata);


Здравствуйте, okman, Вы писали:

O>Здравствуйте, Losar, Вы писали:


L>>Есть подписанный файл, если изменить его контент,

L>>то при просмотре информации о сертификате есть сообщение "This digital signature is not valid"

L>>Как определить программно, что сигнатура не валидна?


O>Я делал так.

O>Сначала определял наличие Certificate Table в исполняемом файле (ImageEnumerateCertificates) и
O>проверял, возвращает ли ImageGetCertificateHeader значение WIN_CERT_TYPE_PKCS_SIGNED_DATA.
O>Если хотя бы одно из условий не выполняется, значит, файл не подписан.
O>Дальше зовем WinVerifyTrust (флаги могут отличаться, в зависимости от условий задачи).
O>Если возвращает код, отличный от ERROR_SUCCESS, значит, подпись невалидна.
Re: Как определить что подпись файла не валидна?
От: baranovda Российская Империя  
Дата: 18.05.12 14:20
Оценка:
Здравствуйте, Losar, Вы писали:

L>Привет.


L>Есть подписанный файл, если изменить его контент,

L>то при просмотре информации о сертификате есть сообщение "This digital signature is not valid"

L>Как определить программно, что сигнатура не валидна?


На васике:

Public Function Verify(ByVal szFileName As String) As Long
          Dim fResult As Long
          Dim dwEncoding As Long
          Dim dwContentType As Long
          Dim dwFormatType As Long
          Dim hStore As Long
          Dim hMsg As Long
    fResult = CryptQueryObject( _
        CERT_QUERY_OBJECT_FILE, ByVal StrPtr(szFileName), _
        CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, _
        CERT_QUERY_FORMAT_FLAG_BINARY, 0&, dwEncoding, _
        dwContentType, dwFormatType, hStore, hMsg, ByVal 0&)
    Verify = fResult
End Function
http://files.rsdn.org/67021/op.jpg
Re[2]: Как определить что подпись файла не валидна?
От: Losar Россия  
Дата: 18.05.12 14:30
Оценка:
Спасибо.

Но CryptQueryObject(CERT_QUERY_OBJECT_FILE, pszFileName,
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY,
0, NULL, &dwContentType, NULL, &hStore,&hMsg, NULL)
возвращает true и потом даже можно вытащить имя.


Здравствуйте, baranovda, Вы писали:

B>Здравствуйте, Losar, Вы писали:


L>>Привет.


L>>Есть подписанный файл, если изменить его контент,

L>>то при просмотре информации о сертификате есть сообщение "This digital signature is not valid"

L>>Как определить программно, что сигнатура не валидна?


B>На васике:


B>
B>Public Function Verify(ByVal szFileName As String) As Long
B>          Dim fResult As Long
B>          Dim dwEncoding As Long
B>          Dim dwContentType As Long
B>          Dim dwFormatType As Long
B>          Dim hStore As Long
B>          Dim hMsg As Long
B>    fResult = CryptQueryObject( _
B>        CERT_QUERY_OBJECT_FILE, ByVal StrPtr(szFileName), _
B>        CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, _
B>        CERT_QUERY_FORMAT_FLAG_BINARY, 0&, dwEncoding, _
B>        dwContentType, dwFormatType, hStore, hMsg, ByVal 0&)
B>    Verify = fResult
B>End Function
B>
Re[3]: Как определить что подпись файла не валидна?
От: baranovda Российская Империя  
Дата: 18.05.12 14:45
Оценка:
Здравствуйте, Losar, Вы писали:

L>Спасибо.

Пардон, написал этот код сто лет назад для простой проверки наличия подписи у модуля и что он делает в деталях забыл.
Вот тут, мне кажется, по теме исчерпывающе: http://stackoverflow.com/questions/7241453/read-and-validate-certificate-from-executable
http://files.rsdn.org/67021/op.jpg
Re[3]: Как определить что подпись файла не валидна?
От: okman Беларусь  
Дата: 18.05.12 16:52
Оценка: +1
Здравствуйте, Losar, Вы писали:

L>Дело в том что сейчас на такой файл WinVerifyTrust возвращает OK.


Это странно, потому что у меня все отрабатывает нормально.
Только что взял три exe файла — один без подписи, второй с подписью, третий тоже с
подписью, но с одним модифицированным байтом. Утилита проверки подписи, основанная на
вышеописнном подходе, выдала:

>File (1) is not signed.
>File (2) has valid signature.
>File (3) has corrupted signature.


L>Код как я работаю с WinVerifyTrust:


L>
L>GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
L>WINTRUST_DATA wintrustdata;
L>WINTRUST_FILE_INFO fileinfo;
 
L>memset(&fileinfo, 0, sizeof(fileinfo));
L>fileinfo.cbStruct          = sizeof(fileinfo);
L>fileinfo.pcwszFilePath     = pszFileName;
L>fileinfo.pgKnownSubject    = NULL;
L>fileinfo.hFile             = NULL;
 
L>memset(&wintrustdata, 0, sizeof(wintrustdata));

L>wintrustdata.cbStruct            = sizeof(wintrustdata);
L>wintrustdata.fdwRevocationChecks = WTD_REVOKE_NONE;
L>wintrustdata.dwStateAction       = WTD_STATEACTION_CLOSE;
L>wintrustdata.hWVTStateData       = NULL;
L>wintrustdata.pwszURLReference    = NULL;
L>wintrustdata.dwUIChoice          = WTD_UI_NONE;
L>wintrustdata.dwProvFlags         = 0;
L>wintrustdata.dwUnionChoice       = WTD_CHOICE_FILE;
L>wintrustdata.pFile               = &fileinfo;
L>HRESULT hr = WinVerifyTrust((HWND)INVALID_HANDLE_VALUE, &guidPublishedSoftware, &wintrustdata);    
L>


У меня код аналогичен, вот только я вместо WTD_STATEACTION_CLOSE использую WTD_STATEACTION_IGNORE.
По-моему, когда WinVerifyTrust используется для с флагом WTD_STATEACTION_CLOSE, она
выполняет не верификацию подписи, а закрытие хэндла hWVTStateData, который был получен
предыдущим вызовом. Может быть, поэтому и возвращается ERROR_SUCCESS на сломаной подписи.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.