次の方法で共有


ものまね

一部のファイル システムでは、元の呼び出し元に代わって操作を実行すると便利な場合があります。 たとえば、ネットワーク ファイル システムでは、適切な資格情報を使用して後続の操作を実行できるように、ファイルを開いた時点で呼び出し元のセキュリティ情報をキャプチャする必要がある場合があります。 ファイル システム内と特定のアプリケーションの両方で、この種の機能が役立つ他の多くの特殊なケースがあることは間違いありません。

偽装に必要な主なルーチンは次のとおりです。

  • PsImpersonateClientSeImpersonateClientEx—偽装を開始します。 特定のスレッドが示されていない限り、偽装は現在のスレッド コンテキストで行われます。

  • PsRevertToSelf--は、現在のスレッド コンテキスト内で偽装を終了します。

  • PsReferencePrimaryToken--指定されたプロセスのプライマリ (プロセス) トークンの参照を保持します。 この関数は、システム上の任意のプロセスのトークンをキャプチャするために使用できます。

  • PsDereferencePrimaryToken--以前に参照されたプライマリ トークンの参照を解放します。

  • SeCreateClientSecurityFromSubjectContext--(たとえば、 IRP_MJ_CREATE 処理中に FSD に提供される) サブジェクト コンテキストからの偽装に役立つクライアント セキュリティ コンテキストを返します。

  • SeCreateClientSecurity--- システム上の既存のスレッドのセキュリティ資格情報に基づいてクライアント セキュリティ コンテキストを作成します。

  • ImpersonateSecurityContext-カーネル セキュリティ サービス ksecdd.sys内のセキュリティ コンテキストを偽装します。

  • RevertSecurityContext---カーネル セキュリティ サービス ksecdd.sys内で偽装を終了します。

偽装は簡単に実装できます。 次のコード例は、基本的な偽装を示しています。

NTSTATUS PerformSpecialTask(IN PFSD_CONTEXT Context)
{
  BOOLEAN CopyOnOpen;
  BOOLEAN EffectiveOnly;
  SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
  NTSTATUS Status;
  PACCESS_TOKEN oldToken;

  //
  // We need to perform a task in the system process context
  //
  if (NULL == Context->SystemProcess) {

    return STATUS_NO_TOKEN;

  }

  //
  // Save the existing token, if any (otherwise NULL)
  //
  oldToken = PsReferenceImpersonationToken(PsGetCurrentThread(),
                                           &CopyOnOpen,
                                           &EffectiveOnly,
                                           &ImpersonationLevel);

  Status = PsImpersonateClient( PsGetCurrentThread(),
                                Context->SystemProcess,
                                TRUE,
                                TRUE,
                                SecurityImpersonation);
  if (!NT_SUCCESS(Status)) {

    if (oldToken)
        PsDereferenceImpersonationToken(oldToken);
    return Status;

  }

  //
  // Perform task - whatever it is
  //


  //
  // Restore to previous impersonation level
  //
  if (oldToken) {
    Status = PsImpersonateClient(PsGetCurrentThread(),
                                 oldToken,
                                 CopyOnOpen,
                                 EffectiveOnly,
                                 ImpersonationLevel);

    if (!NT_SUCCESS(Status)) {
      //
      // This is bad - we can't restore, we can't leave it this way 
      //
      PsRevertToSelf();
    }
    PsDereferenceImpersonationToken(oldToken);
  } else {
    PsRevertToSelf();
  }

  return Status;
}

この偽装コードには、ファイル システム開発者が利用できるさまざまなバリエーションがありますが、この手法の基本的な図が提供されます。