Treiberkompatibilität mit Speicherintegrität und VBS

Arbeitsspeicherintegrität ist ein virtualisierungsbasiertes Sicherheitsfeature (VBS), das in Windows 10, Windows 11 und Windows Server 2016 und höher verfügbar ist. Speicherintegrität und VBS verbessern das Bedrohungsmodell von Windows und bieten einen besseren Schutz vor Schadsoftware, die versucht, den Windows-Kernel auszunutzen. VBS verwendet den Windows-Hypervisor, um eine isolierte virtuelle Umgebung zu erstellen, die zum Vertrauensstamm des Betriebssystems wird, das davon ausgeht, dass der Kernel kompromittiert werden kann. Die Speicherintegrität ist eine wichtige Komponente, die Windows schützt und härtet, indem die Codeintegrität im Kernelmodus in der isolierten virtuellen Umgebung von VBS ausgeführt wird. Die Speicherintegrität schränkt auch Kernelspeicherbelegungen ein, die verwendet werden könnten, um das System zu kompromittieren. So wird sichergestellt, dass Kernelspeicherseiten erst nach dem Bestehen von Codeintegritätsprüfungen innerhalb der sicheren Laufzeitumgebung ausführbare Dateien werden und ausführbare Seiten selbst nie beschreibbar sind.

Hinweis

Die Speicherintegrität wird manchmal auch als hypervisorgeschützte Codeintegrität (Hypervisor-Protected Code Integrity, HVCI) oder durch Hypervisor erzwungene Codeintegrität bezeichnet und wurde ursprünglich als Teil von Device Guard veröffentlicht. Device Guard wird nicht mehr verwendet, außer um die Speicherintegrität und VBS-Einstellungen in Gruppenrichtlinie oder der Windows-Registrierung zu ermitteln.

Die Speicherintegrität ist standardmäßig für sauber Installationen von Windows 10 im S-Modus und Windows 11 auf kompatibler Hardware aktiviert, wie unter Aktivieren der Speicherintegrität beschrieben. Auf anderen Systemen, die die Anforderungen für die automatische Aktivierung der Speicherintegrität nicht erfüllen, können Kunden eine der unter Aktivieren der Speicherintegrität beschriebenen Methoden verwenden.

Anwendungskompatibilität

Obwohl die Kompatibilität mit der Speicherintegrität seit dem Windows 10 Anniversary Update (1607) für alle Treiber erforderlich ist, sind einige Anwendungen und Hardwaregerätetreiber möglicherweise immer noch nicht kompatibel. Diese Inkompatibilität kann zu Fehlern bei Geräten oder Software führen und in seltenen Fällen zu einem Startfehler (Bluescreen) führen. Solche Probleme können auftreten, nachdem der Speicherintegritätsschutz aktiviert wurde oder während des Aktivierungsprozesses selbst. Wenn Sie ein Anwendungsentwickler sind und überprüfen möchten, ob Ihre Treiber und Softwarepakete mit der Speicherintegrität kompatibel sind, führen Sie die folgenden Schritte aus.

Einige Beispiele, bei denen Inkompatibilitäten mit der Speicherintegrität beobachtet wurden, sind:

  • Anti-Cheat-Lösungen mit Spielen
  • Eingabemethoden von Drittanbietern
  • Passwortschutz für Banking von Drittanbietern

Wir haben hart daran gearbeitet, die betroffenen Erfahrungen zu minimieren. Wenn also eine Inkompatibilität für einen startkritischen Treiber besteht, wird der Speicherintegritätsschutz automatisch deaktiviert, wenn er automatisch aktiviert wurde. Wenn Inkompatibilitäten mit anderen Apps auftreten, empfehlen wir Ihnen, nach Updates für die jeweilige App und Version zu suchen, die das Problem auftritt, bevor Sie den Speicherintegritätsschutz deaktivieren.

So erstellen Sie kompatible Treiber

Da Speicherseiten und -abschnitte niemals beschreibbar und ausführbar sein können, ist der erste Schritt, für eine klare Trennung von Daten und Code zu sorgen und nicht zu versuchen, Codepages direkt zu modifizieren.

  • Melden Sie sich standardmäßig bei NX an
  • Verwenden Sie NX-APIs/-Flags für die Speicherzuweisung – NonPagedPoolNx
  • Verwenden Sie keine Abschnitte, die sowohl beschreibbar als auch ausführbar sind
  • Versuchen Sie nicht, den ausführbaren Systemspeicher direkt zu ändern
  • Verwenden Sie keinen dynamischen Code im Kernel
  • Laden Sie Datendateien nicht als ausführbar
  • Abschnittsausrichtung muss ein Vielfaches von 0x1000 (PAGE_SIZE) sein. z. B. DRIVER_ALIGNMENT=0x1000

Verwenden Sie die neueste Version von WDK und Visual Studio , um kompatible Treiber bei Verwendung von Standardeinstellungen zu erstellen.

Überprüfen der Treiberkompatibilität mit der Speicherintegrität

