Как установить владельца файла на СИСТЕМУ?

С точки зрения кода это довольно просто:

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

Это вызывает исключение, которое говорит: «Идентификатору безопасности не разрешено быть владельцем этого объекта».

Предположительно это означает, что я не имею права назначать этого пользователя владельцем: источник 1, источник 2. Однако я могу очень легко использовать Explorer, чтобы установить владельцем этого файла SYSTEM. Поскольку Explorer может это каким-то образом, у меня должны быть необходимые права - так как же мне сделать то, что делает Explorer, и установить владельцем файла SYSTEM?


person Roman Starkov    schedule 23.06.2016    source источник
comment
Как установить владельца в проводнике Windows? Не добавляет разрешения для нового пользователя / группы (как в .NET AddAccessRule) все, что вы можете делать в проводнике? Согласно this, вы не можете изменить владельца файла на другое лицо, кроме себя или группы администраторов.   -  person Christian.K    schedule 23.06.2016
comment
@ Christian.K Свойства / Безопасность / Дополнительно / Владелец / Редактировать / Другие пользователи и группы / введите Система / нажмите ОК. Закройте все, откройте снова, чтобы убедиться, что все работает. Это было так.   -  person Roman Starkov    schedule 23.06.2016
comment
Ах да, спасибо. После некоторого поиска в Google и изучения ссылочного кода. Похоже, что вам нужны права SE_TAKE_OWNERSHIP_NAME и SE_RESTORE_NAME. В противном случае вы можете установить владельца только себе или группе BUILTIN \ Adminstrations. Немного поэкспериментируя с кодом, похоже, подтвердит последнее. Извините, у меня сейчас нет времени искать / записывать код P / Invoke, чтобы сделать AdjustTokenPrivileges необходимое для проверки этого ...   -  person Christian.K    schedule 24.06.2016
comment
@ Christian.K Спасибо, этой информации оказалось достаточно, чтобы все заработало. Достаточно одного SE_RESTORE_NAME.   -  person Roman Starkov    schedule 24.06.2016


Ответы (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,
}
person Roman Starkov    schedule 24.06.2016
comment
Если вы получаете сообщение об ошибке UnauthorizedAccessException от System.Security.AccessControl.Win32.GetSecurityInfo, попробуйте это - person Rui Caramalho; 29.01.2021