代码方面,这非常简单:
var fs = IO.File.GetAccessControl(path);
fs.SetOwner(new NTAccount("NT AUTHORITY\\SYSTEM"));
IO.File.SetAccessControl(path, fs);
这会抛出一个异常,说明"安全标识符不允许是该对象的所有者。"
据说这意味着我无权将此用户指定为所有者:source 1,source 2。但是,我可以非常轻松地使用Explorer将此文件的所有者设置为SYSTEM。由于资源管理器可以以某种方式完成,我必须拥有必要的权限 - 那么我该如何处理资源管理器并将文件的所有者设置为SYSTEM?
答案 0 :(得分:1)
在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,
}