Es gibt drei Schritte zum Überprüfen der Treiberkompatibilität:

  1. Verwenden Sie driver verifier (siehe Abschnitt unten), mit aktivierten Codeintegritätskompatibilitätsprüfungen.
  2. Testen Sie den Treiber auf einem System mit aktivierter Speicherintegrität.
  3. Führen Sie den HyperVisor Code Integrity Readiness Test im Windows HLK aus.

Driver Verifier-Kompatibilitätsprüfungen

Driver Verifier verfügt über ein Codeintegritätsoptionsflag (0x02000000), um zusätzliche Überprüfungen zu aktivieren, die die Konformität mit der Speicherintegrität überprüfen. Verwenden Sie den folgenden Befehl, um dies über die Befehlszeile zu aktivieren:

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

Um diese Option auszuwählen, wenn Sie die Verifier-GUI verwenden, wählen Sie Benutzerdefinierte Einstellungen erstellen (für Code-Entwickler), wählen Sie Weiter und wählen Sie dann Code-Integritätsprüfungen.

Für den Erfolg gibt es keine Ausgabe. Unten sehen Sie ein Beispiel für einen Fehlerausgang.

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

Testen des Treibers mit aktivierter Speicherintegrität

Obwohl Windows die Speicherintegrität für die meisten Systeme standardmäßig aktiviert, gibt es mehrere Gründe, die dies verhindern können. Informationen zum Aktivieren der Speicherintegrität finden Sie unter Aktivieren der Speicherintegrität. Testen Sie dann die Funktionalität Ihres Treibers. Achten Sie darauf, alle Codepfade in Ihrem Treiber auszuführen, um sicherzustellen, dass Ihr Treiber zur Laufzeit keine Vorgänge ausführt, die mit der Speicherintegrität nicht kompatibel sind.

HLK-Tests (Desktop und Server)

Der HLK-Test hyperVisor Code Integrity Readiness Test muss erfolgreich sein, damit Treiber für die Microsoft-Signatur genehmigt werden. Speicherintegritätskompatible Treiber sind sowohl für die Desktop- als auch für die Serveredition erforderlich. Der HLK-Test ist ein grundlegender Test, der geschrieben wurde, um sicherzustellen, dass speicherintegritätskompatible Treiber ordnungsgemäß geladen und vom Betriebssystem ausgeführt werden.

Obwohl das einfache Bestehen des HLK-Tests für eine Microsoft-Signatur für den Treiber ausreichend ist, empfehlen wir dringend gründliche Funktionstests mit aktivierter Speicherintegrität. Beispielsweise kann es zu falsch codierten Speicherbelegungen kommen, die den NX-Schutz verletzen und Fehler verursachen, die vom Test nicht abgefangen werden. Der Treiberautor sollte den Treiber gründlich testen, während die Speicherintegrität aktiviert bleibt.

Während der Treiberentwicklung und während des HLK-Tests muss die Speicherintegrität möglicherweise deaktiviert werden, da sie das Laden des Treibers verhindern kann.

Der HLK Hypervisor Code Integrity Readiness Test ist als Teil des Windows Server Assurance AQ erforderlich, und die Flags zum Aktivieren von Codeintegritätsprüfungen werden auch festgelegt, während die Treiberüberprüfung während anderer HLK-Tests aktiviert wird.

Häufig gestellte Fragen

Was ist mit vorhandenen Treibern? Muss ich diese Treiber neu erstellen, damit sie mit Windows 10 funktionieren?

Das ist unterschiedlich. Viele Treiber werden bereits kompatibel sein. Wenn Sie Standardeinstellungen mit den alten Versionen von WDK und Visual Studio verwenden, besteht ein bekanntes Problem darin, dass der INIT-Abschnitt als RWX gekennzeichnet ist. In Windows 10 wird das W jedoch automatisch entfernt. Wenn dies also das einzige Problem ist, ist der Treiber kompatibel.

Gewusst wie überprüfen, ob die Speicherintegrität aktiviert ist?

Die einfachste Methode besteht darin, die Systeminformations-App (msinfo32) auszuführen. Suchen Sie nach der folgenden Zeile: "Virtualisierungsbasierte Sicherheitsdienste werden ausgeführt". Es sollte Folgendes melden: „Hypervisor erzwungene Codeintegrität“. Es gibt auch eine WMI-Schnittstelle für die Überprüfung mithilfe von Verwaltungstools. Weitere Informationen finden Sie unter Überprüfen aktivierter VBS- und Speicherintegritätsfeatures.

Die Speicherintegrität kann auch in der Windows-Sicherheit-App unter Einstellungen>Updatesicherheit &>Windows-Sicherheit>Gerätesicherheit>Details zur>Speicherintegrität überprüft werden. Weitere Informationen finden Sie unter KB4096339.

Kann ich überprüfen, ob die Speicherintegrität programmgesteuert über den Kernel aktiviert ist, um das Treiberverhalten zu ändern?

Ja, Sie können NtQuerySystemInformation verwenden: https://msdn.microsoft.com/library/windows/desktop/ms724509(v=vs.85).aspx

Die SYSTEM_CODEINTEGRITY_INFORMATION-Struktur verfügt über einen 0x400-Wert, der angibt, dass die Speicherintegrität aktiviert ist.

