You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#为LOCALSYSTEM应用添加SE_BACKUP_NAME等权限的实现方法

C# 为LOCALSYSTEM运行的进程启用SE_BACKUP_NAME与SE_RESTORE_NAME特权

以LOCALSYSTEM账户运行的进程,默认已经在访问令牌中持有SeBackupPrivilege(对应常量SE_BACKUP_NAME)和SeRestorePrivilege(对应常量SE_RESTORE_NAME),仅默认处于禁用状态,不需要额外向系统申请添加特权,通过P/Invoke调用Windows原生API启用对应特权即可。

实现步骤

  • 引入advapi32.dll中令牌操作相关的原生函数,定义所需的结构体、访问常量
  • 打开当前进程的访问令牌,获取对应特权的LUID(本地唯一标识符)
  • 调用令牌调整接口启用目标特权,补充必要的错误校验逻辑

完整可运行代码

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

public static class PrivilegeManager
{
    // 目标特权常量定义
    public const string SE_BACKUP_NAME = "SeBackupPrivilege";
    public const string SE_RESTORE_NAME = "SeRestorePrivilege";
    private const int SE_PRIVILEGE_ENABLED = 0x00000002;
    private const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
    private const int TOKEN_QUERY = 0x0008;

    [StructLayout(LayoutKind.Sequential)]
    private struct LUID
    {
        public uint LowPart;
        public int HighPart;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct LUID_AND_ATTRIBUTES
    {
        public LUID Luid;
        public uint Attributes;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct TOKEN_PRIVILEGES
    {
        public uint PrivilegeCount;
        public LUID_AND_ATTRIBUTES Privileges;
    }

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);

    [DllImport("advapi32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges,
        ref TOKEN_PRIVILEGES NewState, uint BufferLength, IntPtr PreviousState, IntPtr ReturnLength);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr GetCurrentProcess();

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr hObject);

    /// <summary>
    /// 为当前进程启用指定特权
    /// </summary>
    /// <param name="privilegeName">特权名称,传入SE_BACKUP_NAME/SE_RESTORE_NAME即可</param>
    /// <exception cref="Win32Exception">API调用失败时抛出对应系统错误信息</exception>
    public static void EnablePrivilege(string privilegeName)
    {
        IntPtr processToken = IntPtr.Zero;
        try
        {
            // 打开当前进程的访问令牌
            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out processToken))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            // 查询特权对应的本地唯一标识LUID
            if (!LookupPrivilegeValue(null, privilegeName, out LUID luid))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            // 构造特权启用参数
            TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES
            {
                PrivilegeCount = 1,
                Privileges = new LUID_AND_ATTRIBUTES
                {
                    Luid = luid,
                    Attributes = SE_PRIVILEGE_ENABLED
                }
            };

            // 执行令牌特权调整
            if (!AdjustTokenPrivileges(processToken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
        finally
        {
            // 释放令牌句柄
            if (processToken != IntPtr.Zero)
            {
                CloseHandle(processToken);
            }
        }
    }

    // 调用示例
    public static void Main()
    {
        // 程序入口处优先启用两个特权,再执行业务逻辑
        EnablePrivilege(SE_BACKUP_NAME);
        EnablePrivilege(SE_RESTORE_NAME);
        
        // 后续业务代码
        Console.WriteLine("备份、还原特权已成功启用");
    }
}

注意事项

  • 该逻辑仅对当前进程生效,特权在进程运行期间持续有效,进程退出后自动回收
  • 这两项特权会绕过文件系统、注册表的ACL权限检查,安全风险较高,不需要使用时可以通过相同逻辑传入0作为Attributes值禁用特权,缩小攻击面
  • 由于程序以LOCALSYSTEM身份运行,不存在令牌中缺少对应特权的问题,不需要额外修改系统本地安全策略配置;如果是普通管理员账户运行的程序,需要提前在本地安全策略中将对应特权分配给运行账户,否则调用会抛出"特权不存在"的错误

内容的提问来源于stack exchange,提问作者Jeff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 13:03:20