2014-10-06 5 views
1

У меня есть приложение, которое пытается проверить подпись mmc.exe (services). (контекст приложения, который, как мне кажется, не имеет значения) Я пытаюсь использовать функцию winapi, которая не работает с WinVerifyTrust. Я получаю TRUST_E_BAD_DIGEST, когда я пытаюсь проверить из каталога, и TRUST_E_NOSIGNATURE при попытке получить информацию о файле. очень важно упомянуть, что моя функция преуспевает в win7, XP, но не работает на win8.Получение цифровой подписи из mmc.exe в окнах 8

это фрагмент кода для функции

CATALOG_INFO InfoStruct = {0}; 
InfoStruct.cbStruct = sizeof(CATALOG_INFO); 

WINTRUST_CATALOG_INFO WintrustCatalogStructure = {0}; 
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO); 

WINTRUST_FILE_INFO WintrustFileStructure = {0}; 
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO); 

GUID ActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2; 

//Get a context for signature verification. 
HCATADMIN Context = NULL; 
if(!::CryptCATAdminAcquireContext(&Context, NULL, 0)){ 
    return false; 
} 

//Open file. 

cx_handle hFile(::CreateFileW(filename_.c_str(), GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL)); 
if(INVALID_HANDLE_VALUE == (HANDLE)hFile) 
{ 
    CryptCATAdminReleaseContext(Context, 0); 
    return false; 
} 

//Get the size we need for our hash. 
DWORD HashSize = 0; 
::CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, NULL, 0); 
if(HashSize == 0) 
{ 
    //0-sized has means error! 
    ::CryptCATAdminReleaseContext(Context, 0); 
    return false; 
} 

//Allocate memory. 
buffer hashbuf(HashSize); 

//Actually calculate the hash 
if(!CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, hashbuf.data, 0)) 
{ 
    CryptCATAdminReleaseContext(Context, 0); 
    return false; 
} 

//Convert the hash to a string. 
buffer MemberTag(((HashSize * 2) + 1) * sizeof(wchar_t)); 
for(unsigned int i = 0; i < HashSize; i++){ 
    swprintf(&((PWCHAR)MemberTag.data)[i * 2], L"%02X", hashbuf.data[i ]); 
} 

//Get catalog for our context. 
HCATINFO CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, hashbuf, HashSize, 0, NULL); 
if (CatalogContext) 
{ 
    //If we couldn't get information 
    if (!CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0)) 
    { 
     //Release the context and set the context to null so it gets picked up below. 
     CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0); 
     CatalogContext = NULL; 
    } 
} 

//If we have a valid context, we got our info. 
//Otherwise, we attempt to verify the internal signature. 

WINTRUST_DATA WintrustStructure = {0}; 
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA); 

if(!CatalogContext) 
{ 
    load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure); 
} 
else 
{ 
    load_signature_verification_from_catalog(WintrustStructure, WintrustCatalogStructure, InfoStruct, MemberTag); 
} 

//Call our verification function. 
long verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure); 

//Check return. 
bool is_success = SUCCEEDED(verification_res) ? true : false; 

// if failed with CatalogContext, try with FILE_INFO 
if(!is_success && CatalogContext && verification_res != TRUST_E_NOSIGNATURE) 
{ 
    //warning2(L"Failed verification with Catalog Context: 0x%x %s ; Retrying with FILE_INFO.", verification_res, (const wchar_t*)format_last_error(verification_res)); 

    load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure); 
    verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure); 
    is_success = SUCCEEDED(verification_res) ? true : false; 
} 

if(perr && !is_success && verification_res != TRUST_E_NOSIGNATURE) 
{ 
    perr->code = verification_res; 
    perr->description = format_last_error(verification_res); 
} 

//Free context. 
if(CatalogContext){ 
    ::CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0); 
} 

//If we successfully verified, we need to free. 
if(is_success) 
{ 
    WintrustStructure.dwStateAction = WTD_STATEACTION_CLOSE; 
    ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure); 
} 

::CryptCATAdminReleaseContext(Context, 0); 

return is_success; 

Я не думаю, что любая вещь изменилась в этой функции от win7, чтобы выиграть 8 так, что может пойти не так?

UPDATE

я заметил, что моя функция делает работу для менеджера задач на победу 8. но опять-таки для ММС не работает.

ответ

2

Похоже, что ваш общий подход правильный, и сами функции не изменились. Однако есть тонкие изменения; данные, по которым они действуют, изменились. Хеши, хранящиеся для файлов в Windows 8, согласно комментариям на CryptCATAdminCalcHashFromFileHandle, вычисляются с использованием хэшей SHA-256.

Хеширующий алгоритм SHA-256 не поддерживается CryptCATAdminCalcHashFromFileHandle, поэтому вы должны обновить код для использования CryptCATAdminAcquireContext2 и CryptCATAdminCalcHashFromFileHandle2 на Windows 8; первый позволяет вам получить HCATADMIN с заданным алгоритмом хеширования, а последний позволяет использовать этот HCATADMIN.

(Интересно, что WINTRUST_CATALOG_INFO также указывает это направление с его HCATADMIN hCatAdmin членом, документированный как «Windows 8 и Windows Server 2012:. Поддержка этого пользователя начинается»)

+0

есть способ, чтобы избежать использования этих функций? я не уверен, что они поддерживаются победой xp и выиграют 7. – whIsrael

+0

@whIsrael Вы правы; по документам они доступны только для Windows 8/Windows Server 2012 и более поздних версий. Так ... просто не называйте их. Все эти функции динамически связаны вручную, поэтому условно вызывают правильный путь кода. –