Change ownership of registry key through command-line

Discussion in 'Windows 10' started by Magmarock, Jul 6, 2019.

  1. Magmarock

    Magmarock MDL Member

    Oct 12, 2016
    175
    22
    10
    Hi there. I'm writing a sensitive script and I need to be able to change ownership and permissions of specific registry keys. The script in question will work like an on & off switch. Every time it's used it must grant itself permission to change a value in the registry, then lock it down to prevent other programs and the user from altering the settings.

    This must all be done without the use of 3rd tools. I can use regini to restrict access, but retaking access afterwards is where I run into problems. Does anyone know how to do this?
     
  2. TairikuOkami

    TairikuOkami MDL Expert

    Mar 15, 2014
    1,172
    1,055
    60
    That can not be done, you can use powershell at best, but not CMD, you can not even remove folders from a folder via CMD, it is very limited, besides it is being deprecated and replaced by powershell.
     
  3. rpo

    rpo MDL Expert

    Jan 3, 2010
    1,447
    1,424
    60
    You can adapt the code to your need, it's up to you.
     
  4. Magmarock

    Magmarock MDL Member

    Oct 12, 2016
    175
    22
    10
    I'm not very experienced with powershell. What's the code I need?
     
  5. rpo

    rpo MDL Expert

    Jan 3, 2010
    1,447
    1,424
    60
    I just give you a powershell script example. I use it to take ownership of the "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\UserSwitch".
    Code:
    ## 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 rele);
      [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 TOKEN_QUERY = 0x00000008;
      internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
      public static bool EnablePrivilege(long processHandle, string privilege) {
        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;
        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;
      }
    }
    '@
    # Take ownership privilege
    $ProcessHandle = (Get-Process -id $pid).Handle
    $type = Add-Type $definition -PassThru
    $max_retry=10
    for ($i=1; $i -le $max_retry;$i++){
        $status=$type[0]::EnablePrivilege($processHandle, "SeTakeOwnershipPrivilege")
        if ($status){break}
        if ($i -eq $max_retry){read-host "Unable to take ownership privilege";exit}
        start-sleep 1|out-null
        }
    #
    $keypath="SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\UserSwitch"
    #
    # Get localized admin group name
    $admin=(get-wmiobject win32_group| Where-Object {$_.sid -eq "s-1-5-32-544"}).name
    # Change Owner to the local Administrators group
    $regKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("$keypath", "ReadWriteSubTree", "TakeOwnership")
    $regACL = $regKey.GetAccessControl()
    $regACL.SetOwner([System.Security.Principal.NTAccount]"$admin")
    $regKey.SetAccessControl($regACL)
    # Change Permissions for the local Administrators group
    $regKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("$keypath", "ReadWriteSubTree", "ChangePermissions")
    $regACL = $regKey.GetAccessControl()
    $regRule = New-Object System.Security.AccessControl.RegistryAccessRule ("$admin","FullControl","ContainerInherit","None","Allow")
    $regACL.SetAccessRule($regRule)
    # Change Permissions for System
    $regRule = New-Object System.Security.AccessControl.RegistryAccessRule ("SYSTEM","SetValue","ContainerInherit","None","Deny")
    $regACL.SetAccessRule($regRule)
    $regKey.SetAccessControl($regACL)
    New-ItemProperty -Path "HKLM:\$keyPath" -Name "Enabled" -Value 1 -PropertyType DWORD -Force |out-null
    
    The Administrators group gets ownership of the key and gets "FullControl" of the key.
    The system account is no longer the owner of the key and "SetValue" is denied; it can read but no change.
     
  6. pf100

    pf100 Duct Tape Coder

    Oct 22, 2010
    2,069
    3,449
    90
    I think I'm misunderstanding you. Surely you know you can remove folders from a folder with cmd. You can remove the UpdateAssistantV2 folder from the Windows folder like this:
    Code:
    takeown /f "%systemroot%\UpdateAssistantV2" /a
    icacls "%systemroot%\UpdateAssistantV2" /reset
    del %systemroot%\UpdateAssistantV2\*.* /f /q
    rmdir %systemroot%\UpdateAssistantV2 /s /q
    If it's not a system protected folder the first two lines of code aren't necessary.
    But I think you know all of this, so what did you mean?
     
  7. LiteOS

    LiteOS Windowizer

    Mar 7, 2014
    2,209
    983
    90
    Run the script in trusted installer account
     
  8. abbodi1406

    abbodi1406 MDL KB0000001

    Feb 19, 2011
    16,226
    84,916
    340
    I think he means removing all folders from a folder (i.e. all the content of a folder without knowing them)
    as example C:\Windows\SoftwareDistribution\Download\

    there are two ways that works
    the easy
    Code:
    pushd %systemroot%\SoftwareDistribution\Download
    rd /s /q .
    popd
    
    the pro
    Code:
    for /f "delims=" %i in ('dir /b /s /ad %systemroot%\SoftwareDistribution\Download 2^>nul') do rd /s /q "%~i"
    del /f /q %systemroot%\SoftwareDistribution\Download\*
     
  9. pf100

    pf100 Duct Tape Coder

    Oct 22, 2010
    2,069
    3,449
    90
    I like the "dir /b /s /ad" trick to get subdirectory names in a "for" loop. I've never seen that before.
     
  10. boyonthebus

    boyonthebus MDL Expert

    Sep 16, 2018
    1,168
    752
    60
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  11. TairikuOkami

    TairikuOkami MDL Expert

    Mar 15, 2014
    1,172
    1,055
    60
    It does not work, when I am trying to remove desktop.
     
  12. Magmarock

    Magmarock MDL Member

    Oct 12, 2016
    175
    22
    10
    The Powershell script doesn't work for me either.
     
  13. rpo

    rpo MDL Expert

    Jan 3, 2010
    1,447
    1,424
    60
    Are you talking about the script i posted? It works for me as it is. You must run the the script with admin privileges and ensure you are allowed to run ps scripts.
     
  14. AveYo

    AveYo MDL Expert

    Feb 10, 2009
    1,836
    5,694
    60
    #17 AveYo, Jul 9, 2019
    Last edited: Jul 13, 2019
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  15. abbodi1406

    abbodi1406 MDL KB0000001

    Feb 19, 2011
    16,226
    84,916
    340
    @BAU

    RtlAdjustPrivilege don't work with TrustedInstaller owned
     
  16. AveYo

    AveYo MDL Expert

    Feb 10, 2009
    1,836
    5,694
    60
    How come? the powershell process gets the required access. After that, it's only the script to blame - which I did refactored and appears to work fine.
    Can you please give a non-working regkey example with the updated snippet that otherwise works after using something else (AdjustTokenPrivileges or DuplicateToken)?
    I do have a variant with DuplicateToken but that's a few lines more code and at this point is probably more convenient to just hijack trustedinstaller service
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  17. abbodi1406

    abbodi1406 MDL KB0000001

    Feb 19, 2011
    16,226
    84,916
    340