2014-12-26 4 views
2

로컬 관리자 계정으로 실행되는 Windows 서비스에서 프로세스를 실행하려고합니다. 컴퓨터는 Windows 7이고 그 컴퓨터는 Remote Desktop/Terminal Service APIs입니다.다른 사용자의 프로세스 실행

코드는

5. 먼저 내가 모두 SE_DEBUG_NAMESE_TCB_NAME 권한을 사용할 수 있도록 SetPrivilege를 호출 한 후, 현재 스레드에서 토큰을 얻기 위해 시도 = 오류 코드로 WTSQueryUserToken에 실패했습니다. WTSQueryUserToken으로 전화를 걸지만 오류가 발생하면

서비스가 로컬 시스템 (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'을 활성화해야 할 수도 있습니다. 그것이 기본 프로세스 토큰을 대체 할 수있는 것이며, "프로세스로 원하는 모든 것을하십시오."라는 거룩한 삼위 일체에서 세 번째 프로세스 토큰입니다. MSDN에서 [Privilege Constants] (http://msdn.microsoft.com/en-us/library/windows/desktop/bb530716%28v=vs.85%29.aspx)를 참조하십시오. – jww

+0

대상 사용자 계정에 필요한 일부 로그온 권한이 있습니다. 이벤트 로그 ('eventvwr')에는 자세한 정보가있는 자세한 정보가 있어야합니다. 또한 처음에는 기술 자료 문서 [NTRights 유틸리티를 사용하여 로그온 사용자 권한을 설정하는 방법] (http://support.microsoft.com/kb/315276)을 참조하십시오. 더 많은 정보를 얻으려면 발끝을 잡아야합니다. – jww

+0

또한 사용중인 Windows 버전은 무엇입니까? 이 서버 2008입니까? 터미널 서비스는 XP 및 2003 (및 다른 경우)에서 약간 다르게 작동하며 다른 사용자를 지원할 때 도움이 될 수 있습니다. – jww

답변

1

코드는 ... 오류 코드 = 5로 WTSQueryUserToken에 내가 부족 어떤 생각을 실패?

이 MSDN 문서가 유용 할 것이라고 생각합니다. Launching an interactive process from Windows Service in Windows Vista and later. 기사에 따르면, 당신은 WTSQueryUserToken를 사용하는 경우 다음과 같은 호출해야합니다

WTSQueryUserToken (WTSGetActiveConsoleSessionId(), &hToken); 

그런 다음 CreateProcessAsUser에 대한 호출에서 검색 토큰을 사용합니다. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERYOpenThreadToken에 전화에서


, 당신 수도 TOKEN_ALL_ACCESS 같은 뭔가 일시적으로 상승이 당신이 주름이 밖으로 일 (여전히 전화를해야하는 경우 그건) 때까지. MSDN의 Access Rights for Access-Token Objects을 참조하십시오.

+0

나는 WTSGetActiveConsoleSessionId()와 TOKEN_ALL_ACCESS를 사용하여 이것을 이미 시도해 보았고 여전히 WTSQueryUserToken ret를 시도했다. urn error 5! – Joseph

+1

로그인 한 사용자가있는 세션을 사용할 수 있습니다. "활성"세션 (물리적 키보드/마우스/모니터에 연결된 세션) 일 필요는 없습니다. 예를 들어 "활성"세션은 사용자가 로컬에 로그인하지 않은 경우'WinLogon' 데스크탑을 보여줄 수 있습니다. 하지만 원격으로 로그인 한 사용자의 사용자 토큰을 얻을 수 있습니다. –

+1

'WTSGetActiveConsoleSessionId()'는 ** 로컬 콘솔 **에서 활성화 된 세션의 ID를 얻습니다. 사용자가 실제 콘솔에서 앞뒤로 전환하는 빠른 사용자 전환의 경우에는 문제가 없지만 사용자가 콘솔에 연결되어 있지 않은 터미널 서비스에서는 작동하지 않습니다. 따라서 시스템에 원격 로그인을 허용하면'WTSGetActiveConsoleSessionId()'만으로는 의존 할 수 없습니다. 로그인 한 사용자와의 활성 세션을 찾으려면'WTSEnumerateSessions()'를 사용해야 할 수도 있습니다. –