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

SYSTEM服务启动用户会话高权限进程失败,设置SeDebugPrivilege报错ERROR_NOT_ALL_ASSIGNED

SYSTEM服务启动用户会话高权限进程失败,设置SeDebugPrivilege报错ERROR_NOT_ALL_ASSIGNED

哥们,你踩了个常见的坑——你现在是在用户的token上尝试设置SeDebugPrivilege,但普通用户的token本身根本没有这个权限,所以AdjustTokenPrivileges才会返回ERROR_NOT_ALL_ASSIGNED。

问题根源

SeDebugPrivilege是系统级权限,只有SYSTEM这类系统账号默认拥有,但你调用SetPrivilege时传的是WTSQueryUserToken拿到的用户会话token,这个token属于登录的普通用户,默认是没有SeDebugPrivilege的,自然设置失败。

正确的解决步骤

你需要先给服务自身的SYSTEM进程token启用SeDebugPrivilege,再去处理用户会话的token:

  1. 启用服务自身的SeDebugPrivilege
    SYSTEM账号默认持有SeDebugPrivilege,只是这个权限默认处于未启用状态。你需要先打开当前服务进程的token,手动启用这个权限。

  2. 处理用户的受限token
    WTSQueryUserToken拿到的用户token通常是受限token(filtered token),如果要启动高权限进程,得先通过GetLinkedToken获取用户的完整提升token。

  3. 调用CreateProcessAsUser创建进程
    用处理好的用户完整token,配合正确参数调用CreateProcessAsUser,记得及时清理环境块和各种句柄。

修正后的代码示例

// 封装一个启用当前进程SeDebugPrivilege的函数
bool EnableDebugPrivilege()
{
    HANDLE hToken;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        debugFile << "OpenProcessToken failed: " << GetLastError() << std::endl;
        return false;
    }

    LUID luid;
    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
    {
        debugFile << "LookupPrivilegeValue failed: " << GetLastError() << std::endl;
        CloseHandle(hToken);
        return false;
    }

    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        debugFile << "AdjustTokenPrivileges failed: " << GetLastError() << std::endl;
        CloseHandle(hToken);
        return false;
    }

    CloseHandle(hToken);
    return true;
}

bool runPrivilegedProcess(ULONG sessionId)
{
    // 第一步:先给当前SYSTEM服务进程启用SeDebugPrivilege
    if (!EnableDebugPrivilege())
    {
        debugFile << "Failed to enable SeDebugPrivilege on SYSTEM token" << std::endl;
        return false;
    }

    HANDLE userToken;
    if (WTSQueryUserToken(sessionId, &userToken) == FALSE)
    {
        debugFile << "WTSQueryUserToken failed: " << GetLastError() << std::endl;
        return false;
    }

    // 检查用户token是否是受限的,如果是,获取完整的提升token
    HANDLE fullUserToken = NULL;
    TOKEN_ELEVATION_TYPE elevationType;
    DWORD dwSize = sizeof(elevationType);
    if (GetTokenInformation(userToken, TokenElevationType, &elevationType, dwSize, &dwSize))
    {
        if (elevationType == TokenElevationTypeLimited)
        {
            if (!GetLinkedToken(userToken, &fullUserToken))
            {
                debugFile << "GetLinkedToken failed: " << GetLastError() << std::endl;
                CloseHandle(userToken);
                return false;
            }
            // 替换为完整token,关闭原受限token
            CloseHandle(userToken);
            userToken = fullUserToken;
        }
    }

    // 创建用户环境块
    LPVOID envBlock = NULL;
    if (!CreateEnvironmentBlock(&envBlock, userToken, FALSE))
    {
        debugFile << "CreateEnvironmentBlock failed: " << GetLastError() << std::endl;
        CloseHandle(userToken);
        return false;
    }

    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
    si.cb = sizeof(STARTUPINFO);
    // 指定用户会话的桌面,否则进程可能在后台运行无法显示
    si.lpDesktop = L"WinSta0\\Default";

    // 调用CreateProcessAsUser启动高权限进程
    BOOL result = CreateProcessAsUser(
        userToken,
        L"C:\\Your\\Path\\To\\ElevatedApp.exe",  // 替换为你的目标程序路径
        NULL,
        NULL,
        NULL,
        FALSE,
        CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
        envBlock,
        NULL,
        &si,
        &pi
    );

    if (!result)
    {
        debugFile << "CreateProcessAsUser failed: " << GetLastError() << std::endl;
    }
    else
    {
        // 关闭进程和线程句柄
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    // 清理资源
    DestroyEnvironmentBlock(envBlock);
    CloseHandle(userToken);

    return result != FALSE;
}

额外注意点

  • 如果你要启动的是需要UAC提升的程序,确保用户账号本身具备管理员权限,或者已经获取到完整的管理员token
  • CreateProcessAsUser的桌面参数必须指定为WinSta0\\Default,否则进程可能无法在用户会话中正常显示
  • 所有打开的句柄都要记得关闭,避免资源泄漏

备注:内容来源于stack exchange,提问作者Mustafa Chelik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 12:40:30