【问题标题】:Impersonation to get user HKEY_CURRENT_USER does not work?模拟获取用户 HKEY_CURRENT_USER 不起作用?
【发布时间】:2009-09-15 21:56:21
【问题描述】:

我正在尝试从 LocalSystem 服务模拟管理员帐户,以便从管理员 HKEY CURRENT USER 注册表中获取数据 - 为了模拟,我正在使用 Uwe Keim 编写的以下站点上的 codeproject 代码:Impersonator

我的源码如下:

using (new Impersonator("user", ".", "pass"))
{
    RegistryKey rk = Registry.CurrentUser.OpenSubKey("Software\\CompanyName");
    string sValue = rk.GetValue("Value", "").ToString();
    rk2.Close();
}

我的期望是 sValue 将来自用户/通行证帐户(因为我正在模拟它)但奇怪的是它仍然是来自我的服务正在运行的 LocalSystem 帐户的 sValue ...

关于我做错了什么的任何线索?任何帮助将非常感激。 谢谢,

【问题讨论】:

    标签: c#


    【解决方案1】:

    我知道这是一个旧线程,但我最近遇到了同样的问题(尽管来自 C++ Windows 服务)并认为我会分享我的发现,因为许多论坛都提出了同样的问题,但没有一个给出令人满意的答案.

    基本上,我找到了两种方法来解决这个问题,尽管这更多是针对 C 应用程序而不是 .NET 的答案(我没有使用 pinvoke 进行测试,但它可能有效)。

    解决方案 1: 不要使用 RegOpenKey,而是使用RegOpenCurrentUser() 来获取密钥句柄。显然,RegOpenKey 没有获得模拟用户密钥的原因是因为 HKEY_CURRENT_USER 在运行线程中缓存

    解决方案 2: RegDisablePredefinedCache()。这禁用上面提到的缓存并让对 HKEY_CURRENT_USER 的后续调用成为实际模拟用户。这是我采用的解决方案。

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我在该主题上阅读的所有内容似乎都表明,模拟应该让您访问模拟帐户的 HKEY_CurrentUser。但是,这可能是 .NET Registry 实现中的一个怪癖。

      这只是一种预感,而且还未经测试,但您是否考虑过使用 Registry.Users 而不是 Registry.CurrentUser?

      管理员帐户需要find the SID,但您应该能够使用 Regedit 推断出这一点

      【讨论】:

      • 不是一个选项 - 这是一个测试,以确保如果我使用 RegEdit 合并一个转到 HKEY_CURRENT_USER 的 .reg 文件,它会更新 Admin Accounts 注册表而不是 LocalSystem 帐户。
      • 那么为什么这完全排除了这种可能性呢? HKEY_CURRENT_USER 本质上只是一个指向已登录用户的 HKEY_USERS 子键的链接。
      • 假设我有一个 file.REG 文件,它更改了“HKEY_CURRENT_USER\Something\Value=Data”中的一些内容。如果我做 regedit file.REG 我需要它来影响管理员帐户 HKCU 而不是 LocalSystem(服务)。查找 Registry.Users 和 SID 无济于事……明白我的意思吗?
      • 我很困惑。根据您最初的帖子详细信息,我假设您想读取特定用户(在本例中为管理员用户)的注册表项的值。 Registry.Users 调用只是做同样事情的另一种方式,可能会帮助您解决您所看到的怪癖。但是,我认为贾斯汀对他修改后的答案有所了解。先试试吧。
      【解决方案3】:

      默认情况下,HKEY_CURRENT_USER 句柄在进程范围内缓存。因此,当您模拟用户然后访问当前用户配置单元时,您将访问启动进程的用户的配置单元,而不是被模拟的用户。这适用于所有 Win32 进程,而不仅仅是 .Net。如果您希望禁用此缓存,以便所有当前用户调用都转到 HKEY_USERS 下的正确用户配置单元,那么您必须通过 pInvoke 调用 RegDisablePredefinedCache

      请注意,如果被模拟的用户尚未加载其个人资料,则任何 CurrentUser 请求都将转发给 .DEFAULT 用户。所以你可能还需要调用 LoadUserProfile。

      禁用句柄缓存也会导致所有 CurrentUser 请求的速度略有下降。

      【讨论】:

      • 这里的语法有问题。 [DllImport("win32.dll")] private static extern int RegDisablePredefinedCache(); - 导致“找不到指定的模块”。
      • 这编译并运行,但我仍然有这个问题。 [DllImport("Advapi32.dll")] private static extern int RegDisablePredefinedCache();
      【解决方案4】:

      我猜你会发现你运气不好。做不到。

      如果应用程序能够模拟管理员帐户并将值写入 Windows 中的注册表,则会出现巨大的安全漏洞。我的猜测是Registry.CurrentUser 属性将始终引用运行您的应用程序的用户...无论您是否尝试模拟。

      编辑

      原来我没有阅读您正在使用的 Impersonator 代码的实现细节。您的问题可能完全不同。

      在运行模拟代码之前,您的代码是否引用了 Registry 静态类?如果是这样,那就是问题所在。如果您查看 Reflector 中的 Registry.CurrentUser 属性,您会发现它是由 Registry 对象的静态构造函数设置的。静态构造函数在首次引用静态对象时被调用。

      在您的情况下,如果您引用 Registry 对象(无论它是否涉及 CurrentUser),则会调用静态构造函数,它将 CurrentUser 设置为您的原始用户......而不是模拟帐户.

      【讨论】:

      • 我想你可能弄错了。模拟代码实际上以提供的用户身份登录,并且需要完整的登录凭据才能这样做。这里没有安全漏洞,因为您使用代码而不是登录提示登录。
      • Impersonator 是一个 LocalSystem 服务,它拥有与管理员一样多的权利......但如果这没问题,那么为什么它不起作用(任何线索?)
      • impersonator 类是否编译成单独的程序集?如果是这样,您是否尝试将其拉入与您的测试代码相同的模块中以查看其行为是否有所不同?
      • Impersonator 类被添加到同一个程序集(同一个 exe)中,我只是在我的命名空间中添加了一个带有该类的文件,然后去......我知道它有效(有点)因为如果我提供不正确用户/传递它会引发正确的异常(错误的用户名/密码)。
      • 用完全不同的答案更新了答案。事实证明,在这种情况下,Reflector 可能是你的朋友……但和往常一样,我可能是错的。
      猜你喜欢
      • 2019-07-10
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多