How do you take file ownership with PowerShell?
I've figured this out. I can only be done with SE_RESTORE_NAME permissions.
I learned how to do that from: http://cosmoskey.blogspot.com/2010/07/setting-owner-on-acl-in-powershell.html
And with a comment from: http://fixingitpro.com/2011/07/08/set-owner-with-powershell-%E2%80%9Cthe-security-identifier-is-not-allowed-to-be-the-owner-of-this-object%E2%80%9D/
Here's the full command that works for me:
$code = @"
using System;
using System.Runtime.InteropServices;
namespace CosmosKey.Utils
{
public class TokenManipulator
{
[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 const string SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege";
public const string SE_AUDIT_NAME = "SeAuditPrivilege";
public const string SE_BACKUP_NAME = "SeBackupPrivilege";
public const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege";
public const string SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege";
public const string SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege";
public const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege";
public const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege";
public const string SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege";
public const string SE_DEBUG_NAME = "SeDebugPrivilege";
public const string SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege";
public const string SE_IMPERSONATE_NAME = "SeImpersonatePrivilege";
public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege";
public const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege";
public const string SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege";
public const string SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege";
public const string SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege";
public const string SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege";
public const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege";
public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege";
public const string SE_RELABEL_NAME = "SeRelabelPrivilege";
public const string SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege";
public const string SE_RESTORE_NAME = "SeRestorePrivilege";
public const string SE_SECURITY_NAME = "SeSecurityPrivilege";
public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
public const string SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege";
public const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege";
public const string SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege";
public const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege";
public const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
public const string SE_TCB_NAME = "SeTcbPrivilege";
public const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege";
public const string SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege";
public const string SE_UNDOCK_NAME = "SeUndockPrivilege";
public const string SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege";
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;
}
}
}
}
"@
# Take ownership
add-type $code
[void][CosmosKey.Utils.TokenManipulator]::AddPrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
$file = "\\$env:computername\c$\temp\file.txt"
$user = $env:username
$Account = New-Object System.Security.Principal.NTAccount($user)
$FileSecurity = new-object System.Security.AccessControl.FileSecurity
$FileSecurity.SetOwner($Account)
[System.IO.File]::SetAccessControl($file, $FileSecurity)
[void][CosmosKey.Utils.TokenManipulator]::RemovePrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
Elijah W. Gagne
Updated on June 05, 2022Comments
-
Elijah W. Gagne almost 2 years
Issue: I wish to programmaticly (with PowerShell) take ownership of a file that I have absolutely no permissions on.
Update: I've thoroughly rewritten the question to give steps to reproduce the issue. Here's what I'm doing:
########################################################## # Logon as UserA ########################################################## $file = "C:\temp\file.txt" new-item C:\temp -type dir new-item $file -type file # Remove inheritence $isProtected = $true $preserveInheritance = $true $FileSecurity = Get-ACL $file $FileSecurity.SetAccessRuleProtection($isProtected, $preserveInheritance) Set-ACL $file -AclObject $FileSecurity # Remove authenticated users $user = "Authenticated Users" $permission = "Modify" $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit" $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None" $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.RemoveAccessRuleAll($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Remove local users $user = "BUILTIN\Users" $permission = "ReadAndExecute" $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit" $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None" $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.RemoveAccessRuleAll($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Give the current user Full Control $user = $env:username $permission = "FullControl" $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.AddAccessRule($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Remove local administrators $user = "BUILTIN\Administrators" $permission = "FullControl" $Account = New-Object System.Security.Principal.NTAccount($user) $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit" $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None" $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $FileSecurity = Get-ACL $file $FileSecurity.RemoveAccessRuleAll($FileSystemAccessRule) Set-ACL $file -AclObject $FileSecurity # Set the owner to be the current user $user = $env:username $Account = New-Object System.Security.Principal.NTAccount($user) $FileSecurity = new-object System.Security.AccessControl.FileSecurity $FileSecurity.SetOwner($Account) [System.IO.File]::SetAccessControl($file, $FileSecurity) ########################################################## # Log off the server as UserA and logon as UserB ########################################################## $file = "C:\temp\file.txt" # Take ownership $user = $env:username $Account = New-Object System.Security.Principal.NTAccount($user) $FileSecurity = new-object System.Security.AccessControl.FileSecurity $FileSecurity.SetOwner($Account) [System.IO.File]::SetAccessControl($file, $FileSecurity)
This is throwing the error:
Exception calling "SetAccessControl" with "2" argument(s): "Attempted to perform an unauthorized operation." At line:1 char:35 + [System.IO.File]::SetAccessControl <<<< ($path, $FileSecurity) + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : DotNetMethodException
Additional notes:
- $error[0].innerexception is null.
- The steps taken as UserA ensured that userB has absolutely no permissions on
C:\temp\file.txt
. - running
[System.IO.File]::GetAccessControl($path)
throws a similar error (which is expected) - I am of course right-clicking PowerShell and choosing "Run as Administrator".
- I've tried disabling UAC, but that does not make a difference.
- I can take ownership through the GUI so there should be a way to do this programmatically with PowerShell.
What am I doing wrong?
Update and answer:
The accepted answer I posted, works, but seems to be overkill. Simply referencing the file via a UNC path seems to do the trick:
$file = "\\localhost\\c$\temp\file.txt" # Take ownership $user = $env:username $Account = New-Object System.Security.Principal.NTAccount($user) $FileSecurity = new-object System.Security.AccessControl.FileSecurity $FileSecurity.SetOwner($Account) [System.IO.File]::SetAccessControl($file, $FileSecurity)