使用 CreateProcessWithTokenW() 从管理员帐户以非提升模式启动进程

Posted

技术标签:

【中文标题】使用 CreateProcessWithTokenW() 从管理员帐户以非提升模式启动进程【英文标题】:Launching process in non-elevated mode from an admin account using CreateProcessWithTokenW() 【发布时间】:2014-07-27 12:24:15 【问题描述】:

我遵循 Frank K. 的 proposed solution 从提升的用户进程启动普通用户进程。 但是,我在使建议的解决方案正常工作时遇到了一些困难(Win 7 x64 Professional;“普通用户”进程是从具有管理权限的域帐户启动的)。进程创建代码如下所示:

HANDLE processHandle = getProcessHandle("explorer.exe");

if (OpenProcessToken(processHandle, MAXIMUM_ALLOWED, &hToken))

    if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL,
        SecurityImpersonation, TokenPrimary, &hNewToken))
    
    LPWSTR pointer = const_cast<LPWSTR>(commandLine.c_str());
    bRet = CreateProcessWithTokenW(hNewToken,
      0, // logon flags
      0, // application name
      pointer, // command-line
      0, // creation flags
      NULL, // environment - inherit from parent
      NULL, // current directory
      &StartupInfo,
      &ProcInfo);
   ...
    

现在进程是在 CreateProcessWithTokenW 之后创建的,但是我检查进程是否具有管理权限的方法(见下文)表明该进程具有管理员权限(以及 ProcessExplorer,它在进程属性“安全”选项卡中列出:组: BUILTIN\Administrators --> 标志:所有者)。

 BOOL hasAdministratorRights()
 
  SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  PSID AdministratorsGroup;
  BOOL b = AllocateAndInitializeSid(
    &NtAuthority,
    2,
    SECURITY_BUILTIN_DOMAIN_RID,
    DOMAIN_ALIAS_RID_ADMINS,
    0, 0, 0, 0, 0, 0,
    &AdministratorsGroup);

  if (b)
  
    if (!CheckTokenMembership(NULL, AdministratorsGroup, &b))
    
      b = FALSE;
    
    FreeSid(AdministratorsGroup);
  
  return b;
 

注意:如果我在通过 runAs Windows 命令(以及给定的现有本地“用户”帐户)启动的进程/应用程序中调用上面的 hasAdministratorRights(),它将返回 false(因此它确认该进程仅具有用户权限,这是我所期待的)。但是在上面使用 CreateProcessWithTokenW() 创建的进程中调用它时返回 true。

任何想法我可能做错了什么以及为什么我的用户进程无法使用 CreateProcessWithTokenW 正确创建?

在 Frank K. 提出的解决方案中,从本地管理员帐户或从具有管理员权限的域帐户调用 CreateProcessWithTokenW()(和其他 API)时,它们的行为是否存在差异?

最好的问候, 马吕斯

【问题讨论】:

当前(登录)用户是否已经在运行提升?我没有尝试过,但 Frank 的帖子建议您以与 explorer.exe 相同的用户运行新进程。 explorer.exe 也有管理员权限吗?在这种情况下,您已经为已经提升的进程复制了令牌。不知道是不是这样,只是供您检查的想法。 感谢您的建议!实际上,explorer.exe 是管理员组的一部分。下一个问题是:使用什么应用程序来检索“用户”安全令牌?有什么想法吗? 不知道,但您可以查看this SO question,其中有人试图从进程中删除管理权限,这与您尝试执行的操作类似。 谢谢,CreateRestrictedToken() 似乎很有希望。我会试一试(但一周后,因为我将在度假,并且只能访问互联网)。然而,我仍然愿意接受任何其他关于我实施弗兰克方法的问题的建议。 不应提升资源管理器进程。在我看来,好像在有问题的机器上禁用了 UAC;你检查了吗? 【参考方案1】:

问题是在有问题的机器上禁用了 UAC,因此没有创建拆分令牌,并且 Explorer 进程具有完全管理员权限。

原则上,您可以使用CreateRestrictedToken() 解决此问题,但如果禁用 UAC,您可能应该认为这是故意的,这通常会成为默认行为,即赋予新进程管理员权限,这是最明智的选择。

如果您需要确认特定令牌具有管理权限的原因是因为 UAC 被禁用(包括用户是本地管理员帐户的情况),您可以使用 GetTokenInformation() 和 TokenLinkedToken option。

【讨论】:

以上是关于使用 CreateProcessWithTokenW() 从管理员帐户以非提升模式启动进程的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)