CreateProcessAsUser 生成错误 5
Posted
技术标签:
【中文标题】CreateProcessAsUser 生成错误 5【英文标题】:CreateProcessAsUser generating error 5 【发布时间】:2015-09-17 19:39:14 【问题描述】:我尝试混合使用代码 here 和 here 从通过 QtService 初始化的服务运行 GUI exe,但是每当我运行下面的代码时,我都会从 CreateProcessAsUser 收到错误 5。
另外,我看到了类似问题的答案here on ***,但无法弄清楚 DACL 与问题的关系,并且无法使用 Harry Johnson 的答案,因为我没有登录信息来自用户。
那么,谁能帮我理解为什么我从下面的代码中收到错误 5(拒绝访问)?
if(initUiWin())
log->write("InitUiWin executed.");
else
QString errorNumber = QString::number(GetLastError());
log->write("InitUiWin error: " + errorNumber);
-
bool initUiWin()
// obtain the currently active session id; every logged on
// User in the system has a unique session id
uint dwSessionId = WTSGetActiveConsoleSessionId();
// obtain the process id of the winlogon process that
// is running within the currently active session
QString processName("winlogon.exe");
DWORD winlogonPID = FindProcessId(processName.toStdWString(),dwSessionId);
if( winlogonPID != 0 )
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, winlogonPID);
HANDLE hToken;
OpenProcessToken(hProcess,TOKEN_READ,&hToken);
// Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
SECURITY_ATTRIBUTES sa;
sa.nLength = static_cast<DWORD>(sizeof(SECURITY_ATTRIBUTES));
// copy the access token of the winlogon process;
// the newly created token will be a primary token
HANDLE hUserTokenDup;
if (!DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,&sa,
SecurityIdentification,TokenPrimary,&hUserTokenDup))
CloseHandle(hProcess);
CloseHandle(hToken);
return false;
// Get Handle to the interactive window station
HWINSTA hwinsta = NULL;
hwinsta = OpenWindowStation(
_T(L"winsta0"), // the interactive window station
FALSE, // handle is not inheritable
READ_CONTROL | WRITE_DAC); // rights to read/write the DACL
if(hwinsta == NULL)
return false;
// To get the correct default desktop, set the caller's
// window station to the interactive window station.
if (!SetProcessWindowStation(hwinsta))
return false;
// Get a handle to the interactive desktop.
HDESK hdesk = NULL;
hdesk = OpenDesktop(
_T(L"default"), // the interactive window station
0, // no interaction with other desktop processes
FALSE, // handle is not inheritable
READ_CONTROL | // request the rights to read and write the DACL
WRITE_DAC |
DESKTOP_WRITEOBJECTS |
DESKTOP_READOBJECTS);
if(hdesk == NULL)
return false;
// Get the SID for the client's logon session.
PSID pSid = NULL;
if (!GetLogonSID(hUserTokenDup, &pSid))
return false;
// Allow logon SID full access to interactive window station.
if (!AddAceToWindowStation(hwinsta, pSid) )
return false;
// Allow logon SID full access to interactive desktop.
if (!AddAceToDesktop(hdesk, pSid) )
return false;
// Impersonate client to ensure access to executable file.
if (!ImpersonateLoggedOnUser(hUserTokenDup) )
return false;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = static_cast<DWORD>(sizeof(STARTUPINFO));
// interactive window station parameter; basically this indicates
// that the process created can display a GUI on the desktop
wchar_t auxBuffer[16] = L"winsta0\\default";
si.lpDesktop = auxBuffer;
// flags that specify the priority and creation method of the process
int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_BREAKAWAY_FROM_JOB;
// create a new process in the current User's logon session
bool result = CreateProcessAsUser(hUserTokenDup, // client's access token
L"test-ui-systray.exe", // file to execute
NULL, // command line
&sa, // pointer to process SECURITY_ATTRIBUTES
&sa, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
dwCreationFlags, // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
if (pSid)
FreeLogonSID(&pSid);
if (hdesk)
CloseDesktop(hdesk);
if (hwinsta)
CloseWindowStation(hwinsta);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return result;
return false;
【问题讨论】:
如果某个函数(如CreateProcessAsUser
)失败,您应该在该点调用GetLastError()
并保存错误代码。目前您正在调用其他函数,如CloseDesktop
、CloseWindowStation
等,所有这些都可能与GetLastError()
返回的错误代码相混淆。
您的服务是否以LocalSystem
运行?如果是这样,MSDN 文章非常清楚该怎么做。 (WTSQueryUserToken (WTSGetActiveConsoleSessionId (), &hToken);
然后CreateProcessAsUser(hToken, ...
)如果您不是以LocalSystem
运行,那么“没有合法 方法来获取具有正确会话ID 的登录用户令牌”。
更改窗口站和桌面权限的逻辑错误 - 该代码更改了您的窗口站和桌面上的权限,而不是用户的窗口站和桌面上的权限会议。但在这种情况下,您无论如何都不需要更改权限。您确定是 CreateProcessAsUser 失败而不是其他功能之一吗?
最明显的问题是sa
没有初始化。
我认为这是为@JonathanPotter 准备的。我在问您的服务是否以LocalSystem
运行。
【参考方案1】:
把它放在这里是为了可见性。 HarryJohnston 在 cmets 中回答。问题是 OpenProcessToken 中的标志,我刚刚更改了
OpenProcessToken(hProcess,TOKEN_READ,&hToken)
到
OpenProcessToken(hProcess,TOKEN_READ|TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY,&hToken)
【讨论】:
以上是关于CreateProcessAsUser 生成错误 5的主要内容,如果未能解决你的问题,请参考以下文章
CreateProcessAsUser 在活动会话中创建窗口
无密码的 CreateProcessAsUser 和 LogonUser
CreateProcessAsUser 进程以 -1073741502 退出