Compatibilidad de controladores con integridad de memoria y VBS

La integridad de memoria es una característica de seguridad basada en virtualización (VBS) disponible en Windows 10, Windows 11 y Windows Server 2016 y versiones posteriores. La integridad de la memoria y VBS mejoran el modelo de amenazas de Windows y proporcionan protecciones más sólidas contra malware que intentan aprovechar el kernel de Windows. VBS usa el hipervisor de Windows para crear un entorno virtual aislado que se convierte en la raíz de confianza del sistema operativo que supone que el kernel se puede poner en peligro. La integridad de la memoria es un componente crítico que protege y protege Windows mediante la ejecución de la integridad de código del modo kernel dentro del entorno virtual aislado de VBS. La integridad de la memoria también restringe las asignaciones de memoria del kernel que podrían usarse para poner en peligro el sistema, lo que garantiza que las páginas de memoria del kernel solo se realicen ejecutables después de pasar comprobaciones de integridad de código dentro del entorno de tiempo de ejecución seguro y las páginas ejecutables nunca se puedan escribir.

Nota

La integridad de la memoria se conoce a veces como integridad de código protegida por hipervisor (HVCI) o hipervisor que se aplicaba a la integridad de código y se publicó originalmente como parte de Device Guard. Device Guard ya no se usa excepto para localizar la integridad de memoria y la configuración de VBS en directiva de grupo o en el Registro de Windows.

La integridad de la memoria está activada de forma predeterminada en instalaciones limpias de Windows 10 en modo S y Windows 11 en hardware compatible, tal y como se describe en habilitación de la integridad de memoria. En otros sistemas que no cumplen los requisitos de habilitación automática de integridad de memoria, los clientes pueden optar por usar cualquiera de los métodos descritos en cómo habilitar la integridad de la memoria.

Compatibilidad de aplicación

Aunque la compatibilidad con la integridad de la memoria ha sido un requisito para todos los controladores desde la actualización de aniversario de Windows 10 (1607), es posible que algunas aplicaciones y controladores de dispositivos de hardware sigan siendo incompatibles. Esta incompatibilidad puede hacer que los dispositivos o el software no funcionen correctamente y, en raras ocasiones, pueden provocar un error de arranque (pantalla azul). Estos problemas pueden producirse después de que la protección de la integridad de la memoria se haya activado o durante el propio proceso de habilitación. Si es desarrollador de aplicaciones y quiere validar que los controladores y los paquetes de software son compatibles con la integridad de la memoria, siga estos pasos.

Algunos ejemplos en los que hemos observado incompatibilidades con la integridad de la memoria incluyen:

  • Soluciones anti-trampa con juegos
  • Métodos de entrada de terceros
  • Protección con contraseña bancaria de terceros

Hemos trabajado duro para mitigar las experiencias afectadas, por lo que si existe una incompatibilidad para un controlador crítico para el arranque, la protección de la integridad de memoria se desactivará silenciosamente si se hubiera habilitado automáticamente. Si encuentra incompatibilidades con otras aplicaciones, le recomendamos que compruebe si hay actualizaciones de la aplicación específica y la versión que encuentran el problema antes de desactivar la protección de la integridad de la memoria.

Creación de controladores compatibles

Dado que las páginas y secciones de memoria nunca se pueden escribir y ejecutables, el primer paso es garantizar una separación clara de los datos y el código y no intentar modificar directamente las páginas de códigos.

  • Participación en NX de forma predeterminada
  • Uso de las API o marcas de NX para la asignación de memoria: NonPagedPoolNx
  • No use secciones que sean grabables y ejecutables.
  • No intente modificar directamente la memoria del sistema ejecutable
  • No usar código dinámico en el kernel
  • No cargue archivos de datos como ejecutables
  • La alineación de sección debe ser un múltiplo de 0x1000 (PAGE_SIZE). Por ejemplo, DRIVER_ALIGNMENT=0x1000

Use la versión más reciente del WDK y Visual Studio para generar controladores compatibles al usar la configuración predeterminada.

Comprobación de la compatibilidad del controlador con la integridad de memoria

Hay tres pasos para comprobar la compatibilidad del controlador:

  1. Use el Comprobador de controladores (consulte la sección siguiente) con las comprobaciones de compatibilidad de integridad de código habilitadas.
  2. Pruebe el controlador en un sistema con la integridad de memoria habilitada.
  3. Ejecute la prueba de preparación de integridad de código de HyperVisor en HLK de Windows.

Comprobaciones de compatibilidad del comprobador de controladores

El Comprobador de controladores tiene una marca de opción de integridad de código (0x02000000) para habilitar comprobaciones adicionales que validan el cumplimiento de la integridad de la memoria. Para habilitarlo desde la línea de comandos, use el siguiente comando:

verifier.exe /flags 0x02000000 /driver <driver.sys>

