Programming/Tips

VC++ 6.0 MFC ActiveX 권한 상승 사용하기

acidpop 2012. 2. 15. 14:10
반응형

여러곳을 돌아 다녀보아도 Visual C++ 6.0 으로 ActiveX 권한 상승문제는 정확하게 써놓은곳이 잘 없다.

거의 다 ATL 위주의 설명이 많아 블로그에 포스팅한다.


권한 상승 하는 방법은 크게 두가지로 분류가 된다.

자신의 객체를 권한 상승 시켜서 필요한 메서드만 관리자 권한으로 수행하게 하는 일시적인 권한 상승방법이 있고

Internet Explorer 자체를 관리자 권한으로 상승 시키는 방법이 있다.

여기서 포스팅하는 방법은 Internet Explorer 자체를 관리자 권한으로 상승시키는 방법이다.

1. 권한상승에 관한 코드 준비

필자는 stdafx.h 파일에 아래 코드를 선언하였다.

// 권한상승
typedef struct _TOKEN_ELEVATION {
    DWORD TokenIsElevated;
} TOKEN_ELEVATION, *PTOKEN_ELEVATION;

#ifndef CSIDL_PROGRAM_FILES
#define CSIDL_PROGRAM_FILES 0x0026
#endif // CSIDL_PROGRAM_FILES

#include 
#include 


BOOL IsVistaOrHigher(void);
HRESULT IsElevated(BOOL *pElevated);
BOOL ShellExecWithVerb(HWND hWnd, LPCTSTR lpVerb, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory);
BOOL ShellExecWithElevation(HWND hWnd, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory);
BOOL OpenUrlWithElevation(HWND hWnd, LPCTSTR lpUrl);




2. 선언한 코드들의 구현부

구현부는 아무 cpp 파일에 붙여 넣기 하여도 된다.
단, stdafx.h 를 include 하는 cpp 여야 한다.

BOOL IsVistaOrHigher(void)
{
	OSVERSIONINFO versionInfo;
	versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	
	if (GetVersionEx(&versionInfo) &&
		versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
		versionInfo.dwMajorVersion >= 6)
		return TRUE;
	else
		return FALSE;
}



HRESULT IsElevated(BOOL *pElevated)
{
	HRESULT hResult = E_FAIL;
	HANDLE hToken = NULL;
	
	if (!IsVistaOrHigher())
		return hResult;
	
	if (!OpenProcessToken(
		GetCurrentProcess(),
		TOKEN_QUERY,
		&hToken))
		return hResult;
	
	TOKEN_ELEVATION te = { 0 };
	DWORD dwReturnLength = 0;
	const int TokenElevation = 20;
	
	if (GetTokenInformation(
		hToken,
		(TOKEN_INFORMATION_CLASS)TokenElevation,
		&te,
		sizeof(te),
		&dwReturnLength))
	{
		hResult = te.TokenIsElevated ? S_OK : S_FALSE;
		
		if (pElevated)
			*pElevated = (te.TokenIsElevated != 0);
	}
	
	CloseHandle(hToken);
	return hResult;
}



BOOL ShellExecWithVerb(HWND hWnd, LPCTSTR lpVerb, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory)
{
	SHELLEXECUTEINFO executeInfo;
	memset(&executeInfo, 0, sizeof(executeInfo));
	
	executeInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	executeInfo.fMask = 0;
	executeInfo.hwnd = hWnd;
	executeInfo.lpVerb = lpVerb;
	executeInfo.lpFile = lpPath;
	executeInfo.lpParameters = lpParameters;
	executeInfo.lpDirectory = lpDirectory;
	executeInfo.nShow = SW_NORMAL;
	
	return ShellExecuteEx(&executeInfo);
}



BOOL ShellExecWithElevation(HWND hWnd, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory)
{
	return ShellExecWithVerb(hWnd, _T("runas"), lpPath, lpParameters, lpDirectory);
}



BOOL OpenUrlWithElevation(HWND hWnd, LPCTSTR lpUrl)
{
	_TCHAR lpBuffer[MAX_PATH + 1];
	
	if (!SHGetSpecialFolderPath(hWnd, lpBuffer, CSIDL_PROGRAM_FILES, 0))
		return FALSE;
	
	_tcscat(lpBuffer, _T("\\Internet Explorer\\iexplore.exe"));
	return ShellExecWithElevation(hWnd, lpBuffer, lpUrl, _T(""));
}


 



