【发布时间】:2020-03-04 06:54:16
【问题描述】:
我正在尝试从 Windows 服务(以 SYSTEM 身份运行)调用 Windows api(似乎只在登录用户的上下文中工作)。我能够获得登录用户的令牌。当我调用 ImpersonateLoggedOnUser() 时,我没有收到任何错误,它返回 true。但是 DoSomethingInUserContext() 仍然在 SYSTEM 上下文中执行。我究竟做错了什么?
DWORD sessionIdDw = WTSGetActiveConsoleSessionId();
HANDLE hToken;
if (!WTSQueryUserToken(sessionIdDw, &hToken))
LOG() << "WTSQueryUserToken failed: " << GetLastError();
HANDLE hDuplicated = NULL;
if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenImpersonation, &hDuplicated)) {
LOG() << "DuplicateTokenEx failed: " <<GetLastError();
}
if (!ImpersonateLoggedOnUser(hDuplicated)) {
LOG() << "ImpersonateLoggedOnUser failed " << GetLastError();
}
else {
DoSomethingInUserContext();
if (!RevertToSelf()) {
LOG() << "RevertToSelf failed" << GetLastError();
}
}
CloseHandle(hDuplicated);
CloseHandle(hToken);
【问题讨论】:
-
不是因为我使用的winapi不接受用户令牌
-
@NGambit 模拟不是正确的解决方案。
EnumWindows()枚举与调用线程关联的桌面窗口。模拟不会改变调用线程的桌面。因此,您正在枚举服务会话中的窗口,而不是用户会话。请参阅Why EnumWindows Not Working in service? 此外,由于会话 0 隔离,“允许服务与桌面交互”在 Vista+ 中不再有效。 -
“HKLM\System\CurrentControlSet\Services”中的服务模板条目将具有包含
SERVICE_USER_SERVICE(0x40) 标志的类型。服务控制管理器为每个用户会话生成一个 LUID,并在会话中启动一个名称中包含此 LUID 的用户服务实例。一些示例:“CDPUserSvc_LUID”、“OneSyncSvc_LUID”、“WpnUserService_LUID”、“LxssManagerUser_LUID”。
标签: c++ windows winapi impersonation