2014-12-26 3 views
2

Я пытаюсь выполнить процесс из службы 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; 
} 
+2

Обычно вам нужен только один из 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

+0

Есть некоторые права входа, которые могут потребоваться для учетной записи целевого пользователя. Журнал событий ('eventvwr') должен иметь больше информации для вас с более подробной информацией. Кроме того, для начинающих см. Статью базы знаний [Как установить права входа в систему с помощью утилиты NTRights] (http://support.microsoft.com/kb/315276). Он должен дать вам палец для поиска дополнительной информации. – jww

+0

Также, какая версия Windows вы используете. Это Server 2008? Службы терминалов ведут себя несколько иначе как в XP, так и в 2003 году (и, вероятно, другие), и это может помочь другим в оказании вам помощи. – jww

ответ

1

Код провалившегося на WTSQueryUserToken с кодом ошибки = 5 ... Любая идея, что мне не хватает?

Я думаю, что эта статья в MSDN может быть вам полезна: Launching an interactive process from Windows Service in Windows Vista and later. Согласно этой статье, вы должны вызвать следующий при использовании WTSQueryUserToken:

WTSQueryUserToken (WTSGetActiveConsoleSessionId(), &hToken); 

Затем используйте маркер найденный в вызове CreateProcessAsUser.


В вашем вызове OpenThreadToken с TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, вы могли бы временно увеличение это что-то вроде TOKEN_ALL_ACCESS, пока вы не морщины разработаны (что, если вам все еще нужно, чтобы сделать вызов). См. Access Rights for Access-Token Objects на MSDN.

+0

Я уже пробовал это и снова попробовал, используя WTSGetActiveConsoleSessionId() и TOKEN_ALL_ACCESS, но еще WTSQueryUserToken ret Ошибка урны 5! – Joseph

+1

Вы можете использовать любой сеанс, в котором пользователь вошел в систему, он не обязательно должен быть «активным» сеансом (подключенным к физической клавиатуре/мыши/монитору). Например, «активный» сеанс может показывать рабочий стол «WinLogon», когда пользователь не регистрируется локально. Но вы можете получить токен пользователя для удаленного пользователя. –

+1

'WTSGetActiveConsoleSessionId()' получает идентификатор сеанса, который активен в ** локальной консоли **. Это нормально для быстрого переключения пользователей, когда пользователи переключаются туда и обратно на физической консоли, но это не работает для служб терминалов, где пользователи не подключены к консоли. Поэтому, если вы разрешаете удаленный вход в систему на машине, вы не можете полагаться на 'WTSGetActiveConsoleSessionId()' самостоятельно, возможно, вам придется использовать 'WTSEnumerateSessions()', чтобы найти активный сеанс с зарегистрированным пользователем. –

Смежные вопросы