Compartilhar via


Representação

Alguns sistemas de arquivos podem achar útil executar operações em nome do chamador original. Por exemplo, um sistema de arquivos de rede pode precisar capturar as informações de segurança do chamador no momento em que um arquivo é aberto para que uma operação subsequente possa ser executada usando as credenciais apropriadas. Sem dúvida, há vários outros casos especiais em que esse tipo de recurso é útil, tanto em um sistema de arquivos quanto em aplicativos específicos.

As principais rotinas necessárias para a suplantação incluem:

  • PsImpersonateClientSeImpersonateClientEx– inicia a simulação. A menos que uma thread específica seja indicada, a personificação é feita no contexto atual da thread.

  • PsRevertToSelf– encerra a representação dentro do contexto atual do thread.

  • PsReferencePrimaryToken– mantém uma referência do token primário (processo) para o processo especificado. Essa função pode ser usada para capturar o token para qualquer processo no sistema.

  • PsDereferencePrimaryToken – lança uma referência em um token primário referenciado anteriormente.

  • SeCreateClientSecurityFromSubjectContext – retorna um contexto de segurança do cliente útil para representação de um contexto de sujeito (fornecido para o FSD durante o tratamento IRP_MJ_CREATE, por exemplo).

  • SeCreateClientSecurity– cria um contexto de segurança do cliente com base nas credenciais de segurança de um thread existente no sistema.

  • ImpersonateSecurityContext– simula o contexto de segurança em ksecdd.sys, o serviço de segurança do kernel.

  • RevertSecurityContext– encerra a impersonação dentro de ksecdd.sys, o serviço de segurança do kernel.

A impersonação é simples de implementar. O exemplo de código a seguir demonstra a representação básica:

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;
}

Há várias variantes desse código de personificação que estão disponíveis para desenvolvedores de sistemas de arquivos, mas ele fornece uma ilustração básica da técnica.