模拟用户

7
我们正在开发一个C# .NET Windows服务。
我们的服务在系统帐户下运行,我们正在尝试模拟已登录的用户USER。模拟是成功的,即在模拟后调用System.Security.Principal.WindowsIdentity.GetCurrent()时,我们得到了正确的用户'USER'。
问题在于,当我们尝试访问用户配置文件时,我们没有得到预期的结果。一个例子是访问注册表CURRENT_USER。我们得到了访问被拒绝的错误。当使用第三方函数时,我们假设它在某种程度上使用了注册表,我们会得到“真实”(在模拟之前)用户的详细信息。此外,在调用Environment.ExpandEnvironmentVariables("%TEMP%")时,我们得到的是系统配置文件而不是已登录用户的配置文件。
是否有一种完全模拟不同用户的方法?我知道我们可以使用LoadUserProfile来获取特定用户配置文件,但这对我们来说不好,因为我们正在运行使用当前用户配置文件的第三方dll。
我们的模拟代码基于这个

1
首先,你应该使用System.IO.Path.GetTempPath(); 如果仍然不能正常工作,这可能是由于以下问题:https://dev59.com/W3NA5IYBdhLWcg3wfN2O 请查看已接受的答案以及它的工作方式。 - lahsrah
1
@David - 这不正确,我尝试运行一个控制台应用程序以检查。该应用程序在用户A下运行并模拟用户B。在模拟后调用Environment.ExpandEnvironmentVariables("%TEMP%")时,仍然得到用户A。 - user844541
1
尝试模拟已登录用户 - 一台机器上可能有多个用户登录... - Damien_The_Unbeliever
好的。建议已删除。做得很好,非常彻底! - David
@user844541 - 你正在使用哪个第三方库? - Security Hound
显示剩余3条评论
2个回答

3
正如你发现的那样,模拟身份无法设置HKEY_CURRENT_USER或环境变量。这是因为模拟令牌是每个线程的,而HKCU和环境是每个进程的。
如果您需要访问用户的常规环境,则需要使用HKEY_USERS\SID和模拟用户的SID,例如HKEY_USERS\S-1-5-21-12345678-12345678-12345678-1234。调用LoadUserProfile以确保键已加载。(如果它应该是当前登录的用户,则应已加载,因此您可能不应该那样做,但是检查它是否存在并在不存在时返回错误)。
您还可以确定他们的常规环境,因为这在HKCU中的"Environment"键下。您只需将其与系统环境组合即可。
如果第三方DLL确实要求正确设置HKCU和环境,则需要创建一个进程,在用户的登录会话中托管DLL,并以某种方式发送操作结果回来。如果仅需要环境,则可以创建子进程并手动设置环境。
但是,您没有说明为什么要这样做。听起来您已经将其作为解决更大问题的一部分。如果可能的话,建议您查看是否有一种方法可以在根本不获取用户环境或HKCU的情况下完成所需的操作。
为什么DLL不能直接在用户自己的会话中运行?为什么需要服务?您是否可以重新架构解决方案,使其有一个用户模式部分,在登录会话中运行并托管第三方DLL,而它与服务通信,以便服务只执行绝对必要的操作?

1
对于建议在用户会话中运行某些内容,我给予+1。几乎每次我遇到类似的服务和用户账户问题时,这都是解决的方法。 - Basic

2
我注意到代码没有调用LoadUserProfile,因此用户配置文件未加载。
请注意,在该函数的注释中,HKEY_CURRENT_USER仍未被替换。
在调用第三方DLL之前,我认为您可以通过调用RegOverridePredefKey来解决此问题。
请注意,在使所有事情正常工作时可能需要进行许多神秘操作 - 我建议在调用第三方库之前尽可能晚地进行覆盖,并尽快在之后恢复(希望这是对库的单个调用)。
作为一种替代方案,我强烈建议尝试寻找一个不需要所有这些麻烦的不同第三方提供的解决方案。

调用 RegOverridePredefKey 在这种情况下没有帮助,因为它是每个进程的,而模拟是每个线程的。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接