2014 dxdy logo

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

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




Начать новую тему Ответить на тему
 
 Программная проверка подписи драйверов в Windows XP
Сообщение17.05.2016, 16:41 
Заслуженный участник
Аватара пользователя


01/08/06
3046
Уфа
Возникла задача проверки подписи драйверов в 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 


27/08/14
206
А Verifier.exe на XP показывает, что подпись валидна или просто, что подпись есть? Если WinVerifyTrust возвращает TRUST_E_NOSIGNATURE, это не обязательно означает, что нет подписи - необходимо вызвать GetLastError(), чтобы более точно узнать причину.

 Профиль  
                  
 
 Re: Программная проверка подписи драйверов в Windows XP
Сообщение18.05.2016, 00:18 
Заслуженный участник


04/03/09
906
В 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 
Заслуженный участник
Аватара пользователя


01/08/06
3046
Уфа
Большое спасибо всем откликнувшимся!
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 
Заслуженный участник
Аватара пользователя


01/08/06
3046
Уфа
После того, как ошибка локализовалась, не составило особого труда её найти: при импорте CryptCATAdminEnumCatalogFromHash забыл указать __stdcall. После исправления всё заработало.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 5 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group