Minispy File System Minifilter Driver サンプルを動かしてみる

今回は、ファイルシステムミニフィルタ ドライバのサンプル Minispy File System Minifilter Driver をご紹介します。

 

このサンプルは、システム上の任意の I/O を監視しログに記録する方法を示すサンプルです。

 

Minispy は、ユーザーモード アプリケーションの minispy.exe とカーネルモード ドライバの minispy.sys で構成されています。Minispy.sys が、様々なI/O に対応するコールバックを、フィルタマネージャに登録します。このコールバックが、システム上の任意のI/O を記録します。ユーザーが、この記録された情報を要求した時に、minispy.sys がminispy.exe にその情報を渡し、minispy.exe が画面上に出力、またはファイルにログしていきます。

 

あるデバイス上のI/O を監視するためには、minispy.exe を使って、明示的に minispy.sys をそのデバイスにアタッチする必要があります。あるデバイス上の I/O の監視をやめる場合もminispy.exe を使います。

 

今回は、このサンプルをWindows 10 (1709) x86 にインストールして、C ドライブ上で監視した I/O の情報がコマンドプロンプトやファイル上に出力されるところをお見せしたいと思います。サンプルをビルドする、開発側のPC はWindows 10 (1709) x64 にVisual Studio 2017 とWDK for Windows 10 Version 1709 がインストールされています。

 

1. サンプルの入手

 

Minispy File System Minifilter Driver サンプルは、以下のサイトの右側の緑色の [Clone or Download] ボタンを押すと表示される [Download ZIP] ボタンでWindows-driver-samples-master.zipをダウンロードすると、Windows-driver-samples-master\filesys\miniFilter\minispy のフォルダにあります。

 

https://github.com/Microsoft/Windows-driver-samples

 

2. サンプルのビルド

 

このフォルダのminispy.sln を、Visual Studio 2017 で開きます。Filter の方がminispy.sys、User の方が minispy.exe のプロジェクトです。

 

clip_image002

 

[ ソリューション ‘minispy’] を右クリックして [構成マネージャー] をクリックします。

 

clip_image004

 

今回は、[アクティブソリューション構成] を [Debug] 、[アクティブ ソリューション プラットフォーム] を [Win32] とします。

 

また、minispy.exe 側でVisual C++ Runtime (VCRUNTIME14D.dll) のインストールを省略するために、User フォルダの下のプロジェクトminispy を右クリックして [プロパティ] を開き、[構成プロパティ]-[C/C++]-[コード生成]-[ランタイム ライブラリ] を [マルチスレッド デバッグ(/MTd)] に変更します。

 

clip_image006

 

 

[ソリューション ‘minispy’] を右クリックして[ソリューションのリビルド] をクリックします。

これで、minispy.sys とminispy.exe ができます。

次のステップに必要なファイルと場所は以下です。

 

ファイル

場所

minispy.sys

\minispy\filter\Debug\minispy

minispy.exe

\minispy\user\Debug

minispy.inf

\minispy

 

 

3. サンプルのインストールと動作確認の準備

 

上記のファイルをWindows 10 (1709) x86 の環境にコピーします。例えば、C:\minispy というフォルダを作って、そこに置きます。minispy.inf を右クリックして、[インストール] をクリックすれば、インストールできます。

 

