Entwicklungsleitfaden für VBS-Enklaven (virtualisierungsbasierte Sicherheit)
In diesem Entwicklungsleitfaden wird beschrieben, wie Sie eine einfache VBS-Enklave erstellen, unterschreiben und debugen.
Voraussetzungen
Um mit VBS-Enklaven zu beginnen, müssen Sie die folgenden Anforderungen erfüllen:
- Anzeigen und Erfüllen der Geräteanforderungen in der VBS-Enklavenübersicht.
- Anzeigen und Erfüllen von Entwicklungsvoraussetzungen in der Übersicht über VBS-Enklaven.
- Es wird empfohlen, die Desktopentwicklung mit C++-Workload über das Visual Studio-Installationsprogramm zu installieren. Es installiert alle erforderlichen Tools, einschließlich des Windows Software Development Kit (SDK).
- Laden Sie den Beispielcode von GitHub herunter. Es veranschaulicht den Lebenszyklus einer VBS-Enklave, einschließlich der Art, wie Funktionsaufrufe in die Enklave ausgeführt werden.
- Jede Enklave muss über eine Host-App verfügen. Der Beispielcode enthält eine Visual Studio-Projektmappe mit zwei Projekten – dem Enklaven-Host und der Test-Enklave.
Erste Schritte
Nachdem Sie die oben genannten Voraussetzungen erfüllt haben, sollten Sie die Lösungsdatei aus dem VbsEnklave-Beispiel in Visual Studio öffnen und kompilieren können. Es erstellt eine Testanwendung zusammen mit der entsprechenden Enklave. Sie können die Anwendung jedoch erst erfolgreich ausführen, wenn die Enklave mit einem gültigen Zertifikat signiert ist.
In dieser Anleitung wird beschrieben, wie Sie eine einfache VBS-Enklave auf Ihrem Entwicklungscomputer erstellen. Die Schritte zum Erstellen einer VBS-Enklave sind:
- Schreiben einer VBS-Enklaven-DLL und einer entsprechenden Hostanwendung
- Kompilieren der DLL und des Hosts
- Signieren der VBS-Enklaven-DLL
- Debuggen der VBS-Enklave
Beginnen wir damit, den Lebenszyklus einer Enklave zu verstehen. Die Enklaven-APIs werden in der folgenden Reihenfolge aufgerufen:
Schritt 1: Schreiben von VBS-Enklaven
Sehen wir uns den Beispielcode an, um zu verstehen, wie eine Anwendung geschrieben wird, die eine VBS-Enklave verwendet.
Schreiben des Enklaven-Hosts
Denken Sie daran, dass eine VBS-Enklaven-DLL einfach eine DLL ist und daher eine Hostanwendung erfordert. Die Hostanwendung ist nichts anderes als eine Windows-Standardanwendung. Um VBS-Enklaven zu verwenden, muss der Host Windows-Enklaven-APIs aus dem enclaveapi.h-Header verwenden. Das Einschließen windows.h
in Ihre Hostanwendung bietet Zugriff auf diese APIs.
Schreiben der DLL zum Laden in eine Testenklave
Im Test-Enklaven-Projekt finden Sie Beispielcode, der zusammen mit den nachstehenden Schritten ausgeführt werden soll.
In unserem Enklaven-Beispiel erstellen wir eine einfache Enklave, mit der XORs die Eingabe mit 0xDADAF00D
verwendet und das Ergebnis zurückgibt. Gehen wir wie folgt vor:
Beginnen Sie mit dem Einschließen von
winenclave.h
. Beziehen Sie sich im Beispielcode aufSamples/VbsEnclave/Test enclave/precomp.h
:#include <winenclave.h>
winenclave.h
ist die zentrale einschließende Datei für VBS-Enklaven und enthält selbstwindows.h
,ntenclv.h
undwinenclaveapi.h
.Jede in einer Enklave geladene DLL erfordert eine Konfiguration. Diese Konfiguration wird mithilfe einer globalen
const
-Variablen mit dem Namen IMAGE_ENCLAVE_CONFIG der Art__enclave_config
definiert. Beziehen Sie sich im Beispielcode aufSamples/VbsEnclave/Test enclave/enclave.c
:const IMAGE_ENCLAVE_CONFIG __enclave_config = { sizeof(IMAGE_ENCLAVE_CONFIG), IMAGE_ENCLAVE_MINIMUM_CONFIG_SIZE, IMAGE_ENCLAVE_POLICY_DEBUGGABLE, // DO NOT SHIP DEBUGGABLE ENCLAVES TO PRODUCTION 0, 0, 0, { 0xFE, 0xFE }, // family id { 0x01, 0x01 }, // image id 0, // version 0, // SVN 0x10000000, // size 16, // number of threads IMAGE_ENCLAVE_FLAG_PRIMARY_IMAGE };
Hinweis
Pro Enklave kann nur ein primäres Bild vorhanden sein. Wenn Sie mehrere primäre Bilder laden, wird das geladene zuerst als primär behandelt, und der Rest wird als Abhängigkeiten behandelt. In diesem Beispiel gibt es keine Abhängigkeiten außer den Enklaven-Plattform-DLLs.
Die
DllMain()
-Funktion ist obligatorisch und definiert den Einstiegspunkt in die Enklave. Sie wird währendInitializeEnclave()
aufgerufen. Beziehen Sie sich im Beispielcode aufSamples/VbsEnclave/Test enclave/enclave.c
.BOOL DllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD dwReason, _In_ LPVOID lpvReserved ) { UNREFERENCED_PARAMETER(hinstDLL); UNREFERENCED_PARAMETER(lpvReserved); if (dwReason == DLL_PROCESS_ATTACH) { InitialCookie = 0xDADAF00D; } return TRUE; }
Alle Funktionen innerhalb der Enklave, die von der Hostanwendung aufgerufen werden, müssen exportiert und vom Typ LPENCLAVE_ROUTINE sein. Die Signatur der Funktion sieht folgendermaßen aus:
void* CALLBACK enclaveFunctionName(_In_ void* Context)
Beziehen Sie sich im Beispielcode auf
Samples/VbsEnclave/Test enclave/enclave.c
.void* CALLBACK CallEnclaveTest( _In_ void* Context ) { WCHAR String[32]; swprintf_s(String, ARRAYSIZE(String), L"%s\n", L"CallEnclaveTest started"); OutputDebugStringW(String); return (void*)((ULONG_PTR)(Context) ^ InitialCookie); }
Hinweis
Nur auf die vom primären Enklaven-Bild exportierten Funktionen kann über die Hostanwendung zugegriffen werden.
Anschließend können Sie die Funktion mithilfe einer
.DEF
-Datei exportieren. Beziehen Sie sich im Beispielcode aufSamples/VbsEnclave/Test enclave/vbsenclave.def
. Weitere Informationen finden Sie unter Exportieren aus einer DLL mithilfe von DEF-Dateien.
So wird eine einfache VBS-Enclave-DLL geschrieben.
Schritt 2: Kompilieren von VBS-Enklaven
Nachdem wir unsere VBS-Enclave-DLL geschrieben haben, kompilieren wir sie.
Kompilieren des Enklaven-Hosts
Das Kompilieren der Host-App ist identisch mit der Kompilierung einer beliebigen Windows-Anwendung, aber mit dem Hinzufügen von onecore.lib
zur Liste der Abhängigkeiten beim Verknüpfen.
Kompilieren der Test-Enclave-DLL
Bevor wir die Test-Enclave-DLL erstellen können, sind einige Änderungen an den Compiler- und Linker-Konfigurationen erforderlich:
Der MSVC-Linker stellt ein
/ENCLAVE
-Flag bereit, mit dem die Enklaven-Konfigurationsdetails aufgenommen werden. Das/ENCLAVE
-Flag ist nicht mit inkrementellen Verknüpfungen kompatibel, daher müssen wir/INCREMENTAL:NO
festlegen.[Debug config only]
/EDITANDCONTINUE
ist nicht mit/INCREMENTAL:NO
kompatibel. Daher verwenden wir/Zi
anstelle von/ZI
für Debug Information Format im Compiler.[Nur Debug-Konfiguration] Die Konfiguration für grundlegende Runtime-Überprüfungen muss auf Standard festgelegt werden. Runtime-Fehlerüberprüfung werden in VBS-Enklaven nicht unterstützt.
Die digitale Signatur einer Enclave-DLL muss zur Ladezeit überprüft werden und erfordert das Festlegen des
/INTEGRITYCHECK
-Flags im Linker.Enklaven-DLLs müssen für Ablaufsteuerungsschutz (CFG) instrumentiert werden, für die wir das
/GUARD:MIXED
-Flag im Linker verwenden.Enklaven verfügen über eigene Versionen von Plattform-, Startup-, Runtime- und UCRT-Bibliotheken. Um sicherzustellen, dass die Nicht-Enklaven-Versionen nicht verknüpft werden, verwenden Sie das
/NODEFAULTLIB
-Flag. Fügen Sie anschließend die richtigen Bibliotheken unterAdditionalDependencies
hinzu. Im Beispielcode werden diese Bibliotheken unter dem VBS_Enclave_Dependencies-Makro gekapselt. Im Folgenden sind die VBS-Enklaven-Bibliotheken aufgeführt:libcmt.lib
undlibvcruntime.lib
: Zu finden im Ordnerenclave
mit den Visual C++ Build-Tools, siehe C-Laufzeit (CRT) und C++ Standardbibliothek (STL) .lib-Dateien.vertdll.lib
undbcrypt.lib
: Zu finden im Ordnerum
mit den Windows SDK-Bibliotheken.ucrt.lib
: Zu finden im Ordnerucrt_enclave
mit den Windows SDK-Bibliotheken.
Hinweis
In VBS-Enklaven werden keine anderen Plattformbibliotheken unterstützt.
Zusammenfassend sind die folgenden Änderungen erforderlich:
Compiler (nur Debug-Konfiguration):
- Debuginformationsformat
/Zi
- Grundlegende Laufzeitüberprüfungen
Default
Linker:
/ENCLAVE
/NODEFAULTLIBS
+AdditionalDependencies
/INCREMENTAL:NO
/INTEGRITYCHECK
/GUARD:MIXED
Sie können jetzt die Enklaven-DLL kompilieren.
Sichern mit VEIID
VEIID (das VBS-Enklaven Import-ID Bindunggsdienstprogramm) ist ein Tool im Windows SDK, das die Importtabellen in einer VBS-Enklave mit bekannten IDs für Plattform-DLLs aktualisiert. Dadurch wird die Sicherheit von VBS-Enklaven verbessert, indem verhindert wird, dass eine bösartige (signierte) DLL mit demselben Namen wie eine der Plattform-DLLs geladen wird.
Im Beispielcode erfolgt dies automatisch als Post-Buildereignis.
Hinweis
Es wird nachdrücklich empfohlen, die Verwendung eigener nicht primärer DLLs über die Plattform-DLLs hinaus zu vermeiden. Behalten Sie stattdessen den gesamten Code innerhalb der Enklaven-DLL selbst bei.
Schritt 3: Signieren von VBS-Enclave-DLLs
VBS-Enklaven müssen signiert werden, um erfolgreich geladen zu werden. Die Signatur auf einer Enklave enthält Informationen über den Enklaven-Autor. Dies wird verwendet, um die Autor-ID für eine Enklave abzuleiten. Sie können Ihre Enklave testen, bevor Sie sie für die Produktion signieren.
Testsignatur – Lokal
Jedes Enklaven-Signaturzertifikat erfordert mindestens 3 EKUs:
Codesignatur-EKU -
1.3.6.1.5.5.7.3.3
Enklaven-EKU -
1.3.6.1.4.1.311.76.57.1.15
Autor-EKU - Die EKU ist von der Art
1.3.6.1.4.1.311.97.X.Y.Z
, wobeiX
größer als999
ist.Für Tests können Sie eine beliebige Autor-EKU verwenden, die diesem Muster entspricht. Für die Produktion wird eine Autoren-EKU als Teil des Produktionszertifikats bereitgestellt (weitere Details zur Produktionssignierung finden Sie unten).
Beispiel:
1.3.6.1.4.1.311.97.814040577.346743379.4783502.105532346
Wenn Sie ihre Enklaven-DLL während der Entwicklung signieren möchten, aktivieren Sie die Testsignierung. Mit aktivierter Testsignatur können Sie ein Zertifikat erstellen, das diese drei EKUs enthält, und Ihre Enklave damit signieren. Verwenden Sie das Cmdlet New-SelfSignedCertificate, um ein Zertifikat zu erstellen. Beachten Sie, dass Enklaven-DLLs als Seiten-Hash signiert sein müssen.
Hinweis
Sobald Sie über ein Zertifikat verfügen, können Sie den Anmeldevorgang im Post-Buildereignis automatisieren.
New-SelfSignedCertificate -CertStoreLocation Cert:\\CurrentUser\\My -DnsName "MyTestEnclaveCert" -KeyUsage DigitalSignature -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256 -TextExtension "2.5.29.37={text}1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.76.57.1.15,1.3.6.1.4.1.311.97.814040577.346743379.4783502.105532346"
signtool sign /ph /fd SHA256 /n "MyTestEnclaveCert" vbsenclave.dll
Mit der signierten Enklave-DLL können Sie sie jetzt in einer Umgebung laden, in der die Testsignatur aktiviert ist.
Produktionssignierung – Trusted Signing (früher Azure Code Signing)
Die Produktionssignatur für Enklaven wird über das VBS-Enklavenzertifikatprofil in Trusted Signing bereitgestellt. Ausführliche Informationen zur Verwendung von Trusted Signing finden Sie in der Dokumentation.
Mit Trusted Signing können Sie auch Ihre Enklave an der Befehlszeile signieren. Dadurch wird eine fertige, signierte Enklave ausgegeben, wenn Sie Ihre Enklave in Visual Studio erstellen.
Schritt 4: Debuggen von VBS-Enklaven
Normalerweise wird der Speicher einer Enklaven vor Debuggern ausgeblendet und vor VTL0 geschützt. Wenn Sie jedoch Ihre VBS-Enclave-DLL debuggen möchten, können Sie sie erstellen, um sie während der Entwicklung zu debuggen. Enklaven sind ein VTL1-Benutzermodusprozess und können daher mit einem Benutzermodus-Debugger gedebuggt werden.
So können Sie Ihre Enklave debuggierbar machen:
- Die Enclave-DLL-Image-Konfiguration muss das Debugging zulassen – Setzen Sie dazu das IMAGE_ENCLAVE_POLICY_DEBUGGABLE-Flag in IMAGE_ENCLAVE_CONFIG.
- Das Debuggen muss während der Erstellung von Enklaven zulässig sein – Dies erfolgt durch Festlegen des Flags ENCLAVE_VBS_FLAG_DEBUG in der Struktur ENCLAVE_CREATE_VBS_INFO, die an den CreateEnclave-Aufruf übergeben wird.
So debuggen Sie Ihre Enklave:
- Fügen Sie den Benutzermodus-Debugger an den Enklaven-Hostprozess an.
- Laden Sie die Enklaven-Symbole neu, nachdem der Hostprozess das Enklaven-Bild im Speicher geladen hat.
- Legen Sie Haltepunkte für die Funktionen innerhalb der Enklave fest. Der Debugger wird in einen Enklaven-Aufruf eingegliedert.
Sie können auch die Haltepunkte für den Benutzermodus für CreateEnclave, InitializeEnklave usw. unterbrechen, die weiter in den entsprechenden Code in ntdll.dll
gelangen.
Hinweis
Verwenden Sie nie debuggierbare Enklaven in Produktionsumgebungen.
Damit können Sie jetzt Ihre erste VBS-Enklave erstellen und bereitstellen. Bei Fragen wenden Sie sich bitte an Windows Developer Support.