How can I change particular registry owner in C#

Shirai_Kuroko 26 Reputation points
2022-02-08T09:31:28.73+00:00

0

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 Learn 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?

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,648 questions
0 comments No comments
{count} votes

Accepted answer
  1. Castorix31 83,206 Reputation points
    2022-02-08T13:08:39+00:00

    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)

    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);
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful