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

已提权进程无凭据时,如何启动非管理员权限的原程序?

问题解答

核心结论

可以在无登录凭据的提权进程中启动非管理员权限的程序,核心是通过创建并使用受限用户令牌,移除管理员权限组的权限,从而回到原用户的非管理员上下文。

实现步骤

1. 获取当前提权进程的主令牌

提权进程拥有当前用户的完整访问令牌,首先需要打开这个令牌以进行后续操作:

HANDLE hCurrentToken = NULL;
if (!OpenProcessToken(GetCurrentProcess(), 
    TOKEN_DUPLICATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY, 
    &hCurrentToken))
{
    // 处理错误,可调用GetLastError()获取错误码
    return FALSE;
}

2. 定位并标记管理员组SID为禁用

从令牌的组信息中找到管理员组的SID,将其设置为SE_GROUP_USE_FOR_DENY_ONLY,这样后续生成的受限令牌会自动排除管理员权限:

// 先获取令牌组信息的内存大小
DWORD dwBufferSize = 0;
GetTokenInformation(hCurrentToken, TokenGroups, NULL, 0, &dwBufferSize);
PTOKEN_GROUPS pTokenGroups = (PTOKEN_GROUPS)LocalAlloc(LPTR, dwBufferSize);
if (!GetTokenInformation(hCurrentToken, TokenGroups, pTokenGroups, dwBufferSize, &dwBufferSize))
{
    // 清理资源并处理错误
    LocalFree(pTokenGroups);
    CloseHandle(hCurrentToken);
    return FALSE;
}

// 初始化管理员组SID
SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
PSID pAdminSid = NULL;
if (!AllocateAndInitializeSid(&ntAuthority, 2, 
    SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0, &pAdminSid))
{
    LocalFree(pTokenGroups);
    CloseHandle(hCurrentToken);
    return FALSE;
}

// 遍历组信息,标记管理员组为禁用
for (DWORD i = 0; i < pTokenGroups->GroupCount; i++)
{
    if (EqualSid(pTokenGroups->Groups[i].Sid, pAdminSid))
    {
        pTokenGroups->Groups[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
        break;
    }
}

FreeSid(pAdminSid);

3. 创建受限令牌

用处理后的组信息生成受限令牌,这个令牌会移除原令牌中的管理员权限:

HANDLE hRestrictedToken = NULL;
if (!CreateRestrictedToken(hCurrentToken, 0, 0, NULL, 0, NULL, pTokenGroups, &hRestrictedToken))
{
    LocalFree(pTokenGroups);
    CloseHandle(hCurrentToken);
    return FALSE;
}

// 清理临时资源
LocalFree(pTokenGroups);
CloseHandle(hCurrentToken);

4. 使用受限令牌启动非管理员程序

通过CreateProcessWithTokenW调用受限令牌启动目标程序,确保程序运行在原用户的非管理员上下文:

STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };

// 替换为你的原程序路径和启动参数
LPCWSTR szProgramPath = L"C:\\Path\\To\\Your\\OriginalProgram.exe";
LPCWSTR szCommandLine = L"C:\\Path\\To\\Your\\OriginalProgram.exe";

if (!CreateProcessWithTokenW(hRestrictedToken, LOGON_WITH_PROFILE, 
    szProgramPath, (LPWSTR)szCommandLine, 0, NULL, NULL, &si, &pi))
{
    CloseHandle(hRestrictedToken);
    return FALSE;
}

// 清理句柄资源
CloseHandle(hRestrictedToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

关键注意事项

  • 无需登录凭据:所有操作基于当前提权进程的令牌调整,不需要输入用户名/密码
  • 上下文一致性:生成的受限令牌属于原用户,仅移除管理员权限,程序会运行在原用户的桌面和环境变量中
  • 路径权限:确保原程序的路径对非管理员用户有执行权限(比如ProgramFiles下的程序默认允许普通用户执行)
  • 错误处理:所有Windows API调用都需要检查返回值,通过GetLastError()排查具体问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 12:07:32