代码,这很简单:
var fs = IO.File.GetAccessControl(path);
fs.SetOwner(new NTAccount("NT AUTHORITY\SYSTEM"));
IO.File.SetAccessControl(path, fs);
这引发了一个例外,上面写着"安全标识符不允许成为此对象的所有者。"
据说这意味着我无权将此用户分配为所有者:源1,源2。但是,我可以很容易地使用Explorer将该文件的所有者设置为系统。由于Explorer可以以某种方式做到这一点,因此我必须拥有必要的权利 - 那么我该如何做Explorer的工作并将文件的所有者设置为系统?
在Christian.k的帮助下,他将我指向AdjustTokenPrivileges
和SE_RESTORE_NAME
,所有需要完成的就是启用这种特权:
// Allow this process to circumvent ACL restrictions
WinAPI.ModifyPrivilege(PrivilegeName.SeRestorePrivilege, true);
// Sometimes this is required and other times it works without it. Not sure when.
WinAPI.ModifyPrivilege(PrivilegeName.SeTakeOwnershipPrivilege, true);
// Set owner to SYSTEM
var fs = IO.File.GetAccessControl(path);
fs.SetOwner(new NTAccount("NT AUTHORITY\SYSTEM"));
IO.File.SetAccessControl(path, fs);
这是这种ModifyPrivilege
助手方法的代码:
static class WinAPI
{
/// <summary>
/// Enables or disables the specified privilege on the primary access token of the current process.</summary>
/// <param name="privilege">
/// Privilege to enable or disable.</param>
/// <param name="enable">
/// True to enable the privilege, false to disable it.</param>
/// <returns>
/// True if the privilege was enabled prior to the change, false if it was disabled.</returns>
public static bool ModifyPrivilege(PrivilegeName privilege, bool enable)
{
LUID luid;
if (!LookupPrivilegeValue(null, privilege.ToString(), out luid))
throw new Win32Exception();
using (var identity = WindowsIdentity.GetCurrent(TokenAccessLevels.AdjustPrivileges | TokenAccessLevels.Query))
{
var newPriv = new TOKEN_PRIVILEGES();
newPriv.Privileges = new LUID_AND_ATTRIBUTES[1];
newPriv.PrivilegeCount = 1;
newPriv.Privileges[0].Luid = luid;
newPriv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
var prevPriv = new TOKEN_PRIVILEGES();
prevPriv.Privileges = new LUID_AND_ATTRIBUTES[1];
prevPriv.PrivilegeCount = 1;
uint returnedBytes;
if (!AdjustTokenPrivileges(identity.Token, false, ref newPriv, (uint) Marshal.SizeOf(prevPriv), ref prevPriv, out returnedBytes))
throw new Win32Exception();
return prevPriv.PrivilegeCount == 0 ? enable /* didn't make a change */ : ((prevPriv.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) != 0);
}
}
const uint SE_PRIVILEGE_ENABLED = 2;
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState,
UInt32 BufferLengthInBytes, ref TOKEN_PRIVILEGES PreviousState, out UInt32 ReturnLengthInBytes);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
struct TOKEN_PRIVILEGES
{
public UInt32 PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1 /*ANYSIZE_ARRAY*/)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
[StructLayout(LayoutKind.Sequential)]
struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential)]
struct LUID
{
public uint LowPart;
public int HighPart;
}
}
enum PrivilegeName
{
SeAssignPrimaryTokenPrivilege,
SeAuditPrivilege,
SeBackupPrivilege,
SeChangeNotifyPrivilege,
SeCreateGlobalPrivilege,
SeCreatePagefilePrivilege,
SeCreatePermanentPrivilege,
SeCreateSymbolicLinkPrivilege,
SeCreateTokenPrivilege,
SeDebugPrivilege,
SeEnableDelegationPrivilege,
SeImpersonatePrivilege,
SeIncreaseBasePriorityPrivilege,
SeIncreaseQuotaPrivilege,
SeIncreaseWorkingSetPrivilege,
SeLoadDriverPrivilege,
SeLockMemoryPrivilege,
SeMachineAccountPrivilege,
SeManageVolumePrivilege,
SeProfileSingleProcessPrivilege,
SeRelabelPrivilege,
SeRemoteShutdownPrivilege,
SeRestorePrivilege,
SeSecurityPrivilege,
SeShutdownPrivilege,
SeSyncAgentPrivilege,
SeSystemEnvironmentPrivilege,
SeSystemProfilePrivilege,
SeSystemtimePrivilege,
SeTakeOwnershipPrivilege,
SeTcbPrivilege,
SeTimeZonePrivilege,
SeTrustedCredManAccessPrivilege,
SeUndockPrivilege,
SeUnsolicitedInputPrivilege,
}