使用 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有三种方式(不使用,动态使用,静态使用,默认是动态使用)