2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Программная проверка подписи драйверов в Windows XP
Сообщение17.05.2016, 16:41 
Аватара пользователя
Возникла задача проверки подписи драйверов в Windows XP.

Конкретно меня интересуют haspnt.sys, hardlock.sys — это драйверы аппаратного ключа защиты от копирования HASP (эмуляторы ключа заменяют эти файлы неподписанными версиями, таким образом, их можно проверить).

Неожиданно столкнулся с трудностями при решении этой задачи.

В Windows 7 драйвера имеют электронную подпись. Это можно проверить, щёлкнув правой кнопкой мыши на системном файле EXE, DLL или SYS и выбрав в выпавшем меню "Свойства" — появится окно свойств с вкладкой "Цифровые подписи". Я научился проверять такие файлы с помощью функции WinVerifyTrust из wintrust.dll, она прекрасно работает (ActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2).

Однако в Windows XP такой вкладки у файлов драйверов, как правило, нет, соответственно, WinVerifyTrust возвращает ошибку проверки на любом таком файле. Несмотря на это, стандартные средства Windows (например, Verifier.exe, Process Explorer Марка Руссиновича) каким-то образом видят, подписан файл или нет. Какими средствами они для этого пользуются, никак не могу понять!

Анализ Verifier.exe показывает, что он импортирует из wintrust.dll вышеупомянутую функцию WinVerifyTrust, а также функции CryptCATAdminAcquireContext, CryptCATAdminCalcHashFromFileHandle, CryptCATAdminEnumCatalogFromHash, CryptCATCatalogInfoFromContext. Я нашёл пример использования последних четырёх функций: https://rsdn.ru/forum/winapi/3143959.all, однако у меня на любом файле функция CryptCATAdminEnumCatalogFromHash возвращает false (остальные функции из примера, которые до неё вызываются, срабатывают нормально).
Функцию WinVerifyTrust тоже пробовал с различными ActionID, которые смог нарыть на просторах интернета: WINTRUST_ACTION_GENERIC_CERT_VERIFY, WINTRUST_ACTION_GENERIC_VERIFY_V2, WIN_TRUST_SUBJTYPE_RAW_FILE, WIN_TRUST_SUBJTYPE_PE_IMAGE, WINTRUST_ACTION_GENERIC_CHAIN_VERIFY и даже WIN_TRUST_SUBJTYPE_JAVA_CLASS, WIN_TRUST_SUBJTYPE_CABINET — всё без толку, работает только с файлами, подписанными "по-взрослому", на остальных возвращает TRUST_E_NOSIGNATURE.

Может, у кого-нибудь есть опыт работы в этой области? Интересует Windows XP, но было бы интересно проверять аутентичность дрейверов и в более ранних версиях, вплоть до Windows 98.

 
 
 
 Re: Программная проверка подписи драйверов в Windows XP
Сообщение17.05.2016, 17:55 
А Verifier.exe на XP показывает, что подпись валидна или просто, что подпись есть? Если WinVerifyTrust возвращает TRUST_E_NOSIGNATURE, это не обязательно означает, что нет подписи - необходимо вызвать GetLastError(), чтобы более точно узнать причину.

 
 
 
 Re: Программная проверка подписи драйверов в Windows XP
Сообщение18.05.2016, 00:18 
В verifier.exe происходит следующее:
перебираются все драйвера в системной папке и для каждого вызывается функция IsDriverSigned.
Видим, что для каждого драйвера эта функция WinVerifyTrust вызывается до 3 раз, хотя для подавляющего большинства хватает и одного вызова, т.е. до функции VerifyIsFileSigned дело не доходит.
код: [ скачать ] [ спрятать ]
Используется синтаксис C
BOOL __stdcall VerifyIsFileSigned(LPWSTR lpFileName, struct DRIVER_VER_INFO_ *driver_info)
{
        LONG result;
        GUID policyGUID1 = DRIVER_ACTION_VERIFY;
        GUID policyGUID2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
       
        WINTRUST_DATA wtData;
        WINTRUST_FILE_INFO wtFileInfo;
       
        wtFileInfo.cbStruct = 16;
        wtFileInfo.hFile = 0;
        wtFileInfo.pcwszFilePath = lpFileName;
        wtFileInfo.pgKnownSubject = 0;
       
        memset(driver_info, 0, sizeof(struct DRIVER_VER_INFO_));
        driver_info->cbStruct = 1088;
       
        memset(&wtData, 0, sizeof(wtData));
        wtData.cbStruct = 44;
        wtData.dwUIChoice = 2;
        wtData.dwUnionChoice = 1;
        wtData.dwStateAction = 3;
        wtData.pPolicyCallbackData = driver_info;
        wtData.fdwRevocationChecks = 0;
        wtData.pFile = &wtFileInfo;
        result = WinVerifyTrust(AfxGetThread()->GetMainWnd()->m_hWnd, &policyGUID1, &wtData);
        if (result)
        {
                result = WinVerifyTrust(AfxGetThread()->GetMainWnd()->m_hWnd, &policyGUID2, &wtData);
        }
        if ( driver_info->pcSignerCertContext )
        {
                CertFreeCertificateContext(*v5);
                driver_info->pcSignerCertContext = 0;
        }
        return result == 0;
}

