Skip to content

윈도우 서비스에서 유저 권한으로 createprocess 하는 부분을 해결하느라 엄청 애를 먹었다...

결론은 아래처럼 하면 된다.

 


http://duzi077.tistory.com/25

 

 

PROCESS_INFORMATION pi;  
    STARTUPINFO si;  
    BOOL bResult  = FALSE;  
    DWORD dwSessionId,winlogonPid;  
    HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;  
    DWORD dwCreationFlags;  
 
    // Log the client on to the local computer.  
 
    dwSessionId  = WTSGetActiveConsoleSessionId();  
 
    //////////////////////////////////////////  
    // Find the winlogon process  
    ////////////////////////////////////////  
 
    PROCESSENTRY32 procEntry;  
 
    HANDLE hSnap  = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  
    if (hSnap  = = INVALID_HANDLE_VALUE)  
    {  
        return 1 ;  
    }  
 
    procEntry.dwSize  = sizeof(PROCESSENTRY32);  
 
    if ( !Process32First(hSnap, &procEntry))  
    {  
        return 1 ;  
    }  
 
    do  
    {  
        if (wcsicmp(procEntry.szExeFile, L"winlogon.exe" = = 0)  
        {  
            // We found a winlogon process...make sure it's running in the console session  
            DWORD winlogonSessId = 0;  
            if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId)  
            {  
                winlogonPid = procEntry.th32ProcessID;  
                break;  
            }  
        }  
 
    } while (Process32Next(hSnap, &procEntry));  
 
    ////////////////////////////////////////////////////////////////////////  
 
    WTSQueryUserToken(dwSessionId,&hUserToken);  
    dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;  
    ZeroMemory(&si, sizeof(STARTUPINFO));  
    si.cb= sizeof(STARTUPINFO);  
    si.lpDesktop = L"winsta0\\default";  
    ZeroMemory(&pi, sizeof(pi));  
    TOKEN_PRIVILEGES tp;  
    LUID luid;  
    hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);  
 
    if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY  
        |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID  
        |TOKEN_READ|TOKEN_WRITE,&hPToken))  
    {  
        int abcd = GetLastError();  
        printf("Process token open Error: %u\n",GetLastError());   
    }  
 
    if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))  
    {  
        printf("Lookup Privilege value Error: %u\n",GetLastError());  
    }  
    tp.PrivilegeCount =1;  
    tp.Privileges[0].Luid =luid;  
    tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;  
 
    DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);  
    int dup = GetLastError();  
 
    //Adjust Token privilege  
    SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));  
 
    if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))  
    {  
        int abc =GetLastError();  
        printf("Adjust Privilege value Error: %u\n",GetLastError());  
    }  
 
    if (GetLastError()== ERROR_NOT_ALL_ASSIGNED)  
    {  
        printf("Token does not have the provilege\n");  
    }  
 
    LPVOID pEnv =NULL;  
 
    if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))  
    {  
        dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;  
    }  
    else  
        pEnv=NULL;  
 

 

 

#서비스에서 UI 있는 프로그램을 실행시킬 수는 있지만 SYSTEM 권한으로 실행되어 UI가 나오지 않는 문제 발생

윈도우는 User Interface, GDI, 커널 메인 객체를 제공한다.

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

Station은 클립보드, desktop등을 포함하는 프로세스와 관련이 있는 보안 객체이고, Desktop은 Station내에 존재하며 논리화면, 윈도우, 메뉴, 훅과 같은 User Interface를 포함하는 보안객체이다. 

로그온 화면을 관리하는 winlogon desktop, 화면보호기를 담당하는 screen saver desktop, 평상시 윈도우 화면을 보여주는 interactive desktop 3가지로 나눠진다.

 

사용자가 로그온을 하게 되면 WinSta0\Winlogon 에서 smss.exe(세션메니져), winlogon.exe, msgina.dll 를 통해 일련의 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"; 와 같이 설정하여 실행시켜야 한다. 서비스 프로그램중에서 mtask.exe와 같은 프로그램은 WinSta0을 사용한다. 

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


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



번호 제목 글쓴이 날짜 조회 수
439 좋은 화장품 WHRIA 2012.07.11 8903
438 이랬으면 좋겠네. WHRIA 2012.07.15 7720
437 MBC 최강연승 퀴즈쇼 [2] WHRIA 2012.08.13 9316
436 XP home 에서 동시 접속 늘리기 file WHRIA 2012.08.25 8872
435 서버 이전 WHRIA 2012.10.03 8627
434 whria.net 복구 WHRIA 2012.12.09 7654
433 PhotoPhoto 프로젝트 시작 WHRIA 2012.12.09 7504
432 윈도우 readyboost 기능도 쓸만하네 WHRIA 2012.12.10 7776
431 Boost lib 를 쓸까 MFC 를 쓸까 WHRIA 2012.12.10 7467
430 구글 넥서스(nexus) 4 주문하는법 WHRIA 2012.12.14 7509
429 SSD 참 좋군 WHRIA 2012.12.19 10601
428 Mediainfo 를 이용해서 날짜 알아내기 WHRIA 2012.12.20 10416
427 리눅스는 망했다. WHRIA 2012.12.25 8451
426 파일의 magic number WHRIA 2012.12.26 9291
425 GomPhoto 만들었음 [2] WHRIA 2012.12.31 9226

Powered by Xpress Engine / Designed by Sketchbook

sketchbook5, 스케치북5

sketchbook5, 스케치북5

나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소