Share via


TrustedInstaller in registry access denied

Question

Tuesday, June 11, 2019 7:28 PM

Hi,

I am trying to change a permission on a registry key and Trustinstaller is the owner.

$acl= get-acl -path "HKLM:\Software\Classes\ASP.HostEncode\CLSID"
$acl | Format-list
$object=new-object system.security.Principal.NTAccount("BUILTIN\Administrateurs")
$acl.setowner($object)
$acl|set-acl

I ran the same script with system account as owner but Trusted installer is making the script to return Permission denied security exception.

What is happening?

What is the solution?

Thanks,

All replies (15)

Tuesday, June 11, 2019 8:02 PM

You cannot change the owner of an installer key.  The installer will always block you.  One method is to terminate the installer and then take ownership of the key and then set the new owner.

\(ツ)_/


Tuesday, June 11, 2019 10:19 PM

Hi,

I am not sure understanding you. The installation is over and the registry key as the TrustedInstaller account. SO I need changing the owner. I am able to do that with system but not TrustedInstaller.

I don't believe it is not possible?!

Thanks,


Tuesday, June 11, 2019 10:50 PM

What you just posted doesn't make sense.  Are you trying to remove the trusted installer as owner of a key that it has taken ownership of?

\(ツ)_/


Tuesday, June 11, 2019 11:16 PM

Hi,

I installed an old software. Some keys used by that software are owned by TrustedInstaller Account. I need set the administrators group as the owner changing the permission of this key and set back Trustedinstaller account as the owner.

Thanks,


Tuesday, June 11, 2019 11:31 PM

Hi,

Sound this is working:

