Руководство по разработке для анклавов безопасности на основе виртуализации (VBS)
В этом руководстве по разработке описывается, как создавать, подписывать и отлаживать базовый анклав VBS.
Необходимые компоненты
Чтобы приступить к работе с анклавами VBS, необходимо выполнить следующие требования:
- Просмотр и соответствие требованиям устройств в обзоре анклава VBS.
- Просмотр и удовлетворение предварительных требований для разработки в обзоре анклава VBS.
- Рекомендуется установить рабочую нагрузку C++ для разработки классических приложений с помощью установщика Visual Studio. Она установит все необходимые средства, включая пакет SDK для Программного обеспечения Windows.
- Скачайте пример кода из GitHub. Он демонстрирует жизненный цикл анклава VBS, включая способ выполнения вызовов функций в анклав.
- У каждого анклава должно быть хост-приложение. Пример кода содержит решение Visual Studio с двумя проектами — узлом анклава и тестовой анклавом.
Начало работы
Выполнив указанные выше предварительные требования, вы сможете открыть файл решения из примера VbsEnclave в Visual Studio и скомпилировать его. Он создает тестовое приложение вместе с соответствующим анклавом. Однако вы не сможете успешно запустить приложение, пока анклав не будет подписан действительным сертификатом.
В этом руководстве описано, как создать базовый анклав VBS на компьютере разработки. Ниже приведены шаги по созданию анклава VBS:
- Создание библиотеки DLL анклава VBS и соответствующего ведущего приложения
- Компиляция библиотеки DLL и узла
- Подписывай библиотеку DLL анклава VBS
- Отладка анклава VBS
Начнем с понимания жизненного цикла анклава. API анклава вызываются в следующем порядке:
Шаг 1. Написание анклавов VBS
Давайте рассмотрим пример кода и понимаем, как написать приложение, использующее анклав VBS.
Написание узла анклава
Помните, что библиотека DLL анклава VBS — это просто библиотека DLL, поэтому для нее требуется хост-приложение. Ведущее приложение не является ни чем стандартным приложением Windows. Чтобы использовать анклавы VBS, узел должен использовать API анклава Windows из заголовка enclaveapi.h. В том числе windows.h
в хост-приложении будет предоставляться доступ к этим API.
Запись библиотеки DLL для загрузки в тестовый анклав
Ознакомьтесь с примером кода в проекте тестового анклава , чтобы выполнить следующие действия.
В нашем примере анклава мы создадим простой анклава, который XOR входных данных с 0xDADAF00D
и возвращает результат. Давайте разберем, как это сделать:
Начните с включения
winenclave.h
. В примере кода см. следующие сведенияSamples/VbsEnclave/Test enclave/precomp.h
:#include <winenclave.h>
winenclave.h
является центральным файлом включения для анклавов VBS и сам включаетwindows.h
, .ntenclv.h
winenclaveapi.h
Для каждой библиотеки DLL, загруженной в анклава, требуется конфигурация. Эта конфигурация определяется с помощью глобальной
const
переменной с именем__enclave_config
типа IMAGE_ENCLAVE_CONFIG. В примере кода см. следующие сведенияSamples/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 };
Примечание.
На анклаве может быть только один первичный образ. При загрузке нескольких первичных образов один загруженный первый обрабатывается как первичный, а остальные рассматриваются как зависимости. В этом примере нет зависимостей, отличных от библиотек DLL платформы анклава.
Функция
DllMain()
является обязательной и определяет точку входа в анклава. Он вызывается во времяInitializeEnclave()
. В примере кода обратитесь кSamples/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; }
Все функции внутри анклава, вызываемые из ведущего приложения, должны быть экспортированы и иметь тип LPENCLAVE_ROUTINE. Подпись функции выглядит следующим образом:
void* CALLBACK enclaveFunctionName(_In_ void* Context)
В примере кода обратитесь к
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); }
Примечание.
Доступ к функциям, экспортируемым основным образом анклава, можно получить из ведущего приложения.
Затем можно экспортировать функцию с помощью
.DEF
файла. В примере кода обратитесь кSamples/VbsEnclave/Test enclave/vbsenclave.def
. Дополнительные сведения см. в статье "Экспорт из библиотеки DLL с помощью DEF-файлов".
И вот как вы пишете базовую библиотеку DLL анклава VBS.
Шаг 2. Компиляция анклава VBS
Теперь, когда мы написали библиотеку DLL анклава VBS, давайте скомпилируем ее.
Компиляция узла анклава
Компиляция ведущего приложения совпадает с компиляцией любого приложения Windows, но с добавлением onecore.lib
к списку зависимостей при связывании.
Компиляция библиотеки DLL тестового анклава
Прежде чем мы создадим библиотеку DLL тестового анклава, требуются некоторые изменения конфигураций компилятора и компоновщика:
Компоновщик MSVC предоставляет
/ENCLAVE
флаг, который выбирает сведения о конфигурации анклава. Флаг/ENCLAVE
несовместим с добавочным связыванием, поэтому нам нужно задать/INCREMENTAL:NO
.[Только конфигурация отладки]
/EDITANDCONTINUE
несовместим с/INCREMENTAL:NO
, поэтому вместо отладочного формата информации в компиляторе используется/Zi
/ZI
.[Только конфигурация отладки] Для конфигурации базовой проверки среды выполнения необходимо задать значение Default. Проверки ошибок среды выполнения не поддерживаются в анклавах VBS.
Цифровая подпись БИБЛИОТЕКи DLL анклава должна быть проверена во время загрузки и требует установки
/INTEGRITYCHECK
флага в компоновщике.Библиотеки DLL анклава должны быть инструментированы для элемента управления Flow Guard (CFG), для которого мы используем
/GUARD:MIXED
флаг в компоновщике.Анклава имеют собственные версии платформы, запуска, среды выполнения и UCRT libs. Чтобы убедиться, что мы не связываем версии без анклава, используйте
/NODEFAULTLIB
флаг. Затем добавьте правильные libs вAdditionalDependencies
. В примере кода эти библиотеки инкапсулируются в макросе VBS_Enclave_Dependencies . Ниже приведены библиотеки анклава VBS:libcmt.lib
иlibvcruntime.lib
— найден в папкеenclave
с инструментами сборки Visual C++, см. статью c runtime (CRT) и стандартные библиотеки C++ (STL) .lib.files.vertdll.lib
иbcrypt.lib
— найден в папкеum
с библиотеками пакета SDK для Windows.ucrt.lib
— Найден в папкеucrt_enclave
с библиотеками Пакета SDK для Windows.
Примечание.
Другие библиотеки платформы не поддерживаются в анклавах VBS.
В итоге требуются следующие изменения:
Компилятор (только для отладки):
- Формат сведений отладки:
/Zi
- Основные проверки среды выполнения:
Default
Компоновщик:
/ENCLAVE
/NODEFAULTLIBS
+AdditionalDependencies
/INCREMENTAL:NO
/INTEGRITYCHECK
/GUARD:MIXED
Теперь можно скомпилировать библиотеку DLL анклава.
Защита с помощью VEIID
VEIID (служебная программа привязки идентификатора импорта ИД VBS) — это средство в пакете SDK для Windows, которое обновляет таблицы импорта в анклавах VBS с известными идентификаторами для библиотек DLL платформы. Это повышает безопасность анклавов VBS, предотвращая загрузку вредоносных (подписанных) БИБЛИОТЕК DLL с тем же именем, что и одна из библиотек DLL платформы.
В примере кода это выполняется автоматически в качестве события после сборки.
Примечание.
Настоятельно рекомендуется избегать использования собственных библиотек DLL, отличных от основных библиотек DLL, помимо библиотек DLL платформы. Вместо этого сохраните весь код в самой библиотеке DLL анклава.
Шаг 3. Подписывание dll VBS анклава
Для успешной загрузки анклавов VBS необходимо подписать. Подпись анклава содержит сведения о авторе анклава. Он используется для получения идентификатора автора для анклава. Прежде чем подписать анклав для рабочей среды, вы можете протестировать анклав.
Подписывание тестов — local
Для каждого сертификата подписи анклава требуется по крайней мере 3 EKUs:
EKU подписывания кода —
1.3.6.1.5.5.7.3.3
Анклав EKU -
1.3.6.1.4.1.311.76.57.1.15
EKU автора — EKU имеет форму
1.3.6.1.4.1.311.97.X.Y.Z
, гдеX
больше999
.Для тестирования можно использовать любой EKU автора, соответствующий этому шаблону. Для рабочей среды EKU автора будет предоставлен в рамках рабочего сертификата (дополнительные сведения о подписи рабочей среды приведены ниже).
Пример:
1.3.6.1.4.1.311.97.814040577.346743379.4783502.105532346
Если вы хотите подписать библиотеку DLL анклава во время разработки, включите тестовую подпись. С включенной проверкой подписи вы можете создать сертификат, содержащий эти три EKUs, и подписать анклав с ним. Для создания сертификата можно использовать командлет New-SelfSignedCertificate . Обратите внимание, что библиотеки DLL Анклава должны быть хэш-кодами страницы.
Примечание.
После получения сертификата можно автоматизировать процесс подписывания в событии после сборки.
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
С подписанным библиотекой DLL анклава теперь можно загрузить ее в среду, в которой включена тестовая подпись.
Рабочая подпись — доверенный подписывание (прежнее название — подпись кода Azure)
Рабочая подпись анклава предоставляется через профиль сертификата анклава VBS в доверенном подписи. Дополнительные сведения об использовании доверенного подписывания см. в документации.
Доверенный подписывание также позволяет подписать анклав в командной строке. Это выводит готовый к выполнению анклав со знаком при сборке анклава в Visual Studio.
Шаг 4. Отладка анклавов VBS
Как правило, память анклава скрыта от отладчиков и защищена от VTL0. Однако если вы хотите выполнить отладку библиотеки DLL анклава VBS, их можно создать для отладки во время разработки. Анклава — это процесс пользовательского режима VTL1, поэтому его можно отлаживать с помощью отладчика пользовательского режима.
Чтобы сделать анклав отладчиком:
- Конфигурация образа DLL анклава должна разрешить отладку . Это делается путем установки флага IMAGE_ENCLAVE_POLICY_DEBUGGABLE в IMAGE_ENCLAVE_CONFIG.
- Отладка должна быть разрешена во время создания анклава. Это делается путем задания флага ENCLAVE_VBS_FLAG_DEBUG в структуре ENCLAVE_CREATE_VBS_INFO, переданной вызову CreateEnclave.
Чтобы выполнить отладку анклава, выполните приведенные действия.
- Подключите отладчик пользовательского режима к процессу узла анклава.
- Перезагрузите символы анклава после загрузки образа анклава в памяти.
- Задайте точки останова для функций внутри анклава. Отладчик прерывается на вызов анклава.
Кроме того, можно разбить точки останова в пользовательском режиме для CreateEnclave, InitializeEnclave и т. д., что еще раз переходит в соответствующий кодntdll.dll
.
Примечание.
Никогда не используйте отладочные анклава в рабочих средах.
С помощью этого вы можете создать и развернуть первый анклав VBS. Если у вас есть вопросы, обратитесь в службу поддержки разработчиков Windows.