Windows 10 has a new feature called Device Guard that gives organizations the ability to lock down devices in a way that provides advanced malware protection against new and unknown malware variants as well as Advanced Persistent Threats (APTs). Device Guard can use hardware technology and virtualization to isolate the Code Integrity (CI) decision-making function from the rest of the Windows operating system. When using virtualization-based security to isolate Code Integrity, the only way kernel memory can become executable is through a Code Integrity verification. This means that kernel memory pages can never be Writable and Executable (W+X) and executable code cannot be directly modified.
How to build compatible drivers
Since memory pages and sections can never be writable and executable, the first step is to ensure a clear separation of data and code and not to attempt to directly modify code pages.
- Opt-in to NX by default
- Use NX APIs/flags for memory allocation – NonPagedPoolNx
- Don’t use sections that are both writable and executable
- Don’t attempt to directly modify executable system memory
- Don’t use dynamic code in kernel
- Don’t load data files as executable
- Section Alignment must be a multiple of 0x1000 (PAGE_SIZE). E.g. DRIVER_ALIGNMENT=0x1000
Use the latest version of the WDK and Visual Studio 2015 to produce compatible drivers when using default settings. Visual Studio 2013 currently marks the INIT section as RWX. This will be patched soon, but is still compatible as Windows 10 will automatically strip the write permission (W) from the INIT section.
How to verify driver compatibility
There are four steps to verify driver compatibility:
1. Use Driver Verifier with the new Code Integrity compatibility checks enabled
2. Test the driver on a system with virtualization-based isolation of Code Integrity enabled.
3. Run the HyperVisor Code Integrity Readiness Test in the Windows HLK.
4. Use the Device Guard Readiness Tool.
Driver Verifier compatibility checks
Driver Verifier has a new Code Integrity option flag (0x02000000) to enable extra checks that validate compliance with this feature. To enable this from the command line, use the following command:
verifier.exe /flags 0x02000000 /driver <driver.sys>
To choose this option if using the verifier GUI, choose Create custom settings (for code developers), choose Next, and then choose Code integrity checks.
Drivers built with older versions of Visual Studio will fail on the INIT section being WRX. However, if this is the only issue you can ignore this issue and hit go past this in the kernel debugger as this will not cause any compatibility issues with this feature. Forthcoming updates to driver verifier will not flag the INIT section.
Enable virtualization-based isolation for Code Integrity
Virtualization-based security is supported on Enterprise and Server editions of Windows. To enable virtualization-based protection of Code Integrity, the simplest method is to use gpedit as described below. This will turn on Hyper-V and Isolated User Mode and enable the feature:
1. Run gpedit to edit local Group Policy
2. Under Computer Configuration -> Administrative Templates -> System -> Device Guard, choose Turn On Virtualization Based Security
3. In the detailed configuration dialog that appears, choose Enabled, and then select Enable Virtualization Based Protection of Code Integrity
Virtualization-based protection of Code Integrity is now enabled.
HLK testing (Desktop and Server)
A new HLK test, the HyperVisor Code Integrity Readiness Test, needs to pass for HVCI drivers to be approved for Microsoft signing. HVCI-compatible drivers are required for both Desktop and Server SKUs. The HLK test is a basic test written to make sure that HVCI-compatible drivers are correctly loaded and run by the OS.
Although simply passing the HLK test is sufficient for a Microsoft signature for the driver, we strongly recommend thorough functional testing with Device Guard enabled. For example, there might be incorrectly-coded memory allocation violating NX protections causing failures that won’t be caught by the test. The driver author should thoroughly test the driver while keeping Device Guard enabled.
During driver development and during HLK testing, Device Guard should be disabled, as Device Guard might prevent the driver from loading.
Device Guard Readiness Tool
The Device Guard and Credential Guard hardware readiness tool can also be used to check for HVCI compatibility of all installed drivers on the device. The download includes a readme file that contains usage information. Note that while running the Readiness Tool, Device Guard must be disabled, as Device Guard might prevent the driver from loading, and the driver won’t be available for the Readiness Tool to test.
What about existing drivers? Do I need to re-build these drivers to get them to work with Windows 10?
It depends. Many drivers will already be compatible. If using standard settings with the old versions of the WDK and Visual Studio, a known issue is that the INIT section is marked as RWX. In Windows 10, however, the W will automatically be stripped, so if this is the only issue then the driver will be compatible.
How do I verify that Virtualization Based Protection of Code Integrity is enabled?
The simplest mechanism is to run the System Information app (msinfo32). Look for the following line: “Device Guard Security Services Running”. It should report: “Hypervisor enforced Code Integrity”. There is also a WMI interface for checking using management tools.
Can I verify that Virtualization Based Protection of Code Integrity is enabled programmatically from kernel in order to alter driver behavior?
Yes, you can use NtQuerySystemInformation: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx
The SYSTEM_CODEINTEGRITY_INFORMATION structure has a new 0x400 value exposed, indicating that virtualization based protection of Code Integrity is on.
How do I fix compatibility issues?
In addition to double checking that there are no W+X pages and the driver sections are aligned correctly as mentioned above, the most likely issue will be improper memory allocation. Information about the Code Analysis warnings related to memory allocation issued is available on MSDN on the following page:
The following MSDN links show some examples of commonly-used APIs that cause executable memory to be allocated, along with some example fixes:
Which APIs are potentially affected?
The following list of APIs that are not reserved for system use may be impacted: