훈, IT 공부/C,C++,MFC

C/C++/Window, 서비스에서 UI 실행시키기

IT훈이 2019. 5. 10.
반응형

서비스 UI에서 동작시키는법

[문제발생]

 서비스에서 UI가 있는 A.exe 프로그램을 CreateProcess() API를 사용하여 실행을 시켰다. 실행은 되었지만 UI가 있는 프로그램임에도 불구하고 UI가 나타나지 않는다. 그 이유는 SYSTEM권한으로 실행되어서 UI가 발생되지 않았던 것이다. 

 

[문제분석]

 윈도우는 기본적으로 User Interface, GDI, 커널 메인 객체를 제공한다. 커널은 안전하지만, UI, GDI는 그렇지 않기 때문에 추가적인 보안성을 제공하기 위해 윈도우는 Stations와 desktops을 사용한다.

 

각 윈도우 데스크탑은 세션과 윈도우 스테이션에 속하며, 각 세션에서 오직 한번에 하나의 테스크탑만이 활성되 될 수 있다. 그리고 그것은 반드시 WinSta0에 속해야 한다.

Station -  Clipborad, destop 등을 포함하는 프로세스와 관련이 있는 보안 객체

Desktop - Station내에 존재하며 논리화면, 윈도우, 메뉴, 훅과 같은 User Interface를 포함하는 보안 객체

 

- 평상시 윈도우 화면을 보여주는 interactive desktop

- 로그온 화면을 관리하는 winlogon desktop,

- 화면 보호기를 담당하는 screen saver desktop,

총 3가지로 나뉘어진다.

 

WinSta0은 3개의 로드된 데스크탑을 가진다.

WinSta0\Default         사용자의 작업이 수행되는 쉘 환경( 사용자 테스크탑 )

- WinSta0\Winlogon      로그온 테스크탑 (로그온화면)     

- WinSta0\Screen-Saver  화면 보호기가 실행되는 순간 사용되는 Desktop

( 액티브 데스크탑의 핸들을 가져오기 위해서는 OpenInputDesktop() 함수를 사용하면된다. )

 

사용자가 로그온을 하게 되면 WinSta0\Winlogon 에서 smss.exe(세션메니져), winlogon.exe msgina.dl 를 통해 일련의 logon 작업을 거쳐 최종적으로 Winst0\default 라는 interactive window station을 생성한다. 

그러므로 사용자는 Winsta0의 station에서만이 UI 및 키 입력을 받을 수 있다. (즉 서비스의 경우는 Service-0x0-3e7$\default 로 생성됨) 

 

Winlogon과 default desktop은 서로 메시지나 대화상자를 공유할 수 없다. 자신의 desktop(winlogon, default)에서만 사용이 가능하다. 하지만 클립 보드는 Station에서 관리하기 때문에 다른 desktop에서 사용이 가능하다.

 

Service의 경우 LocalSystem 계정(administrator 보다 상위)으로 실행되어 Service-0x0-3e7$\default 와 같은 station을 생성하므로 UI및 키 입력을 받을 수 없다. 그래서 서비스 내에서 UI를 가진 프로그램을 실행시키기 위해서는 STARTUPINFO구조체를 si.lpDesktop = "WinSta0\\Default"; 와 같이 설정하여 실행시켜야 한다.

typedef struct _STARTUPINFOA {
  DWORD  cb;
  LPSTR  lpReserved;
  LPSTR  lpDesktop;
  LPSTR  lpTitle;
  DWORD  dwX;
  DWORD  dwY;
  DWORD  dwXSize;
  DWORD  dwYSize;
  DWORD  dwXCountChars;
  DWORD  dwYCountChars;
  DWORD  dwFillAttribute;
  DWORD  dwFlags;
  WORD   wShowWindow;
  WORD   cbReserved2;
  LPBYTE lpReserved2;
  HANDLE hStdInput;
  HANDLE hStdOutput;
  HANDLE hStdError;
} STARTUPINFOA, *LPSTARTUPINFOA;

서비스 프로그램중에서 mtask.exe와 같은 프로그램은 WinSta0을 사용한다. 반면 서비스 프로그램을 UI 또는 키 입력을 받기 위해서는 CreateService로 실행시 SERVICE_INTERATIVE_PROCESS 옵션을 사용하거나 서비스 등록정보에서 로그인정보에 "데스크와 상호 작용"을 설정하면 서비스도 UI 및 키입력을 받을 수 있다.

Session -> WindowStation -> Desktop와 같은 구조를 이루는데 다른 Session에서는 같은 winsta0\default를 가졌더라도 메시지 및 UI가 공유 될 수 없다. 즉 Session 1에 logon한 사용자가 실행시킨 프로그램에서 표시된 대화상자는 Session 2로 logon 사용자의 화면에는 나타나지 않는다는 말이다.

 

서비스 프로그램에서 UI있는 프로그램을 수행시키기 위해서는 CreateProcess()로는 안되고 CreateProcessAsUser()를 사용해야된다.

 

 

참조 : https://duzi077.tistory.com/25

 

반응형

댓글