Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tej sekcji opisano sposób implementowania kodu zgodnego z integralnością pamięci.
Uwaga
Integralność pamięci jest czasami określana jako integralność kodu chronionego przez hypervisor (HVCI) lub jako integralność kodu wymuszana przez hypervisori została pierwotnie wydana jako część Device Guard. Funkcja Device Guard nie jest już używana z wyjątkiem lokalizacji integralności pamięci i ustawień VBS w zasadach grupy lub rejestrze systemu Windows.
Aby zaimplementować zgodny kod, upewnij się, że kod sterownika wykonuje następujące czynności:
- Domyślnie włącza NX
- Używa interfejsów API NX i flag do alokacji pamięci (NonPagedPoolNx)
- Nie używa sekcji, które są zarówno zapisywalne, jak i wykonywalne
- Nie próbuje bezpośrednio modyfikować pamięci systemu wykonywalnego
- Nie używa kodu dynamicznego w jądrze
- Nie ładuje plików danych jako pliku wykonywalnego
- Wyrównanie sekcji jest wielokrotnością 0x1000 (PAGE_SIZE). Np. DRIVER_ALIGNMENT=0x1000
Następująca lista identyfikatorów DDI, które nie są zarezerwowane do użytku systemowego, może być dotknięta.
Testowanie zgodności sterowników integralności pamięci za pomocą testów integralności kodu w HLK
Aby uzyskać więcej informacji na temat testu zabezpieczeń dotyczącego podstawowych zasad systemu, zobacz Test gotowości integralności kodu HyperVisor i integralność pamięci oraz VBS.
Aby uzyskać więcej informacji na temat powiązanego testu podstawowych funkcji urządzenia, zobacz Testy Device.DevFund.
Poniższa tabela służy do interpretowania danych wyjściowych i określania, jakie zmiany kodu sterownika są potrzebne do naprawienia różnych typów niezgodności integralności pamięci.
| Ostrzeżenie | Odkupienie |
Wykonywanie typu puli |
Obiekt wywołujący określił typ puli wykonywalnych. Wywoływanie funkcji przydzielania pamięci, która żąda pamięci wykonywalnej. Upewnij się, że wszystkie typy puli zawierają nie wykonywalną flagę NX. |
Wykonywanie ochrony strony |
Obiekt wywołujący określił ochronę strony wykonywalnych. Określ maskę ochrony strony "no execute". |
Wykonywanie mapowania stron |
Wywołujący określił mapowanie listy deskryptora pamięci wykonywalnej (MDL). Upewnij się, że używana maska zawiera MdlMappingNoExecute. Aby uzyskać więcej informacji, zobacz MmGetSystemAddressForMdlSafe |
Sekcja Execute-Write |
Plik obrazu zawiera sekcję wykonywalną i zapisywalną. |
Błędy wyrównania sekcji |
Obraz zawiera sekcję, która nie jest wyrównana do strony. Wyrównanie sekcji musi być wielokrotną 0x1000 (PAGE_SIZE). Np. DRIVER_ALIGNMENT=0x1000 |
IAT w sekcji wykonywalnego pliku |
Tabela adresów importu (IAT) nie powinna być sekcją wykonywalną pamięci. Ten problem występuje, gdy IAT znajduje się w sekcji pamięci przeznaczonej wyłącznie do odczytu i wykonywania (RX). Oznacza to, że system operacyjny nie będzie mógł zapisywać danych w funkcji IAT w celu ustawienia poprawnych adresów, dla których odwołuje się biblioteka DLL. Jednym ze sposobów, w jaki może się to zdarzyć, jest użycie opcji /MERGE (Połącz sekcje) w łączeniu kodu. Jeśli na przykład plik rdata (dane inicjowane tylko do odczytu) jest scalany z danymi tekstowymi (kod wykonywalny), możliwe, że dane IAT mogą znajdować się w sekcji wykonywalnej pamięci. |
Nieobsługiwane relokacje
W systemie Windows 10 w wersji 1507–Windows 10 w wersji 1607 ze względu na użycie losowego układu przestrzeni adresowej (ASLR) może wystąpić problem z wyrównaniem adresów i relokacją pamięci. System operacyjny musi przenieść adres z miejsca, gdzie linker ustawił domyślny adres podstawowy, do rzeczywistej lokalizacji przypisanej przez metodę losowego rozmieszczania przestrzeni adresowej (ASLR). Ta relokacja nie może przekraczać granicy strony. Rozważmy na przykład 64-bitową wartość adresu rozpoczynającą się od przesunięcia 0x3FFC na stronie. Wartość adresu nakłada się na następną stronę z przesunięciem 0x0003. Ten typ nakładających się relokacji nie jest obsługiwany przed systemem Windows 10 wersja 1703.
Taka sytuacja może wystąpić, gdy inicjalizator zmiennej typu strukturalnego ma niewyrównany wskaźnik do innej globalnej zmiennej, określony w taki sposób, że linker nie może przenieść zmiennej, aby uniknąć przekraczającej relokacji. Linker spróbuje przenieść zmienną, ale istnieją sytuacje, w których może nie być w stanie tego zrobić (na przykład w przypadku dużych niespasowanych struktur lub dużych tablic niespasowanych struktur). W razie potrzeby, moduły powinny być montowane przy użyciu opcji /Gy (COMDAT), aby umożliwić linkerowi jak największe wyrównanie kodu modułu.
#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
};
Istnieją inne sytuacje związane z użyciem kodu asemblera, w których ten problem może również wystąpić.
Integralność kodu weryfikatora sterowników
Użyj flagi opcji integralności kodu weryfikatora sterowników (0x02000000), aby włączyć dodatkowe kontrole sprawdzające zgodność z tą funkcją. Aby włączyć tę funkcję z poziomu wiersza polecenia, użyj następującego polecenia.
verifier.exe /flags 0x02000000 /driver <driver.sys>
Aby wybrać tę opcję, jeśli używasz graficznego interfejsu użytkownika weryfikatora, wybierz pozycję Utwórz ustawienia niestandardowe (dla deweloperów kodu), wybierz przycisk Dalej, a następnie wybierz pozycję Sprawdzanie integralności kodu.
Możesz użyć opcji wiersza polecenia /query weryfikatora, aby wyświetlić bieżące informacje weryfikatora sterownika.
verifier /query