Windows/Windows Programming

프로세스 권한 상승 - ShellExecuteEx()

MOLOKINI 2016. 4. 16. 13:41

윈도우에는 사용자 권한 상승(사용자 계정 컨트롤 : UAC - User Account Control)이라는 기능이 있습니다.

이 기능은 윈도우 사용자에게 보다 높은 수준의 보안성을 제공하는 역할을 하는데요.

 

짧게 요약하자면, 관리자 권한과 일반 사용자 권한의 차등을 두어 관리자 권한을 갖지 않았다면 접근할 수 있는 리소스를 제한해 보안성을 높이는 방법입니다.

 

- 요런거 많이 보셨을거에요~

 

프로세스가 수행되려면 때때로 관리자 권한이 필요한 경우도 있을텐데 앞서 포스팅한 CreateProcess 함수를 보면 권한 상승과 관련된 플래그나 인자는 없습니다.

 

그럼, 어떻게 코드 레벨에서 권한 상승(관리자 권한)된 프로세스로 실행을 시킬 수 있을까요?

 

이럴 때에는 CreateProcess 대신 ShellExecuteEx 함수를 사용해야합니다.

 

 

https://msdn.microsoft.com/ko-kr/library/windows/desktop/bb759784(v=vs.85).aspx

- R : Required, 필수인자

- O : Optional, 생략가능한 인자

- out : outparam, 리턴 출력 값

 멤버 설명 
DWORD cbSize (R) 구조체의 크기, sizeof(SHELLEXECUTEINFO)
ULONG fMask (R) 구조체 플래그로 여러 속성을 OR연산으로 사용 가능... 
자세한 내용은 생략하겠습니다. (궁금하시면 위 msdn 링크로 이동해보세요~)
HWND hwnd (O) 부모 윈도우의 핸들
LPCTSTR lpVerb (R) 권한 상승과 관련된 필드
- open : lpFile 인자로 파일 실행, (문서, PE, 폴더 등등)
- edit : lpFile 인자로 파일 수정 시도, (오로지 문서 파일만 가능!)
- explore : lpFile 인자로 설정된 폴더 오픈
- find : 설정된 폴더부터 검색을 시작
- print : lpFile 인자로 설정된 문서 파일 인쇄작업 (역시 문서 파일만 가능)
- properties : lpFile 인자로 설정된 파일의 속성 보기
- runas : lpFile 인자로 설정된 파일을 관리자 권한으로 실행
LPCTSTR lpFile (R) 실행 할 파일의 경로 지정
LPCTSTR lpParameter (O) 실행 파일의 파라미터 지정, cmdline
LPCTSTR lpDirectory (O) 실행 될 디렉토리 지정, NULL이면 현재 프로세스가 실행되는 경로로 설정 
int nShow (R)  실행한 프로세스가 어떻게 화면상에 표시될 것인지 결정
자세한 내용은 생략, 추가 정보는 아래 링크 확인
https://msdn.microsoft.com/ko-kr/library/windows/desktop/bb762153(v=vs.85).aspx
- nShowCmd 인자 관련 내용 
HINSTANCE hInstApp (out) 실패시 에러코드 리턴 
LPVOID lpIDList (O) 파일 실행에 필요한 추가 플래그들 포함 (ITEMIDLIST 구조체)
역시, 자세한 내용은 생략
https://msdn.microsoft.com/ko-kr/library/windows/desktop/bb773321(v=vs.85).aspx
LPCTSTR lpClass (O) 프로그램ID, URI, 파일 확장자, 레지스트리 등을 명시 
HKEY hKeyClass (O) 현재 파일의 레지스트리 키의 핸들 
DWORD dwHotKey (O) 현재 프로세스에 대한 단축키 지정, WM_SETHOTKEY
자세한 내용은 생략
https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms646284(v=vs.85).aspx 
union DUMMYUNIONNAME (O) HANDLE hIcon : 파일의 아이콘 핸들로 비스타 이후로는 사용되지 않음
HANDLE hMonitor : 현재 보여지는 문서의 모니터 핸들(?)
HANDLE hProcess (out) 새로 시작되는 프로세스의 핸들로 때로는 NULL이 될 수도 있음 

 

그럼 이 ShellExecuteEx를 이용해 관리자 권한으로 프로세스를 실행시키려면 아래와 같이 코드를 짤 수 있습니다. (예)

 

BOOL bShellExecute = FALSE;

SHELLEXECUTEINFO stShellInfo = { sizeof(SHELLEXECUTEINFO) }; // 구조체 초기화

 

stShellInfo.lpVerb = TEXT("runas");                                        // 관리자 권한 실행

stShellInfo.lpFile = TEXT("C:\Windows\System32\cmd.exe");     // 권리자 권한으로 실행시킬 파일

stShellInfo.nShow = SW_SHOWNORMAL;                               // 실행될 프로세스의 윈도우 보여주기

 

bShellExecute = ShellExecuteEx(&stShellInfo);

 

if(!bShellExecute)

{

    DWORD dwStatus = GetLastError();

    if(dwStatus == ERROR_CANCELED)

    {

         // 사용자의 권한 상승 거절

    }

    else if (dwStatus == ERROR_FILE_NOT_FOUND)

    {

        // lpFile로 지정한 파일이 존재하지 않음

    }

}

 

만약, 부모 프로세스가 관리자 권한으로 실행되고 있고 자식 프로세스도 관리자 권한으로 실행되어야 할 때에는 굳이 ShellExecuteEx로 실행시킬 필요가 없습니다.

- 자식도 관리자 권한으로 실행되거든요