使用 SCH_CRED_FORMAT_CERT_HASH 时,AcquireCredentialsHandle 在内核模式下失败

Posted

技术标签:

【中文标题】使用 SCH_CRED_FORMAT_CERT_HASH 时,AcquireCredentialsHandle 在内核模式下失败【英文标题】:AcquireCredentialsHandle fails in kernel mode, when using SCH_CRED_FORMAT_CERT_HASH 【发布时间】:2019-01-11 03:37:28 【问题描述】:

我在内核驱动程序中调用AcquireCredentialsHandle,传入SCHANNEL_CRED,并将dwCredFormat 设置为SCH_CRED_FORMAT_CERT_HASH。它以SEC_E_NO_CREDENTIALS 失败。这是我的代码:

BYTE certHashBytes[20] =  0x6d,0x64,0xed,0x56,0xd2,0x94,0x15,0xf4,0x49,0x08,0xaf,0x18,0xf1,0xca,0xf5,0xa2,0xc8,0x01,0x20,0x96 ;
CredHandle credHandle;
RtlZeroMemory(&credHandle, sizeof(CredHandle));

SCHANNEL_CRED schannelCred;
RtlZeroMemory(&schannelCred, sizeof(SCHANNEL_CRED));
schannelCred.dwVersion = 4;
schannelCred.cCreds = 1;
schannelCred.paCred = certHashBytes;
schannelCred.dwCredFormat = 1;

UNICODE_STRING unispName;
RtlUnicodeStringInit(&unispName, L"Microsoft Unified Security Protocol Provider");
TimeStamp ts;

SECURITY_STATUS res = AcquireCredentialsHandle(NULL, &unispName, SECPKG_CRED_INBOUND, NULL, &schannelCred, NULL, NULL, &credHandle, &ts);
DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, "AcquireCredentialsHandle %x\n", res);

对于用户帐户和本地计算机,我的证书哈希绝对正确,并且正确安装在 MY 商店中。我知道这一点是因为它在用户模式下可以正常工作,如下所示:

HCERTSTORE certStore = CertOpenSystemStore(NULL, L"MY");
BYTE certHashBytes[20] =  0x6d,0x64,0xed,0x56,0xd2,0x94,0x15,0xf4,0x49,0x08,0xaf,0x18,0xf1,0xca,0xf5,0xa2,0xc8,0x01,0x20,0x96 ;
CERT_NAME_BLOB certHash  20, certHashBytes ;
PCCERT_CONTEXT cert = CertFindCertificateInStore(certStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH, &certHash, NULL);

CredHandle credHandle;
ZeroMemory(&credHandle, sizeof(CredHandle));

SCHANNEL_CRED cred;
ZeroMemory(&cred, sizeof(SCHANNEL_CRED));
cred.dwVersion = SCHANNEL_CRED_VERSION;
cred.cCreds = 1;
cred.paCred = &cert;

SECURITY_STATUS res = AcquireCredentialsHandle(NULL, const_cast<LPWSTR>(UNISP_NAME), SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credHandle, NULL);

我相信我按照 MSDN 中关于如何准确使用 SCH_CRED_FORMAT_CERT_HASH 的说明进行操作 - 有什么问题?

【问题讨论】:

您是否启用了Schannel event logging?这对调试有很大帮助。 @kabanus 是的,但我的司机什么也没有。 我的猜测是私钥有问题。您的私钥是否正确存储/加载在 PROV_RSA_SCHANNEL CSP 中? "...在用户模式下可以正常工作..." -> 并不意味着它可以在服务器端工作。如果您在系统日志中看到任何事件(例如 36867、36868 ,36871 ),能否填写我们的信息? @tukan 如果它在用户模式下工作,那么为什么不能在内核模式下工作?通过SECPKG_CRED_INBOUND 参数,它们都充当服务器端。此外,mmc 表明私钥对于用户帐户和本地计算机都很好。 'eventvwr' 中的 'System' 中没有任何内容。 如果我引用 John Banes 的话:“好吧,仅仅因为私钥适用于客户端操作并不意味着它将适用于服务器端。服务器端操作是不同的,所以是对私钥的要求。”。如果事件查看器中没有任何内容,那么我很乐意将其传递给其他人。 【参考方案1】:

如果不进行调试,很难确定,但我发现一些可能是问题所在: - 如果证书链无法验证;或者它是自签名的;或者在您执行代码检查 CRL 时机器无法访问互联网,您的调用将失败。如果是这种情况,请使用CRYPT_E_NO_REVOCATION_CHECK - 如果您的证书的目的对于向远程服务器证明身份是正确的?

Windows 中最近进行了一些安全强化,在证书方面非常挑剔。自签名证书有时比签名证书更容易测试。我看到越来越多的正在运行的应用程序因为没有 100% 的证书而停止工作。没有它,我不明白问题是什么。

【讨论】:

这是从comodo买的证书,我可以上网。我也已经尝试过使用 CRYPT_E_NO_REVOCATION_CHECK。此外,如果其中任何一种情况,它也不会在用户模式下工作。 我建议您向微软开一个案例,以便我们通过内核转储文件分析情况,或者如果您可以提供驱动程序,则使用内核的源代码和符号进行内核转储。有一些有用的捕获,但我相信你做的最多(如果你编写内核驱动程序,你就是高级开发人员)。由于它在用户模式下工作,我建议您使用作为服务运行的系统帐户或通过 psexec -i -s 测试您的用户模式版本,如果您还没有这样做的话。我会牢记您的问题,并会在一周内与一些朋友交谈,看看是否有人提出任何想法。 谢谢。我确实问过微软 (social.msdn.microsoft.com/Forums/windowsdesktop/en-US/…) 但没有人帮忙。有没有更好的开箱方式? 让我看看我明天是否可以对您的请求有所帮助,但我认为您的情况需要进行更深入的分析。搜索“打开 Microsoft 支持案例”,您将看到选项。如果您是合作伙伴,则可以使用您的合作伙伴帐户打开案例,无需任何额外费用。 我搜索“打开 Microsoft 支持案例”,但只能看到昂贵的选项。

以上是关于使用 SCH_CRED_FORMAT_CERT_HASH 时,AcquireCredentialsHandle 在内核模式下失败的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)