Impersonate时读取HKEY_CURRENT_USER的问题(Registry.CurrentUser为空)

来源:互联网 发布:淘宝刷单新规则影响 编辑:程序博客网 时间:2024/05/21 17:17

 环境:Win10 Pro 64bit , EN , .Net4.0 , C# , Visual Studio 2013


运行方式:

              1. 用户logon Windows

              2. 用管理员权限调起cmd

               3. PsExec.exe -s -d -i 我的程序路径 (我的程序此时获得system权限)。

问题:    访问Admin用户的HKEY_CURRENT_USER时发现Registry.CurrentUser居然是null !!


根本原因:访问另一个用户的HKCU要特殊处理


解决方案: 1
. LogonUser()时可以使用LOGON32_LOGON_INTERACTIVE或者LOGON32_LOGON_BATCH不可用LOGON32_LOGON_NEWCREDENTIAL(因为有些权限被移除了)

                   2. 使用Win32的RegOpenCurrentUser()才能访问到。

注意点: 1. 如果User A没有logon,想访问它的HKCU就必须用到LoadUserProfile()

                2. 如果User A已经logon,访问它就是RegOpenCurrentUser()

************************************* 参考***************************************************

1http://stackoverflow.com/questions/16477370/access-currentuser-registry-key-for-impersonated-user-compatibility-with-net

         优点:作者很好的展示了在.Net下如何使用RegOpenCurrentUser()访问

         缺点:作者写得是针对.Net3.5的,.Net4.0以上code要有点变化,否则会Exeception。

2https://social.msdn.microsoft.com/Forums/vstudio/en-US/fd531413-1ea9-4141-bba8-c1c5e9270001/access-currentuser-registry-key-for-impersonated-user-compatibility-with-net-35?forum=csharpgeneral

      优点: 最终采纳的方法,但是其中投票的答案提示去看"http://pinvoke.net/default.aspx/advapi32/RegOpenKeyEx.html, at the end of page, it give sample for .NET 4.0 and .NET 3.5 code"

3LoadUserProfile()。MSDN的描述

        If a service or an application impersonates a user, the system does not load the user's profile. Therefore, the service or application should load the user's profile with LoadUserProfile 这段话很容易让人误会这个是impersonate必须的!!!!

         该死的MSDN LoadUserProfile()在尾巴上有一句 the caller must be an administrator or the LocalSystem account. It is not sufficient for the caller to merely impersonate the administrator or LocalSystem account.  可惜当时我没理解到,所有花了好多时间去尝试使用它。4http://stackoverflow.com/questions/38634070/why-loaduserprofile-fails-with-error-5-denied-access-in-this-code-running-in  提到“

          It isn't a function for a user to load their own profile, ordinarily the system calls it on the user's behalf.

          The reason you shouldn't call LoadUserProfile is that the user is already logged on, so the profile will already be loaded.

          If you just want to open a logged-on user's registry hive, use RegOpenCurrentUser. (Note that you do want to use impersonation with this function, as documented.)

         这里也说了,要用RegOpenCurrentUser()

5http://stackoverflow.com/questions/459248/what-is-the-difference-loaduserprofile-vs-regopencurrentuser

       特点:A用户访问B用户的HKCU, A已登录而B没有

         LoadUserProfile()是在User还没logon时才用的 !!所以(https://www.codeproject.com/articles/124981/impersonating-user-accessing-files-and-hkcu)的作者才能访问HKEY_CURRENT_USER。

       RegOpenCurrentUser则必须User已经logon了 !

6http://stackoverflow.com/questions/1429837/impersonation-to-get-user-hkey-current-user-does-not-work

      Solution 2: RegDisablePredefinedCache(). This disables the cache mentioned above and lets subsequent calls to HKEY_CURRENT_USER be of the actual impersonated user. This is the solution I went with.

      这种方法没实验过,下次试试吧!

  

************************** 步骤 , 回忆用 *******************************

完整过程(各种坑):

    1.  发现Impersonate代码后Registry.CurrentUser为null ,以为OS有更新过,就重启了,回来依旧。

    2. 然后用进程本身System权限访问,发现不为null。蒙圈了。为啥Impersonate后就null了??我可是Admin权限啊!!

    3. cn.bing.com搜索了下。首先怀疑是不是自己的Impersonate不全啊?就看了https://www.codeproject.com/articles/4051/windows-impersonation-using-c

    4.  看到作者用的 const int LOGON32_LOGON_INTERACTIVE = 2; 而我用的 NewCredentials = 9 。启动程序,GetLastError()提示用户必须要设密码,我的Admin没设密码。

    5. 手工加上密码,再运行,还是一样,CurrentUser is null !!

    6. 继续搜索,       https://www.codeproject.com/articles/124981/impersonating-user-accessing-files-and-hkcu

       文章展示了Impersonate的步骤,而且还有demo

    7. 根据上篇文章,我以为要用到Win32的LoadUserProfile()

       Services and applications that call LoadUserProfile should check to see if the user has a roaming profile. If the user has a roaming profile, specify its path as thelpProfilePath member ofPROFILEINFO. To retrieve the user's roaming profile path, you can call theNetUserGetInfo function, specifying information level 3 or 4.

   8.   于是又搜索PInvoke c#版的LoadUserProfile()与LoadUserProfile(),各种折腾。

       LoadUserProfile()返回Access_Denied了!!Impersonate()的Admin还会权限不足吗??蒙逼了。

       https://social.msdn.microsoft.com/Forums/vstudio/en-US/8a1540f1-1b1c-485a-b3e2-a3c886f27c32/loaduserprofile-returns-erroraccessdenied?forum=vcgeneral

       文章里有人说you need the SE_RESTORE_NAME and SE_BACKUP_NAME privileges to make a call to this function.


   9. 于是又调用AdjustTokenPrivileges()尝试加上2个必须权限。中间又加了N多Code。

  10. 权限加了后发现(估计Admin默认有这2权限),Registry.CurrentUser还是null !!

   11. 再次搜索,才找到http://stackoverflow.com/questions/16477370/access-currentuser-registry-key-for-impersonated-user-compatibility-with-net

   12. 运行,这次报错是作者提供的pointerToRegistryKey()。

   13. 再次搜索,最终答案https://social.msdn.microsoft.com/Forums/vstudio/en-US/fd531413-1ea9-4141-bba8-c1c5e9270001/access-currentuser-registry-key-for-impersonated-user-compatibility-with-net-35?forum=csharpgeneral

    14. 我发现LogonUser()传入LOGON32_LOGON_NEW_CREDENTIALS时返回结果还是null,换成LOGON32_LOGON_INTERACTIVE才成功了!!

          用LOGON32_LOGON_NEW_CREDENTIALS时,System.Security.Principal.WindowsIdentity.GetCurrent().Name返回的是System用户,换成Interactive后返回的是Admin用户. 

遗留疑问:


        有人用DuplicateToke()与WindowsIdentity对象实现Impersonate,而我用的是ImpersonateLoggedOnUser()~,有啥不同??~

0 0
原创粉丝点击