[BlueLeaf1336]> PROBLEMS> 探求其之壱>

探求其之壱 > 権限付与でプロセスをもっと覗く

historyTOP

2006/02/07:作成

システム系のプロセスの情報取得に失敗するTOP

すでに何度か書いていますが、いくつかのプロセスの情報取得に失敗したままです。もちろんタスクマネージャでは表示しているのに、です。たとえばこんなプロセスです。

イメージ名(Exe名)その説明備考
[System Process]−タスクマネージャでは System Idle Process
csrss.exeClient Server Runtime Process−
svchost.exeGeneric Host Process for Win32 Services5つのプロセスが動いているうち2つは取得できている
sqlservr.exeSQL Server Windows NTVisual Studio 2005 Express Edition
wdfmgr.exeWindows User Mode Driver Manager−
alg.exeApplication Layer Gateway Service−

基本的には、C:¥Windows¥System32¥ に置いてある Exe がほとんどです。単純にそのプロセスの情報を覗くための権限が足りないんだろうと思われるわけで。

そこまで考えると、以前、Windows をシャットダウンするために権限付与が必要だったことに思い至りました。OpenProcessToken・LookupPrivilegeValue・AdjustTokenPrivileges といった API や、「シャットダウン権限の付与」などで検索してみると、いくらでもヒットします。以下はそのうちの2つです。

ひとつは、まさに権限を付与するための関数を Delphi で書いたもの、もうひとつは、それぞれの権限の意味を日本語で説明してくれているものです。

まさにその権限付与関数そのものTOP

あまりにそのままでも仕方がないので、コメントを日本語に直してみましたが意味不明でした。Platform SDK を参照して追記すべき情報を拾ったり...してないし。

//  Torry's Delphi Pages
//  http://www.swissdelphicenter.ch/torry/showcode.php?id=1177

//  Windows NT 系のシステムでは、正しい権限を与えないと使えない関数が
//  あります。たとえば、ExitWindowsEx を使用したシステムのシャットダ
//  ウンや再起動、システム時刻の変更などです。
//  以下のコードは、権限を調整するための関数です。
//  AdjustTokenPrivileges() は、指定したアクセストークン(?)で、権限を
//  与えたり取り消したりします。

unit NTPrivilege;

interface

uses
    Windows, SysUtils;

//  NT Defined Privileges from winnt.h
//  winnt.h で定義されている権限
const
    SE_CREATE_TOKEN_NAME = 'SeCreateTokenPrivilege';
    SE_ASSIGNPRIMARYTOKEN_NAME = 'SeAssignPrimaryTokenPrivilege';
    SE_LOCK_MEMORY_NAME = 'SeLockMemoryPrivilege';
    SE_INCREASE_QUOTA_NAME = 'SeIncreaseQuotaPrivilege';
    SE_UNSOLICITED_INPUT_NAME = 'SeUnsolicitedInputPrivilege';
    SE_MACHINE_ACCOUNT_NAME = 'SeMachineAccountPrivilege';
    SE_TCB_NAME = 'SeTcbPrivilege';
    SE_SECURITY_NAME = 'SeSecurityPrivilege';
    SE_TAKE_OWNERSHIP_NAME = 'SeTakeOwnershipPrivilege';
    SE_LOAD_DRIVER_NAME = 'SeLoadDriverPrivilege';
    SE_SYSTEM_PROFILE_NAME = 'SeSystemProfilePrivilege';
    SE_SYSTEMTIME_NAME = 'SeSystemtimePrivilege';
    SE_PROF_SINGLE_PROCESS_NAME = 'SeProfileSingleProcessPrivilege';
    SE_INC_BASE_PRIORITY_NAME = 'SeIncreaseBasePriorityPrivilege';
    SE_CREATE_PAGEFILE_NAME = 'SeCreatePagefilePrivilege';
    SE_CREATE_PERMANENT_NAME = 'SeCreatePermanentPrivilege';
    SE_BACKUP_NAME = 'SeBackupPrivilege';
    SE_RESTORE_NAME = 'SeRestorePrivilege';
    SE_SHUTDOWN_NAME = 'SeShutdownPrivilege';
    SE_DEBUG_NAME = 'SeDebugPrivilege';
    SE_AUDIT_NAME = 'SeAuditPrivilege';
    SE_SYSTEM_ENVIRONMENT_NAME = 'SeSystemEnvironmentPrivilege';
    SE_CHANGE_NOTIFY_NAME = 'SeChangeNotifyPrivilege';
    SE_REMOTE_SHUTDOWN_NAME = 'SeRemoteShutdownPrivilege';
    SE_UNDOCK_NAME = 'SeUndockPrivilege';
    SE_SYNC_AGENT_NAME = 'SeSyncAgentPrivilege';
    SE_ENABLE_DELEGATION_NAME = 'SeEnableDelegationPrivilege';
    SE_MANAGE_VOLUME_NAME = 'SeManageVolumePrivilege';

//-----------------------------------------------------------------------------
//  権限の付与と取り消し
function NTSetPrivilege(sPrivilege: string; bEnabled: Boolean): Boolean;

implementation

//-----------------------------------------------------------------------------
//  権限の付与と取り消し
function NTSetPrivilege(sPrivilege: string; bEnabled: Boolean): Boolean;
var
    hToken: THandle;
    TokenPriv: TOKEN_PRIVILEGES;
    PrevTokenPriv: TOKEN_PRIVILEGES;
    ReturnLength: Cardinal;
