使用 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有三种方式(不使用,动态使用,静态使用,默认是动态使用)