次の方法で共有


ハンドル管理

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

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

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

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

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

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

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

  • ObReferenceObjectByHandle を呼び出し、正しい アクセスモード (通常は Irp->リクエスタモード), 必要なアクセス, ObjectType パラメータ (IoFileObjectType や ExEventObjectType など) を指定して、ハンドルをオブジェクトポインタに変換するのがベストプラクティスです。

  • ハンドルを呼び出し内で直接使用する必要がある場合は、関数の Zw バリアントではなく、関数の Nt バリアントを使用するのが最善です。 これにより、パラメータのチェックが強制され、前のモードが ユーザーモード したがって信頼されていません。 Nt 関数に渡されるポインターであるパラメーターは、以前のモードが ユーザーモード. Nt ルーチンと Zw ルーチンは、エラーに対してチェックする必要があるエラー情報を含む IoStatusBlock パラメーターを返します。

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

ドライバーは、適切な予防策を講じずに、ユーザー モード アプリケーションから渡されたハンドルやパラメーターに依存してはなりません。

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