1

代码方面,这非常简单:

var fs = IO.File.GetAccessControl(path);
fs.SetOwner(new NTAccount("NT AUTHORITY\\SYSTEM"));
IO.File.SetAccessControl(path, fs);

这会引发一个异常,提示“不允许安全标识符成为该对象的所有者”。

据说这意味着我无权将此用户分配为所有者:source 1source 2。但是,我可以很容易地使用资源管理器将此文件的所有者设置为 SYSTEM。由于资源管理器可以以某种方式做到这一点,我必须拥有必要的权限 - 那么我怎样才能执行资源管理器所做的并将文件的所有者设置为 SYSTEM?

4

1 回答 1

2

在将我指向and的Christian.K的帮助下,需要做的就是在进程令牌上启用此特权:AdjustTokenPrivilegesSE_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,
}
于 2016-06-24T12:58:26.783 回答