Change ownership of registry key through command-line

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

  1. abbodi1406

    abbodi1406 MDL KB0000001

    Feb 19, 2011
    9,346
    34,756
    300
    You mean desktop.ini files? or Desktop folder?

    hidden files needs del /f /q /ah
     
  2. abbodi1406

    abbodi1406 MDL KB0000001

    Feb 19, 2011
    9,346
    34,756
    300
    @BAU

    This make it works
    Code:
    public static extern IntPtr RtlAdjustPrivilege(int a,bool b,bool c,ref bool d);
    previously
    Code:
    public static extern int RtlAdjustPrivilege(ulong a,bool b,bool c,ref bool d);
     
  3. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    350
    552
    10
  4. abbodi1406

    abbodi1406 MDL KB0000001

    Feb 19, 2011
    9,346
    34,756
    300
    Well, for me, the latest script still don't work :)

    i thought it might be something different between Windows 8.1 and 10, but it failed on both
    changed ulong to int and it worked
     
  5. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    350
    552
    10
    No idea why it worked for some and not for others, too many unknown factors, but I'm suspecting the amount of installed RAM has something to do with it
    The beauty of using undocumented winapi functions - it can be lean code-wise but it can also be mean :)
    Thanks again!
     
  6. Magmarock

    Magmarock MDL Junior Member

    Oct 12, 2016
    55
    11
    0
    #30 Magmarock, Jul 12, 2019 at 21:35
    Last edited: Jul 12, 2019 at 21:42
    (OP)

    You're right. That's my bad and I apologize. I didn't want to use a 3rd party tool because I thought it might complicate things for the client when a simple icon they can click on would do the job. Windows update blocker is simple enough for them to use and I should've stated that in the original thread. I'll be studing the code that people submitted and see if I can make sense of it.
     
  7. Magmarock

    Magmarock MDL Junior Member

    Oct 12, 2016
    55
    11
    0
    By snippet part do you mean the reg_takeownership.bat in your previous post or the one I am replying to? When it comes to powershell I'm very new to it, so I must apologize for being a little dense on this one. So I set the target registry at the top or at the bottom of the script?
     
  8. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    350
    552
    10
    Snippet is the same in all posts, as I have edited all of them after every change for consistency.
    Technically the script I've shared is primarily batch (CMD - Command Prompt), with just the snippet being contained powershell (so, a hybrid script).
    And of course you would set the target registry key somewhere at the top of your own script, before calling the snippet and doing all the reg add and whatever else you need.

    I'm hesitant to offer further advice since it appears you are not familiar with batch scripts at all, contrary to the text you have written in original post.
    Here's a bit more descriptive rundown, but Googling basic batch scripting stuff would be way more helpful

    yourscript.bat

    @echo off
    || this is usually what you start with, to prevent the script from spewing all your written commands on the screen
    ::any line starting with :: or rem won't be executed i.e. just a comment
    title bla bla
    color 9f
    echo hello world

    ::
    by-the-way, most registry manipulation require admin rights, so you either echo your users to right-click this script and run as Admin
    :: or invoke it automatically via something like in the next two lines:
    set "args="%~f0" %*" & call set "args=%%args:"=\"%%"
    reg query HKU\S-1-5-20>nul||(if "%?%" neq "y" powershell -c "start cmd -ArgumentList '/c set ?=y&call %args%' -verb runas" &exit)
    :: from here on, script should have admin rights

    :: set your target key (or you could simply insert the key directly as the first parameter after :reg_takeownership, but that would make lines hard to read
    set "regkey=HKLM\Whatever"

    :: get the current user sid to be used with the snippet (or instead of %CU% you could use the Administrator group = S-1-5-32-544 like in the example
    for /f "tokens=2" %%s in ('whoami /user /fo list') do set CU=%%s

    :: unlock the regkey with the snippet:
    call :reg_takeownership "%regkey%" FullControl Allow %CU%

    ::
    manipulate the regkey however you want:
    reg add "%regkey%" /v "leet" /d "1337" /f
    reg add "%regkey%\something" /v "else" /d "uhhhh" /f

    :: lock the regkey again with the snippet if necessary
    call :reg_takeownership "%regkey%" "ReadPermissions, ReadKey" Allow %CU%
    ::
    here you could also set the owner back to system (S-1-5-18) or trustedinstaller like in the previous example
    call :reg_takeownership "%regkey%" "ReadPermissions, ReadKey" Allow %CU% S-1-5-18

    :: anything else you might have in your script..
    ..........

    :: finish the directly executed script with exit/b or goto:eof
    exit/b

    :: this is where you would copy-paste the snippet and any other contained snippets aka goto :labels ( that each should end with exit/b or goto:eof )
     
  9. Magmarock

    Magmarock MDL Junior Member

    Oct 12, 2016
    55
    11
    0
    Thanks for the help. I'm familiar with batch scripting yes, but only basic stuff. I've written an OEM batch script for pire installing assets into Windows

    Here's an example of a script I wrote.

    Code:
    pushd %~dp0
    
    REM installing VC++ updates
    start /wait Updates\"Visual C++ Redistributable\2005 SP1 ATL vcredist_x64.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2005 SP1 ATL vcredist_x86.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2008 SP1 MFC vcredist_x64.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2008 SP1 MFC vcredist_x86.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2010 SP1 MFC vcredist_x64.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2010 SP1 MFC vcredist_x86.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2012 Update 4 vcredist_x64.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2012 Update 4 vcredist_x86.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2013 vcredist_x64.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2013 vcredist_x86.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2017 vc_redist.x64.exe" /q
    start /wait Updates\"Visual C++ Redistributable\2017 vc_redist.x86.exe" /q
    
    REM auxiliary updates
    start /wait Updates\directx_Jun2010_redist\DXSETUP.exe /silent
    start /wait Updates\OpenAL.exe /silent
    msiexec /i "Updates\Microsoft XNA Framework Redistributable 4.0.msi" /passive
    
    REM smartscreen off
    reg add "hklm\SOFTWARE\Policies\Microsoft\Windows\System" /v EnableSmartScreen /t REG_DWORD /d 0 /f
    
    REM defender off
    reg add "hklm\SYSTEM\CurrentControlSet\Services\WinDefend" /v  Start /t REG_DWORD  /d 4 /f
    
    REM firewall off
    reg add "hklm\SYSTEM\CurrentControlSet\Services\mpssvc" /v  Start /t REG_DWORD  /d 4 /f
    
    REM updates off
    reg add "hklm\SYSTEM\CurrentControlSet\Services\wuauserv" /v  Start /t REG_DWORD  /d 4 /f
    
    REM medic updates off
    reg add "hklm\SYSTEM\CurrentControlSet\Services\WaaSMedicSvc" /v  Start /t REG_DWORD  /d 4 /f
    
    REM orchestrator updates off
    reg add "hklm\SYSTEM\CurrentControlSet\Services\UsoSvc" /v  Start /t REG_DWORD  /d 4 /f
    
    REM security center off
    reg add "hklm\SYSTEM\CurrentControlSet\Services\wscsvc" /v  Start /t REG_DWORD  /d 4 /f
    
    
    REM importing reg scritps
    reg import "Reg\Personal.reg"
    reg import "Reg\Telemetry.reg"
    
    REM setting permissions
    regini "Reg\regini.txt"
    
    Powershell is something I'd like to learn but I'm struggling with the syntax. It's nothing like Batch or Linux Bash
     
  10. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    350
    552
    10
    Thing is a snippet is to be used as-is so the powershell syntax there does not matter much - only the parameters used to call the snippet count (and you can just expand upon the examples)
    but of course it is advised to verify any code you did not write that it does not do something malicious behind your back.
    Scripts shared around mdl are generally safe since many knowledgeable users can quickly tell at a glance, and admins here do manage the forums.
     
  11. Magmarock

    Magmarock MDL Junior Member

    Oct 12, 2016
    55
    11
    0
    I see. In your last example I see a call to the reg_takeownership bat file but where's the call to the ps1 script?
     
  12. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    350
    552
    10
    call batch command can launch an external program or batch script
    or can jump to execute all commands after a :label_name ( notice it starts with a single : ) that resides somewhere inside the script, then resume executing commands from where it jumped

    In all my examples the call is to the snippet that should be incorporated in the batch script itself
    not to a separate batch file or ps1 script - because that's what a snippet is - a ready to use copy-paste-able code.

    Did I not literally draw it for you in the previous post?! We're not on the same page.
    Try going slowly line by line through the shared script, you'll get it eventually...
     
  13. Magmarock

    Magmarock MDL Junior Member

    Oct 12, 2016
    55
    11
    0

    I apologize for seeming dense. Okay so this is the code I'm talking about
    Code:
    :reg_takeownership  key:"HKCU\Console" perm:"FullControl" access:"Allow" user:"S-1-5-32-544" owner(optional):"S-1-5-18"
    set "pargs=$regkey='%~1'; $p='%~2'; $a='%~3'; $u='%~4'; $o='%~5';"
    powershell -noprofile -c "%pargs%; $f=[io.file]::ReadAllText('%~f0') -split ':ps_reg_own\:.*';iex ($f[1]);" & exit/b
    :ps_reg_own: [     pastebin.com/XTPt0JSC      AveYo: call :reg_takeownership "HKLM\MyKey" FullControl Allow S-1-5-18
    $dll0='[DllImport("ntdll.dll")]public static extern IntPtr RtlAdjustPrivilege(int a,bool b,bool c,ref bool d);';
    $nt=Add-Type -Member $dll0 -Name Nt -PassThru; foreach($i in @(9,17,18)){$null=$nt::RtlAdjustPrivilege($i,1,0,[ref]0)}
    $root=$true; if($o -eq ''){$o=$u}; $rk=$regkey -split '\\',2; $key=$rk[1];
    switch -regex ($rk[0]){ '[mM]'{$HK='LocalMachine'};'[uU]'{$HK='CurrentUser'};default{$HK='ClassesRoot'}; }
    $usr=0,0,0; $sec=0,0,0; $rule=0,0,0; $perm='FullControl',$p,$p; $access='Allow',$a,$a; $s=$o,$u,'S-1-5-32-544';
    for($i=0;$i -le 2;$i++){ $usr[$i]=[System.Security.Principal.SecurityIdentifier]$s[$i];
     $rule[$i]=[System.Security.AccessControl.RegistryAccessRule]::new($usr[$i], $perm[$i], 3, 0, $access[$i]);
     $sec[$i]=[System.Security.AccessControl.RegistrySecurity]::new(); }
    function Reg_TakeOwnership { param($hive, $key, $root=$false);
     $reg=[Microsoft.Win32.Registry]::$hive.OpenSubKey($key,'ReadWriteSubTree','TakeOwnership'); $sec[2].SetOwner($usr[2]);
     $reg.SetAccessControl($sec[2]); if($root){ $reg=$reg.OpenSubKey('','ReadWriteSubTree','ChangePermissions');
      $acl=$reg.GetAccessControl(); $acl.SetAccessRuleProtection($false,$false); $acl.ResetAccessRule($rule[1]);
      $reg.SetAccessControl($acl); } $sec[0].SetOwner($usr[0]); $reg.SetAccessControl($sec[0]); }
    Reg_TakeOwnership $HK $key $true; if($root){ $r=[Microsoft.Win32.Registry]::$HK.OpenSubKey($key);
     foreach($sk in $r.GetSubKeyNames()){try{ Reg_TakeOwnership $HK "$($key+'\\'+$sk)" $false}catch{} }}
    Get-Acl "$($rk[0]+':\\'+$rk[1])" | fl
    :ps_reg_own: ]
    
    Some of these commands look like they are from command or batch. While others look like they are from PW. Oh wait
    Code:
     powershell -noprofile -c
    that's the call to use powershell isn't it?
     
  14. BAU

    BAU MDL Senior Member

    Feb 10, 2009
    350
    552
    10
  15. Magmarock

    Magmarock MDL Junior Member

    Oct 12, 2016
    55
    11
    0

    YAY I'm learning! Please accept my thanks and apologizes for taking your time. I shall study this code to improve my skills and I appreciate what you've done for me.