Search code examples
c#registrysystem

How can I change particular registry owner in C#


I want to read and write the key

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

The key's default owner is SYSTEM,I can change it manually in regedit but, I want my program can do this(change the owner of Registry) I have tried the code below:

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); 
}
 

Both the operation failed with:

not allow requested registry privilidge.

I have also tried the code on Microsoft docs but it didn't work. https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.win32.registrykey.setaccesscontrol?view=dotnet-plat-ext-3.1

How can I get the ownership for my program?


Solution

  • I got my answer when I asked the same question on MSDN.Link: https://learn.microsoft.com/en-us/answers/questions/726748/how-can-i-change-particular-registry-owner-in-c.html

    Answer From 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);
     }
    

    Utility function :

     // 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;
     }
    

    Declarations :

     [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);