Skip to content

Commit

Permalink
Set owner fix for issue (#1184) (#1185)
Browse files Browse the repository at this point in the history
* Microwin and fixes

* Fix for #1184, takeown doesn't work on non English Windows

---------

Co-authored-by: KonTy <[email protected]>
  • Loading branch information
KonTy and KonTy authored Nov 17, 2023
1 parent a0c5118 commit 69614f1
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 12 deletions.
8 changes: 4 additions & 4 deletions functions/private/MicroWin-Helper.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [sw
{
if(([string]::IsNullOrEmpty($pathToDelete))) { return }
if (-not (Test-Path -Path "$($pathToDelete)")) { return }

# special code, for some reason when you try to delete some inbox apps
# we have to get and delete log files directory.
takeown /a /r /d Y /f "$($scratchDir)\Windows\System32\LogFiles\WMI\RtBackup" > $null
Set-Owner -Path "$($scratchDir)\Windows\System32\LogFiles\WMI\RtBackup" -Recurse -Verbose
icacls "$($scratchDir)\Windows\System32\LogFiles\WMI\RtBackup" /q /c /t /reset > $null
takeown /a /r /d Y /f "$($scratchDir)\Windows\System32\WebThreatDefSvc" > $null

Set-Owner -Path "$($scratchDir)\Windows\System32\WebThreatDefSvc" -Recurse -Verbose
icacls "$($scratchDir)\Windows\System32\WebThreatDefSvc" /q /c /t /reset > $null

$itemsToDelete = [System.Collections.ArrayList]::new()

if ($mask -eq "")
Expand Down
206 changes: 206 additions & 0 deletions functions/private/set-owner.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
Function Set-Owner {
<#
.SYNOPSIS
Changes owner of a file or folder to another user or group.
.DESCRIPTION
Changes owner of a file or folder to another user or group.
.PARAMETER Path
The folder or file that will have the owner changed.
.PARAMETER Account
Optional parameter to change owner of a file or folder to specified account.
Default value is 'Builtin\Administrators'
.PARAMETER Recurse
Recursively set ownership on subfolders and files beneath given folder.
.NOTES
Name: Set-Owner
Author: Boe Prox
Version History:
1.0 - Boe Prox
- Initial Version
.EXAMPLE
Set-Owner -Path C:\temp\test.txt
Description
-----------
Changes the owner of test.txt to Builtin\Administrators
.EXAMPLE
Set-Owner -Path C:\temp\test.txt -Account 'Domain\bprox
Description
-----------
Changes the owner of test.txt to Domain\bprox
.EXAMPLE
Set-Owner -Path C:\temp -Recurse
Description
-----------
Changes the owner of all files and folders under C:\Temp to Builtin\Administrators
.EXAMPLE
Get-ChildItem C:\Temp | Set-Owner -Recurse -Account 'Domain\bprox'
Description
-----------
Changes the owner of all files and folders under C:\Temp to Domain\bprox
#>
[cmdletbinding(
SupportsShouldProcess = $True
)]
Param (
[parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[Alias('FullName')]
[string[]]$Path,
[parameter()]
[string]$Account = 'Builtin\Administrators',
[parameter()]
[switch]$Recurse
)
Begin {
#Prevent Confirmation on each Write-Debug command when using -Debug
If ($PSBoundParameters['Debug']) {
$DebugPreference = 'Continue'
}
Try {
[void][TokenAdjuster]
} Catch {
$AdjustTokenPrivileges = @"
using System;
using System.Runtime.InteropServices;
public class TokenAdjuster
{
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();
[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_DISABLED = 0x00000000;
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public static bool AddPrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
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;
}
catch (Exception ex)
{
throw ex;
}
}
public static bool RemovePrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_DISABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}
}
}
"@
Add-Type $AdjustTokenPrivileges
}

#Activate necessary admin privileges to make changes without NTFS perms
[void][TokenAdjuster]::AddPrivilege("SeRestorePrivilege") #Necessary to set Owner Permissions
[void][TokenAdjuster]::AddPrivilege("SeBackupPrivilege") #Necessary to bypass Traverse Checking
[void][TokenAdjuster]::AddPrivilege("SeTakeOwnershipPrivilege") #Necessary to override FilePermissions
}
Process {
ForEach ($Item in $Path) {
Write-Verbose "FullName: $Item"
#The ACL objects do not like being used more than once, so re-create them on the Process block
$DirOwner = New-Object System.Security.AccessControl.DirectorySecurity
$DirOwner.SetOwner([System.Security.Principal.NTAccount]$Account)
$FileOwner = New-Object System.Security.AccessControl.FileSecurity
$FileOwner.SetOwner([System.Security.Principal.NTAccount]$Account)
$DirAdminAcl = New-Object System.Security.AccessControl.DirectorySecurity
$FileAdminAcl = New-Object System.Security.AccessControl.DirectorySecurity
$AdminACL = New-Object System.Security.AccessControl.FileSystemAccessRule('Builtin\Administrators','FullControl','ContainerInherit,ObjectInherit','InheritOnly','Allow')
$FileAdminAcl.AddAccessRule($AdminACL)
$DirAdminAcl.AddAccessRule($AdminACL)
Try {
$Item = Get-Item -LiteralPath $Item -Force -ErrorAction Stop
If (-NOT $Item.PSIsContainer) {
If ($PSCmdlet.ShouldProcess($Item, 'Set File Owner')) {
Try {
$Item.SetAccessControl($FileOwner)
} Catch {
Write-Warning "Couldn't take ownership of $($Item.FullName)! Taking FullControl of $($Item.Directory.FullName)"
$Item.Directory.SetAccessControl($FileAdminAcl)
$Item.SetAccessControl($FileOwner)
}
}
} Else {
If ($PSCmdlet.ShouldProcess($Item, 'Set Directory Owner')) {
Try {
$Item.SetAccessControl($DirOwner)
} Catch {
Write-Warning "Couldn't take ownership of $($Item.FullName)! Taking FullControl of $($Item.Parent.FullName)"
$Item.Parent.SetAccessControl($DirAdminAcl)
$Item.SetAccessControl($DirOwner)
}
}
If ($Recurse) {
[void]$PSBoundParameters.Remove('Path')
Get-ChildItem $Item -Force | Set-Owner @PSBoundParameters
}
}
} Catch {
Write-Warning "$($Item): $($_.Exception.Message)"
}
}
}
End {
#Remove priviledges that had been granted
[void][TokenAdjuster]::RemovePrivilege("SeRestorePrivilege")
[void][TokenAdjuster]::RemovePrivilege("SeBackupPrivilege")
[void][TokenAdjuster]::RemovePrivilege("SeTakeOwnershipPrivilege")
}
}
9 changes: 5 additions & 4 deletions functions/public/Invoke-WPFMicrowin.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,16 @@ function Invoke-WPFMicrowin {
$keepProvisionedPackages = $sync.WPFMicrowinKeepAppxPackages.IsChecked
$keepDefender = $sync.WPFMicrowinKeepDefender.IsChecked
$keepEdge = $sync.WPFMicrowinKeepEdge.IsChecked
# xcopy we can verify files and also not copy files that already exist, but hard to measure
$mountDir = $sync.MicrowinMountDir.Text
$scratchDir = $sync.MicrowinScratchDir.Text
# xcopy we can verify files and also not copy files that already exist, but hard to measure
$mountDir = $sync.MicrowinMountDir.Text
$scratchDir = $sync.MicrowinScratchDir.Text

$mountDirExists = Test-Path $mountDir
$scratchDirExists = Test-Path $scratchDir
if (-not $mountDirExists -or -not $scratchDirExists) {
Write-Error "Required directories do not exist."
return
}
}
try {
Write-Host "Mounting Windows image. This may take a while."
dism /mount-image /imagefile:$mountDir\sources\install.wim /index:$index /mountdir:$scratchDir
Expand Down
2 changes: 1 addition & 1 deletion scripts/main.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,4 @@ $sync["CheckboxFilter"].Add_TextChanged({
#Write-Host "Your Windows Product Key: $((Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey)"

$sync["Form"].ShowDialog() | out-null
Stop-Transcript
Stop-Transcript
6 changes: 3 additions & 3 deletions winutil.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2301,6 +2301,7 @@ function Invoke-WPFMicrowin {
# xcopy we can verify files and also not copy files that already exist, but hard to measure
$mountDir = $sync.MicrowinMountDir.Text
$scratchDir = $sync.MicrowinScratchDir.Text

$mountDirExists = Test-Path $mountDir
$scratchDirExists = Test-Path $scratchDir
if (-not $mountDirExists -or -not $scratchDirExists) {
Expand Down Expand Up @@ -7672,7 +7673,6 @@ $commonKeyEvents = {
return
}

# Escape removes focus from the searchbox that way all shortcuts will start workinf again
if ($_.Key -eq "Escape") {
if ($sync.CheckboxFilter.IsFocused)
{
Expand All @@ -7683,7 +7683,7 @@ $commonKeyEvents = {
}
}

# don't ask, I know what I'm doing, just go...
# Exit WinUtil
if (($_.Key -eq "Q" -and $_.KeyboardDevice.Modifiers -eq "Ctrl"))
{
$ret = [System.Windows.Forms.MessageBox]::Show("Are you sure you want to Exit?", "Winutil", [System.Windows.Forms.MessageBoxButtons]::YesNo,
Expand Down Expand Up @@ -7814,4 +7814,4 @@ $sync["CheckboxFilter"].Add_TextChanged({
#Write-Host "Your Windows Product Key: $((Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey)"

$sync["Form"].ShowDialog() | out-null
Stop-Transcript
Stop-Transcript

0 comments on commit 69614f1

Please sign in to comment.