Memóriaintegritással kompatibilis kód implementálása

Ez a szakasz a memóriaintegritással kompatibilis kód implementálását ismerteti.

Megjegyzés:

A memóriaintegritást néha hipervizor által védett kódintegritásnak ( HVCI) vagy hipervizor által kikényszerített kódintegritásnaknevezik, és eredetileg a Device Guardrészeként jelent meg. A Device Guard már nem használható, kivéve a memória integritását és a VBS-beállításokat a csoportházirendben vagy a Windows-beállításjegyzékben.

A kompatibilis kód implementálásához győződjön meg arról, hogy az illesztőprogram kódja a következő:

  • Alapértelmezés szerint az NX-et választja
  • NX API-kat/jelzőket használ a memóriafoglaláshoz (NonPagedPoolNx)
  • Nem használ írható és végrehajtható szakaszokat
  • Nem próbálja meg közvetlenül módosítani a végrehajtható rendszermemóriát
  • Nem használ dinamikus kódot a kernelben
  • Nem tölt be adatfájlokat végrehajtható fájlként
  • A szakasz igazítása a 0x1000 (PAGE_SIZE) többszöröse. Pl. DRIVER_ALIGNMENT=0x1000

A rendszerhasználatra nem fenntartott DDI-k következő listája érintett lehet:

DDI név
ExAllocatePool
ExAllocatePoolWithQuota
ExAllocatePoolWithQuotaTag
ExAllocatePoolWithTag
ExAllocatePoolWithTagPriority
ExInitializeNPagedLookasideList
ExInitializeLookasideListEx
MmAllocateContiguousMemory
MmAllocateContiguousMemorySpecifyCache
MmAllocateContiguousMemorySpecifyCacheNode
MmAllocateContiguousNodeMemory
MmCopyMemory
MmMapIoSpace
MmMapLockedPages
MmMapLockedPagesSpecifyCache
MmProtectMdlSystemAddress
ZwAllocateVirtualMemory
ZwCreateSection
ZwMapViewOfSection
NtCreateSection
NtMapViewOfSection
ClfsCreateMarshallingArea
NDIS
NdisAllocateMemoryWithTagPriority
Raktározás
StorPortGetDataInBufferSystemAddress
StorPortGetSystemAddress
ChangerClassAllocatePool
Kijelző
DxgkCbMapMemory
VideoPortAllocatePool
Hang miniport
IMiniportDMus::NewStream
IMiniportMidi::NewStream
IMiniportWaveCyclic::NewStream
IPortWavePci::NewMasterDmaChannel
IMiniportWavePci::NewStream
Hangport-osztály
PcNewDmaChannel
PcNewResourceList
PcNewResourceSublist
IFS
FltAllocatePoolAlignedWithTag
FltAllocateContext
WDF
WdfLookasideListCreate
WdfMemoryCreate
WdfDeviceAllocAndQueryProperty
WdfDeviceAllocAndQueryPropertyEx
WdfFdoInitAllocAndQueryProperty
WdfFdoInitAllocAndQueryPropertyEx
WdfIoTargetAllocAndQueryTargetProperty
WdfRegistryQueryMemory

A HLK kódintegritási tesztjeinek használata a memóriaintegritási illesztőprogram kompatibilitásának teszteléséhez

A kapcsolódó rendszerbiztonsági teszttel kapcsolatos további információkért lásd: HyperVisor Code Integrity Readiness Test and Memory integrity and VBS.

A kapcsolódó eszköz alapszintű tesztjével kapcsolatos további információkért lásd: Device.DevFund-tesztek.

Az alábbi táblázat segítségével értelmezze a kimenetet, és határozza meg, hogy milyen illesztőprogram-kódmódosításokra van szükség a különböző memóriaintegritási inkompatibilitások javításához.

Figyelmeztetés Megváltás

Készlettípus végrehajtása

A hívó egy végrehajtható készlettípust adott meg. Végrehajtható memóriát kérő memóriakiosztási függvény meghívása.

Győződjön meg arról, hogy minden készlettípus tartalmaz nem végrehajtható NX-jelzőt.

