Compartir a través de


Implementación de código compatible con la integridad de memoria

En esta sección se describe cómo implementar código compatible con la integridad de memoria.

Nota

La integridad de memoria se conoce a veces como integridad de código protegida por hipervisor (HVCI) o hipervisoraplicada 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.

Para implementar código compatible, asegúrese de que el código de controlador haga lo siguiente:

  • Opts in to NX by default (Participar en NX de forma predeterminada)
  • Usa las API o marcas de NX para la asignación de memoria (NonPagedPoolNx)
  • No usa secciones que son grabables y ejecutables
  • No intenta modificar directamente la memoria del sistema ejecutable
  • No usa código dinámico en el kernel
  • No carga archivos de datos como ejecutables
  • La alineación de sección es un múltiplo de 0x1000 (PAGE_SIZE). Por ejemplo, DRIVER_ALIGNMENT=0x1000

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

Nombre de DDI
ExAllocatePool
ExAllocatePoolWithQuota
ExAllocatePoolWithQuotaTag
ExAllocatePoolWithTag
ExAllocatePoolWithTagPriority
ExInitializeNPagedLookasideList
ExInitializeLookasideListEx
MmAllocateContiguousMemory
MmAllocateContiguousMemorySpecifyCache
MmAllocateContiguousMemorySpecifyCacheNode
MmAllocateContiguousNodeMemory
MmCopyMemory
MmMapIoSpace
MmMapLockedPages
MmMapLockedPagesSpecifyCache
MmProtectMdlSystemAddress
ZwAllocateVirtualMemory
ZwCreateSection
ZwMapViewOfSection
NtCreateSection
NtMapViewOfSection
ClfsCreateMarshallingArea
NDIS
NdisAllocateMemoryWithTagPriority
Storage
StorPortGetDataInBufferSystemAddress
StorPortGetSystemAddress
ChangerClassAllocatePool
Pantalla
DxgkCbMapMemory
VideoPortAllocatePool
Miniporte de audio
IMiniportDMus::NewStream
IMiniportMidi::NewStream
IMiniportWaveCíclica::NewStream
IPortWavePci::NewMasterDmaChannel
IMiniportWavePci::NewStream
Clase de puerto de audio
PcNewDmaChannel
PcNewResourceList
PcNewResourceSublist
IFS
FltAllocatePoolAlignedWithTag
FltAllocateContext
RDF
WdfLookasideListCreate
WdfMemoryCreate
WdfDeviceAllocAndQueryProperty
WdfDeviceAllocAndQueryPropertyEx
WdfFdoInitAllocAndQueryProperty
WdfFdoInitAllocAndQueryPropertyEx
WdfIoTargetAllocAndQueryTargetProperty
WdfRegistryQueryMemory

Uso de las pruebas de integridad de código en HLK para probar la compatibilidad del controlador de integridad de memoria

Para obtener más información sobre la prueba de seguridad de aspectos básicos del sistema relacionada, consulte Prueba de preparación de integridad de código de HyperVisor e integridad de memoria y VBS.

Para obtener más información sobre la prueba de aspectos básicos del dispositivo relacionada, consulte Pruebas de Device.DevFund.

Use la tabla siguiente para interpretar la salida y determinar qué cambios de código de controlador son necesarios para corregir los distintos tipos de incompatibilidades de integridad de memoria.

Advertencia Redención

Tipo de grupo de ejecución

El llamador 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

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.


Reasignaciones no admitidas

En Windows 10, la versión 1507 a Windows 10, 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.


Integridad del código del comprobador del controlador

Use la marca de opción Integridad de código del comprobador de controladores (0x02000000) para habilitar comprobaciones adicionales que validan el cumplimiento de esta característica. 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, seleccione Crear configuración personalizada (para desarrolladores de código), seleccione Siguiente y, a continuación, seleccione Comprobaciones de integridad de código.

Puede usar la opción de línea de comandos del comprobador /query para mostrar la información del comprobador del controlador actual.

verifier /query

Consulte también

Lista de comprobación de seguridad del controlador