begin
    //  Windows NT/2000/XP 以降でないと意味なし
    Result := True;
    if not (Win32Platform = VER_PLATFORM_WIN32_NT) then Exit;

    //  プロセストークンを取得する
    if OpenProcessToken(GetCurrentProcess(),
        TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken) then
    begin
        try
            //  locally unique identifier (LUID) を取得する
            if LookupPrivilegeValue(nil, PChar(sPrivilege),
                                    TokenPriv.Privileges[0].Luid) then
            begin
                //  one privilege to set
                TokenPriv.PrivilegeCount := 1;

                //  権限を付与するための設定
                if (bEnabled) then
                begin
                    TokenPriv.Privileges[0].Attributes  := SE_PRIVILEGE_ENABLED;
                end

                //  取り消すための設定
                else
                begin
                    TokenPriv.Privileges[0].Attributes := 0;
                end;

                //  replaces a var parameter
                ReturnLength := 0;
                PrevTokenPriv := TokenPriv;

                //  権限を適用する
                AdjustTokenPrivileges(hToken, False, TokenPriv, SizeOf(PrevTokenPriv),
                                        PrevTokenPriv, ReturnLength);
            end;
        finally
            CloseHandle(hToken);
        end;
    end;

    //  AdjustTokenPrivileges() の成功判定
    Result := GetLastError = ERROR_SUCCESS;
end;

end.

いろいろと権限を付与してみようTOP

さて、この関数をそのまま使って、定義済みの権限をひとつずつ、起動時に付与、終了時に解除してみました。ところで、付与と解除、とか、付与と取り消し、とか勝手に呼んでますが、合ってるんでしょうか?

その結果を書くにあたって、もうひとつの参考サイトの表をぱくって拡張することにします。

権利名意味(感謝)結果あるいは発生した例外
SE_ASSIGNPRIMARYTOKEN_NAMEプロセスのプライマリ・トークン割り当て参照された特権のうち、一部の特権が呼び出し側に割り当てられていません。
SE_AUDIT_NAME監査ログ・エントリの作成参照された特権のうち、一部の特権が呼び出し側に割り当てられていません。
SE_BACKUP_NAMEバックアップ操作の実行変化なし
SE_CHANGE_NOTIFY_NAMEファイルやディレクトリの変更通知の受信変化なし
SE_CREATE_PAGEFILE_NAMEページ・ファイルの作成変化なし
SE_CREATE_PERMANENT_NAME永続的オブジェクトの作成参照された特権のうち、一部の特権が呼び出し側に割り当てられていません。
SE_CREATE_TOKEN_NAMEプライマリ・トークンの作成参照された特権のうち、一部の特権が呼び出し側に割り当てられていません。
SE_DEBUG_NAMEプロセスのデバッグこれ!! [System Process] 以外のプロセス情報が取得できるようになった
SE_INC_BASE_PRIORITY_NAMEプロセスの基本優先順位の上昇変化なし
SE_INCREASE_QUOTA_NAMEプロセスに割り当てられているクォータの増加変化なし
SE_LOAD_DRIVER_NAMEデバイス・ドライバのロードおよびアンロード変化なし
SE_LOCK_MEMORY_NAMEメモリの物理ページのロック変化なし
SE_MACHINE_ACCOUNT_NAMEシステム名の変更参照された特権のうち、一部の特権が呼び出し側に割り当てられていません。
SE_PROF_SINGLE_PROCESS_NAME単一プロセスのプロファイル情報の収集変化なし
SE_REMOTE_SHUTDOWN_NAMEネットワーク要求によるシャットダウン変化なし
SE_RESTORE_NAMEバックアップ復元操作の実行変化なし
SE_SECURITY_NAMEセキュリティ関連関数の実行変化なし
SE_SHUTDOWN_NAMEローカル・システムのシャットダウン変化なし
SE_SYSTEM_ENVIRONMENT_NAME不揮発性RAM内のシステム設定情報の変更変化なし
SE_SYSTEM_PROFILE_NAMEシステム全体のプロファイル情報の収集変化なし
SE_SYSTEMTIME_NAMEシステムの時刻修正変化なし
SE_TAKE_OWNERSHIP_NAMEオブジェクトの所有権の取得変化なし
SE_TCB_NAME信頼コンピュータ・ベースの一部として識別参照された特権のうち、一部の特権が呼び出し側に割り当てられていません。
SE_UNSOLICITED_INPUT_NAME端末デバイスからの非要求入力の読み取り指定された特権は存在しません。
SE_UNDOCK_NAME不明変化なし
SE_SYNC_AGENT_NAME不明変化なし
SE_ENABLE_DELEGATION_NAME不明変化なし
SE_MANAGE_VOLUME_NAME不明変化なし

「変化なし」というのは、あくまで「今まで取得できていなかったプロセスの情報を取得できるようになったか」という点から見たものです。実際には何らかの変化がおきているはずですが、その変化を利用していないだけです。

そういうわけで、SE_DEBUG_NAME 権限を与えると、見事に取れるようになりました。じゃあ、最後のひとつはどうするんかという問題は残るんですが...

進捗状況TOP

20060207TaskMan.zip(8,862Bytes) ソースコードと実行ファイルです。

今までできているべきだったことができるようになっただけです。しかも、基本的に自分では何もせずに。インターネットに感謝。

EOFTOP