Win32API プロセストークンに割り当てられている特権を有効にする AdjustTokenPrivileges
プロセストークンに割り当てられている特権を有効にするためには、AdjustTokenPrivileges関数を用いる。
手順は以下のとおり
No | 項目 |
1 | OpenProcessToken関数で、プロセストークンを取得する |
2 | LookupPrivilegeValue関数で、特権に対応するLUID(ローカル一意識別子)を取得する |
3 | TOKEN_PRIVILEGES型のオブジェクトに、LUID(ローカル一意識別子)と特権の属性(有効にするか無効にするか)を指定する |
プロセストークン割り当てられている特権を有効/無効にする関数を「EnablePrivileges関数」という関数で実装する。第1引数が特権名で第2引数が有効か無効かを表すフラグである。
main関数で、通常は無効になっている「シャットダウン特権」と「システム時刻変更特権」を有効にしている。
シャットダウン特権を有効にすることで、ExitWindowsEx関数でウィンドウズをシャットダウンすることができるようになり、システム時刻変更特権を有効にすることで、SetSystemTime関数やSetSystemTimeAdjustment関数でシステム時刻を設定することができるようになる。
#include <windows.h> #include <stdio.h> BOOL EnablePrivileges(LPTSTR lpPrivilegeName, BOOL bEnable) { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tokenPrivileges; BOOL bRet; //1.OpenProcessToken関数で、プロセストークンを取得する bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); if (!bRet) { return FALSE; } //2.LookupPrivilegeValue関数で、特権に対応するLUID(ローカル一意識別子)を取得する bRet = LookupPrivilegeValue(NULL, lpPrivilegeName, &luid); if (bRet) { //3.TOKEN_PRIVILEGES型のオブジェクトに、LUID(ローカル一意識別子)と特権の属性(有効にするか無効にするか)を指定する tokenPrivileges.PrivilegeCount = 1; tokenPrivileges.Privileges[0].Luid = luid; tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; //4.AdjustTokenPrivileges関数で、特権を有効にする AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0); bRet = GetLastError() == ERROR_SUCCESS; } CloseHandle(hToken); return bRet; } int main() { //シャットダウン特権を有効にする EnablePrivileges(SE_SHUTDOWN_NAME, TRUE); //システム時刻変更特権を有効にする EnablePrivileges(SE_SYSTEMTIME_NAME, TRUE); return 0; }
上記の例では、本当に特権が設定できているかが分からないため、特権を設定した後にLookupPrivilegeName関数やLookupPrivilegeDisplayName関数を用いて、特権が設定できていることを確認する。
#include <windows.h> #include <stdio.h> BOOL EnablePrivileges(LPTSTR lpPrivilegeName, BOOL bEnable) { HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tokenPrivileges; BOOL bRet; //1.OpenProcessToken関数で、プロセストークンを取得する bRet = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); if (!bRet) { return FALSE; } //2.LookupPrivilegeValue関数で、特権に対応するLUID(ローカル一意識別子)を取得する bRet = LookupPrivilegeValue(NULL, lpPrivilegeName, &luid); if (bRet) { //3.TOKEN_PRIVILEGES型のオブジェクトに、LUID(ローカル一意識別子)と特権の属性(有効にするか無効にするか)を指定する tokenPrivileges.PrivilegeCount = 1; tokenPrivileges.Privileges[0].Luid = luid; tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; //4.AdjustTokenPrivileges関数で、特権を有効にする AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0); bRet = GetLastError() == ERROR_SUCCESS; } CloseHandle(hToken); return bRet; } int main() { HANDLE hToken; PTOKEN_PRIVILEGES pTokenPrivileges; char szPrivilegeName[256]; char szDisplayName[256]; DWORD dwLength; DWORD dwLanguageId; DWORD i; //シャットダウン特権を有効にする EnablePrivileges(SE_SHUTDOWN_NAME, TRUE); //システム時刻変更特権を有効にする EnablePrivileges(SE_SYSTEMTIME_NAME, TRUE); ////////////////////////////////////////////////////////////////////////////////// //プロセストークンの特権情報を取得して、表示する if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { return 1; } GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwLength); pTokenPrivileges = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, dwLength); if (pTokenPrivileges == NULL) { CloseHandle(hToken); return 1; } GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, dwLength, &dwLength); for (DWORD i = 0; i < pTokenPrivileges->PrivilegeCount; i++) { dwLength = sizeof(szPrivilegeName)/sizeof(szPrivilegeName[0]); LookupPrivilegeNameA(NULL, &pTokenPrivileges->Privileges[i].Luid, szPrivilegeName, &dwLength); dwLength = sizeof(szDisplayName)/sizeof(szPrivilegeName[0]); LookupPrivilegeDisplayNameA(NULL, szPrivilegeName, szDisplayName, &dwLength, &dwLanguageId); puts("----------------------------------------------------------------------"); printf("PrivilegeName: %s\n", szPrivilegeName); printf("DisplayName: %s\n", szDisplayName); printf("Enable: %s\n\n", pTokenPrivileges->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED ? "True" : "False"); } CloseHandle(hToken); LocalFree(pTokenPrivileges); return 0; }
シャットダウン特権は有効になっているが、システム時刻変更特権は有効になっていない。実際にシステム時刻変更特権を設定する際に、AdjustTokenPrivileges関数で失敗している。GetLastError関数の値はERROR_NOT_ALL_ASSIGNED(1300:「参照された特権のうち、一部の特権が呼び出し側に割り当てられていません。」)であった。これは、ユーザー権限ではシステム時刻変更権限は元々割り当てられていなかったということである。
---------------------------------------------------------------------- PrivilegeName: SeShutdownPrivilege DisplayName: システムのシャットダウン Enable: True ---------------------------------------------------------------------- PrivilegeName: SeChangeNotifyPrivilege DisplayName: 走査チェックのバイパス Enable: True ---------------------------------------------------------------------- PrivilegeName: SeUndockPrivilege DisplayName: ドッキング ステーションからコンピュータを削除 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeIncreaseWorkingSetPrivilege DisplayName: プロセス ワーキング セットの増加 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeTimeZonePrivilege DisplayName: タイム ゾーンの変更 Enable: False
管理者権限で実行したときには、シャットダウン特権、システム時刻変更特権の両方が有効になった。
---------------------------------------------------------------------- PrivilegeName: SeIncreaseQuotaPrivilege DisplayName: プロセスのメモリ クォータの増加 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeSecurityPrivilege DisplayName: 監査とセキュリティ ログの管理 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeTakeOwnershipPrivilege DisplayName: ファイルとその他のオブジェクトの所有権の取得 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeLoadDriverPrivilege DisplayName: デバイス ドライバのロードとアンロード Enable: False ---------------------------------------------------------------------- PrivilegeName: SeSystemProfilePrivilege DisplayName: システム パフォーマンスのプロファイル Enable: False ---------------------------------------------------------------------- PrivilegeName: SeSystemtimePrivilege DisplayName: システム時刻の変更 Enable: True ---------------------------------------------------------------------- PrivilegeName: SeProfileSingleProcessPrivilege DisplayName: 単一プロセスのプロファイル Enable: False ---------------------------------------------------------------------- PrivilegeName: SeIncreaseBasePriorityPrivilege DisplayName: スケジューリング優先順位の繰り上げ Enable: False ---------------------------------------------------------------------- PrivilegeName: SeCreatePagefilePrivilege DisplayName: ページ ファイルの作成 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeBackupPrivilege DisplayName: ファイルとディレクトリのバックアップ Enable: False ---------------------------------------------------------------------- PrivilegeName: SeRestorePrivilege DisplayName: ファイルとディレクトリの復元 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeShutdownPrivilege DisplayName: システムのシャットダウン Enable: True ---------------------------------------------------------------------- PrivilegeName: SeDebugPrivilege DisplayName: プログラムのデバッグ Enable: False ---------------------------------------------------------------------- PrivilegeName: SeSystemEnvironmentPrivilege DisplayName: ファームウェア環境値の修正 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeChangeNotifyPrivilege DisplayName: 走査チェックのバイパス Enable: True ---------------------------------------------------------------------- PrivilegeName: SeRemoteShutdownPrivilege DisplayName: リモート コンピュータからの強制シャットダウン Enable: False ---------------------------------------------------------------------- PrivilegeName: SeUndockPrivilege DisplayName: ドッキング ステーションからコンピュータを削除 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeManageVolumePrivilege DisplayName: ボリュームの保守タスクを実行 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeImpersonatePrivilege DisplayName: 認証後にクライアントを偽装 Enable: True ---------------------------------------------------------------------- PrivilegeName: SeCreateGlobalPrivilege DisplayName: グローバル オブジェクトの作成 Enable: True ---------------------------------------------------------------------- PrivilegeName: SeIncreaseWorkingSetPrivilege DisplayName: プロセス ワーキング セットの増加 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeTimeZonePrivilege DisplayName: タイム ゾーンの変更 Enable: False ---------------------------------------------------------------------- PrivilegeName: SeCreateSymbolicLinkPrivilege DisplayName: シンボリック リンクの作成 Enable: False
参考
http://d.hatena.ne.jp/s-kita/20110409/1302337488
http://msdn.microsoft.com/ja-jp/library/cc401938.aspx