インストールしても、以下のようにまだこのサンプルドライバはロードされていません。(fltmc.exe の使い方の詳細は、以前の記事「fltmc.exe の使い方」<https://blogs.msdn.microsoft.com/jpwdkblog/2013/02/27/fltmc-exe/> をご参照ください。)

 

>fltmc

 

フィルター名                      インスタンス数 階層          フレーム

------------------------------  -------------  ------------  -----

WdFilter                                3       328010         0

storqosflt                              0       244000         0

wcifs                                   1       189900         0

CldFlt                                  0       180451         0

FileCrypt                               0       141100         0

luafv                                   1       135000         0

npsvctrig                               1        46000         0

Wof                                     2        40700         0

FileInfo                                3        40500         0

 

そこで、以下のコマンドでこのサンプルドライバをロードします。

 

> fltmc load minispy

 

これにより、以下のようにminispy がロードされています。ただ、まだインスタンス数が 0 であることから、ボリュームへのアタッチはされていません。

 

>fltmc

 

フィルター名                      インスタンス数 階層          フレーム

------------------------------  -------------  ------------  -----

Minispy                                 0       385100         0

WdFilter                                3       328010         0

storqosflt                              0       244000         0

wcifs                                   1       189900         0

CldFlt                                  0       180451         0

FileCrypt                               0       141100         0

luafv                                   1       135000         0

npsvctrig                               1        46000         0

Wof                                     2        40700         0

FileInfo                                3        40500         0

 

なお、上記まで行わないと、minispy.exe の実行時に以下のエラーが出ます。

 

C:\minispy>minispy

Connecting to filter's port...

Could not connect to filter: 0x80070002

 

上記のminispy.sys のロードを行うことで、minispy.exe を以下のように実行できるようになります。

 

C:\minispy>minispy

Connecting to filter's port...

Creating logging thread...

 

Dos Name        Volume Name                            Status

--------------  ------------------------------------  --------

                \Device\Mup

C:              \Device\HarddiskVolume2

                \Device\HarddiskVolume1

                \Device\NamedPipe

                \Device\Mailslot

 

Hit [Enter] to begin command mode...

 

最後の行の指示通り、Enter を押すと、コマンドが入力できるようになります。

? を入力して、どのようなコマンドがあるか見てみます。

 

>?

Valid switches: [/a <drive>] [/d <drive>] [/l] [/s] [/f [<file name>]]

    [/a <drive>] starts monitoring <drive>

    [/d <drive> [<instance id>]] detaches filter <instance id> from <drive>

    [/l] lists all the drives the monitor is currently attached to

    [/s] turns on and off showing logging output on the screen

    [/f [<file name>]] turns on and off logging to the specified file

  If you are in command mode:

    [enter] will enter command mode

    [go|g] will exit command mode

    [exit] will terminate this program

>

 

オプションを表にすると以下の通りです。

 

オプション

説明

/a <ドライブ>

<ドライブ> の監視を開始します。/a は、minispy.sys をそのドライブに「アタッチ」するということです。

/d <ドライブ>[<インスタンスID>]

<インスタンスID> のminispy.sys を<ドライブ> からデタッチします。これにより監視を停止します。

/l

現在minispy.sys により監視しているすべてのドライブをリストします。

/s

スクリーンへのログ出力をON/OFF します。(デフォルトはON です。)

/f [<ファイル名>]

ファイルへのログ出力をON/OFF します。

ON の時は<ファイル名> が必須で、OFF の時は<ファイル名> が不要です。

 

コマンドモードについては以下の操作ができます。

・Enter を押せばコマンドモードに入ります。

・go またはg を入力すれば、コマンドモードから抜けます。

・exit を入力すれば、minispy.exe を終了します。

 

ここまでを理解したら、コマンドモードのまま、以下を実行して、C ドライブにアタッチしてみましょう。

 

>/a c:

    Attaching to c:...     Instance name: Minispy - Top Instance

 

実際、/l オプションを実行したら、C ドライブにアタッチできている(Status がAttached) と出力されます。

 

>/l

 

Dos Name        Volume Name                            Status

--------------  ------------------------------------  --------

                \Device\Mup

C:              \Device\HarddiskVolume2               Attached

                \Device\HarddiskVolume1

                \Device\NamedPipe

                \Device\Mailslot

>

 

 

4. サンプルの動作確認

 

以上で準備ができたので、動作確認として、C ドライブ上で監視した I/O の情報がコマンドプロンプトやファイル上に出力されるところをお見せしたいと思います。

 

コマンドモードのまま、g を入力して、スクリーン上にログを出力します。

 

>g

Should be logging to screen...

Opr  SeqNum   PreOp Time  PostOp Time   Process.Thrd      Major/MinorOperation          IrpFlags      DevObj   FileObj  Transact   status:inform                               Arguments                             Name

--- -------- ------------ ------------ ------------- ----------------------------------- ------------- -------- -------- -------- ----------------- ----------------------------------------------------------------- -----------------------------------

IRP 00000D69 14:43:32:574 14:43:32:634        4.a54  IRP_MJ_WRITE                        00060a01 N--- 8DF72388 8DF74398 00000000 00000000:00001000 1:00001000 2:00000000 3:0006F000 4:00000000 5:9F1BC000 6:00000000 \Device\HarddiskVolume2\ProgramData\Microsoft\Windows Defender\Support\MpWppTracing-03172018-123129-00000003-ffffffff.bin

                                                                     IRP_MN_NORMAL

 

上記は、出力のヘッダの部分と、最初のログの一行を抜粋しています。実際には、全部一行で表示できるようにコマンドプロンプトの設定を調整するか、ファイルに出力して、ヘッダの行とログの行の各項目の対応関係がわかるようにした方が、わかりやすいと思います。

 

上記の例を表にすると、以下のようになります。

 

ヘッダ

意味

ログ出力例

Opr

IRP、Fast I/O、FsFilter のいずれかのオペレーション

IRP:FLT_CALLBACK_DATA_IRP_OPERATION

FIO:FLT_CALLBACK_DATA_FAST_IO_OPERATION

FSF:FLT_CALLBACK_DATA_FS_FILTER_OPERATION

IRP

SeqNum

シーケンス番号

00000D69

PreOpTime

Pre-operation コールバックが呼ばれた時刻

14:43:32:574

PostOpTime  

Post-operation コールバックが呼ばれた時刻

14:43:32:634

Process.Thrd     

プロセスID とスレッドID

4.a54

Major/MinorOperation         

Major Function とMinor Function

IRP_MJ_WRITE

IRP_MN_NORMAL

IrpFlags     

IRP のフラグ。

値に以下が含まれるかどうかをアルファベット一文字でも示す。

N:IRP_NOCACHE

P:IRP_PAGING_IO

S:IRP_SYNCHRONOUS_API

Y:IRP_SYNCHRONOUS_PAGING_IO

00060a01N---

DevObj

デバイスオブジェクトのアドレス

8DF72388

FileObj

ファイルオブジェクトのアドレス

8DF74398

Transact

FLT_RELATED_OBJECTS 構造体のTransaction

00000000

status:inform                              

FLT_CALLBACK_DATA 構造体のIoStatus.Status とIoStatus.Information

00000000:00001000

Arguments                            

引数

Arg1 ~ Arg6 は、それぞれ、Data->Iopb->Parameters.Others.Argument*

1:000010002:00000000 3:0006F000 4:00000000 5:9F1BC0006:00000000

Name

ファイル名

\Device\HarddiskVolume2\ProgramData\Microsoft\Windows  Defender\Support\MpWppTracing-03172018-123129-00000003-ffffffff.bin

 

 

続いて、ファイルに出力してみます。/f の後にファイル名を指定して実行後、g を入力します。

 

>/f c:\minispy\log.txt

    Log to file c:\minispy\log.txt

>g

Should be logging to screen...

IRP 0000DDD2 15:26:04:616 15:26:04:616        4.a54  IRP_MJ_WRITE                        00060a01 N--- 8DF72388 8DF74398 00000000 00000000:00001000 1:00001000 2:00000000 3:001C9000 4:00000000 5:9F15E000 6:00000000 \Device\HarddiskVolume2\ProgramData\Microsoft\Windows Defender\Support\MpWppTracing-03172018-123129-00000003-ffffffff.bin

                                                                     IRP_MN_NORMAL

 

ファイル出力をやめるために、Enter を実行してコマンドモードにし、/f を入力します。(ファイル出力を止めない状態でログを開こうとすると、別のプロセスが使用中というエラーになります。)

 

>/f

    Stop logging to file

 

ログファイルを開いてみます。以下のように上記と同じログがありつつも、コマンドプロンプト(スクリーン) 上に表示されるよりも多く記録されていました。

 

clip_image008

 

 

上記の内容が、ファイルシステムミニフィルタドライバを開発される方のお役に立てば幸いです。

 

WDK サポートチーム 津田