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?
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.
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.
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?
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\*
I like the "dir /b /s /ad" trick to get subdirectory names in a "for" loop. I've never seen that before.
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.
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