이 블로그 검색

2015년 11월 19일 목요일

SYSTEM 권한(Windows Service) 에서 일반사용자 (user) 권한으로 프로세스 실행

[출처] http://kimsuny.egloos.com/v/2752669 

INT_PTR ExcuteAsUser(TCHAR* szCmd)
{
 BOOL bRet;
 INT_PTR hr;
 HANDLE processToken = NULL;
 TOKEN_PRIVILEGES oldTokenPrivileges = { 0 };
 HANDLE impersonationToken = NULL;
 HANDLE userToken = NULL;
 LPVOID pEnvironment = NULL;
 PROCESS_INFORMATION processInformation = { 0 };
 __try {

  bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &processToken);
  if (!bRet) {
   hr = GetLastError();
   return hr;
  }
  
  // This step might not be necessary because SeTcbPrivilege is enabled by default for Local System
  LUID luid;
  bRet = LookupPrivilegeValue(NULL, SE_TCB_NAME, &luid);
  if (!bRet) {
   hr = GetLastError();
   return hr;
  }
  
  TOKEN_PRIVILEGES adjTokenPrivileges = { 0 };
  adjTokenPrivileges.PrivilegeCount = 1;
  adjTokenPrivileges.Privileges[0].Luid = luid;
  adjTokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  DWORD dwOldTPLen;
  bRet = AdjustTokenPrivileges(processToken, FALSE, &adjTokenPrivileges, sizeof(TOKEN_PRIVILEGES), &oldTokenPrivileges, &dwOldTPLen);
  if (bRet) {
   hr = GetLastError();
   if (hr == ERROR_SUCCESS);
   else if (hr == ERROR_NOT_ALL_ASSIGNED) {
    // Enabled by default
   }
  }
  else {
   hr = GetLastError();
   return hr;
  }

//WTSGetActiveConsoleSessionId, WTSQueryUserToken 함수를 Kernel32.dll에서 직접가져오는 이유는
//원래 함수가 XP이상 지원이라서..
  HMODULE hInstKernel32 = NULL;
  HMODULE hInstWtsapi32 = NULL;
  typedef DWORD (WINAPI *WTSGetActiveConsoleSessionIdPROC)();
  WTSGetActiveConsoleSessionIdPROC WTSGetActiveConsoleSessionId = NULL;
  hInstKernel32 = LoadLibrary("Kernel32.dll");
  if (!hInstKernel32)
  {
   return -1;
  }
  WTSGetActiveConsoleSessionId = (WTSGetActiveConsoleSessionIdPROC)GetProcAddress(hInstKernel32,"WTSGetActiveConsoleSessionId");

  DWORD conSessId = WTSGetActiveConsoleSessionId();
  if (conSessId == 0xFFFFFFFF) {
   // There is no session attached to the console
   return ERROR_SUCCESS;
  }

  typedef BOOL (WINAPI *WTSQueryUserTokenPROC)(ULONG SessionId, PHANDLE phToken );
  WTSQueryUserTokenPROC WTSQueryUserToken = NULL;
  hInstWtsapi32 = LoadLibrary("Wtsapi32.dll");
  if (!hInstWtsapi32)
  {
   return -1;
  }
  WTSQueryUserToken = (WTSQueryUserTokenPROC)GetProcAddress(hInstWtsapi32,"WTSQueryUserToken");
  bRet = WTSQueryUserToken(conSessId, &impersonationToken);
  if (!bRet) {
   hr = GetLastError();
   return hr;
  }

  bRet = DuplicateTokenEx(impersonationToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &userToken);
  if (!bRet) {
   hr = GetLastError();
   return hr;
  }
  STARTUPINFO si = { 0 };
  si.cb = sizeof(STARTUPINFO);
  si.lpDesktop = _T("winsta0\\default");

  bRet = CreateEnvironmentBlock(&pEnvironment, userToken, TRUE);
  if (!bRet) {
   hr = GetLastError();
   return hr;
  }

  bRet = CreateProcessAsUser(
   userToken,
   szCmd,
   NULL,
   NULL,
   NULL,
   FALSE,
   CREATE_UNICODE_ENVIRONMENT,
   pEnvironment,
   NULL,
   &si,
   &processInformation
   );
  if (!bRet) {
   hr = GetLastError();
   return hr;
  }
 }
 __finally {
  if (processInformation.hThread) {
   CloseHandle(processInformation.hThread);
  }
  if (processInformation.hProcess) {
   CloseHandle(processInformation.hProcess);
  }
  if (pEnvironment) {
   bRet = DestroyEnvironmentBlock(pEnvironment);
  }
  if (userToken) {
   CloseHandle(userToken);
  }
  if (impersonationToken) {
   CloseHandle(impersonationToken);
  }
  if (processToken) {
   bRet = AdjustTokenPrivileges(processToken, FALSE, &oldTokenPrivileges, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
   CloseHandle(processToken);
  }
 }
 return 0;
}

댓글 없음:

댓글 쓰기