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

以用户账户运行的服务如何在非0会话启动子进程?

如何在用户账户运行的Session 0服务中跨会话启动子进程?

可行,但普通用户账户运行的服务跨会话创建进程会比System账户受限更多。你当前遇到的ERROR_ACCESS_DENIED(错误码5)核心原因是:直接修改自身令牌的Session ID后,Windows会话隔离机制会阻止普通用户账户的令牌在非原会话中创建进程,且部分特权即使启用也无法突破会话权限检查。

核心解决方案思路

不要修改当前服务的令牌会话ID,而是获取目标会话中已登录用户的合法令牌,用这个令牌来创建进程。具体步骤如下:

  1. 获取目标会话的用户令牌

    • 用WTSEnumerateSessions枚举系统中的所有会话,定位到你要启动进程的目标会话ID。
    • 调用WTSQueryUserToken获取该会话中登录用户的令牌(这个API需要SE_TCB_NAME特权,必须提前给服务账户分配该权限)。
  2. 复制并配置令牌权限

    • 用DuplicateTokenEx将获取到的用户令牌复制为Primary类型令牌,确保复制时包含TOKEN_ASSIGN_PRIMARY、TOKEN_QUERY、TOKEN_ADJUST_PRIVILEGES等必要权限。
    • 启用三个关键特权:SE_TCB_NAME、SE_ASSIGNPRIMARYTOKEN_NAME、SE_INCREASE_QUOTA_NAME,这些特权需要在本地安全策略的「用户权利指派」中分配给服务账户。
  3. 创建进程时的关键参数设置

    • 用CreateEnvironmentBlock从目标用户令牌生成对应会话的环境变量块,避免使用服务的环境变量。
    • 设置STARTUPINFO的lpDesktop为"winsta0\\default",确保进程能正确关联到目标会话的桌面。
    • 指定目标用户的默认目录作为CreateProcessAsUserW的lpCurrentDirectory参数。

修正后的代码示例

// 替换为你的目标会话ID
DWORD targetSessionID = 1;
HANDLE hUserToken = NULL;

// 1. 获取目标会话的用户令牌
if (!WTSQueryUserToken(targetSessionID, &hUserToken)) {
    // 处理错误:比如检查SE_TCB_NAME特权是否已分配
    return GetLastError();
}

// 2. 复制为Primary令牌
HANDLE hPrimaryToken = NULL;
if (!DuplicateTokenEx(
    hUserToken,
    TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_DEFAULT,
    NULL,
    SecurityIdentification,
    TokenPrimary,
    &hPrimaryToken
)) {
    CloseHandle(hUserToken);
    return GetLastError();
}
CloseHandle(hUserToken);

// 3. 启用必要特权
EnablePrivilege(SE_TCB_NAME, hPrimaryToken);
EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME, hPrimaryToken);
EnablePrivilege(SE_INCREASE_QUOTA_NAME, hPrimaryToken);

// 4. 创建目标会话的环境块
LPVOID lpEnv = NULL;
if (!CreateEnvironmentBlock(&lpEnv, hPrimaryToken, TRUE)) {
    CloseHandle(hPrimaryToken);
    return GetLastError();
}

// 5. 配置STARTUPINFO,指定目标桌面
STARTUPINFOW si = { sizeof(si) };
si.lpDesktop = L"winsta0\\default";
PROCESS_INFORMATION pi = { 0 };

// 6. 跨会话创建进程
BOOL success = CreateProcessAsUserW(
    hPrimaryToken,
    L"C:\\your\\path\\myproc2.exe", // 替换为实际进程路径
    NULL,
    NULL,
    NULL,
    FALSE,
    CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE,
    lpEnv,
    L"C:\\Users\\TargetUserName\\Documents", // 替换为目标用户的默认目录
    &si,
    &pi
);

// 清理资源
if (lpEnv) DestroyEnvironmentBlock(lpEnv);
CloseHandle(hPrimaryToken);
if (success) {
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
} else {
    return GetLastError();
}

关键注意事项

  • 必须给服务账户分配以下用户权利:「替换进程级令牌」、「调整进程内存配额」、「作为操作系统的一部分操作」(通过本地安全策略->本地策略->用户权利指派配置)。
  • 目标会话必须是已登录的活跃用户会话,WTSQueryUserToken无法获取未登录会话的令牌。
  • 不要尝试直接修改自身服务令牌的Session ID,普通用户账户的令牌不允许跨会话使用,这是Windows会话隔离的安全限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:55:36