Sledgehammer - Windows 10 Update Control

Discussion in 'MDL Projects and Applications' started by pf100, Nov 28, 2016.

  1. pf100

    pf100 Duct Tape Coder

    Oct 22, 2010
    2,069
    3,447
    90
    @grumple Whenever the script needs to be updated I post it at the top of the first post and I post it here in the thread, or somebody else does first. If I get a report of a vulnerability with the script, I fix it and post an update.

    If an upgrade creates an x:\windows.old folder the script should be run again because the \windows folder has been replaced so previously locked files aren't locked anymore; however, the LockFiles task will rename or lock the required system files so it should be mostly okay since rempl and update assistant most likely won't be included in a feature update anyway.

    I can say that right now with v2.7.2 of the script, if you run Sledgehammer and close it, I have a 100% certainty that Microsoft can't override it.

    Using the script normally, doing updates manually, I'm about 99.999% sure Microsoft can't override it.
     
  2. Whistler4

    Whistler4 MDL Member

    Jul 30, 2015
    204
    192
    10
    #1642 Whistler4, Sep 5, 2020
    Last edited: Sep 5, 2020
    I'm still using v2.7.0 on Windows 10 1909, and it's working effectively after monthly updates through August. But I wouldn't trust Sledgehammer versions before 2.7.2 for Windows 10 2004. As FAQ C4 says about Windows Feature Updates in the Readme file, ". . . always use the latest version of the script."
     
  3. spanishfly

    spanishfly MDL Senior Member

    Dec 5, 2018
    352
    527
    10
    #1643 spanishfly, Sep 8, 2020
    Last edited: Sep 8, 2020
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. AveYo

    AveYo MDL Expert

    Feb 10, 2009
    1,836
    5,692
    60
    #1644 AveYo, Sep 8, 2020
    Last edited: Sep 10, 2020
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. pf100

    pf100 Duct Tape Coder

    Oct 22, 2010
    2,069
    3,447
    90
    @spanishfly @BAU Thanks for the info and to both of you and others involved for doing this work.
     
  6. spanishfly

    spanishfly MDL Senior Member

    Dec 5, 2018
    352
    527
    10
    #1646 spanishfly, Sep 10, 2020
    Last edited: Sep 10, 2020
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  7. Windows_Addict

    Windows_Addict MDL Expert

    Jul 19, 2018
    1,248
    3,415
    60
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  8. AveYo

    AveYo MDL Expert

    Feb 10, 2009
    1,836
    5,692
    60
    #1648 AveYo, Sep 10, 2020
    Last edited: Sep 10, 2020
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  9. spanishfly

    spanishfly MDL Senior Member

    Dec 5, 2018
    352
    527
    10
    #1649 spanishfly, Sep 11, 2020
    Last edited: Sep 11, 2020
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  10. AveYo

    AveYo MDL Expert

    Feb 10, 2009
    1,836
    5,692
    60
    Snippet tries to keep original owner when run recursively by design and that will spew an error when it cannot add permissions, but then it will retry, this time after taking ownership, so if you base your conclusion only on the script output, you might be wrong.

    Did you actually check the permissions in the registry after running #2 as-is?
    Chances are high you will see Everyone denied on each and every key.

    In any case, this is not the right thread for an extended discussion about reg_own
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  11. spanishfly

    spanishfly MDL Senior Member

    Dec 5, 2018
    352
    527
    10
    #1651 spanishfly, Sep 11, 2020
    Last edited: Sep 12, 2020
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  12. AveYo

    AveYo MDL Expert

    Feb 10, 2009
    1,836
    5,692
    60
    Anyway, there is one situation where reg_own fails to set permissions without intermediate call:
    - Exclusive own by TrustedInstaller, with just read permissions defined for System and Administrators
    So the snippet is denied change permissions since it runs under Administrators account by default (powershell)

    Simple fix is to first add FullControl for Administrators and then do your initial operation.

    Better fix is to first add FullControl for a surrogate account (as to not override built-in Administrators),
    do your initial operations, then remove the surrogate account.

    Example

    Code:
    Path   : Microsoft.PowerShell.Core\Registry::HKLM\SOFTWARE\SomeKey
    Owner  : NT SERVICE\TrustedInstaller
    Group  : NT SERVICE\TrustedInstaller
    Access : NT AUTHORITY\SYSTEM Allow  -2147483648
             NT AUTHORITY\SYSTEM Allow  ReadKey
             BUILTIN\Administrators Allow  -2147483648
             BUILTIN\Administrators Allow  ReadKey
             BUILTIN\Users Allow  ReadKey
             BUILTIN\Users Allow  -2147483648
             NT SERVICE\TrustedInstaller Allow  FullControl
             NT SERVICE\TrustedInstaller Allow  268435456
             APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  -2147483648
             APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  ReadKey
    
    To just change somevalue and keep everything as is (sneaky), could call the snippet like this:
    Code:
    :: 1. first make sure we have permissions to make changes by using the surrogate admin group S-1-5-114
    call :reg_own "HKLM\SOFTWARE\SomeKey" all S-1-5-114 "" Allow "FullControl"
    :: 2. do our thing
    reg add "HKLM\SOFTWARE\SomeKey" /f /v somevalue /d snippetrullz
    :: could now add any permissions without getting access denied errors (commented below)
    rem call :reg_own "HKLM\SOFTWARE\SomeKey" all S-1-5-18 "" Deny "FullControl"
    reg add "HKLM\SOFTWARE\SomeKey\More" /f /v othervalue /d 1 /t reg_dword
    :: 3. once done, remove surrogate admin group - the original Administrators remains unchanged
    call :reg_own "HKLM\SOFTWARE\SomeKey" none S-1-5-114 ""
    
    This is probably the GOLD showcase usage for my reg_own snippet
    adjusting any values without leaving changed permissions and changed ownership behind,
    something much harder to do in regedit and other tools when processing keys recursively...
    :rolleyes:
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  13. spanishfly

    spanishfly MDL Senior Member

    Dec 5, 2018
    352
    527
    10
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  14. AveYo

    AveYo MDL Expert

    Feb 10, 2009
    1,836
    5,692
    60
    Well the last example was meant for the standard use case of changing a value that was locked by the OS, while your use case is different.
    Denying permissions works absolutely fine for a specific key, but when doing it recursively we need to be smart about it,
    as you can end up with "put the cart before the horses" situation - effectively denying yourself making further permission changes to subkeys.
    So, never use FullControl when setting deny permissions recursively. WriteKey will also deny "Read Control" so don't use that either.
    Instead, just deny all write permissions explicitly: "SetValue,CreateSubkey,CreateLink,Delete,ChangePermissions,TakeOwnership"
    So for your use case, this should work:
    Code:
    @echo off &title reg_own deny experiment
    
    :::: Ask for elevation passing any batch arguments (don't care for passing user or ti here since we deny write for everyone)
    set _=call "%~f0" %*&reg query HKU\S-1-5-19>nul 2>nul||(powershell -nop -c start cmd -args '/d/x/q/r',$env:_ -verb runas & exit)
    
    :::: 1. make sure we have permissions to make changes by adding S-1-1-0 (Everyone) recursively
    REM call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" all S-1-1-0 "" Allow "FullControl"
    
    :::: 2. do our thing with the above registry key - if not doing anything to it 1. is not needed and only doing 3. is enough to lock key
    
    :::: 3. deny write for S-1-1-0 (Everyone) and set owner to S-1-2-3 (dummy) - must be last and use explicit write when recursively
    set VO=verbose-output :: now silent by default, only lists rights if VO is defined; to undefine: set "VO="
    set write="SetValue,CreateSubkey,CreateLink,Delete,ChangePermissions,TakeOwnership"
    call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" all S-1-1-0 S-1-2-3 Deny %write%
    
    ECHO:
    ECHO:
    ECHO Your key is now locked and it's safe to update windows
    
    ECHO:
    pause
    exit/b
    
    :reg_own #key [optional] all user owner access permission  :  call :reg_own "HKCU\My" "" S-1-5-32-545 S-1-5-18 Allow FullControl
    powershell -nop -c $A='%~1','%~2','%~3','%~4','%~5','%~6';iex(([io.file]::ReadAllText('%~f0')-split':Own1\:.*')[1])&exit/b:Own1:
    $D1=[IO.IODescriptionAttribute].Module.GetType('System.Diagnostics.Process').GetMethods(42) |? {$_.Name -eq 'SetPrivilege'}
    'SeSecurityPrivilege','SeTakeOwnershipPrivilege','SeBackupPrivilege','SeRestorePrivilege' |% {$D1.Invoke($null, @("$_",2))}
    $path=$A[0]; $rk=$path-split'\\',2; $HK=gi -lit Registry::$($rk[0]) -fo; $s=$A[1]; $sps=[Security.Principal.SecurityIdentifier]
    $u=($A[2],'S-1-5-32-544')[!$A[2]];$o=($A[3],$u)[!$A[3]];$w=$u,$o |% {new-object $sps($_)}; $old=!$A[3];$own=!$old; $y=$s-eq'all'
    $rar=new-object Security.AccessControl.RegistryAccessRule( $w[0], ($A[5],'FullControl')[!$A[5]], 1, 0, ($A[4],'Allow')[!$A[4]] )
    $x=$s-eq'none'; function Own1($k){$t=$HK.OpenSubKey($k,2,'TakeOwnership'); 0,4 |% {try{$o=$t.GetAccessControl($_)}catch{$old=0}}
    if($old){$own=1;$w[1]=$o.GetOwner($sps)};$o.SetOwner($w[0]);$t.SetAccessControl($o); $c=$HK.OpenSubKey($k,2,'ChangePermissions')
    $p=$c.GetAccessControl(2);if($y){$p.SetAccessRuleProtection(1,1)};$p.ResetAccessRule($rar);if($x){$p.RemoveAccessRuleAll($rar)}
    $c.SetAccessControl($p);if($own){$o.SetOwner($w[1]);$t.SetAccessControl($o)};if($s){$subkeys=$HK.OpenSubKey($k).GetSubKeyNames()
    foreach($n in $subkeys){Own1 "$k\$n"}}};Own1 $rk[1];if($env:VO){get-acl Registry::$path|fl} #:Own1: lean & mean snippet by AveYo
    ::-_-::
    
    
    Could instead Allow FullControl for Everyone, then Allow just ReadKey for specific accounts, and finally remove Everyone:
    Code:
    @echo off &title reg_own readkey only experiment
    
    :::: Define TI sid (TrustedInstaller)
    for /f "tokens=3" %%a in ('sc.exe showsid TrustedInstaller') do set TI=%%a >nul
    :::: Define USER sid before asking for elevation since it gets replaced for limited accounts
    set _=call "%~f0" %* &if "%USER%"=="" for /f "tokens=2" %%u in ('whoami /user /fo list') do set USER=%%u
    :::: Ask for elevation passing USER and any batch arguments - ps also enables debug priviledge unlike vbs
    reg query HKU\S-1-5-19>nul 2>nul||(powershell -nop -c start cmd -args '/d/x/q/rset USER=%USER%^&',$env:_ -verb runas &exit)
    
    :::: 1. make sure we have permissions to make changes by adding S-1-1-0 (Everyone) recursively
    call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" all S-1-1-0 "" Allow "FullControl"
    
    :::: 2. only allow ReadKey for S-1-5-32-544 (Administrators), S-1-5-18 (SYSTEM) and %TI% (TrustedInstaller) to prevent OS changes
    call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" all S-1-5-32-544 "" Allow ReadKey
    call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" all S-1-5-18 "" Allow ReadKey
    call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" all %TI% "" Allow ReadKey
    :::: Cleanup previous experiment with S-1-5-114 (surrogate admins group)
    call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" none S-1-5-114 ""
    
    set VO=verbose-output :: snippet now silent by default, will only lists rights if VO is defined; to undefine: set "VO="
    
    :::: 3.a either remove S-1-1-0 (Everyone) and set owner to S-1-2-3 (dummy) - here preferred over using global deny but both are fine
    call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" none S-1-1-0 S-1-2-3
    :::: 3.b or deny write for S-1-1-0 (Everyone) - must be last and should use explicit write when run recursively, not FUllControl
    REM set write="SetValue,CreateSubkey,CreateLink,Delete,ChangePermissions,TakeOwnership"
    REM call :reg_own "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications" all S-1-1-0 S-1-2-3 Deny %write%
    
    ECHO:
    ECHO:
    ECHO Your key is now locked and it's safe to update windows
    
    ECHO:
    pause
    exit/b
    
    :reg_own #key [optional] all user owner access permission  :  call :reg_own "HKCU\My" "" S-1-5-32-545 S-1-5-18 Allow FullControl
    powershell -nop -c $A='%~1','%~2','%~3','%~4','%~5','%~6';iex(([io.file]::ReadAllText('%~f0')-split':Own1\:.*')[1])&exit/b:Own1:
    $D1=[IO.IODescriptionAttribute].Module.GetType('System.Diagnostics.Process').GetMethods(42) |? {$_.Name -eq 'SetPrivilege'}
    'SeSecurityPrivilege','SeTakeOwnershipPrivilege','SeBackupPrivilege','SeRestorePrivilege' |% {$D1.Invoke($null, @("$_",2))}
    $path=$A[0]; $rk=$path-split'\\',2; $HK=gi -lit Registry::$($rk[0]) -fo; $s=$A[1]; $sps=[Security.Principal.SecurityIdentifier]
    $u=($A[2],'S-1-5-32-544')[!$A[2]];$o=($A[3],$u)[!$A[3]];$w=$u,$o |% {new-object $sps($_)}; $old=!$A[3];$own=!$old; $y=$s-eq'all'
    $rar=new-object Security.AccessControl.RegistryAccessRule( $w[0], ($A[5],'FullControl')[!$A[5]], 1, 0, ($A[4],'Allow')[!$A[4]] )
    $x=$s-eq'none'; function Own1($k){$t=$HK.OpenSubKey($k,2,'TakeOwnership'); 0,4 |% {try{$o=$t.GetAccessControl($_)}catch{$old=0}}
    if($old){$own=1;$w[1]=$o.GetOwner($sps)};$o.SetOwner($w[0]);$t.SetAccessControl($o); $c=$HK.OpenSubKey($k,2,'ChangePermissions')
    $p=$c.GetAccessControl(2);if($y){$p.SetAccessRuleProtection(1,1)};$p.ResetAccessRule($rar);if($x){$p.RemoveAccessRuleAll($rar)}
    $c.SetAccessControl($p);if($own){$o.SetOwner($w[1]);$t.SetAccessControl($o)};if($s){$subkeys=$HK.OpenSubKey($k).GetSubKeyNames()
    foreach($n in $subkeys){Own1 "$k\$n"}}};Own1 $rk[1];if($env:VO){get-acl Registry::$path|fl} #:Own1: lean & mean snippet by AveYo
    ::-_-::
    
    
    So you see, the snippet is quite versatile, it's just that I haven't given good directions :)
    One improvement would be doing recursiveness in reverse, but that would bloat the 12-lines snippet and it's not really needed if planning changes like above.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  15. spanishfly

    spanishfly MDL Senior Member

    Dec 5, 2018
    352
    527
    10
    Part of giving good directions is having bright students! I'm finding out that I really didn't know as much as I thought I did about OS privilege manipulation. I think understanding and managing permissions is crucial if you're trying to gain control of an online system. I feel honored that you've taken as much time as you have to expand my knowledge bubble a bit further. So thank you for taking me through some more examples. I feel like I'm getting closer to understanding the power and versatility of the snippet tool.

    The several examples you've shared with the embedded explanations are very helpful for me to grasp the logic of the reg-own tool.
    When I was playing around with reg-own in my earlier tests, I accidentally managed to do something really cool. Unfortunately, I didn't notice right away and I then couldn't duplicate the steps I took.The "cool thing" I accidentally did is what you purposefully demonstrated in the second script "reg_own readkey only experiment" Thanks!

    I like how "set VO=verbose-output" (if($env:VO)) makes this script more end-user friendly.

    If I understood DOS scripting better, I could grasp what you're doing differently when you "Define TI sid (TrustedInstaller)" to also "enable debug privilege unlike vbs" I can see there is a difference with your earlier script, but ... yeah ...

    One comment on utility of the"%write%" parameters used in the first script "reg_own deny experiment"
    The list of parameters assigned to %write% (which match the parameters you used in "reg_own snippet usage - mdl TrustedInstaller example #2") is possibly enough to lock down some keys and maybe even locks down most keys. However, with "InboxApplications", only denying "FullControl" works to stop Windows from accessing the "child-keys" and provisioning System Application packages. If you're interested in how Windows uses the "InboxApplications" key then take a look at post #5587 by @GodHand.​
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  16. GodHand

    GodHand MDL Addicted

    Jul 15, 2016
    534
    926
    30
    I see I have multiple alerts in this thread but there's way too much information to try to sift through as to what is being requested. Please summarize what I'm specifically being tagged for, in particular in connection with said comment:

    For the record I have never withheld any information I have asserted as knowing with complete certainty. Moreover, I do not make posts that give any definitive source of information while also withholding specific details that directly pertain to said information.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  17. Homer712

    Homer712 MDL Member

    Oct 22, 2018
    118
    45
    10
    Quick question (off the topic of the last couple of pages/posts). Once you trigger the Sledgehammer script and go through the process and get to the Wumgr window, there is an entry (if memory serves me) to do the updates offline. Does that mean that it's possible to download the updates (via the Windows 10 Forums site) and then have Wumgr install the already downloaded updates from there?
     
  18. Carlos Detweiller

    Carlos Detweiller Emperor of Ice-Cream

    Dec 21, 2012
    6,324
    7,042
    210
    Offline mode in WuMgr uses the wsusscn2.cab catalog from Microsoft to determine required patches. It's called offline because the scanning does not use Windows Update. Downloading the catalog and updates still requires being online, however.
    Advantage: Will probably work even if Windows Update is slightly out of order.
    Disadvantage: Does only contain B releases, not Previews.

    Edit: Check out the meaning of the box "Download and update manually". This might be more like what you desire.
     
  19. Homer712

    Homer712 MDL Member

    Oct 22, 2018
    118
    45
    10
    Carlos, thanks for the reply. I have enough issues with the B releases (I'm assuming that those are the "released to the public" releases) so I think I'll stay away from the "Preview" releases, which I believe are released to the MS guinea pigs, I mean beta testers group :D

    I'll check out the "Download and update manually" to see how that works.
     
  20. Enthousiast

    Enthousiast MDL Tester

    Oct 30, 2009
    47,191
    94,422
    450