Para elegir esta opción si usa la GUI del comprobador, elija Crear configuración personalizada (para desarrolladores de código), elija Siguiente y, a continuación, seleccione Comprobaciones de integridad de código.

Para que se complete correctamente, no hay ninguna salida. A continuación se muestra un ejemplo de una salida de error.

Driver Verifier: Enabled for DvCi.sys, flags 0x2000000, build 16299, key o4Dbg8OVJqaBYlqWQ2QvRH

\*\*\*\*\*\*\*\*\*\*\* Verifier Detected a Code Integrity Issue \*\*\*\*\*\*\*\*\*\*\*\*

\*\* The caller 0xFFFFF8094B9852F0 specified an executable page protection 0x40.

\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

\*\*\* Verifier assertion failed \*\*\*

(B)reak, (I)gnore, (W)arn only, (R)emove assert? B

Prueba del controlador con integridad de memoria habilitada

Aunque Windows activará la integridad de la memoria de forma predeterminada para la mayoría de los sistemas, hay varias razones que pueden impedir que esto suceda. Para activar la integridad de la memoria, consulte Cómo activar la integridad de la memoria. A continuación, pruebe la funcionalidad del controlador. Asegúrese de ejercer todas las rutas de acceso de código del controlador para asegurarse de que el controlador no realiza operaciones en tiempo de ejecución que no son compatibles con la integridad de la memoria.

Pruebas de HLK (escritorio y servidor)

La prueba de HyperVisor Code Integrity Readiness Test de HLK debe superarse para que los controladores se aprueben para la firma de Microsoft. Los controladores compatibles con la integridad de memoria son necesarios para las ediciones de escritorio y servidor. La prueba de HLK es una prueba básica escrita para asegurarse de que los controladores compatibles con la integridad de memoria se cargan y ejecutan correctamente por el sistema operativo.

Aunque simplemente pasar la prueba HLK es suficiente para una firma de Microsoft para el controlador, se recomienda encarecidamente realizar pruebas funcionales exhaustivas con la integridad de memoria habilitada. Por ejemplo, podría haber asignaciones de memoria codificadas incorrectamente que infringen las protecciones de NX que provocan errores que la prueba no detectaría. El autor del controlador debe probar exhaustivamente el controlador mientras mantiene habilitada la integridad de la memoria.

Durante el desarrollo del controlador y durante las pruebas de HLK, es posible que sea necesario deshabilitar la integridad de la memoria, ya que puede impedir que el controlador se cargue.

La prueba de preparación de la integridad de código del hipervisor HLK es necesaria como parte de windows Server Assurance AQ y las marcas para habilitar las comprobaciones de integridad de código también se establecen al habilitar el comprobador de controladores durante otras pruebas de HLK.

Preguntas más frecuentes

¿Qué ocurre con los controladores existentes? ¿Es necesario volver a compilar estos controladores para que funcionen con Windows 10?

Depende. Muchos controladores ya serán compatibles. Si usa la configuración estándar con las versiones anteriores de WDK y Visual Studio, un problema conocido es que la sección INIT se marca como RWX. Sin embargo, en Windows 10, el W se quitará automáticamente, por lo que si este es el único problema, el controlador será compatible.

Cómo comprobar que la integridad de memoria está habilitada?

El método más sencillo es ejecutar la aplicación Información del sistema (msinfo32). Busque la línea siguiente: "Servicios de seguridad basados en virtualización en ejecución". Debe informar: "Hipervisor aplicado integridad de código". También hay una interfaz WMI para comprobar el uso de herramientas de administración; consulte Validar las características de integridad de memoria y VBS habilitadas.

La integridad de la memoria también se puede comprobar en la aplicación Seguridad de Windows en Configuración>Update & Security>Seguridad de Windows>Device securityCore isolation detailsMemory integrity (Integridad de memoriadel núcleo deseguridad > del > dispositivo). Para obtener más información, vea KB4096339.

¿Puedo comprobar que la integridad de memoria está habilitada mediante programación desde el kernel para modificar el comportamiento del controlador?

Sí, puede usar NtQuerySystemInformation: https://msdn.microsoft.com/library/windows/desktop/ms724509(v=vs.85).aspx

La estructura SYSTEM_CODEINTEGRITY_INFORMATION tiene un valor 0x400 expuesto, lo que indica que la integridad de la memoria está activada.

Cómo corregir problemas de compatibilidad?

Además de comprobar que no hay páginas W+X y que las secciones del controlador se alinean correctamente, como se mencionó anteriormente, el problema más probable será la asignación de memoria incorrecta. La información sobre las advertencias de análisis de código relacionadas con la asignación de memoria emitida está disponible en MSDN en la página siguiente:

Advertencias de análisis de código para controladores

