在Windows 8从mmc.exe获取数字签名

时间:2014-10-06 13:01:16

标签: c++ windows-8 digital-signature winverifytrust

我有一个尝试验证mmc.exe(服务)签名的应用程序。 (我认为应用程序的上下文是无关紧要的)我正在尝试winapi函数,它们都失败了 的WinVerifyTrust。当我尝试从目录中验证时,我得到TRUST_E_BAD_DIGEST  从文件信息尝试时TRUST_E_NOSIGNATURE。非常重要的是要提到我的功能在win7,XP上成功但在win8上失败。

这是函数的代码片段

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到win 8没有任何改变,所以可能会出错?

更新

我注意到我的功能在win 8中对任务管理器起作用。 但同样对于mmc它不起作用。

1 个答案:

答案 0 :(得分:2)

看来你的一般方法是正确的,功能本身没有改变。然而,有微妙的变化;即他们经营的数据已发生变化。根据对CryptCATAdminCalcHashFromFileHandle的评论,在Windows 8上为文件存储的哈希值是使用SHA-256哈希值计算的。

CryptCATAdminCalcHashFromFileHandle不支持SHA-256哈希算法,因此您必须更新代码以在Windows 8上使用CryptCATAdminAcquireContext2 CryptCATAdminCalcHashFromFileHandle2;前者允许您使用指定的哈希算法获取HCATADMIN,后者允许使用HCATADMIN

(有趣的是,WINTRUST_CATALOG_INFO也将此方向指向其HCATADMIN hCatAdmin成员,记录为“ Windows 8和Windows Server 2012:支持该成员开始。”)< / p>