2010-09-09 57 views
1

我写了一些示例代码,当我从正常用户帐户的上下文中的Windows命令提示符调用时,使用CredEnumerate()转储所有用户保存的凭证。但是,我真的希望能够从SYSTEM用户上下文中完成此操作,因此我已经从SYSTEM cmd提示符测试了我的程序。为什么Win32 API函数CredEnumerate()返回ERROR_NOT_FOUND如果我模拟?

当我跑我的程序作为SYSTEM,我跑的LogonUser像这样:

bLoggedOn = LogonUser(userName.c_str(), domain.c_str(), password.c_str(), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &userToken_); 

然后我在令牌运行ImpersonateLoggedOnUser()给我的本地用户的安全上下文。在此之后我做的:

bOk = CredEnumerate(NULL, 0, &count, &pCredentials); 

而且我预计这以同样的方式返回凭据,如果我不从系统中消失了,人格化。任何人都可以发现我错过的任何东西,真正把自己置于用户的环境中吗?

+1

这些凭据是否存储在注册表中?也许你需要在调用CredEnumerate之前加载用户的注册表配置单元。您可以使用Process Monitor来查看是否发生了这种情况。 – Luke 2010-09-09 21:24:29

+0

嗯,这是一个很好的想法,我没有考虑过它。但是我实际上也遇到了同样的问题,即使我正在模拟的用户实际登录时,我使用psexec踢了一个系统propt。据推测,在这种情况下,用户的注册表配置单元将被加载。 – Benj 2010-09-10 09:06:48

+1

凭证管理API的文档似乎表明这些凭证与登录会话相关联。也许LogonUser导致一个新的登录会话,所以凭证不存在那里。您可以通过使用现有令牌调用ImpersonateLoggedOnUser()来测试此功能,而不是通过LogonUser()获取一个令牌。 – Luke 2010-09-10 11:37:40

回答

2

我想我自己可以自己回答这个问题,因为我已经花了很多年的时间研究如何做到这一点,我不确定它是否广为人知。 CredEnumerate/CredRead永远不会为域密码提供密码信息,无论您使用什么流程上下文或您拥有什么令牌,尽管它似乎在MSDN上提示。获取访问保存的凭证信息的唯一方法是使用lsasrv.dll中的未记录函数LSAICryptUnprotectData()。这可以解密您在%APPDATA%\ Microsoft \ Credentials中找到的文件,并且可以为CredEnumerate提供一个相同的数据结构,除了填入密码。唯一的问题是必须在lsass.exe的进程上下文中完成Windows安全子系统),没有特权等设置足以让一个正常的进程有权这样做。如果您是黑客,您可以通过执行CreateRemoteThread()将线程注入到lsass.exe中,或者如果您尝试以合法的方式执行此操作,即以某种方式扩展Windows操作系统对于像我一样的第三方应用程序,您可以通过创建一个lsass将加载的Windows身份验证软件包来实现此目的。然后,此AP可以使用命名管道或某种此类方法来允许与其他代码进行交互。

+0

看看这个:http://securityxploded.com/networkpasswordsecrets.php – 2013-06-12 17:26:22