관리 메뉴

kisoo

SERVICE PROCESS 에서 HKEY_CURRENT_USER 키 값을 QUERY 하는 방법 본문

01.About Programming /12.Default knowledge

SERVICE PROCESS 에서 HKEY_CURRENT_USER 키 값을 QUERY 하는 방법

JamesK78 2009. 7. 6. 17:47

SERVICE PROCESS 에서 HKEY_CURRENT_USER 을 OPEN 하면 FAILED 가 발생 했다.

NT 이상 VISTA 까지 이 부분을 아래와 같이 처리 하였더니 되더라~~~방법은 CURRENT USER PROCESS 의
SID 값이다.

소스 

우선 아래와 같이 현재 user 의 session id 를 통해서 user process 의 pid 를 구해야 한다. 
user process 중에 항상 뜨는 프로세스가 무엇이 있을까>???? 
바로 explorer.exe 이다. 
이 프로세스의 pid 를 통해서 SID 값을 구하여 레지스트리에 접근 하면 QUERY 가 가능하다. 


 @desc  :  vista / xp / nt 이상의 os 에서 service process 가 HKEY_CURRENT_USERS
       키에 접근 할 수 없기 때문에 USER PROCESS 의 PID 로 SID 값을 구하여
       HKEY_USERS 에 접근 하여 값을 가져 온다.
       여기서 session 의 process id 는 user process 이어야 하므로 explorer.exe 의
       pid 를 구해서 openprocess 한다.

CString CSafeHWCtrlImpl::GetUserSid()
{

 CString strErr = _T("");
 
 HINSTANCE hInst;

 DWORD dwSessionId;

    hInst = LoadLibrary("Kernel32.dll");

    pActiveSessionId = (DWORD(__stdcall *)())::GetProcAddress(hInst, "WTSGetActiveConsoleSessionId");

    dwSessionId = pActiveSessionId();

 DWORD dwProcessID;
    PROCESSENTRY32 procEntry;

 HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

 if (hSnap == INVALID_HANDLE_VALUE)
 {
     strErr.Format("ERROR hSnap Invalid Handle ErrCode %d",GetLastError());
  return strErr;
 }

 procEntry.dwSize = sizeof(PROCESSENTRY32);

 if (!Process32First(hSnap, &procEntry))
 {
     strErr.Format("ERROR Process32First False ErrCode %d",GetLastError());
  return strErr;
 }

 do
 {
  if (_stricmp(procEntry.szExeFile, "explorer.exe") == 0)
  {
   //---------------------------------------------------------------------------------
   // 현재 세션에서 동작 하는 explorer.exe process 를 찾았으므로 process id 를 구한다.
   //---------------------------------------------------------------------------------
   DWORD winlogonSessId = 0;
   if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId)
   {
    dwProcessID = procEntry.th32ProcessID;
    break;
   }
  }

 } while (Process32Next(hSnap, &procEntry));

    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ  , FALSE, dwProcessID);

 //---------------------------------------------------
    // Process Handle이 NULL이면, Open Failed 에러
 //---------------------------------------------------
    if (hProcess == NULL)
    {
  strErr.Format("ERROR_OPEN PROCESS FAILED 1");
        return strErr;
    }

 //-------------------------------------------------------------------------------------------
    // 프로세서의 실행자 SID를 찾는다.
    // 서비스 프로그램은 Local System 계정으로 로그인하였으므로, HKEY_CURRENT_USER로 레지스트리를
    // Open할 경우 Application 와 다른 레지스트리 키로 접근이 된다.
    // 그러므로, Process Token에서, SID를 확보해서 레지스트리를 직접 찾아 가야 한다.
 //-------------------------------------------------------------------------------------------
    HANDLE hTProcess;
    DWORD dwSize;

 //-------------------------------------------------------------------------------------------
    // Process 핸들로 토큰을 얻는다.
 //-------------------------------------------------------------------------------------------
    if (OpenProcessToken(hProcess, TOKEN_QUERY, &hTProcess) == FALSE)
    {
        CloseHandle(hProcess);
  strErr.Format("ERROR_OPEN TOKEN FAILED 2 ");
        return strErr;
    }
 //-------------------------------------------------------------------------------------------
    // 토큰 정보가 저장될 버퍼의 크기를 받아온다.
 //-------------------------------------------------------------------------------------------
    GetTokenInformation(hTProcess, TokenUser, NULL, 0, &dwSize);


    TOKEN_USER *sidUser = (TOKEN_USER *)malloc(dwSize);

    if (GetTokenInformation(hTProcess, TokenUser, sidUser, dwSize, &dwSize) == 0)
    {
        free(sidUser);
        CloseHandle(hTProcess);
        CloseHandle(hProcess);
  strErr.Format("ERROR %d",GetLastError());
        return strErr;
    }

 //----------------------------------------------------
    // STRING SID로 변경한다.
 //----------------------------------------------------
    LPTSTR pszSid;

    ConvertSidToStringSid(sidUser[0].User.Sid, &pszSid);

    free(sidUser);

    CloseHandle(hTProcess);

 //----------------------------------------------------
 // 문자열 더하고 빼고 등등 파싱을 할때
    // 좀더 쉽게 프로그램 하려고, CString으로 변환 하였음.
 //----------------------------------------------------
    CString strUserSID = pszSid;
    LocalFree(pszSid);

    //----------------------------------------------------
    // 레지스트리 오픈
 //----------------------------------------------------
    HKEY hKey = NULL;
    LONG lRet = 0;


    // HKEY_CURRENT_USER\\Software의 레지스트리 키 오픈
    strUserSID +="\\";
 strUserSID +=VOLUME_REGISTRY_PATH;

 return strUserSID;
}


....THREAD 에서 아래와 같이 해주면 된다.

strUserSID = pSafeInstance->GetUserSid();

  if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_USERS, strUserSID, 0, KEY_ALL_ACCESS, &hKey))
  {
      bRunning = FALSE;
  }
  else
  {
   bRunning = TRUE;
   bStatus = FALSE;
   if(hKey != NULL)
    RegCloseKey(hKey);
   break;

  }

 ....쿼리 하고 싶은 키를 쿼리 하면 된다.....코드 생략

Comments