2014-10-06 10 views
1

mmc.exe (서비스) 서명을 확인하려고하는 응용 프로그램이 있습니다. (내가 생각하는 응용 프로그램의 컨텍스트와 관련이 없다) winapi 함수로 시도하고 있는데 모두 WinVerifyTrust와 함께 실패합니다. 카탈로그에서 확인을 시도 할 때 TRUST_E_BAD_DIGEST, 파일 정보에서 시도 할 때는 TRUST_E_NOSIGNATURE가 표시됩니다. 내 함수가 win7, XP에서는 성공하지만 win8에서는 실패한다는 것을 언급하는 것이 매우 중요합니다.windows에서 mmc.exe에서 디지털 서명 받기

이 기능

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; 

내가 어떤 일을 생각하지 않습니다에 대한 코드는 그래서 아마도 잘못 될 수있는 8 승리 WIN7에서이 기능을 변경했다입니까?

UPDATE 나는 나의 기능은 승리 8. 에서 작업 관리자에 대한 작업을 수행하지만, 다시 MMC 것이 작동하지 않습니다 통지를했다.

답변

2

일반적인 접근 방식이 정확하고 기능 자체가 변경되지 않은 것처럼 보입니다. 그러나 미묘한 변화가 있습니다. 즉 그들이 작동하는 데이터가 변경되었습니다. Windows 8의 파일 용으로 저장된 해시는 CryptCATAdminCalcHashFromFileHandle에 대한 설명에 따라 SHA-256 해시를 사용하여 계산됩니다.

SHA-256 해시 알고리즘은 CryptCATAdminCalcHashFromFileHandle에서 지원되지 않으므로 Windows 8에서 CryptCATAdminAcquireContext2CryptCATAdminCalcHashFromFileHandle2을 사용하도록 코드를 업데이트해야합니다. 전자는 특정 해시 알고리즘을 사용하여 HCATADMIN을 획득 할 수 있으며, 후자는 HCATADMIN을 사용할 수 있습니다.

(흥미롭게도, WINTRUST_CATALOG_INFO 또한 문서화의 HCATADMIN hCatAdmin 회원이 방향을 가리키는 "윈도우 8 및 Windows Server 2012 :.이 멤버에 대한 지원이 시작")를

+0

이러한 기능을 사용하지 않도록하는 방법은 무엇입니까? 나는 그들이 XP에서 이기고 7로 승리하는 것을지지하지 않는다. – whIsrael

+0

@whIsrael 네 말이 맞아. 문서별로 Windows 8/Windows Server 2012 이상에서만 사용할 수 있습니다. 그래서 ... 그냥 전화하지 마세요. 이 모든 기능은 수동으로 동적으로 링크되므로 올바른 코드 경로를 조건부로 호출하십시오. –