여기까지가 코드 구성이다

이젠 Javascript 또는 VB에서 호출 할 수 있는 AutoMation 함수를 만든다.


1. Class Wizard 를 연다.

 



2. Add Method 버튼을 클릭한다.

 


위와 같이 지정해 준 다음 OK


3. 다른 메서드를 하나 더 추가 해야 하므로 Add Method 버튼을 다시 클릭

 





4. 다음과 같이 지정 후 OK 버튼 클릭

 




위와 같이 하면 외부 인터페이스로 노출된 함수가 생성이 된것이며

각 함수들을 구현해주어야 한다.


 

 



해당 함수를 선택 Edit code 를 클릭하여 구현부로 이동한다.

long Cxxxxxxxx::GetNeedElevate()
{
	if (IsVistaOrHigher())
	{
		BOOL bResult = FALSE;
		
		if (SUCCEEDED(IsElevated(&bResult)))
		{
			if (bResult == TRUE)
				return 4; // 이미 Elevation이 완료됨
			else
				return 3; // Elevation이 필요함
		}
		else
			return 2; // 상태 정보를 조회할 수 없음
	}
	else
		return 1; // UAC가 지원되지 않는 운영체제로 판단함
	
	return 0;
}
long Cxxxxxxxx::RunElevatedWeb(LPCTSTR szUrl) 
{
	if( GetNeedElevate() == 3 )
	{
		// 권한 상승이 필요함
		OpenUrlWithElevation(NULL, szUrl);
	}

	return 0;
}



각 함수들을 위와 같이 구현 해 주면 ActiveX 준비는 모두 끝났다.

컴파일을 진행하여 ActiveX 를 배포하도록 한다.


이번에는 외부에서 사용하는 측에서 구현이 필요하다.

필자는 Javascript 로 설명을 진행하겠다.



ActiveX 를 object tag 로 올린 페이지에서

<body onload="OnLoad()">

Body 태그의 onload 부분 함수를 지정을 해 준 다음 OnLoad 함수를 구현하여 준다.

function OnLoad()
    {
        // 1 - UAC가 지원되지 않는 운영체제
        // 2 - 상태 정보 조회 불가
        // 3 - 권한 상승 필요
        // 4 - 이미 권한 상승 되어 있음
        if( ActiveXObj.GetNeedElevate() == 3 ){
            alert("Internet Explorer 가 관리자 권한으로 실행되어 있지 않습니다.\nInternet Exploerer 를 관리자 권한으로 실행합니다.");
            ActiveXObj.RunElevatedWeb(parent.document.URL);   // 인자로 다시 열려야 할 URL 을 넘겨준다.
            window.open('about:blank','_top').close();    // 기존 창은 닫기
        }
    }


위와 같이 구현한다.



이젠 마지막으로 Internet Explorer 를 유저 레벨로 실행 시킨 다음 해당 테스트 페이지로 접속해 본다.

위에서 구현한 alert 창이 뜨고 확인을 누르면 UAC 가 수행 되면서 Internet Explorer 창을 열것 이냐고 물어 볼것이다.

 


비록 자신의 회사와 프로그램 이름을 띄우지는 못하지만 해당 url 을 관리자 권한으로 열 수 있게 된다.




물론 사용자 계정 컨트롤을 끄고 사용하면 가장 간편하지만

고객사 PC가 모두 같은 환경일 수 는 없기 때문에 이런 방법들이 필요할 것이다.






http://acidpop.tistory.com/85

Class 화 시켜 만들어둔 모듈을 위 주소에 올려 두었으니

필요하신분들은 사용하시기 바랍니다.

Application 자체를 관리자 권한으로 실행하려면

위 클래스를 선언하여 SelfExecuteWithElevation() 

APP Class 의 InitInstance 함수에서 위 함수만 호출해주면 끝






 

참고 자료 : http://social.msdn.microsoft.com/Forums/ko-KR/visualcplusko/thread/b6af21e0-15af-421d-82f0-45ab055c4b90
반응형