Condividi tramite


Implementare il codice compatibile con l'integrità della memoria

Questa sezione descrive come implementare il codice compatibile con l'integrità della memoria.

Nota

L'integrità della memoria viene talvolta definita integrità del codice protetta da hypervisor (HVCI) o hypervisor applicata all'integrità del codice ed è stata originariamente rilasciata come parte di Device Guard. Device Guard non viene più usato tranne per individuare l'integrità della memoria e le impostazioni VBS in Criteri di gruppo o nel Registro di sistema di Windows.

Per implementare il codice compatibile, assicurarsi che il codice del driver faccia quanto segue:

  • Opta per NX per impostazione predefinita
  • Usa API/flag NX per l'allocazione della memoria (NonPagedPoolNx)
  • Non usa sezioni sia scrivibili che eseguibili
  • Non tenta di modificare direttamente la memoria del sistema eseguibile
  • Non usa codice dinamico nel kernel
  • Non carica i file di dati come eseguibile
  • L'allineamento della sezione è un multiplo di 0x1000 (PAGE_SIZE). Ad esempio DRIVER_ALIGNMENT=0x1000

L'elenco seguente di DDI che non sono riservati all'uso del sistema può essere interessato:

Nome 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
Archiviazione
StorPortGetDataInBufferSystemAddress
StorPortGetSystemAddress
ChangerClassAllocatePool
Visualizza
DxgkCbMapMemory
VideoPortAllocatePool
Audio Miniport
IMiniportDMus::NewStream
IMiniportMidi::NewStream
IMiniportWaveCyclic::NewStream
IPortWavePci::NewMasterDmaChannel
IMiniportWavePci::NewStream
Classe porta audio
PcNewDmaChannel
PcNewResourceList
PcNewResourceSublist
IFS
FltAllocatePoolAlignedWithTag
FltAllocateContext
CDR
WdfLookasideListCreate
WdfMemoryCreate
WdfDeviceAllocAndQueryProperty
WdfDeviceAllocAndQueryPropertyEx
WdfFdoInitAllocAndQueryProperty
WdfFdoInitAllocAndQueryPropertyEx
WdfIoTargetAllocAndQueryTargetProperty
WdfRegistryQueryMemory

Usare i test di integrità del codice in HLK per testare la compatibilità del driver di integrità della memoria

Per altre informazioni sul test di sicurezza dei concetti fondamentali del sistema correlato, vedere Test di conformità all'integrità del codice HyperVisor e integrità della memoria e VBS.

Per altre informazioni sul test dei concetti fondamentali dei dispositivi correlati, vedere Test device.DevFund.

Usare la tabella seguente per interpretare l'output e determinare quali modifiche apportate al codice driver sono necessarie per correggere i diversi tipi di incompatibilità di integrità della memoria.

Avviso Redenzione

Eseguire il tipo di pool

Il chiamante ha specificato un tipo di pool eseguibile. Chiamata di una funzione di allocazione della memoria che richiede memoria eseguibile.

Assicurarsi che tutti i tipi di pool contengano un flag NX non eseguibile.

Esegui protezione pagina

Il chiamante ha specificato una protezione della pagina eseguibile.

Specificare una maschera di protezione della pagina "no execute".

Eseguire il mapping di pagine

Il chiamante ha specificato un mapping del descrittore di memoria eseguibile (MDL).

Assicurarsi che la maschera usata contenga MdlMappingNoExecute. Per altre informazioni, vedere MmGetSystemAddressForMdlSafe

sezione Execute-Write

L'immagine contiene una sezione eseguibile e scrivibile.

Errori di allineamento sezione

L'immagine contiene una sezione non allineata alla pagina.

L'allineamento della sezione deve essere un multiplo di 0x1000 (PAGE_SIZE). Ad esempio DRIVER_ALIGNMENT=0x1000

IAT nella sezione eseguibile

La tabella degli indirizzi di importazione (IAT), non deve essere una sezione eseguibile della memoria.

Questo problema si verifica quando l'IAT si trova in una sezione di sola lettura ed esecuzione (RX). Ciò significa che il sistema operativo non sarà in grado di scrivere nell'IAT per impostare gli indirizzi corretti per dove la DLL a cui si fa riferimento.

Un modo in cui questo può verificarsi è quando si usa l'opzione /MERGE (sezioni combinate) nel collegamento del codice. Ad esempio, se .rdata (dati inizializzati di sola lettura) viene unito ai dati con estensione text (codice eseguibile), è possibile che l'IAT possa terminare in una sezione eseguibile di memoria.


Relocs non supportato

In Windows 10, versione 1507 fino a Windows 10, versione 1607, a causa dell'uso del layout dello spazio indirizzi casuale (ASLR) può verificarsi un problema con la rilocazione di allineamento e memoria degli indirizzi. Il sistema operativo deve spostare l'indirizzo da cui il linker imposta l'indirizzo di base predefinito sulla posizione effettiva assegnata da ASLR. Questa rilocazione non può allontanarsi da un limite di pagina. Si consideri ad esempio un valore di indirizzo a 64 bit che inizia all'offset 0x3FFC in una pagina. Il valore dell'indirizzo si sovrappone alla pagina successiva in corrispondenza dell'offset 0x0003. Questo tipo di rilocazione sovrapposta non è supportato prima di Windows 10 versione 1703.

Questa situazione può verificarsi quando un inizializzatore di tipo struct globale ha un puntatore non allineato a un altro globale, disposto in modo che il linker non possa spostare la variabile per evitare la rilocazione stradling. Il linker tenterà di spostare la variabile, ma esistono situazioni in cui potrebbe non essere in grado di farlo (ad esempio con struct di grandi dimensioni o matrici di struct non allineati o grandi matrici di struct non allineati). Se appropriato, i moduli devono essere assemblati usando l'opzione /Gy (COMDAT) per consentire al linker di allineare il codice del modulo il più possibile.

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

Esistono altre situazioni che coinvolgono l'uso del codice assembler, in cui questo problema può verificarsi anche.


Integrità del codice del verificatore driver

Usare il flag di opzione di integrità del codice di verifica driver (0x02000000) per abilitare controlli aggiuntivi che convalidano la conformità con questa funzionalità. Per abilitare questa operazione dalla riga di comando, usare il comando seguente.

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

Per scegliere questa opzione se si usa la GUI del verificatore, selezionare Crea impostazioni personalizzate (per gli sviluppatori di codice), selezionare Avanti e quindi selezionare Controlli di integrità del codice.

È possibile usare l'opzione della riga di comando /query del verificatore per visualizzare le informazioni sul verificatore del driver corrente.

verifier /query

Vedere anche

Elenco di controllo per la sicurezza dei driver