2014-10-06 21 views
1

我有一個應用程序試圖驗證mmc.exe(服務)簽名。 (我認爲應用程序的上下文無關緊要)我嘗試使用winapi函數,這兩個函數都失敗,並且WinVerifyTrust爲 。當我嘗試從目錄中進行驗證時,我收到了TRUST_E_BAD_DIGEST,當從文件信息中嘗試時,我收到了TRUST_E_NOSIGNATURE 。提及我的功能在win7,XP上成功,但在win8上失敗是非常重要的。在Windows 8上從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; 

我不認爲任何事情的代碼片段在此功能就變也從Win7贏得8等什麼可能出問題?

UPDATE

我也注意到,我的功能確實爲任務管理器工作在贏8 但再次爲MMC這是行不通的。

回答

2

看來你的一般方法是正確的,而且功能本身沒有改變。但是有一些微妙的變化。即他們所在的數據已經改變。根據對CryptCATAdminCalcHashFromFileHandle的評論,存儲在Windows 8上的文件的散列值是使用SHA-256散列值計算的。

CryptCATAdminCalcHashFromFileHandle不支持SHA-256散列算法,因此您必須更新代碼以在Windows 8上使用CryptCATAdminAcquireContext2CryptCATAdminCalcHashFromFileHandle2;前者允許您使用指定的散列算法獲取HCATADMIN,後者允許使用HCATADMIN

(有趣的是,WINTRUST_CATALOG_INFO也指出其HCATADMIN hCatAdmin構件這個方向,記錄爲「視窗8和Windows Server 2012:支持此構件開始」)

+0

是有辦法避免使用那些功能?我不確定他們是否支持win xp和win 7. – whIsrael 2014-10-06 15:27:13

+0

@whIsrael你是對的;根據文檔,它們只能在Windows 8/Windows Server 2012及更高版本上使用。所以...只是不要打電話給他們。所有這些函數都是手動動態鏈接的,因此有條件地調用正確的代碼路徑。 – 2014-10-06 15:39:43