次の方法で共有


ハンドル管理

ドライバー内のセキュリティの問題の重要な原因は、ユーザー モードとカーネル モード コンポーネントの間で渡されるハンドルの使用です。 カーネル環境内でのハンドルの使用には、次のような既知の問題がいくつかあります。

  • 間違った種類のハンドルをカーネル ドライバーに渡すアプリケーション。 カーネル ドライバーは、ファイル オブジェクトが必要なイベント オブジェクトを使用しようとしてクラッシュする可能性があります。

  • 必要なアクセス権を持たないオブジェクトにハンドルを渡すアプリケーション。 カーネル ドライバーは、ユーザーに適切なアクセス許可がない場合でも、呼び出しがカーネル モードから来ているため、動作する操作を実行する可能性があります。

  • アドレス空間内の有効なハンドルではない値を渡すが、システムに対して悪意のある操作を実行するためのシステム ハンドルとしてマークされているアプリケーション。

  • デバイス オブジェクトの適切なハンドル (このドライバーが作成しなかったハンドル) ではない値を渡すアプリケーション。

これらの問題から保護するには、カーネル ドライバーに渡されるハンドルが有効であることを確認するために特に注意する必要があります。 最も安全なポリシーは、ドライバーのコンテキスト内に必要なハンドルを作成することです。 カーネル ドライバーによって作成されたこれらのハンドルでは、OBJ_KERNEL_HANDLE オプションを指定する必要があります。これにより、任意のプロセス コンテキストで有効なハンドルと、カーネル モードの呼び出し元からのみアクセスできるハンドルが作成されます。

アプリケーション プログラムによって作成されたハンドルを使用するドライバーの場合、これらのハンドルの使用は細心の注意を払って行う必要があります。

  • ベスト プラクティスは、正しい AccessMode (通常は Irp->RequestorMode)、DesiredAccessおよび ObjectType パラメーター (IoFileObjectType や ExEventObjectType など) を指定して、ObReferenceObjectByHandle を呼び出して、ハンドルをオブジェクト ポインターに変換することです。

  • ハンドルを呼び出し内で直接使用する必要がある場合は、関数の Zw バリアントではなく、関数の Nt バリアントを使用することをお勧めします。 これにより、以前のモードは UserMode になり、信頼されていないため、オペレーティング システムによるパラメーター チェックと処理検証が適用されます。 ポインターである Nt 関数に渡されるパラメーターは、前のモードが UserMode の場合、検証に失敗する可能性があることに注意してください。 Nt ルーチンと Zw ルーチンは、エラーを確認する必要があるエラー情報を含む IoStatusBlock パラメーターを返します。

  • エラーは、必要に応じて__tryと__exceptを使用して適切にトラップする必要があります。 キャッシュ マネージャー (Cc)、メモリ マネージャー (Mm)、ファイル システム ランタイム ライブラリ ルーチン (FsRtl) の多くは、エラーが発生すると例外を発生させます。

ドライバーは、適切な予防措置を講じることなく、ユーザー モード アプリケーションから渡されたハンドルまたはパラメーターに依存する必要はありません。

Nt バリアントを使用してファイルを開く場合は、Nt バリアントも使用してファイルを閉じる必要があることに注意してください。