Los siguientes vínculos de MSDN muestran algunos ejemplos de API usadas habitualmente que hacen que se asigne memoria ejecutable, junto con algunas correcciones de ejemplo:

Use la tabla siguiente para interpretar la salida para determinar qué cambios de código de controlador son necesarios para resolver los distintos tipos de incompatibilidades de HVCI.

Advertencia Solución
Tipo de grupo de ejecución El autor de la llamada especificó un tipo de grupo ejecutable. Llamar a una función de asignación de memoria que solicita memoria ejecutable. Asegúrese de que todos los tipos de grupo contienen una marca NX no ejecutable.
Ejecutar protección de páginas El autor de la llamada especificó una protección de página ejecutable. Especifique una máscara de protección de página "sin ejecutar".
Ejecutar asignación de páginas El autor de la llamada especificó una asignación de lista de descriptores de memoria ejecutable (MDL). Asegúrese de que la máscara que se usa contiene MdlMappingNoExecute. Para obtener más información, consulte MmGetSystemAddressForMdlSafe.
Sección Execute-Write La imagen contiene una sección ejecutable y grabable.
Errores de alineación de sección La imagen contiene una sección que no está alineada con páginas. La alineación de sección debe ser un múltiplo de 0x1000 (PAGE_SIZE). Por ejemplo, DRIVER_ALIGNMENT=0x1000
Reasignaciones no admitidas En Windows 10 versión 1507 a la versión 1607, debido al uso de la selección aleatoria del diseño del espacio de direcciones (ASLR), puede surgir un problema con la alineación de direcciones y la reubicación de memoria. El sistema operativo debe reubicar la dirección desde donde el enlazador establece su dirección base predeterminada en la ubicación real asignada por ASLR. Esta reubicación no puede estragar un límite de página. Por ejemplo, considere un valor de dirección de 64 bits que comienza en el desplazamiento 0x3FFC en una página. El valor de dirección se superpone a la página siguiente en el 0x0003 de desplazamiento. Este tipo de reasignaciones superpuestas no se admite antes de Windows 10 versión 1703.

Esta situación puede producirse cuando un inicializador de variable de tipo de estructura global tiene un puntero desalineado a otro global, dispuesto de tal manera que el enlazador no pueda mover la variable para evitar la reubicación de estratos. El enlazador intentará mover la variable, pero hay situaciones en las que es posible que no pueda hacerlo, por ejemplo, con estructuras grandes desalineadas o matrices grandes de estructuras mal alineadas. Si procede, los módulos se deben ensamblar mediante la opción /Gy (COMDAT) para permitir que el enlazador alinee el código del módulo tanto como sea posible.

#include <pshpack1.h>

typedef struct _BAD_STRUCT {
      USHORT Value;
      CONST CHAR *String;
} BAD_STRUCT, * PBAD_STRUCT;

#include <poppack.h>

#define BAD_INITIALIZER0 { 0, "BAD_STRING" },
#define BAD_INITIALIZER1 \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0

#define BAD_INITIALIZER2 \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1

#define BAD_INITIALIZER3 \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2

#define BAD_INITIALIZER4 \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3

BAD_STRUCT MayHaveStraddleRelocations[4096] = { // as a global variable
      BAD_INITIALIZER4
};

Hay otras situaciones que implican el uso del código del ensamblador, donde también se puede producir este problema.

IAT en la sección ejecutable La tabla de direcciones de importación (IAT), no debe ser una sección ejecutable de memoria.

Este problema se produce cuando el IAT, se encuentra en una sección de solo lectura y ejecución (RX) de memoria. Esto significa que el sistema operativo no podrá escribir en el IAT para establecer las direcciones correctas para donde se hace referencia al archivo DLL.

Una manera de que esto puede ocurrir es cuando se usa la opción /MERGE (Combinar secciones) en la vinculación de código. Por ejemplo, si .rdata (datos inicializados de solo lectura) se combina con datos .text (código ejecutable), es posible que el IAT termine en una sección ejecutable de memoria.

¿Qué API pueden verse afectadas?

