Я пытаюсь выполнить процесс из службы Windows, выполняемой под учетной записью локального администратора. Машина - Windows 7 и ее использование - Remote Desktop/Terminal Service APIs.Запуск процесса от другого пользователя
Код провалившегося на WTSQueryUserToken
с кодом ошибки = 5.
Сначала я попытался получить маркер из текущего потока, а затем вызвать SetPrivilege
, чтобы включить оба SE_DEBUG_NAME
и SE_TCB_NAME
привилегии. затем позвоните по номеру WTSQueryUserToken
, но получите ошибку 5.
Только для уточнения: Когда услуга находилась в локальной системе (localSystem), этот код работает даже без необходимости вызова SetPrivilege. Теперь проблема в том, что мне нужно переместить службу для запуска под пользователем локального администратора !!!!
Любая идея, что мне не хватает?
Код:
BOOL T_Ex_RunProgram (DWORD sessionId, LPCWSTR targetPath)
{
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("T_Ex_RunProgram: sessionId = %d, targetPath = \"%S\"\n", sessionId, targetPath);
}
#endif
HANDLE htoken;
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &htoken))
{
if (GetLastError() == ERROR_NO_TOKEN)
{
if (!ImpersonateSelf(SecurityImpersonation))
{
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("ImpersonateSelf::RunProgram: dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
return FALSE;
}
if(!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &htoken))
{
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("OpenThreadToken::RunProgram: dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
return FALSE;
}
}
else{
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("OpenThreadToken::RunProgram: GetLastError return unexpected dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
return FALSE;
}
}
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("Before SetPrivilege(SE_DEBUG_NAME)::RunProgram\n");
}
#endif
// enable SeDebugPrivilege
if(!SetPrivilege(htoken, SE_DEBUG_NAME, TRUE))
{
// close token handle
CloseHandle(htoken);
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("SetPrivilege::RunProgram((SE_DEBUG_NAME): dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
return FALSE;
}
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("Before SetPrivilege(SE_TCB_NAME)::RunProgram\n");
}
#endif
// enable SeDebugPrivilege
if(!SetPrivilege(htoken, SE_TCB_NAME, TRUE))
{
// close token handle
CloseHandle(htoken);
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("SetPrivilege(SE_TCB_NAME)::RunProgram: dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
return FALSE;
}
BOOL b = WTSQueryUserToken (sessionId, &htoken);
if (!b)
{
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("T_Ex_RunProgram: WTSQueryUserToken failed. dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
return FALSE;
}
LPWSTR userName, userName1;
DWORD userNameLength;
b = WTSQuerySessionInformationW (WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &userName, &userNameLength);
if (b)
{
userName1 = _wcsdup (userName);
WTSFreeMemory (userName);
}
else
{
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("T_Ex_RunProgram: WTSQuerySessionInformation failed: dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
return FALSE;
}
b = RunProgramWithToken (htoken, userName1, targetPath,sessionId);
DWORD dwreturnErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("Before SetPrivilege(SE_DEBUG_NAME,FALSE)::RunProgram\n");
}
#endif
// enable SeDebugPrivilege
if(!SetPrivilege(htoken, SE_DEBUG_NAME, FALSE))
{
// close token handle
CloseHandle(htoken);
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("SetPrivilege::RunProgram((SE_DEBUG_NAME,FALSE): dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
}
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("Before SetPrivilege(SE_TCB_NAME,FALSE)::RunProgram\n");
}
#endif
// enable SeDebugPrivilege
if(!SetPrivilege(htoken, SE_TCB_NAME, FALSE))
{
// close token handle
CloseHandle(htoken);
DWORD dwErr = GetLastError();
#ifdef DEBUG
if(g_pLog)
{
g_pLog->Format ("SetPrivilege(SE_TCB_NAME,FALSE)::RunProgram: dwErr = %d\n", dwErr);
}
#endif
SetLastError(dwErr);
}
free (userName1);
CloseHandle (htoken);
if (!b)
SetLastError (dwreturnErr);
return b;
}
BOOL SetPrivilege(HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
Обычно вам нужен только один из SE_DEBUG_NAME или SE_TCB_NAME. Но вам может понадобиться включить 'SE_ASSIGNPRIMARYTOKEN_NAME'. Это тот, который позволяет вам заменить основной токен процесса, а третий - в святой троице «делать все, что угодно, с помощью процесса». См. [Константы привилегий] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb530716%28v=vs.85%29.aspx) в MSDN. – jww
Есть некоторые права входа, которые могут потребоваться для учетной записи целевого пользователя. Журнал событий ('eventvwr') должен иметь больше информации для вас с более подробной информацией. Кроме того, для начинающих см. Статью базы знаний [Как установить права входа в систему с помощью утилиты NTRights] (http://support.microsoft.com/kb/315276). Он должен дать вам палец для поиска дополнительной информации. – jww
Также, какая версия Windows вы используете. Это Server 2008? Службы терминалов ведут себя несколько иначе как в XP, так и в 2003 году (и, вероятно, другие), и это может помочь другим в оказании вам помощи. – jww