Change ownership of registry key through command-line

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

  1. Magmarock

    Magmarock MDL Junior Member

    Joined:
    Oct 12, 2016
    Messages:
    55
    Likes Received:
    12
    Trophy Points:
    0
    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. rpo

    rpo MDL Expert

    Joined:
    Jan 3, 2010
    Messages:
    1,166
    Likes Received:
    990
    Trophy Points:
    60
  3. TairikuOkami

    TairikuOkami MDL Expert

    Joined:
    Mar 15, 2014
    Messages:
    1,057
    Likes Received:
    926
    Trophy Points:
    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.
     
  4. Magmarock

    Magmarock MDL Junior Member

    Joined:
    Oct 12, 2016
    Messages:
    55
    Likes Received:
    12
    Trophy Points:
    0
  5. rpo

    rpo MDL Expert

    Joined:
    Jan 3, 2010
    Messages:
    1,166
    Likes Received:
    990
    Trophy Points:
    60
    You can adapt the code to your need, it's up to you.
     
  6. Magmarock

    Magmarock MDL Junior Member

    Joined:
    Oct 12, 2016
    Messages:
    55
    Likes Received:
    12
    Trophy Points:
    0
    I'm not very experienced with powershell. What's the code I need?
     
  7. rpo

    rpo MDL Expert

    Joined:
    Jan 3, 2010
    Messages:
    1,166
    Likes Received:
    990
    Trophy Points:
    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.
     
  8. pf100

    pf100 MDL Expert

    Joined:
    Oct 22, 2010
    Messages:
    1,906
    Likes Received:
    3,055
    Trophy Points:
    60
    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?
     
  9. LiteOS

    LiteOS MDL Expert

    Joined:
    Mar 7, 2014
    Messages:
    1,893
    Likes Received:
    814
    Trophy Points:
    60
    Run the script in trusted installer account
     
  10. abbodi1406

    abbodi1406 MDL KB0000001

    Joined:
    Feb 19, 2011
    Messages:
    12,067
    Likes Received:
    55,427
    Trophy Points:
    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\*
     
  11. pf100

    pf100 MDL Expert

    Joined:
    Oct 22, 2010
    Messages:
    1,906
    Likes Received:
    3,055
    Trophy Points:
    60
    I like the "dir /b /s /ad" trick to get subdirectory names in a "for" loop. I've never seen that before.
     
  12. boyonthebus

    boyonthebus MDL Addicted

    Joined:
    Sep 16, 2018
    Messages:
    917
    Likes Received:
    573
    Trophy Points:
    30
  13. Magmarock

    Magmarock MDL Junior Member

    Joined:
    Oct 12, 2016
    Messages:
    55
    Likes Received:
    12
    Trophy Points:
    0
  14. TairikuOkami

    TairikuOkami MDL Expert

    Joined:
    Mar 15, 2014
    Messages:
    1,057
    Likes Received:
    926
    Trophy Points:
    60
    It does not work, when I am trying to remove desktop.
     
  15. Magmarock

    Magmarock MDL Junior Member

    Joined:
    Oct 12, 2016
    Messages:
    55
    Likes Received:
    12
    Trophy Points:
    0
    The Powershell script doesn't work for me either.
     
  16. rpo

    rpo MDL Expert

    Joined:
    Jan 3, 2010
    Messages:
    1,166
    Likes Received:
    990
    Trophy Points:
    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.
     
  17. BAU

    BAU MDL Addicted

    Joined:
    Feb 10, 2009
    Messages:
    943
    Likes Received:
    2,042
    Trophy Points:
    30
  18. abbodi1406

    abbodi1406 MDL KB0000001

    Joined:
    Feb 19, 2011
    Messages:
    12,067
    Likes Received:
    55,427
    Trophy Points:
    340
    @BAU

    RtlAdjustPrivilege don't work with TrustedInstaller owned
     
  19. BAU

    BAU MDL Addicted

    Joined:
    Feb 10, 2009
    Messages:
    943
    Likes Received:
    2,042
    Trophy Points:
    30
    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
     
  20. abbodi1406

    abbodi1406 MDL KB0000001

    Joined:
    Feb 19, 2011
    Messages:
    12,067
    Likes Received:
    55,427
    Trophy Points:
    340