代码之家  ›  专栏  ›  技术社区  ›  Benj

为什么Win32 API函数CredEnumerate()在模拟时返回ERROR\u NOT\u FOUND?

  •  1
  • Benj  · 技术社区  · 14 年前

    我已经编写了一些示例代码,当我在普通用户帐户的上下文中从windows命令提示符调用时,使用CredEnumerate()转储所有用户保存的凭据。但是,我确实希望能够从系统用户上下文中完成这项工作,因此我已经从系统cmd提示符中测试了我的程序。

    当我作为系统运行程序时,我运行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 回复  |  直到 14 年前
        1
  •  2
  •   Benj    14 年前

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