Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tato část popisuje, jak implementovat kód kompatibilní s integritou paměti.
Poznámka:
Integrita paměti se někdy označuje jako hypervisorem chráněná integrita kódu (HVCI) nebo hypervisorem vynucená integrita kódua původně byla uvedena jako součást Device Guard. Device Guard se už nepoužívá s výjimkou vyhledání integrity paměti a nastavení VBS v zásadách skupiny nebo registru Windows.
Pokud chcete implementovat kompatibilní kód, ujistěte se, že kód ovladače provede následující:
- NX je ve výchozím nastavení povolen.
- Používá NX API a příznaky pro přidělení paměti (NonPagedPoolNx).
- Nepoužívá oddíly, které jsou zapisovatelné i spustitelné.
- Nepokoušá se přímo upravit paměť spustitelného systému.
- Nepoužívá dynamický kód v jádru.
- Nenačítá datové soubory jako spustitelné soubory.
- Zarovnání oddílu je násobkem 0x1000 (PAGE_SIZE). Např. DRIVER_ALIGNMENT=0x1000
Může to mít vliv na následující seznam DDI, které nejsou vyhrazené pro použití systému:
Použití testů integrity kódu v HLK k otestování kompatibility ovladače integrity paměti
Další informace o základním testu bezpečnosti systému naleznete viz HyperVisor Code Integrity Readiness Test a Integrita paměti a VBS.
Další informace o základním testu souvisejícím se zařízením naleznete v tématu Device.DevFund testy.
Pomocí následující tabulky interpretujte výstup a zjistěte, jaké změny kódu ovladače jsou potřeba k opravě různých typů nekompatibility integrity paměti.
| Upozornění | Vykoupení |
Provedení typu fondu |
Volající zadal typ spustitelného fondu. Volání funkce přidělování paměti, která vyžaduje spustitelné paměti. Ujistěte se, že všechny typy fondů obsahují příznak NX, který není spustitelný. |
Spustit ochranu stránky |
Volající zadal ochranu pro spustitelnou stránku. Zadejte masku ochrany stránky s nastavením zákazu provádění. |
Spustit mapování stránek |
Volající zadal mapování seznamu popisů spustitelné paměti (MDL). Ujistěte se, že použitá maska obsahuje MdlMappingNoExecute. Další informace najdete v tématu MmGetSystemAddressForMdlSafe |
oddíl Execute-Write |
Soubor obsahuje spustitelnou a zapisovatelnou sekci. |
Selhání zarovnání sekcí |
Obrázek obsahuje část, která není zarovnaná se stránkou. Zarovnání sekce musí být násobkem 0x1000 (PAGE_SIZE). Např. DRIVER_ALIGNMENT=0x1000 |
IAT v spustitelné sekci |
Tabulka adres importu (IAT) by neměla být spustitelná část paměti. K tomuto problému dochází, když je IAT umístěna v části paměti, která je určena pouze pro čtení a spuštění (RX). To znamená, že operační systém nebude moct zapisovat do IAT, aby nastavil správné adresy pro odkazovanou knihovnu DLL. Jedním ze způsobů, jak k tomu může dojít, je použití možnosti /MERGE (Kombinovat oddíly) v propojení kódu. Pokud je například .rdata (inicializovaná data jen pro čtení) sloučena s daty .text (spustitelný kód), je možné, že IAT může skončit ve spustitelné části paměti. |
Nepodporované relokace
Ve Windows 10 verze 1507 až Windows 10 verze 1607 může dojít kvůli použití randomizace rozložení adresního prostoru (ASLR) k problému s zarovnáním adresy a přemístěním paměti. Operační systém musí přemístit adresu, ze které linker nastavil výchozí základní adresu na skutečné umístění přiřazené službou ASLR. Toto přemístění nemůže překlenout mez stránky. Představte si například 64bitovou hodnotu adresy, která má počátek na posunu 0x3FFC na stránce. Hodnota adresy se překrývá na další stránku na posunu 0x0003. Tento typ překrývajících se relokací není podporován před Windows 10, verze 1703.
K této situaci může dojít, když má inicializátor proměnné globální struktury nesprávně zarovnaný ukazatel na jinou globální proměnnou, která je uspořádána tak, že linker nemůže přesunout proměnnou, aby se zabránilo problémovému přemístění. Linker se pokusí přesunout proměnnou, ale jsou situace, kdy to nemusí být možné provést (například u velkých špatně zarovnaných struktur nebo velkých polí špatně zarovnaných struktur). V případě potřeby by měly být moduly sestaveny pomocí /Gy (COMDAT) volby, aby linker mohl co nejvíce zarovnat kód modulu.
#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
};
Existují i další situace týkající se použití kódu assembleru, kdy k tomuto problému může také dojít.
Integrita kódu verifieru ovladače
Pomocí příznaku integrity kódu Verifieru ovladače (0x02000000) povolte dodatečné kontroly, které ověřují dodržování této funkce. Pokud to chcete povolit z příkazového řádku, použijte následující příkaz.
verifier.exe /flags 0x02000000 /driver <driver.sys>
Pokud chcete tuto možnost zvolit, pokud používáte grafické uživatelské rozhraní ověřovatele, vyberte Vytvořit vlastní nastavení (pro vývojáře kódu), vyberte Dalšía pak vyberte kontroly integrity kódu.
K zobrazení aktuálních informací o ověřovači ovladače můžete použít příkazový řádek s možností /query.
verifier /query