Mattiwatti / EfiGuard

Disable PatchGuard and Driver Signature Enforcement at boot time
GNU General Public License v3.0
1.69k stars 326 forks source link
bootkit driver efi kernel patchguard signing uefi windows

Overview

EfiGuard is a portable x64 UEFI bootkit that patches the Windows boot manager, boot loader and kernel at boot time in order to disable PatchGuard and Driver Signature Enforcement (DSE).

If you're just looking to try EfiGuard, skip to Usage.

Features

Issues and limitations

Usage

There are two ways to use EfiGuard: booting the loader application, which will load the driver and start Windows for you, or installing the driver as a UEFI driver entry so it will be loaded automatically by the firmware.

Installing the driver can be preferable in some advanced configurations such as when multi-booting, but the loader is easiest to use and should work well in all configurations. See the table below for the most important differences between the two methods. If unsure, choose the loader application.

Location Installation Skippable? Which OS is booted?
UEFI Driver Entry Must be on ESP Via UEFI Shell :x: Same as before
Loader Anywhere Not needed :heavy_check_mark: Windows

Loader vs UEFI driver entry comparison

Booting the loader

  1. Download EfiGuard and rename EFI/Boot/Loader.efi to bootx64.efi.
  2. Place the files on a boot drive such as a FAT32 formatted USB stick (for physical machines) or an ISO/virtual disk (for VMs). Assuming drive X:, the paths for the two files should now be X:/EFI/Boot/{bootx64|EfiGuardDxe}.efi
  3. Boot the machine from the drive you used in step 2. Most firmwares provide a boot menu to do this via F8/F10/F11/F12. If not, you will need to configure the BIOS to boot from the new drive.
  4. Windows should now boot, and you should see EfiGuard messages during boot.
  5. If you booted with the SetVariable hook (the default), run EfiDSEFix.exe -d from an Administrator command prompt after boot to disable DSE, or run EfiDSEFix.exe to see the full list of options.

Note that you don't need to use a separate drive for the loader. If preferable, you can install EfiGuard on the ESP that Windows is already installed on. However, this is somewhat more complicated as you will need to add a UEFI boot entry for the loader.

To do this, mount the ESP at X: using mountvol X: /S and follow the steps above, but do not rename the loader and simply copy both files to X:/EFI/Boot. After that, you will need to manually add a UEFI boot entry from the UEFI Shell using bcfg boot addp 0 Loader.efi "EfiGuard", or alternatively using efibootmgr (Linux), EasyUEFI (Windows), or similar.

Installing the driver

  1. Mount the ESP at X: using mountvol X: /S.
  2. Copy EfiGuardDxe.efi to X:/EFI/Boot/EfiGuardDxe.efi.
  3. Boot to the UEFI Shell and add a UEFI driver entry: bcfg driver add 0 EfiGuardDxe.efi "EfiGuardDxe".
  4. Windows should now boot, and you should see EfiGuard messages during boot.
  5. If you booted with the SetVariable hook (the default), run EfiDSEFix.exe -d from an Administrator command prompt after boot to disable DSE, or run EfiDSEFix.exe to see the full list of options.

Note: depending on your firmware, you may need to use "addp" in step 3 instead of "add". VirtualBox is known to require this, and possibly some motherboard firmwares do too.

Note: some very old or noncompliant firmwares may not support this method of installation at all. On these systems you will have no option but to use the loader instead.

Compilation

Compiling EfiGuardDxe and the loader

EfiGuard requires EDK2 to build. If you don't have EDK2 installed, follow the steps in Getting Started with EDK2 first as the EDK2 build system is fairly complex to set up. This section assumes you have a workspace directory that your WORKSPACE environment variable points to, with a copy of EDK2 checked out in workspace/edk2. Supported compilers are MSVC, Clang, GCC and ICC.

  1. Clone the EfiGuard repository into workspace/edk2/EfiGuardPkg.
  2. Open a prompt or shell that sets up the environment variables for EDK2.
  3. Run build -a X64 -t VS2019 -p EfiGuardPkg/EfiGuardPkg.dsc -b RELEASE, substituting your toolchain for VS2019.

This will produce EfiGuardDxe.efi and Loader.efi in workspace/Build/EfiGuard/RELEASE_VS2019/X64.

Compiling EfiDSEFix

EfiDSEFix requires Visual Studio to build.

  1. Open EfiGuard.sln and build the solution.

The output binary EfiDSEFix.exe will be in Application/EfiDSEFix/bin.

The Visual Studio solution also includes projects for EfiGuardDxe.efi and Loader.efi which can be used with VisualUefi, but these projects are not built by default as they will not link without additional code, and the build output will be inferior (bigger) than what EDK2 produces. Loader.efi will not link at all due to VisualUefi missing UefiBootManagerLib. These project files are thus meant as a development aid only and the EFI files should still be compiled with EDK2. To set up VisualUefi for this purpose, clone the repository into workspace/VisualUefi and open EfiGuard.sln.

Architecture

architecture While EfiGuard is a UEFI bootkit, it did not start out as one. EfiGuard was originally an on-disk patcher running on NT (similar to UPGDSED), intended to test the viability of a disassembler-based aproach, as opposed to using PDB symbols and version-specific signatures. PatchNtoskrnl.c still looks very much like this original design. Only after this approach proved successful, with no modifications to code needed in over a year of Windows updates, did UEFI come into the picture as a way to further improve capabilities and ease of use.

Some of the benefits provided by a bootkit approach include:

The initial incarnation of EfiGuard as a bootkit was an attempt to get dude719's UEFI-Bootkit to work with recent versions of Windows 10, because it had become dated and no longer works on the latest versions (like UPGDSED, often caused by version-sensitive pattern scans). While I did eventually get this to work, I was unsatisfied with the result mostly due to the choice of hooking OslArchTransferToKernel, which as noted above executes in protected mode and after ExitBootServices has been called. Apart from this, I was not satisfied with only being able to patch some versions of Windows 10; I wanted the bootkit to work on every EFI-compatible version of Windows x64 released to date. Because of this, I rewrote the bootkit from scratch with the following aims:

A big picture overview of the final EfiGuard boot flow is shown in the diagram above. For the individual component-specific hooks and patches, see EfiGuardDxe/PatchXxx.c in the source files. For driver initialization/unloading and the EFI Boot and Runtime Services hooks, see EfiGuardDxe.c.

Credits

License

EfiGuard is licensed under the GPLv3. Files in the EfiGuardDxe/Zydis submodule are licensed under the MIT license.