最新バージョンの Backdoor.Proxybox には、「rxsupply」という低レベルのファイルシステムドライバがバンドルされていました。この悪質なドライバは、侵入先のコンピュータで滞留時間を少しでも長くするために、マルウェアが使うファイルへのアクセスを拒否するように設計されています。このドライバの機能と、カーネルのファイルシステムへのアクセスをフックする仕組みについてまとめたのが次の図です。
図 1. 悪質なファイルシステムフィルタが仕掛けられたファイルシステムのデバイススタック
悪質なドライバ rxsupply は、システムの起動時に Windows によってサービスとしてロードされます。ドライバのエントリポイントは次のような手順を実行して、ファイルシステムフィルタとして機能します。
まず、独自の IRP フィルタ関数を設定します。
図 2. ドライバのエントリ: IRP ハンドラ設定
次に、自身をファイルシステムドライバのデバイススタックにアタッチします。
図 3. ドライバのエントリ: 悪質なドライバからデバイスを作成し、ファイルシステムのスタックにアタッチ
図 4. ドライバのエントリ: 悪質なデバイスをファイルシステムのデバイススタックにアタッチ
既存のファイルシステムデバイスの IRP 関数に、IRP_MJ_READ のためのトランポリン/フックを構築します。
図 5. ドライバのエントリ: ファイルシステムデバイスの IRP_MJ_READ ハンドラ
ドライバの IRP フィルタ関数
Windows カーネルの各ドライバには、通信の手段として要求を処理するときに使われる一連の関数があります。悪質なドライバ rxsupply では、そのうちの 4 つだけをフィルタで選び出して処理する 1 つの関数によって、すべての IRP が処理されます。
図 6. 悪質なドライバの IRP ハンドラ関数
IRP フィルタ関数によって 0xf5bfb950 で処理される IRP は、ファイルアクセスに関連するものです。
- IRP_MJ_CREATE
- IRP_MJ_READ
- IRP_MJ_WRITE
- IRP_MJ_SET_INFORMATION
ドライバは、どのファイルがアクセスされているか、どのプロセスがアクセスを要求しているかを確認し、ドライバの保護ファイルリストにそのファイルがあれば IRP を投下します。このように悪質な IRP ハンドラを設定したら、次の段階としてドライバは自身をファイルシステムのデバイススタックに挿入します。実際のファイルシステムデバイスに送信された IRP を傍受することがその目的です。
図 7. ドライバの IRP ハンドラ
ファイルシステムのスタック
Windows は、物理セクタからの読み取りをディレクトリパスとファイル名の読み取りへと抽象化するために、物理ディスクデバイスに対するアクセスの処理にファイルシステムドライバを採用しています。また、他のドライバがこのドライバと対話できるように、デバイススタックと呼ばれる構造体を利用しています。デバイススタックとはデバイスのチェーンのようなもので、各デバイスが IRP に対して順次動作します。悪質なドライバの目的は、ファイルシステムデバイスより前に各 IRP を傍受し、それをスタックの下層に渡すかどうかを判断することです。
図 8. ドライバオブジェクト "NTFS" に関連付けられたファイルシステムデバイスの Windbg リストdriver object “NTFS”
図 9. NTFS デバイススタックに関連付けられたデバイスの Windbg リスト
その目的を果たすために、悪質なドライバは標的のファイルシステムデバイスを参照して IoAttachDeviceToDeviceStackSafe を呼び出します。この Windows カーネル関数が、ファイルシステム処理のための IRP 要求を受け取るデバイスのスタックに、悪質なドライバデバイスを挿入します。この時点で、悪質なドライバはファイルシステムデバイスより前に各 IRP を傍受できることになります。これで、どのプロセスがどのファイルに対してアクセスを試行しているかなどを基準にして、実際のファイルシステムデバイスに IRP を渡すかどうかを判断できるようになります。
ファイルシステムの IRP_MJ_READ のフック
ここまで説明したところで、では、このドライバが実際のファイルシステムデバイスで IRP_MJ_READ をフックしなければならないのはなぜか、という疑問が生じます。すでにデバイススタックに自身をインストールし、ファイルシステムより前に IRP を傍受できるようになっているにもかかわらず、です。その答えは、悪質なドライバの IRP ハンドラの実装にあります。
IRP がファイルシステムデバイスに達するまでカーネルのデバイススタックを下方に進むとき、中間デバイスが IRP を操作する可能性があります。IRP がスタック最下層のファイルシステムデバイスまで達すると、IRP_MJ_READ の場合には、IRP バッファがファイルの内容で満たされ、ファイルにアクセスしようとするスタックの各デバイスのスタック最下層から CompletionRoutines が呼び出されます。これらの完了ルーチンを設定するのは、その IRP ハンドラ関数におけるスタックの各デバイスです。
ファイルシステムの IRP_MJ_READ が悪質なドライバからフックされると、保護ファイルにアクセスしているのは信頼できるプロセスかどうかが確認され、その確認が取れた場合に、ファイルへのアクセスが許可されます。この場合、フック関数が完了ルーチンのチェーンにエントリを追加し、それが、ファイルシステムドライバがファイルの内容で IRP バッファを満たした後で実行される最初のルーチンになります。このルーチンが、新しく割り当てられたメモリに元のバッファを移動し、4 つのマジック定数と、割り当てメモリへのポインタによって置き換えることによって、IRP バッファを不明瞭化します。
図 10. NTFS ファイルシステムドライバの IRP_MJ_READ のフック
悪質なドライバはファイルシステムのデバイススタックの最上層からも完了ルーチンを実装します。この完了ルーチンは、悪質なドライバがスタックの最上層に侵入してから最後に実行されます。これが、不明瞭化されたバッファのマジック定数を確認し、ファイルの定数を含む元のバッファを再構築します。ファイルシステムのスタックで二重のアクセスポイントを使うこの手法によって、中間ドライバが保護ファイルの内容を取得することは、ますます難しくなります。
図 11. 悪質なドライバの完了ルーチン: マジック定数のチェック
図 12. Windbg: 不明瞭化された IRP バッファと、実際のファイル内容のバッファへのポインタ
ウイルス対策ソリューションが、ファイルシステムのスタックの最下層で実装されている場合、このタイプの悪質なファイルシステムフィルタドライバや保護されたペイロードを検出できる可能性は高くありません。シマンテックのウイルス対策製品は、Backdoor.Proxybox として検出されるこのグループのバックドアを駆除することができます。
* 日本語版セキュリティレスポンスブログの RSS フィードを購読するには、http://www.symantec.com/connect/ja/item-feeds/blog/2261/feed/all/ja にアクセスしてください。