【发布时间】:2014-06-06 05:56:24
【问题描述】:
我正在尝试使用以下代码从我的服务应用程序运行用户模式进程(以local system 运行。)
用户模式进程的要求是运行没有提升,但在其清单中包含UIAccess="true" 以便能够display top-most windows correctly under Windows 8。
所以我这样做(通过我的服务)来运行我的用户模式进程:
//NOTE: Error checking is omitted for readability
//'dwSessionID' = user session ID to run user-mode process in
//'pUserProcPath' = L"C:\\Program Files (x86)\\Company\\Software\\user_process.exe"
HANDLE hToken = NULL;
WTSQueryUserToken(dwSessionID, &hToken);
HANDLE hToken2;
DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hToken2);
LPVOID pEnvBlock = NULL;
CreateEnvironmentBlock(&pEnvBlock, hToken2, FALSE);
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = L"winsta0\\default";
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
//ImpersonateLoggedOnUser(hToken2); //Not necessary as suggested below
PVOID OldRedir;
Wow64DisableWow64FsRedirection(&OldRedir);
BOOL bSuccess = CreateProcessAsUser(
hToken2, // client's access token
pUserProcPath, // file to execute
NULL, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, // creation flags
pEnvBlock, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
int nOSError = ::GetLastError();
Wow64RevertWow64FsRedirection(OldRedir);
//RevertToSelf(); //Not necessary as suggested below
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
DestroyEnvironmentBlock(pEnvBlock);
CloseHandle(hToken2);
CloseHandle(hToken);
如果 UIAccess="false" 在 user_process.exe 的清单中,这运行良好。
但如果我执行以下操作:
- 为
user_process.exe启用UIAccess="true":
用我的代码签名证书和
将其放在
"C:\Program Files (x86)\Company\Software"文件夹中。
我得到的是CreateProcessAsUser 失败并出现错误ERROR_ELEVATION_REQUIRED。
有人可以建议如何让它工作吗?
PS。我尝试调整我的服务权限以启用SE_DEBUG_NAME 和SE_TCB_NAME,但都没有帮助。
PS2。如果我只是双击使用UIAccess="true" 编译的user_process.exe 进程,代码签名并放置在C:\Program Files (x86)\Company\Software 文件夹中,它就可以正常启动和运行(未提升)。
【问题讨论】:
-
在拨打
CreateProcessAsUser(hToken2, ...)之前,您无需拨打ImpersonateLoggedOnUser(hToken2)。 -
@RemyLebeau:谢谢。这是一个不同的主题,但我很好奇。需要拨打
ImpersonateLoggedOnUser时有解释吗?我一直不清楚。 -
当您想要调用代表当前与调用线程关联的用户执行操作的 API 时,您模拟,但您的线程与您希望 API 看到的用户不同的用户关联。您将用户令牌传递给它们的 API,例如
CreateProcessAsUser(),没有该要求,因为令牌具有他们需要的一切。 -
@RemyLebeau:谢谢。我很欣赏你的解释。现在说得通了。
-
@RemyLebeau:根据 MSDN 文档,如果您希望系统在目标用户的安全上下文而不是调用者的安全上下文中打开可执行文件,则需要使用 CreateProcessAsUser 模拟。