Проверка цифровой подписи файла
От: x64 Россия http://x64blog.name
Дата: 27.10.08 00:32
Оценка: 34 (7)
Вообще-то, это уже обсуждалось в соответствующем форуме, но если кому лень будет разбираться, то вот оно. Примерно так же делает Process Explorer и Autoruns. Подробности здесь
Автор: x64
Дата: 19.10.08
.

#include <softpub.h>
#include <wintrust.h>
#include <mscat.h>

bool
FileVerify (
                        
    LPCWSTR        pwFileName)

{
    HANDLE hCat = NULL;
    bool bResult = false;
    LONG lResult = 0;
    BYTE hash [1024];
    DWORD cb = sizeof (hash);
    HANDLE hFile = INVALID_HANDLE_VALUE;
    WINTRUST_FILE_INFO wfi = {sizeof (WINTRUST_FILE_INFO), 0};
    WINTRUST_DATA wtd = {sizeof (WINTRUST_DATA), 0};
    GUID g = WINTRUST_ACTION_GENERIC_VERIFY_V2;

    if (! CryptCATAdminAcquireContext (&hCat, NULL, 0))
    {
        return false;
    }

    hFile = CreateFile (
        pwFileName,
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
        NULL);

    if (hFile != INVALID_HANDLE_VALUE)
    {
        if (CryptCATAdminCalcHashFromFileHandle (hFile, &cb, hash, 0))
        {
            if (CryptCATAdminEnumCatalogFromHash (hCat, hash, cb, 0, 0))
            {
                bResult = true;
            }
        }

        CryptCATAdminReleaseContext (hCat, 0);
        CloseHandle (hFile);

        if (bResult)
        {
            return bResult;
        }
    }    

    wfi.pcwszFilePath = pwFileName;
    wfi.hFile = NULL;

    wtd.dwUIChoice = WTD_UI_NONE;
    wtd.fdwRevocationChecks = WTD_REVOKE_NONE;
    wtd.dwUnionChoice = WTD_CHOICE_FILE;
    wtd.pFile = &wfi;

    lResult = WinVerifyTrust (
        (HWND) INVALID_HANDLE_VALUE,
        &g,
        &wtd);

    return (lResult == ERROR_SUCCESS);
}
JID: x64j@jabber.ru
Re: Проверка цифровой подписи файла
От: x64 Россия http://x64blog.name
Дата: 11.05.09 11:57
Оценка: 10 (2)
Возможно, кому-то будет интересно узнать, что приведённый выше код инициирует TCP-соединения, а также DNS-запросы (т.е. датаграммы на 53 порт). Это не недостаток и не баг, это просто by design (подробности в MSDN и в сети), но тем не менее для меня это обернулось некоторыми неприятностями.

Однажды я столкнулся с проблемой, когда мой фаервол казалось бы беспричинно повисал (точнее, висло управляющее приложение). Но причина нашлась, это был самый натуральный дедлок, вызванный проверкой цифровой подписи исполняемых файлов тех процессов, которые являются инициаторами той или иной подозрительной активности. Т.е. получался замкнутый круг — для принятия решения о разрешении или блокировке того или иного запроса какого-либо процесса требовалось соединение с Интернет (для проверки подписи), но DNS-запрос в недрах WinVerifyTrust() исходил не от моего приложения (мои всегда разрешаются), а от имени одного из svchost'ов, при этом для разрешения этого DNS-запроса необходимо было сначала разрешить запрос того, первого приложения.

В принципе, понятно, что налицо архитектурные косяки, но тем не менее решение в данном конкретном случае оказалось довольно таки простым. Оказалось, что достаточно добавить вот такую строчку и никаких попыток сетевых соединений более не наблюдается:

    wtd.dwProvFlags = WTD_REVOCATION_CHECK_NONE;


Проверка подписи производиться как обычно, разве что отсутствует on-line проверка на аннулирование сертификата.
JID: x64j@jabber.ru
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.