Програмна перевірка підпису драйверів в windows xp програмування

Виникла задача перевірки підпису драйверів в 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 Марка Руссиновича) якимось чином бачать, підписаний файл чи ні. Яким коштом їх для цього користуються, ніяк не можу зрозуміти!

Може, у когось є досвід роботи в цій галузі? Цікавить Windows XP, але було б цікаво перевіряти автентичність дрейверов і в більш ранніх версіях, аж до Windows 98.

У verifier.exe відбувається наступне:
перебираються всі драйвера в системній папці і для кожного викликається функція IsDriverSigned.
Бачимо, що для кожного драйвера ця функція WinVerifyTrust викликається до 3 разів, хоча для переважної більшості вистачає і одного виклику, тобто до функції VerifyIsFileSigned справа не доходить.

Використовується синтаксис C

BOOL __stdcall VerifyIsFileSigned # 40; LPWSTR lpFileName. struct DRIVER_VER_INFO_ * driver_info # 41;
# 123;
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 # 40; driver_info. 0. sizeof # 40; struct DRIVER_VER_INFO_ # 41; # 41; ;
driver_info -> cbStruct = 1088;

memset # 40; wtData. 0. sizeof # 40; wtData # 41; # 41; ;
wtData. cbStruct = 44;
wtData. dwUIChoice = 2;
wtData. dwUnionChoice = 1;
wtData. dwStateAction = 3;
wtData. pPolicyCallbackData = driver_info;
wtData. fdwRevocationChecks = 0;
wtData. pFile = wtFileInfo;
result = WinVerifyTrust # 40; AfxGetThread # 40; # 41; -> GetMainWnd # 40; # 41; -> m_hWnd. policyGUID1. wtData # 41; ;
if # 40; result # 41;
# 123;
result = WinVerifyTrust # 40; AfxGetThread # 40; # 41; -> GetMainWnd # 40; # 41; -> m_hWnd. policyGUID2. wtData # 41; ;
# 125;
if # 40; driver_info -> pcSignerCertContext # 41;
# 123;
CertFreeCertificateContext # 40; * v5 # 41; ;
driver_info -> pcSignerCertContext = 0;
# 125;
return result == 0;
# 125;

int __stdcall IsDriverSigned # 40; LPCWSTR lpFileName # 41;
# 123;
int isSigned;
GUID policyGUID1 = DRIVER_ACTION_VERIFY;
HANDLE hFile;
BYTE pbHash # 91; 100 # 93; ;
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 # 40; lpFileName. 0x80000000. 3u. 0. 3u. 0x80u. 0 # 41; ;
if # 40; hFile == # 40; HANDLE # 41; - 1 # 41;
# 123;
isSigned = 1;
# 125;
else
# 123;
memset # 40; pbHash. 0. sizeof # 40; pbHash # 41; # 41; ;
pcbHash = 100;
hash_ok = CryptCATAdminCalcHashFromFileHandle # 40; hFile. cbHash. pbHash. 0 # 41; ;
CloseHandle # 40; hFile # 41; ;
if # 40; hash_ok == 1 # 41;
# 123;
memset # 40; wtCatInfo. 0. sizeof # 40; wtCatInfo # 41; # 41; ;
wtCatInfo. cbStruct = 36;
wtCatInfo. pcwszMemberTag = lpFileName;
wtCatInfo. pbCalculatedFileHash = pbHash;
wtCatInfo. cbCalculatedFileHash = cbHash;

memset # 40; driver_info. 0. sizeof # 40; driver_info # 41; # 41; ;
driver_info. cbStruct = одна тисяча вісімдесят вісім;

memset # 40; wtData. 0. sizeof # 40; wtData # 41; # 41; ;
wtData. dwUIChoice = 2;
wtData. dwUnionChoice = 2;
wtData. pPolicyCallbackData = driver_info;
wtData. cbStruct = 44;
wtData. fdwRevocationChecks = 0;
wtData. dwStateAction = 3;
wtData. pCatalog = wtCatInfo;

if # 40; g_hCatAdmin || # 40; CryptCATAdminAcquireContext # 40; g_hCatAdmin. 0. 0 # 41 ;. g_hCatAdmin # 41; # 41;
# 123;
for # 40; phPrevCatInfo = 0; ; phPrevCatInfo = hCatInfo # 41;
# 123;
hCatInfo = CryptCATAdminEnumCatalogFromHash # 40; g_hCatAdmin. pbHash. cbHash. 0. phPrevCatInfo # 41; ;
if # 40 ;. hCatInfo # 41;
break;
memset # 40; psCatInfo. 0. sizeof # 40; psCatInfo # 41; # 41; ;
psCatInfo. cbStruct = 524;
if # 40; CryptCATCatalogInfoFromContext # 40; hCatInfo. psCatInfo. 0 # 41; # 41;
# 123;
wtCatInfo. pcwszCatalogFilePath = psCatInfo. wszCatalogFile;
isSigned = WinVerifyTrust # 40; AfxGetThread # 40; # 41; -> GetMainWnd # 40; # 41; -> m_hWnd. policyGUID1. wtData # 41;> = 0;
if # 40; driver_info -> pcSignerCertContext # 41;
# 123;
CertFreeCertificateContext # 40; * v5 # 41; ;
driver_info -> pcSignerCertContext = 0;
# 125;
# 125;
if # 40; isSigned == 1 # 41;
return isSigned;
# 125;
isSigned = VerifyIsFileSigned # 40; lpFileName. driver_info # 41; ;
# 125;
# 125;
# 125;
return isSigned;
# 125;

Велике спасибі всім, хто відгукнувся!

Якщо WinVerifyTrust повертає TRUST_E_NOSIGNATURE, це не обов'язково означає, що немає підпису - необхідно викликати GetLastError (), щоб більш точно дізнатися причину.

GetLastError () повертає також TRUST_E_NOSIGNATURE.

12d3. спробував Ваш приклад. У мене також не працює. Відмінність від моїх експериментів в тому, що в WinVerifyTrust передається Handle вікна (я передаю 0, у мене вікон немає) і в тому, що додатково перевіряється DRIVER_ACTION_VERIFY (я не знав про цей код), але він все одно не працює.
Однак дещо стало прояснюватися:

Бачимо, що для кожного драйвера ця функція WinVerifyTrust викликається до 3 разів, хоча для переважної більшості вистачає і одного виклику, тобто до функції VerifyIsFileSigned справа не доходить.


Це означає, що повинен спрацьовувати CryptCATAdminEnumCatalogFromHash. Ось ця функція у мене ніяк не хоче працювати. Тобто по хешу файлу (він у мене, на кшталт, нормальний, 22 байта) в "каталозі підписаних файлів", або як він там правильно називається, нічого не знаходиться. Ще раз дякую! Зараз актуальність проблеми знизилася.