function enable-privilege {
 param(
  ## The privilege to adjust. This set is taken from
  ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
  [ValidateSet(
   "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
   "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
   "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
   "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
   "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
   "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
   "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
   "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
   "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
   "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege",  "SeTrustedCredManAccessPrivilege",
   "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
  $Privilege,
  ## The process on which to adjust the privilege. Defaults to the current process.
  $ProcessId = $pid,
  ## Switch to disable the privilege, rather than enable it.
  [Switch] $Disable
 )

 ## Taken from P/Invoke.NET with minor adjustments.
 $definition = @'
 using System;
 using System.Runtime.InteropServices;

 public class AdjPriv
 {
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
   ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
  [DllImport("advapi32.dll", SetLastError = true)]
  internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  internal struct TokPriv1Luid
  {
   public int Count;
   public long Luid;
   public int Attr;
  }

  internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
  internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
  internal const int TOKEN_QUERY = 0x00000008;
  internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
  public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
  {
   bool retVal;
   TokPriv1Luid tp;
   IntPtr hproc = new IntPtr(processHandle);
   IntPtr htok = IntPtr.Zero;
   retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
   tp.Count = 1;
   tp.Luid = 0;
   if(disable)
   {
    tp.Attr = SE_PRIVILEGE_DISABLED;
   }
   else
   {
    tp.Attr = SE_PRIVILEGE_ENABLED;
   }
   retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
   retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
   return retVal;
  }
 }
'@

 $processHandle = (Get-Process -id $ProcessId).Handle
 $type = Add-Type $definition -PassThru
 $type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}

enable-privilege SeTakeOwnershipPrivilege 
$acl= get-acl "HKLM:\SOFTWARE\Classes\test"
$object=new-object system.security.Principal.NTAccount("BUILTIN\Administrateurs")
$acl.setowner($object)
$acl|set-acl

Now I have to set it back to TrustedInstaller as the owner.


Tuesday, June 11, 2019 11:35 PM

What you have admitted is that you are installing software that is incompatible with the version of Windows that you are running.

You cannot take a key way from the TI.  Why do you think that MS has done this.  It is to protect specific keys from being changed.  Old software had a bad habit of altering system keys and overwriting system binaries.  This was why MS locked down the system. 

To change the owner of an installer owned key you must disable the installer service.  For many keys the installer service may just reset the owner back to itself.  None of this is documented outside of the fact that the installer protects its keys.

Look up the documentation for the TrustedInstaller in the MS documentation to learn how it works. 

To alter an installer key you must take ownership of the key which can only be done if the key is not being protected.  After you are the owner you can then change the owner to another account.  When taking ownership yu also have to give yourself "FullControl".

\(ツ)_/


Tuesday, June 11, 2019 11:42 PM

Hi,

Sometimes, you need adjusting security to make software working. This software need to be install and run in Windows XP SP3 compatibility. If installed with an administrator account and start then it will be working. But during SCCM deployment it is not working. The security has change a lot and some registry keys need to be adjust.

Read on Internet and I am not alone to do those manipulations.

Thanks,


Tuesday, June 11, 2019 11:43 PM

Yes. You have to "take" ownership.  You can SetOwner on any key that you own but you must "take" on keys that you don't own.  Once you own a key then you can set another owner.

Enabling the privilege can be done with a script from the Gallery or you can just use the TAKEOWN utility program.  This utility will enable the privilege.  It can also be used to directly give ownership to another account providing you know the accounts password.

TAKEOWN /?

\(ツ)_/


Tuesday, June 11, 2019 11:46 PM

Hi,

Sometimes, you need adjusting security to make software working. This software need to be install and run in Windows XP SP3 compatibility. If installed with an administrator account and start then it will be working. But during SCCM deployment it is not working. The security has change a lot and some registry keys need to be adjust.

Read on Internet and I am not alone to do those manipulations.

Thanks,

Yes but you need to be very careful and you need to test the results on a non-production system.  If you absolutely know what the software does then you may be OK.  In a recent article on security one of the most dangerous security issues was "old software" that asks for too many privileges and alters the underlying system in unsafe ways.  Do this at your won risk.

\(ツ)_/


Tuesday, June 11, 2019 11:47 PM

Hi,

But takeown is for file system not registry?!

Thanks,


Tuesday, June 11, 2019 11:55 PM

Hi,

How may I set back Trusted installer as the owner?

$acl= get-acl "HKLM:\SOFTWARE\Classes\test"
$object=new-object system.security.Principal.NTAccount("NT SERVICE\TrustedInstaller")
$acl.setowner($object)
$acl|set-acl

set-acl : L'identificateur de sécurité ne peut pas être le propriétaire de cet objet.
Au caractère D:\Temp\Sans titre1.ps1:90 : 6

  • $acl|set-acl
    +      ~~~~~~~
        + CategoryInfo          : InvalidOperation : (HKEY_LOCAL_MACHINE\SOFTWARE\Classes\test:String) [Set-Acl], InvalidOperationException
        + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.SetAclCommand

The security identifier cannot be the owner of this object.


Wednesday, June 12, 2019 12:16 AM

Hi,

But takeown is for file system not registry?!

Thanks,

Sorry.  I should have posted SetACL for the registry.

https://www.askvg.com/windows-tip-take-ownership-permission-of-registry-keys-from-command-line/

\(ツ)_/


Wednesday, June 12, 2019 12:20 AM

You have to take ownership before you assign a new owner. 

\(ツ)_/


Wednesday, June 12, 2019 1:56 AM

Hi,

Is it working on Windows 10?

MS is supporting that tool?


Wednesday, June 12, 2019 1:59 AM

function enable-privilege {
 param(
  ## The privilege to adjust. This set is taken from
  ## http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
  [ValidateSet(
   "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege",
   "SeChangeNotifyPrivilege", "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege",
   "SeCreatePermanentPrivilege", "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege",
   "SeDebugPrivilege", "SeEnableDelegationPrivilege", "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege",
   "SeIncreaseQuotaPrivilege", "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege",
   "SeLockMemoryPrivilege", "SeMachineAccountPrivilege", "SeManageVolumePrivilege",
   "SeProfileSingleProcessPrivilege", "SeRelabelPrivilege", "SeRemoteShutdownPrivilege",
   "SeRestorePrivilege", "SeSecurityPrivilege", "SeShutdownPrivilege", "SeSyncAgentPrivilege",
   "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege",
   "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege",  "SeTrustedCredManAccessPrivilege",
   "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
  $Privilege,
  ## The process on which to adjust the privilege. Defaults to the current process.
  $ProcessId = $pid,
  ## Switch to disable the privilege, rather than enable it.
  [Switch] $Disable
 )

 ## Taken from P/Invoke.NET with minor adjustments.
 $definition = @'
 using System;
 using System.Runtime.InteropServices;

 public class AdjPriv
 {
  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
   ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

  [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
  internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
  [DllImport("advapi32.dll", SetLastError = true)]
  internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  internal struct TokPriv1Luid
  {
   public int Count;
   public long Luid;
   public int Attr;
  }

  internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
  internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
  internal const int TOKEN_QUERY = 0x00000008;
  internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
  public static bool EnablePrivilege(long processHandle, string privilege, bool disable)
  {
   bool retVal;
   TokPriv1Luid tp;
   IntPtr hproc = new IntPtr(processHandle);
   IntPtr htok = IntPtr.Zero;
   retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
   tp.Count = 1;
   tp.Luid = 0;
   if(disable)
   {
    tp.Attr = SE_PRIVILEGE_DISABLED;
   }
   else
   {
    tp.Attr = SE_PRIVILEGE_ENABLED;
   }
   retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
   retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
   return retVal;
  }
 }
'@

 $processHandle = (Get-Process -id $ProcessId).Handle
 $type = Add-Type $definition -PassThru
 $type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}

enable-privilege SeTakeOwnershipPrivilege 
$acl= get-acl "HKLM:\SOFTWARE\Classes\test"
$object=new-object system.security.Principal.NTAccount("BUILTIN\Administrateurs")
$acl.setowner($object)
$acl|set-acl


$acl= get-acl "HKLM:\SOFTWARE\Classes\test"
$object=new-object system.security.Principal.NTAccount("NT SERVICE\TrustedInstaller")
$acl.setowner($object)
$acl|set-acl

In that example, I took the ownership with BUILTIN\Administrateurs. Then trying to get it back to NT Service\TrustedInstaller.

With the same error

set-acl : L'identificateur de sécurité ne peut pas être le propriétaire de cet objet.
Au caractère D:\Temp\Sans titre1.ps1:90 : 6
+ $acl|set-acl
+      ~~~~~~~
    + CategoryInfo          : InvalidOperation : (HKEY_LOCAL_MACHINE\SOFTWARE\Classes\test:String) [Set-Acl], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.SetAclCommand