윈도우에는 사용자 권한 상승(사용자 계정 컨트롤 : 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로 실행시킬 필요가 없습니다.

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

Posted by 긍정왕오킹