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

如何通过C# Windows服务检测标准用户以Run as Administrator启动应用

检测标准用户以管理员身份启动的进程

要实现需求,你需要完成两个核心检测:判断进程是否处于提权(管理员)状态,以及确认启动该进程的用户是标准用户(不属于本地管理员组)。以下是具体实现步骤和代码:

1. 检测进程是否提权运行

通过Windows API读取进程令牌的TokenElevation信息,判断进程是否以管理员权限启动:

首先添加必要的P/Invoke声明:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.DirectoryServices.AccountManagement;

public static class ProcessSecurityHelper
{
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, IntPtr tokenInformation, uint tokenInformationLength, out uint returnLength);

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

    private enum TOKEN_INFORMATION_CLASS
    {
        TokenElevation = 20,
        TokenUser = 1
    }

    private struct TOKEN_ELEVATION
    {
        public TokenElevationType TokenIsElevated;
    }

    private enum TokenElevationType
    {
        TokenElevationTypeDefault = 1,
        TokenElevationTypeFull = 2,
        TokenElevationTypeLimited = 3
    }

然后实现检测提权的方法:

public static bool IsProcessElevated(int processId)
    {
        try
        {
            using (var process = Process.GetProcessById(processId))
            {
                // 打开进程令牌,请求查询权限
                if (!OpenProcessToken(process.Handle, 0x0008 /* TOKEN_QUERY */, out IntPtr tokenHandle))
                    return false;

                try
                {
                    var elevationSize = (uint)Marshal.SizeOf(typeof(TOKEN_ELEVATION));
                    IntPtr elevationPtr = Marshal.AllocHGlobal((int)elevationSize);

                    try
                    {
                        if (GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevation, elevationPtr, elevationSize, out _))
                        {
                            var elevation = Marshal.PtrToStructure<TOKEN_ELEVATION>(elevationPtr);
                            // TokenElevationTypeFull表示进程已提权
                            return elevation.TokenIsElevated == TokenElevationType.TokenElevationTypeFull;
                        }
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(elevationPtr);
                    }
                }
                finally
                {
                    CloseHandle(tokenHandle);
                }
            }
        }
        catch (Exception)
        {
            // 处理进程已退出、权限不足等异常
            return false;
        }
    }

2. 检测启动进程的用户是否为标准用户

先获取进程对应的用户SID,再判断该用户是否不属于本地管理员组:

补充P/Invoke和相关方法:

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool ConvertSidToStringSid(IntPtr sid, out string sidString);

    private struct TOKEN_USER
    {
        public SID_AND_ATTRIBUTES User;
    }

    private struct SID_AND_ATTRIBUTES
    {
        public IntPtr Sid;
        public uint Attributes;
    }

    public static string GetProcessUserSid(int processId)
    {
        try
        {
            using (var process = Process.GetProcessById(processId))
            {
                if (!OpenProcessToken(process.Handle, 0x0008 /* TOKEN_QUERY */, out IntPtr tokenHandle))
                    return null;

                try
                {
                    // 先获取所需缓冲区长度
                    GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, IntPtr.Zero, 0, out uint returnLength);
                    IntPtr userPtr = Marshal.AllocHGlobal((int)returnLength);

                    try
                    {
                        if (GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenUser, userPtr, returnLength, out _))
                        {
                            var tokenUser = Marshal.PtrToStructure<TOKEN_USER>(userPtr);
                            if (ConvertSidToStringSid(tokenUser.User.Sid, out string sidString))
                                return sidString;
                        }
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(userPtr);
                    }
                }
                finally
                {
                    CloseHandle(tokenHandle);
                }
            }
        }
        catch (Exception)
        {
            return null;
        }
    }

    public static bool IsStandardUser(string userSid)
    {
        try
        {
            using (var machineContext = new PrincipalContext(ContextType.Machine))
            {
                using (var user = UserPrincipal.FindByIdentity(machineContext, IdentityType.Sid, userSid))
                {
                    if (user == null)
                        return false;

                    var adminGroup = GroupPrincipal.FindByIdentity(machineContext, IdentityType.Name, "Administrators");
                    // 用户不属于管理员组则为标准用户
                    return adminGroup != null && !user.IsMemberOf(adminGroup);
                }
            }
        }
        catch (Exception)
        {
            return false;
        }
    }
}

3. 在WMI监控逻辑中整合检测

在你现有的ManagementEventWatcher回调中,获取进程ID后执行检测:

// 假设你从WMI事件中获取到进程对象
var processId = Convert.ToInt32(e.NewEvent["ProcessId"]);

bool isElevated = ProcessSecurityHelper.IsProcessElevated(processId);
string userSid = ProcessSecurityHelper.GetProcessUserSid(processId);
bool isStandardUser = !string.IsNullOrEmpty(userSid) && ProcessSecurityHelper.IsStandardUser(userSid);

if (isElevated && isStandardUser)
{
    // 符合条件:标准用户以管理员身份启动的进程
    // 执行你的黑白名单管控逻辑(比如终止进程、记录日志等)
}

注意事项

  • 服务运行身份:建议将你的Windows服务设置为Local System身份运行,以获取足够权限访问其他进程的令牌;若使用其他身份,可能需要额外配置SeDebugPrivilege权限。
  • 进程生命周期:进程可能在你检测前已退出,需做好异常捕获和处理。
  • 内置管理员账户:内置管理员本身属于管理员组,即使通过UAC提权,IsStandardUser也会返回false,符合你的需求(只检测标准用户的提权行为)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:10:19