Compartir a través de


Suplantación

Algunos sistemas de archivos pueden resultar útiles para realizar operaciones en nombre del autor de la llamada original. Por ejemplo, un sistema de archivos de red podría necesitar capturar la información de seguridad del autor de la llamada en el momento en que se abre un archivo para que se pueda realizar una operación posterior mediante las credenciales adecuadas. Sin duda hay muchos otros casos especiales en los que este tipo de característica es útil, tanto dentro de un sistema de archivos como en aplicaciones específicas.

Las rutinas clave necesarias para la suplantación incluyen:

  • PsImpersonateClientSeImpersonateClientEx--inicia la suplantación. A menos que se indique un hilo específico, la suplantación se realiza en el contexto del hilo actual.

  • PsRevertToSelf--termina la suplantación en el contexto actual del subproceso.

  • PsReferencePrimaryToken: contiene una referencia en el token principal (proceso) para el proceso especificado. Esta función se puede usar para capturar el token de cualquier proceso del sistema.

  • PsDereferencePrimaryToken--libera una referencia de un token primario que se había referenciado anteriormente.

  • SeCreateClientSecurityFromSubjectContext: devuelve un contexto de seguridad del cliente útil para la suplantación a partir de un contexto del sujeto (proporcionado al FSD durante el manejo de IRP_MJ_CREATE, por ejemplo).

  • SeCreateClientSecurity: crea un contexto de seguridad de cliente basado en las credenciales de seguridad de un subproceso existente en el sistema.

  • ImpersonateSecurityContext--asume el contexto de seguridad dentro de ksecdd.sys, el servicio de seguridad del kernel.

  • RevertSecurityContext: finaliza la suplantación dentro de ksecdd.sys, el servicio de seguridad del kernel.

La suplantación es sencilla de implementar. En el ejemplo de código siguiente se muestra la suplantación 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;
}

Hay numerosas variantes de este código de suplantación que están disponibles para los desarrolladores de sistemas de archivos, pero esto proporciona una ilustración básica de la técnica.