Win32API プロセストークンに割り当てられている特権を有効にする AdjustTokenPrivileges

プロセストークンに割り当てられている特権を有効にするためには、AdjustTokenPrivileges関数を用いる。

手順は以下のとおり

No項目
1OpenProcessToken関数で、プロセストークンを取得する
2LookupPrivilegeValue関数で、特権に対応するLUID(ローカル一意識別子)を取得する
3TOKEN_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;
    }


  • ユーザー権限でプログラムを実行した結果(Windows Vistaで実行)

  • シャットダウン特権は有効になっているが、システム時刻変更特権は有効になっていない。実際にシステム時刻変更特権を設定する際に、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
    




  • 管理者権限でプログラムを実行した結果(Windows Vistaで実行)

  • 管理者権限で実行したときには、シャットダウン特権、システム時刻変更特権の両方が有効になった。

    ----------------------------------------------------------------------
    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