如何在 C# 中更改特定的注册表所有者

How can I change particular registry owner in C#

我要读写key

HKEY_CLASSES_ROOT\CLSID\{1eeb5b5a-06fb-4732-96b3-975c0194eb39}\InProcServer32

密钥的默认所有者是 SYSTEM,我可以在 regedit 中手动更改它,但是,我希望我的程序可以这样做(更改注册表的所有者) 我试过下面的代码:

try
{
    string user = Environment.UserDomainName + "\" + Environment.UserName;
    RegistryKey rk = Registry.ClassesRoot.OpenSubKey(@"CLSID\{1eeb5b5a-06fb-4732-96b3-975c0194eb39}\InProcServer32",
                      RegistryKeyPermissionCheck.ReadWriteSubTree,
                      RegistryRights.ChangePermissions);
    RegistrySecurity rs = new RegistrySecurity();
    RegistryAccessRule rar = new RegistryAccessRule(user,
                                 RegistryRights.FullControl,
                                 AccessControlType.Allow);
    rs.AddAccessRule(rar);
    rk.SetAccessControl(rs);
    rk.Close();
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Console.WriteLine("test");

try
{
    var subKey = Registry.ClassesRoot.OpenSubKey(@"CLSID\{1eeb5b5a-06fb-4732-96b3-975c0194eb39}\InProcServer32", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership);
    subKey.SetValue("", @"%SystemRoot%\system32\explorerframe.dll", RegistryValueKind.ExpandString);
                    }catch (Exception ex) { Console.WriteLine(ex.Message); 
}
 

两个操作都失败了:

not allow requested registry privilidge.

我也试过微软文档上的代码,但没有用。 https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.win32.registrykey.setaccesscontrol?view=dotnet-plat-ext-3.1

如何获得我的程序的所有权?

当我在 MSDN.Link 上问同样的问题时,我得到了答案: https://docs.microsoft.com/en-us/answers/questions/726748/how-can-i-change-particular-registry-owner-in-c.html

来自Castorix31的回答:

A way is with Win32 APIs (tested on Windows 10 21H1, as Admin (Manifest)) :

if (!EnablePrivilege(SE_TAKE_OWNERSHIP_NAME, true))
     return;
    
 string sName = "Christian";
 System.Security.Principal.NTAccount ntAccount = new System.Security.Principal.NTAccount(sName);
 string sSid = ntAccount.Translate(typeof(System.Security.Principal.SecurityIdentifier)).Value;
 // S-1-5-21-3423049853-1102793660-1424913857-1001
 IntPtr pSid = IntPtr.Zero;
 ConvertStringSidToSid(sSid, out pSid);
 IntPtr hKey = IntPtr.Zero;
 uint dwErr = RegOpenKeyEx((IntPtr)HKEY_CLASSES_ROOT, "CLSID\{1eeb5b5a-06fb-4732-96b3-975c0194eb39}\InProcServer32", 0, KEY_WOW64_64KEY | WRITE_OWNER, ref hKey);
 if (dwErr == 0)
 {
     uint dwRet = SetSecurityInfo(hKey,
           SE_OBJECT_TYPE.SE_REGISTRY_KEY,
           OWNER_SECURITY_INFORMATION,
           pSid,
           IntPtr.Zero,
           IntPtr.Zero,
           IntPtr.Zero);
     RegCloseKey(hKey);
 }

效用函数:

 // From MS SDK : Win7Samples\winbase\bootconfigurationdata\bcdsamplelib\Utils.cs
 private bool EnablePrivilege(string lpszPrivilege, bool bEnablePrivilege)
 {
     bool retval = false;
     int ltkpOld = 0;
     IntPtr hToken = IntPtr.Zero;
     TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
     tkp.Privileges = new int[3];
     TOKEN_PRIVILEGES tkpOld = new TOKEN_PRIVILEGES();
     tkpOld.Privileges = new int[3];
     LUID tLUID = new LUID();
     tkp.PrivilegeCount = 1;
     if (bEnablePrivilege)
         tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
     else
         tkp.Privileges[2] = 0;
     if (LookupPrivilegeValue(null, lpszPrivilege, out tLUID))
     {
         System.Diagnostics.Process proc = System.Diagnostics.Process.GetCurrentProcess();
         if (proc.Handle != IntPtr.Zero)
         {
             if (OpenProcessToken(proc.Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out hToken) != false)
             {
                 tkp.PrivilegeCount = 1;
                 tkp.Privileges[2] = SE_PRIVILEGE_ENABLED;
                 tkp.Privileges[1] = tLUID.HighPart;
                 tkp.Privileges[0] = tLUID.LowPart;
                 const int bufLength = 256;
                 IntPtr tu = Marshal.AllocHGlobal(bufLength);
                 Marshal.StructureToPtr(tkp, tu, true);
                 if (AdjustTokenPrivileges(hToken, false, tu, bufLength, IntPtr.Zero, ref ltkpOld) != false)
                 {
                     int nErr = Marshal.GetLastWin32Error();
                     // successful AdjustTokenPrivileges doesn't mean privilege could be    changed
                     //ERROR_NOT_ALL_ASSIGNED   1300(0x514)
                     if (nErr == 0)
                     {
                         retval = true; // Token changed
                     }
                 }
                 TOKEN_PRIVILEGES tokp = (TOKEN_PRIVILEGES)Marshal.PtrToStructure(tu, typeof(TOKEN_PRIVILEGES));
                 Marshal.FreeHGlobal(tu);
             }
         }
     }
     if (hToken != IntPtr.Zero)
     {
         CloseHandle(hToken);
     }
     return retval;
 }

声明:

 [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 public static extern uint RegOpenKeyEx(IntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, ref IntPtr phkResult);
 public const int HKEY_CURRENT_USER = unchecked((int)0x80000001);
 public const int HKEY_CLASSES_ROOT = unchecked((int)0x80000000);
 public const int KEY_WOW64_64KEY = 0x0100;
 public const int WRITE_OWNER = 0x00080000;
 [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 public static extern uint RegCloseKey(IntPtr hKey);
 [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 public static extern bool LookupPrivilegeValue([In] string lpSystemName, [In] string lpName, [Out] out LUID Luid);
 [StructLayout(LayoutKind.Sequential)]
 public struct LUID
 {
     public int LowPart;
     public int HighPart;
 }
 [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, IntPtr NewState, int BufferLength, IntPtr PreviousState, ref int ReturnLength);
 [StructLayout(LayoutKind.Sequential)]
 public struct LUID_AND_ATTRIBUTES
 {
     public LUID Luid;
     public int Attributes;
 }
 [StructLayout(LayoutKind.Sequential)]
 internal struct TOKEN_PRIVILEGES
 {
     internal int PrivilegeCount;
     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
     internal int[] Privileges;
 }
 public const int TOKEN_ASSIGN_PRIMARY = 0x1;
 public const int TOKEN_DUPLICATE = 0x2;
 public const int TOKEN_IMPERSONATE = 0x4;
 public const int TOKEN_QUERY = 0x8;
 public const int TOKEN_QUERY_SOURCE = 0x10;
 public const int TOKEN_ADJUST_PRIVILEGES = 0x20;
 public const int TOKEN_ADJUST_GROUPS = 0x40;
 public const int TOKEN_ADJUST_DEFAULT = 0x80;
 public const int TOKEN_ALL_ACCESS = TOKEN_ASSIGN_PRIMARY
       + TOKEN_DUPLICATE + TOKEN_IMPERSONATE + TOKEN_QUERY
       + TOKEN_QUERY_SOURCE + TOKEN_ADJUST_PRIVILEGES
       + TOKEN_ADJUST_GROUPS + TOKEN_ADJUST_DEFAULT;
 public const string SE_RESTORE_NAME = "SeRestorePrivilege";
 public const string SE_DEBUG_NAME = "SeDebugPrivilege";
 public const string SE_TCB_NAME = "SeTcbPrivilege";
 public const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
 public const int SE_PRIVILEGE_ENABLED_BY_DEFAULT = (0x00000001);
 public const int SE_PRIVILEGE_ENABLED = (0x00000002);
 public const int SE_PRIVILEGE_REMOVED = (0X00000004);
 public const int SE_PRIVILEGE_USED_FOR_ACCESS = unchecked((int)0x80000000);
 [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 public static extern bool OpenProcessToken(IntPtr hProcess, uint desiredAccess, out IntPtr hToken);
 [DllImport("Kernel32.dll", SetLastError = true)]
 public static extern bool CloseHandle(IntPtr hObject);
 [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
 public static extern uint SetSecurityInfo(IntPtr handle, SE_OBJECT_TYPE ObjectType, uint SecurityInfo,
     IntPtr psidOwner, IntPtr psidGroup, IntPtr pDacl, IntPtr pSacl);
 public const int OWNER_SECURITY_INFORMATION = 0x00000001;
 public enum SE_OBJECT_TYPE
 {
     SE_UNKNOWN_OBJECT_TYPE = 0,
     SE_FILE_OBJECT,
     SE_SERVICE,
     SE_PRINTER,
     SE_REGISTRY_KEY,
     SE_LMSHARE,
     SE_KERNEL_OBJECT,
     SE_WINDOW_OBJECT,
     SE_DS_OBJECT,
     SE_DS_OBJECT_ALL,
     SE_PROVIDER_DEFINED_OBJECT,
     SE_WMIGUID_OBJECT,
     SE_REGISTRY_WOW64_32KEY,
     SE_REGISTRY_WOW64_64KEY,
 }
 [DllImport("Advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 public static extern bool ConvertStringSidToSid(string StringSid, out IntPtr Sid);