Lapvédelem végrehajtása

A hívó egy végrehajtható oldalvédelmet adott meg.

Adjon meg egy "nincs végrehajtás" oldalvédelmi maszkot.

Oldalleképezés végrehajtása

A hívó meghatározta a végrehajtható memórialeírók listájának (MDL) leképezését.

Győződjön meg arról, hogy a használt maszk tartalmazza az MdlMappingNoExecute elemet. További információ: MmGetSystemAddressForMdlSafe

Execute-Write szakasz

A kép végrehajtható és írható szakaszt tartalmaz.

Szakaszillesztési hibák

A kép olyan szakaszt tartalmaz, amely nem laphoz igazítva van.

A szakasz igazításának több 0x1000 (PAGE_SIZE) kell lennie. Pl. DRIVER_ALIGNMENT=0x1000

IAT a végrehajtható szakaszban

Az importálási címtábla (IAT) nem lehet végrehajtható memóriaszakasz.

Ez a probléma akkor fordul elő, ha az IAT csak olvasási és végrehajtási (RX) memóriaszakaszban található. Ez azt jelenti, hogy az operációs rendszer nem tud majd írni az IAT-be a megfelelő címek beállításához, ahol a hivatkozott DLL található.

Ennek egyik módja a /MERGE (Szakaszok egyesítése) lehetőség használata a kód csatolásában. Ha például a .rdata (írásvédett inicializált adatok) egyesül a .text adatokkal (végrehajtható kód), akkor lehetséges, hogy az IAT a memória végrehajtható szakaszába kerül.


Nem támogatott áthelyezések

A Windows 10 1507-es és Windows 10-es, 1607-es verziójában a címtérelrendezés véletlenszerűsítése (ASLR) miatt probléma merülhet fel a címek igazításával és a memória áthelyezésével kapcsolatban. Az operációs rendszernek át kell helyeznie azt a címet, ahonnan a hivatkozáskezelő alapértelmezett alapcímét az ASLR által hozzárendelt tényleges helyre állítja. Ez az áthelyezés nem tudja átlépni az oldalhatárt. Vegyünk például egy 64 bites címértéket, amely 0x3FFC eltolásnál kezdődik egy lapon. A cím értéke átnyúlik a következő lapra az eltolási értéknél 0x0003. Az ilyen átfedő áthelyezések nem támogatottak a Windows 10 1703-as verziója előtt.

Ez a helyzet akkor fordulhat elő, ha egy globális strukturális típusú változó inicializálója egy másik globálisra mutató, helytelenül igazított mutatóval rendelkezik, úgy, hogy a kapcsoló nem tudja áthelyezni a változót a folytonos áthelyezés elkerülése érdekében. Az összeállító megpróbálja áthelyezni a változót, de vannak olyan helyzetek, amikor nem tudja ezt megtenni (például nagy, rosszul igazított struktúrákkal vagy nagy méretű, rosszul igazított struktúrák tömbjeivel). Szükség esetén a modulokat a /Gy (COMDAT) beállítással kell összeállítani, hogy a linker a lehető legnagyobb mértékben igazítsa a modul kódját.

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

Vannak más helyzetek is, amelyek az assembler kód használatával kapcsolatosak, ahol ez a probléma szintén előfordulhat.


Illesztőprogram-ellenőrző kódintegritása

Az Illesztőprogram-ellenőrző kódintegritási beállításjelzőjével (0x02000000) engedélyezheti a funkciónak való megfelelést ellenőrző további ellenőrzéseket. Ha ezt a parancssorból szeretné engedélyezni, használja az alábbi parancsot.

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

Ha ezt a beállítást a hitelesítő grafikus felhasználói felület használatával szeretné kiválasztani, válassza az Egyéni beállítások létrehozása (kódfejlesztők számára), a Tovább, majd a Kódintegritási ellenőrzések lehetőséget.

A hitelesítő parancssor/lekérdezés beállítással megjelenítheti az illesztőprogram aktuális hitelesítő adatait.

verifier /query

Lásd még:

Járművezetői biztonsági ellenőrzőlista