Wie behebe ich Kompatibilitätsprobleme?

Zusätzlich zur doppelten Überprüfung, dass keine W+X-Seiten vorhanden sind und die Treiberabschnitte wie oben erwähnt korrekt ausgerichtet sind, ist das wahrscheinlichste Problem eine falsche Speicherzuweisung. Informationen zu den Warnungen zur Codeanalyse im Zusammenhang mit der ausgegebenen Speicherzuweisung finden Sie auf MSDN auf der folgenden Seite:

Codeanalyse für Treiberwarnungen

Die folgenden MSDN-Links zeigen einige Beispiele für häufig verwendete APIs, die dazu führen, dass ausführbarer Speicher zugewiesen wird, zusammen mit einigen Beispielkorrekturen:

Verwenden Sie die folgende Tabelle, um die Ausgabe zu interpretieren, um festzustellen, welche Treibercodeänderungen erforderlich sind, um die verschiedenen Typen von HVCI-Inkompatibilitäten zu beheben.

Warnung Lösung
Ausführen des Pooltyps Der Aufrufer hat einen ausführbaren Pooltyp angegeben. Aufrufen einer Speicherzuweisungsfunktion, die ausführbaren Speicher anfordert. Stellen Sie sicher, dass alle Pool-Typen ein nicht ausführbares NX-Flag enthalten.
Seitenschutz ausführen Der Aufrufer hat einen ausführbaren Seitenschutz angegeben. Geben Sie eine Seitenschutzmaske "keine Ausführung" an.
Seitenzuordnung ausführen Der Aufrufer hat eine MDL-Zuordnung (Executable Memory Descriptor List) angegeben. Stellen Sie sicher, dass die verwendete Maske MdlMappingNoExecute enthält. Weitere Informationen finden Sie unter MmGetSystemAddressForMdlSafe
Execute-Write-Abschnitt Das Image enthält einen ausführbaren und einen beschreibbaren Abschnitt.
Abschnittsausrichtungsfehler Das Bild enthält einen Abschnitt, der nicht seitenausgerichtet ist. Abschnittsausrichtung muss ein Vielfaches von 0x1000 (PAGE_SIZE) sein. Z.B. DRIVER_ALIGNMENT=0x1000
Nicht unterstützte Relocs In Windows 10, Version 1507 bis Version 1607, kann aufgrund der Verwendung von Address Space Layout Randomization (ASLR) ein Problem mit der Adressausrichtung und Speicherverschiebung auftreten. Das Betriebssystem muss die Adresse, von der der Linker seine standardmäßige Basisadresse festgelegt hat, an den tatsächlichen Speicherort verschieben, den ASLR zugewiesen hat. Diese Verschiebung kann eine Seitengrenze nicht überschreiten. Betrachten Sie beispielsweise einen 64-Bit-Adresswert, der mit offset 0x3FFC auf einer Seite beginnt. Der Adresswert überlappen sich mit der nächsten Seite beim Offset 0x0003. Diese Art überlappender Verlagerungen wird vor Windows 10 Version 1703 nicht unterstützt.

Diese Situation kann auftreten, wenn ein globaler Strukturtypvariablen-Initialisierer einen falsch ausgerichteten Zeiger auf einen anderen globalen Zeiger aufweist, der so ausgelegt ist, dass der Linker die Variable nicht verschieben kann, um die Verlagerung von Verschiebungen zu vermeiden. Der Linker versucht, die Variable zu verschieben, aber es gibt Situationen, in denen dies möglicherweise nicht möglich ist, z. B. mit großen falsch ausgerichteten Strukturen oder großen Arrays falsch ausgerichteter Strukturen. Gegebenenfalls sollten Module mit der Option /Gy (COMDAT) zusammengestellt werden, damit der Linker den Modulcode so weit wie möglich ausrichten kann.

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

Es gibt andere Situationen, die die Verwendung von Assemblercode betreffen, in denen dieses Problem ebenfalls auftreten kann.

IAT im ausführbaren Abschnitt Die Importadressentabelle (IAT) sollte kein ausführbarer Speicherabschnitt sein.

Dieses Problem tritt auf, wenn sich das IAT in einem Nur-Lese- und Ausführungsbereich (RX) befindet. Dies bedeutet, dass das Betriebssystem nicht in die IAT schreiben kann, um die richtigen Adressen für den Speicherort der referenzierten DLL festzulegen.

Eine Möglichkeit, wie dies auftreten kann, ist die Verwendung der Option /MERGE (Abschnitte kombinieren) in Codeverknüpfung. Wenn z. B. Rdata (Schreibgeschützte initialisierte Daten) mit TEXT-Daten (ausführbarer Code) zusammengeführt wird, ist es möglich, dass das IAT möglicherweise in einem ausführbaren Speicherabschnitt endet.

Welche APIs sind potenziell betroffen?

Die folgende Liste der APIs, die nicht für die Systemverwendung reserviert sind, können sich auf folgende Auswirkungen auswirken:

   
API-Name Beschreibung
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
IMiniportWaveCyclic::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