Mattiwatti / EfiGuard

Disable PatchGuard and Driver Signature Enforcement at boot time
GNU General Public License v3.0
1.78k stars 333 forks source link

PatchGuard still triggers on windows 10 1909 #12

Closed dumbasPL closed 4 years ago

dumbasPL commented 4 years ago

I have a driver that hooks SSDT function and after a while i get a bsod with a Stop Code CRITICAL_STRUCTURE_CORRUPTION

Windows 10 pro 1909 (build 18363.778) EfiGuard v1.0.2 (not latest but also the fix in the latest version is for newer windows version) EfiDSEFix.exe -i

SystemBootEnvironmentInformation:
        - BootIdentifier: {525c7818-68bb-11ea-8e6c-00d8615536c2}
        - FirmwareType: UEFI
        - BootFlags: 0x0

SystemModuleInformation:
        - Kernel: ntoskrnl.exe (\SystemRoot\system32\ntoskrnl.exe)

SystemCodeIntegrityInformation:
        - IntegrityOptions: 0x0001

SystemKernelDebuggerInformation:
        - KernelDebuggerEnabled: 0
        - KernelDebuggerNotPresent: 1

SystemKernelDebuggerInformationEx:
        - DebuggerAllowed: 0
        - DebuggerEnabled: 0
        - DebuggerPresent: 0

SharedUserData->KdDebuggerEnabled: 0x00

SystemKernelDebuggerFlags: 0x00

SystemCodeIntegrityPolicyInformation:
        - Options: 0x40000000
        - HVCIOptions: 0x0000

Also i use a signed driver(using a leaked cert) so i don't disable DSE

I do not get any errors in the loader itself

let me know what else i need to provide to help

Mattiwatti commented 4 years ago

That is interesting and definitely not working as intended. Since I haven't been able to reproduce this yet, some questions:

A small note: EfiGuard v1.0.3 has an update for Windows 10 20H1, but this change does not affect compatibility with older versions, and only affects an optional patch. All versions of EfiGuard work with all UEFI versions of Windows released so far.

dumbasPL commented 4 years ago

Does this happen reliably on every boot?

Here is the interesting part. I hibernate my pc a lot. I believe it once triggered after a fresh boot but i'm not 100% certain. When i boot it up after hibernation it still triggers the efi file correctly since it's set as my default boot option but maybe windows is doing something weird.

Can you share some source snippet of how you are hooking the SSDT? Alternatively, if you can confirm that some other open source SSDT hook (like TitanHide) works to reproduce the issue, that is fine too.

TitanHide is the base i use so the hooking is identical but i'm just hooking different functions.
Also it's definitely not my hook that's the problem since if i just call the original and nothing more it also crashes.

Are you using a virtual machine or are you on bare metal? If the latter, can you reproduce this in a VM?

Right now i'm running bare metal.(i7-9700K, MVMe ssd as boot drive)

Also just a side note. Ever since i started using EfiGuard i am getting random freezes. Usually after 3-4 days after the initial non hibernated boot. Again Hibernation might have something to do with it. And they happen regardless of if i'm doing something with the kernel or not.
I usually looks like this:

this is not a hardware or driver problem since it never happened to me when i'm not using EfiGuard.

I will setup a clean vm and just run it in the background to see what happens on a vm.
I will also try to trigger it on a clean boot to see if that's the issue.

Also any ideas on how i can debug any of this to give more information to you?

Mattiwatti commented 4 years ago

Thanks for the update.

Re: hibernation: this is an issue I have always been aware of potentially existing, but which I don't believe I can do much about, if I'm right about the cause. The issue with hibernation is that the OS needs up to date EFI memory type information to save and restore RAM to and from disk to perform S4 entry/resume. This information is set in the MemoryTypeInformation EFI variable. A boot application (such as the EfiGuard loader) is supposed to update this variable prior to booting an OS. In EDK2 this is done with BmSetMemoryTypeInformationVariable. The EfiGuard loader purposely does not call BmSetMemoryTypeInformationVariable because this will result in a system reset, which will either result in an infinite loop (if EfiGuard is booted again) or a non-working EfiGuard (due to the EFI runtime service hooks no longer being present). The relevant code in EDK2:

//
// If the Memory Type Information settings have been modified and the boot option belongs to boot category,
// then reset the platform so the new Memory Type Information setting will be used to guarantee that an S4
// entry/resume cycle will not fail.
//
if (MemoryTypeInformationModified) {
  DEBUG ((EFI_D_INFO, "Memory Type Information settings change.\n"));
  if (Boot && PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {
    DEBUG ((EFI_D_INFO, "...Warm Reset!!!\n"));
    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
  }
}

So, the chances of this being fixed are not great. That said, I've never tested what happens if BmSetMemoryTypeInformationVariable is compiled in with the system reset call removed. I expect nothing interesting, but I may follow up on this post with a version of the loader with this change for you to try if you want.

With regards to PatchGuard I have better news in that I found an additional initialization vector and two rarely performed verification checks, all of which I've patched out. Please try the following driver and let me know if it fixes the BSOD: EfiGuardDxe-b5d0353.zip.

dumbasPL commented 4 years ago

Good news!

third day with new driver active and no BSOD yet

I will continue testing but right now it seems to work

Mattiwatti commented 4 years ago

Alright, that's definitely encouraging. I would say three days is well past the point where PatchGuard can be assumed to be disabled; my personal record is 24 hours for a BSOD. If you want more certainty it is probably better to reboot once a day or so in order to try to get "lucky" with an additional PatchGuard context initialization call at boot.

I've made a modified loader for you to test: Loader-hibernate-test.zip.

There are two files in this ZIP: Loader.reset.efi and Loader.noreset.efi. Both of these will call the BmSetMemoryTypeInformationVariable function to set EFI memory type information: Loader.reset.efi calls the unmodified function and Loader.noreset.efi calls a version of this function that sets the variable but does not reboot if the data was changed. Simply put:

Therefore you will want to try Loader.reset.efi first, and only use Loader.noreset.efi if Loader.reset.efi fails to boot.

Let me know if either of these fixes the issue, and also whether Loader.reset.efi causes (a) system reset(s). If these do not fix the problem, the issue is more likely related to some behaviour of the Windows resume loader (winresume.efi).

dumbasPL commented 4 years ago

So, Loader.reset.efi boots fine into windows but after like an hour it does the "freeze" issue I described earlier. And it happens quite consistently too.

Loader.noreset.efi works flawlessly but the EfiGuardDxe-b5d0353.zip also worked flawlessly across multiple days and multiple hibernations/reboots.

I would say you can merge the noreset one with 1.0.3 if it isn't already and make a new release. Let me know what do you think and close the issue if that's all. If you want any additional feedback feel free to ask

Mattiwatti commented 4 years ago

Thanks. It's interesting that the 'no reset' version works better for you, if anything I was expecting the opposite. But using the 'reset' version was not an option anyway: I tested it on my own machine and it went into an infinite boot loop.

I've published a new v1.1 release that includes both fixes. Thanks for taking the time to test this.