名前付きカーネルオブジェクトの一覧を取得
任意のプロセスが使用している名前付きカーネルオブジェクトの一覧を取得したいのですが。
それ、Win32でできるよ!
ということで書いてみた*1。よければどうぞー(named_kernel_object.cab)。
動作確認は 2008x64 のみだけど、適当に修正すれば大抵の環境で動くと思う。 x86の2000/2003/Vistaでも動作するようにしました。
概略
プログラムはオブジェクトタイプを列挙するEnumObjectType関数、ハンドルテーブルを列挙するEnumHandleTable関数、オブジェクトディレクトリを再帰的に列挙するEnumObjectDirectory関数で構成されている。
表題の実装はEnumHandleTable関数にあり、次の処理によってプロセスが持つハンドル一覧が列挙され、名前を持つものについてはそれも出力される。
- NtQuerySystemInformation(SystemHandleInformation によりシステムのハンドルテーブル(SYSTEM_HANDLE_INFORMATION)を取得する
- ハンドルテーブルから、指定したプロセスが所有するハンドルを検索する
- 自プロセス以外を指定した場合は、ハンドルテーブルのハンドル値をDuplicateHandleで複製して扱う
- 取得したハンドルによる NtQueryObject(Handle, ObjectNameInformation でオブジェクトの名前(OBJECT_NAME_INFORMATION)を取得する
これで名前があるオブジェクトに関しては名前が取得できる。ただしDuplicateHandleはすべてのオブジェクトハンドルを複製できるわけではないことと、システムプロセスが持つ一部のハンドルに対してNtQueryObjectを実行するとAPIのバグによりスレッドがデッドロックすることに注意する。
技術メモ
wsprintfやwprintfでも書式指定子 %wZ を受け付けるようだ。DbgPrint だけかと思っていた。 ユーザーモードではUNICODE_STRINGの出番はほとんどないのだけど。