La siguiente lista de API que no están reservadas para el uso del sistema puede verse afectada:

   
Nombre de la API Descripción
ExAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff544501(v=vs.85).aspx
ExAllocatePoolWithQuota https://msdn.microsoft.com/library/windows/hardware/ff544506(v=vs.85).aspx
ExAllocatePoolWithQuotaTag https://msdn.microsoft.com/library/windows/hardware/ff544513(v=vs.85).aspx
ExAllocatePoolWithTag https://msdn.microsoft.com/library/windows/hardware/ff544520(v=vs.85).aspx
ExAllocatePoolWithTagPriority https://msdn.microsoft.com/library/windows/hardware/ff544523(v=vs.85).aspx
ExInitializeNPagedLookasideList https://msdn.microsoft.com/library/windows/hardware/ff545301(v=vs.85).aspx
ExInitializeLookasideListEx https://msdn.microsoft.com/library/windows/hardware/ff545298(v=vs.85).aspx
MmAllocateContiguousMemory https://msdn.microsoft.com/library/windows/hardware/ff554460(v=vs.85).aspx
MmAllocateContiguousMemorySpecifyCache https://msdn.microsoft.com/library/windows/hardware/ff554464(v=vs.85).aspx
MmAllocateContiguousMemorySpecifyCacheNode https://msdn.microsoft.com/library/windows/hardware/ff554464(v=vs.85).aspx
MmAllocateContiguousNodeMemory https://msdn.microsoft.com/library/windows/hardware/jj602795(v=vs.85).aspx
MmCopyMemory https://msdn.microsoft.com/library/windows/hardware/dn342884(v=vs.85).aspx
MmMapIoSpace https://msdn.microsoft.com/library/windows/hardware/ff554618(v=vs.85).aspx
MmMapLockedPages https://msdn.microsoft.com/library/windows/hardware/ff554622(v=vs.85).aspx
MmMapLockedPagesSpecifyCache https://msdn.microsoft.com/library/windows/hardware/ff554629(v=vs.85).aspx
MmProtectMdlSystemAddress https://msdn.microsoft.com/library/windows/hardware/ff554670(v=vs.85).aspx
ZwAllocateVirtualMemory https://msdn.microsoft.com/library/windows/hardware/ff566416(v=vs.85).aspx
ZwCreateSection https://msdn.microsoft.com/library/windows/hardware/ff566428(v=vs.85).aspx
ZwMapViewOfSection https://msdn.microsoft.com/library/windows/hardware/ff566481(v=vs.85).aspx
NtCreateSection https://msdn.microsoft.com/library/windows/hardware/ff556473(v=vs.85).aspx
NtMapViewOfSection https://msdn.microsoft.com/library/windows/hardware/ff556551(v=vs.85).aspx
StorPortGetDataInBufferSystemAddress https://msdn.microsoft.com/library/windows/hardware/jj553720(v=vs.85).aspx
StorPortGetSystemAddress https://msdn.microsoft.com/library/windows/hardware/ff567100(v=vs.85).aspx
DxgkCbMapMemory https://msdn.microsoft.com/library/windows/hardware/ff559533(v=vs.85).aspx
IMiniportDMus::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536701(v=vs.85).aspx
FltAllocatePoolAlignedWithTag https://msdn.microsoft.com/library/windows/hardware/ff541762(v=vs.85).aspx
FltAllocateContext https://msdn.microsoft.com/library/windows/hardware/ff541710(v=vs.85).aspx
ChangerClassAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff551402(v=vs.85).aspx
IMiniportMidi::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536710(v=vs.85).aspx
IMiniportWaveCíclica::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536723(v=vs.85).aspx
IPortWavePci::NewMasterDmaChannel https://msdn.microsoft.com/library/windows/hardware/ff536916(v=vs.85).aspx
IMiniportWavePci::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536735(v=vs.85).aspx
PcNewDmaChannel https://msdn.microsoft.com/library/windows/hardware/ff537712(v=vs.85).aspx
PcNewResourceList https://msdn.microsoft.com/library/windows/hardware/ff537717(v=vs.85).aspx
PcNewResourceSublist https://msdn.microsoft.com/library/windows/hardware/ff537718(v=vs.85).aspx
VideoPortAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff570180(v=vs.85).aspx
ClfsCreateMarshallingArea https://msdn.microsoft.com/library/windows/hardware/ff541520(v=vs.85).aspx
WdfLookasideListCreate https://msdn.microsoft.com/library/windows/hardware/ff548694(v=vs.85).aspx
WdfMemoryCreate https://msdn.microsoft.com/library/windows/hardware/ff548706(v=vs.85).aspx
WdfDeviceAllocAndQueryProperty https://msdn.microsoft.com/library/windows/hardware/ff545882(v=vs.85).aspx
WdfDeviceAllocAndQueryPropertyEx https://msdn.microsoft.com/library/windows/hardware/dn265599(v=vs.85).aspx
WdfFdoInitAllocAndQueryProperty https://msdn.microsoft.com/library/windows/hardware/ff547239(v=vs.85).aspx
WdfFdoInitAllocAndQueryPropertyEx https://msdn.microsoft.com/library/windows/hardware/dn265612(v=vs.85).aspx
WdfIoTargetAllocAndQueryTargetProperty https://msdn.microsoft.com/library/windows/hardware/ff548585(v=vs.85).aspx
WdfRegistryQueryMemory https://msdn.microsoft.com/library/windows/hardware/ff549920(v=vs.85).aspx
NdisAllocateMemory https://msdn.microsoft.com/library/windows/hardware/ff550762(v=vs.85).aspx