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