HCATADMIN g_hCatAdmin;

int __stdcall IsDriverSigned(LPCWSTR lpFileName)
{
        int isSigned;
        GUID policyGUID1 = DRIVER_ACTION_VERIFY;
        HANDLE hFile;
        BYTE pbHash[100];
        DWORD cbHash;
        int hash_ok;
        HCATINFO phPrevCatInfo;
        HCATINFO hCatInfo;

        CATALOG_INFO psCatInfo;
        WINTRUST_CATALOG_INFO wtCatInfo;
        DRIVER_VER_INFO driver_info;
        WINTRUST_DATA wtData;
       
        isSigned = 0;
        hFile = CreateFileW(lpFileName, 0x80000000, 3u, 0, 3u, 0x80u, 0);
        if ( hFile == (HANDLE)-1 )
        {
                isSigned = 1;
        }
        else
        {
                memset(pbHash, 0, sizeof(pbHash));
                pcbHash = 100;
                hash_ok = CryptCATAdminCalcHashFromFileHandle(hFile, &cbHash, pbHash, 0);
                CloseHandle(hFile);
                if ( hash_ok == 1 )
                {
                        memset(&wtCatInfo, 0, sizeof(wtCatInfo));
                        wtCatInfo.cbStruct = 36;
                        wtCatInfo.pcwszMemberTag = lpFileName;
                        wtCatInfo.pbCalculatedFileHash = pbHash;
                        wtCatInfo.cbCalculatedFileHash = cbHash;
                       
                        memset(&driver_info, 0, sizeof(driver_info));
                        driver_info.cbStruct = 1088;
                       
                        memset(&wtData, 0, sizeof(wtData));
                        wtData.dwUIChoice = 2;
                        wtData.dwUnionChoice = 2;
                        wtData.pPolicyCallbackData = &driver_info;
                        wtData.cbStruct = 44;
                        wtData.fdwRevocationChecks = 0;
                        wtData.dwStateAction = 3;
                        wtData.pCatalog = &wtCatInfo;
                       
                        if ( g_hCatAdmin || (CryptCATAdminAcquireContext(&g_hCatAdmin, 0, 0), g_hCatAdmin) )
                        {
                                for ( phPrevCatInfo = 0; ; phPrevCatInfo = hCatInfo )
                                {
                                        hCatInfo = CryptCATAdminEnumCatalogFromHash(g_hCatAdmin, pbHash, cbHash, 0, &phPrevCatInfo);
                                        if ( !hCatInfo )
                                                break;
                                        memset(&psCatInfo, 0, sizeof(psCatInfo));
                                        psCatInfo.cbStruct = 524;
                                        if ( CryptCATCatalogInfoFromContext(hCatInfo, &psCatInfo, 0) )
                                        {
                                                wtCatInfo.pcwszCatalogFilePath = psCatInfo.wszCatalogFile;
                                                isSigned = WinVerifyTrust(AfxGetThread()->GetMainWnd()->m_hWnd, &policyGUID1, &wtData) >= 0;
                                                if ( driver_info->pcSignerCertContext )
                                                {
                                                        CertFreeCertificateContext(*v5);
                                                        driver_info->pcSignerCertContext = 0;
                                                }      
                                        }
                                        if ( isSigned == 1 )
                                                return isSigned;
                                }
                                isSigned = VerifyIsFileSigned(lpFileName, &driver_info);
                        }
                }
        }
        return isSigned;
}


 

 
 
 
 Re: Программная проверка подписи драйверов в Windows XP
Сообщение18.05.2016, 13:37 
Аватара пользователя
Большое спасибо всем откликнувшимся!
Progger в сообщении #1124153 писал(а):
Если WinVerifyTrust возвращает TRUST_E_NOSIGNATURE, это не обязательно означает, что нет подписи - необходимо вызвать GetLastError(), чтобы более точно узнать причину.
GetLastError() возвращает также TRUST_E_NOSIGNATURE.

12d3, попробовал Ваш пример. У меня также не работает. Отличие от моих экспериментов в том, что в WinVerifyTrust передаётся Handle окна (я передаю 0, у меня окон нету) и в том, что дополнительно проверяется DRIVER_ACTION_VERIFY (я не знал про этот код), но он всё равно не работает.
Однако кое-что стало проясняться:
12d3 в сообщении #1124245 писал(а):
Видим, что для каждого драйвера эта функция WinVerifyTrust вызывается до 3 раз, хотя для подавляющего большинства хватает и одного вызова, т.е. до функции VerifyIsFileSigned дело не доходит.

Это значит, что должен срабатывать CryptCATAdminEnumCatalogFromHash. Вот эта функция у меня никак не хочет работать. То есть по хешу файла (он у меня, вроде, нормальный, 22 байта) в "каталоге подписанных файлов", или как он там правильно называется, ничего не находится. Ещё раз спасибо! Сейчас актуальность проблемы снизилась.

 
 
 
 Re: Программная проверка подписи драйверов в Windows XP
Сообщение19.05.2016, 08:08 
Аватара пользователя
После того, как ошибка локализовалась, не составило особого труда её найти: при импорте CryptCATAdminEnumCatalogFromHash забыл указать __stdcall. После исправления всё заработало.

 
 
 [ Сообщений: 5 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group