Token관련 API
Windows의 Token은 계정의 권한과 같은 개념이다.
윈도우엔 권한이 있어야만 실행 가능한 것들이 있다.
(현재 로그인 세션의 권한을 저장하고 있는 변수라고 생각하면 된다.)
BOOL WINAPI OpenProcessToken(
_In_ HANDLE ProcessHandle,
_In_ DWORD DesiredAccess,
_Out_ PHANDLE TokenHandle
);
ProcessHandle : Token을 얻어올 프로세스 핸들
DesiredAccess : 해당 프로세스에서 필요한 액세스 권한
TokenHandle : 얻어온 토큰이 저장될 핸들
BOOL WINAPI LookupPrivilegeValue(
_In_opt_ LPCTSTR lpSystemName,
_In_ LPCTSTR lpName,
_Out_ PLUID lpLuid
);
*LUID = locally unique identifier의 약자로 Windows가 부팅되면서 부여되는 64비트크기의 고유한 값이다.
함수 이름 그대로 PrivilegeValue 값을 Lookup하는 함수.
PrivilegeValue는 LUID로 구분되어 OS가 리부팅 되기전까지 가지고 있는 고유한 값이다.
(각 권한마다 매 부팅시 LUID가 부여되며 우리는 이 LUID로 권한을 disable || enable 시킬 수 있는 것이다.)
lpSystemName : Privilege값을 얻어올 시스템 이름. NULL입력시 로컬 시스템.
(MSDN에서 의미하는 System이 호스트단위인지는 잘 모르겠다. 공유가 가능한 LAN상에서 타 시스템의 Token도 가지고 올 수 있는건지 MSDN에선 Local system과 일반 system을 구분하고 있다.)
lpName : PrivilegeValue를 얻어올 PrivilegeName.
lpLuid : PrivilegeValue를 받을 LUID자료형의 포인터.
BOOL WINAPI AdjustTokenPrivileges(
_In_ HANDLE TokenHandle,
_In_ BOOL DisableAllPrivileges,
_In_opt_ PTOKEN_PRIVILEGES NewState,
_In_ DWORD BufferLength,
_Out_opt_ PTOKEN_PRIVILEGES PreviousState,
_Out_opt_ PDWORD ReturnLength
);
명시된 Access Token 의 권한을 Disable || Enable 시킬 수 있는 API함수
TokenHandle : 권한을 수정 할 Token의 핸들.
DisableAllPrivileges : 수정과는 관계없는 인자이므로 FALSE를 전달하면 된다. 이 값이 TRUE일 경우 NewState값은 무시되며 모든 권한이 Disable된다
NewState : 수정할 토큰에대한 정보를 담은 TOKEN_PRIVILEGES 구조체의 포인터 (예제 참조)
BufferLength : 버퍼의 크기 입력. 수정되기전의 Privileges 값을 받을 때 사용되는 버퍼같은데 어떻게 사용하는지는 자세하게 알지 못하겠다. 0으로 설정하려면 PreviousState (변경되기 전의 값을 받을 포인터) 또한 NULL이어야 한다.
PreviousState : 변경되기전 Privileges값을 받기위한 포인터
ReturnLength : 변경되기전 Privileges 값을 리턴받기위해 필요한 바이트 크기. TOKEN_PRIVILEGES의 크기를 말하는 것 같다. 이 역시 PreviousState값이 NULL일 경우에만 NULL을 전달 할 수 있다.
예제
int main(int argc, char *argv[])
{
if(!SetPrivilege(SE_DEBUG_NAME, TRUE))
return 1;
return 0;
}
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
printf("OpenProcessToken error : %u\n", GetLastError());
return FALSE;
}
if(!LookupPrivilegeValue(NULL, lpszPrivilege, &luid))
{
printf("LookupPrivilegeValue error : %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if(bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0; // disable
if(!AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error : %u\n", GetLastError());
return FALSE;
}
if(GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
** TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY 에 대해
TOKEN_ADJUST_PRIVILEGES : Token에 Access권한을 설정하는 AdjustTokenPrivileges를 호출할때 필요하다
MSDN : Required to enable or disable the privileges in an access token.
TOKEN_QUERY : 어떤 값인지 감을 못잡겠다 .
MSDN의 내용대로라면 Lookup API를 쓰기위해 지정해주는 mask가 아닐까 한다.
query : 질의, 문의
MSDN : Required to query an access token.