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

SDDL正确定义及进程权限配置求助:仅允许管理员终止进程

问题分析与修正方案

核心问题点

  1. 代码执行顺序错误:app.Run()是阻塞调用,后续的ProtectCurrentProcess()永远不会执行。
  2. 对象类型指定错误:进程属于SE_PROCESS类型,而非SE_KERNEL_OBJECT,类型不匹配会导致权限设置失败。
  3. SDDL字符串过于宽泛:当前SDDL给管理员所有权限、拒绝普通用户所有权限,既不符合"仅限制终止权限"的需求,还会导致进程自身或其他合法操作失败。
  4. 潜在内存泄漏:未手动释放ConvertStringSecurityDescriptorToSecurityDescriptor生成的安全描述符。

修正后的代码

using System.ComponentModel;
using System.Diagnostics;
using RemoteMaster.Client.Abstractions;
using RemoteMaster.Client.Core.Abstractions;
using RemoteMaster.Client.Core.Extensions;
using RemoteMaster.Client.Services;
using Windows.Win32.Foundation;
using Windows.Win32.Security.Authorization;
using static Windows.Win32.PInvoke;

internal class Program
{
    private static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args).ConfigureCoreUrls();

        builder.Services.AddCoreServices();
        builder.Services.AddSingleton<IScreenCapturerService, BitBltCapturer>();
        builder.Services.AddSingleton<ICursorRenderService, CursorRenderService>();
        builder.Services.AddSingleton<IInputService, InputService>();
        builder.Services.AddSingleton<IPowerService, PowerService>();

        var app = builder.Build();

        ProtectCurrentProcess(); // 移至app.Run()前执行
        app.MapCoreHubs();

        app.Run();
    }

    private static unsafe void ProtectCurrentProcess()
    {
        const uint DACL_SECURITY_INFORMATION = 0x00000004;
        const uint SDDL_REVISION_1 = 1;
        const uint WRITE_DAC = 0x00400000;

        // 显式获取带WRITE_DAC权限的进程句柄,确保有权修改DACL
        using var currentProcess = OpenProcess(WRITE_DAC, false, (uint)Process.GetCurrentProcess().Id);
        if (currentProcess.IsInvalid)
        {
            throw new Win32Exception();
        }

        // SDDL说明:
        // D:P - 指定DACL
        // (D;;TM;;;WD) - 拒绝所有用户(WD)的进程终止权限(TM对应PROCESS_TERMINATE)
        // (A;;TM;;;BA) - 允许管理员组(BA)的进程终止权限
        const string restrictedSddl = "D:P(D;;TM;;;WD)(A;;TM;;;BA)";

        if (!ConvertStringSecurityDescriptorToSecurityDescriptor(restrictedSddl, SDDL_REVISION_1, out var sd, null))
        {
            throw new Win32Exception();
        }

        try
        {
            if (!GetSecurityDescriptorDacl(sd, out var daclPresent, out var pDacl, out var defaultDacl) || !daclPresent)
            {
                throw new Win32Exception();
            }

            var result = SetSecurityInfo(
                currentProcess,
                SE_OBJECT_TYPE.SE_PROCESS, // 修正为进程对象类型
                DACL_SECURITY_INFORMATION,
                null, null, *pDacl, null);

            if (result != WIN32_ERROR.ERROR_SUCCESS)
            {
                throw new Win32Exception((int)result);
            }
        }
        finally
        {
            LocalFree(sd); // 手动释放安全描述符,避免内存泄漏
        }
    }
}

关键修正说明

  • 执行顺序调整:将进程保护逻辑移至app.Run()前,确保Web应用启动时即完成权限配置。
  • 进程句柄获取:用OpenProcess显式获取带WRITE_DAC权限的句柄,比GetCurrentProcess的伪句柄更可靠,确保拥有修改权限的权限。
  • 对象类型修正:使用SE_PROCESS匹配进程对象类型,避免权限设置失败。
  • 精准SDDL配置:仅针对进程终止权限(TM对应PROCESS_TERMINATE)做限制,拒绝普通用户、允许管理员操作,不影响进程其他合法权限。
  • 内存泄漏修复:在finally块中调用LocalFree释放安全描述符。

进阶优化(保留原有权限)

如果需要保留进程原有权限,仅添加终止权限的限制,需避免直接替换DACL,而是基于原DACL添加ACE:

  1. 用GetSecurityInfo获取进程原有DACL。
  2. 创建新ACL,复制原有ACE后添加拒绝普通用户、允许管理员终止权限的ACE。
  3. 调用SetSecurityInfo设置新DACL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:53:17