diff options
author | Matthijs Lavrijsen <mattiwatti@gmail.com> | 2023-03-26 15:22:09 +0200 |
---|---|---|
committer | Matthijs Lavrijsen <mattiwatti@gmail.com> | 2023-03-26 15:22:09 +0200 |
commit | 82b91beedf492b3725d987bfa2e5001f33686007 (patch) | |
tree | daf4f0e68ba745ad95e72ea3d08f43fe0a88fe6e | |
parent | 4465715c2c3abbd554f2ee09360532bcf257d34a (diff) |
EfiGuardDxe: clear and restore CR0.WP when copying
This is intended to deal with the UEFI memory protection protocol (EFI_MEMORY_ATTRIBUTE_PROTOCOL) introduced in the UEFI 2.10 specification.
-rw-r--r-- | EfiGuardDxe/EfiGuardDxe.h | 1 | ||||
-rw-r--r-- | EfiGuardDxe/PatchBootmgr.c | 11 | ||||
-rw-r--r-- | EfiGuardDxe/PatchNtoskrnl.c | 26 | ||||
-rw-r--r-- | EfiGuardDxe/PatchWinload.c | 22 |
4 files changed, 38 insertions, 22 deletions
diff --git a/EfiGuardDxe/EfiGuardDxe.h b/EfiGuardDxe/EfiGuardDxe.h index 0970d3b..249ed8c 100644 --- a/EfiGuardDxe/EfiGuardDxe.h +++ b/EfiGuardDxe/EfiGuardDxe.h @@ -49,6 +49,7 @@ extern BOOLEAN gEfiGoneVirtual; // Universal template bytes for a faux call inline hook (mov [e|r]ax, <addr>, push [e|r]ax, ret) // extern CONST UINT8 gHookTemplate[(sizeof(VOID*) / 4) + sizeof(VOID*) + 2]; +extern CONST UINTN gHookTemplateAddressOffset; // diff --git a/EfiGuardDxe/PatchBootmgr.c b/EfiGuardDxe/PatchBootmgr.c index 490d040..5730664 100644 --- a/EfiGuardDxe/PatchBootmgr.c +++ b/EfiGuardDxe/PatchBootmgr.c @@ -24,6 +24,11 @@ CONST UINT8 gHookTemplate[] = 0x50, // push [e|r]ax 0xC3 // ret }; +#if defined(MDE_CPU_X64) +CONST UINTN gHookTemplateAddressOffset = 2; +#elif defined(MDE_CPU_IA32) +CONST UINTN gHookTemplateAddressOffset = 1; +#endif // Signature for [bootmgfw|bootmgr]!ImgArch[Efi]StartBootApplication @@ -49,7 +54,7 @@ HookedBootManagerImgArchStartBootApplication( ) { // Restore the original function bytes that we replaced with our hook - CopyMem(OriginalFunction, OriginalFunctionBytes, sizeof(gHookTemplate)); + CopyWpMem(OriginalFunction, OriginalFunctionBytes, sizeof(gHookTemplate)); // Clear the screen and paint it, paint it bl... green CONST INT32 OriginalAttribute = SetConsoleTextColour(EFI_GREEN, TRUE); @@ -325,8 +330,8 @@ PatchBootManager( CopyMem(BackupAddress, (VOID*)OriginalAddress, sizeof(gHookTemplate)); // Place faux call (push addr, ret) at the start of the function to transfer execution to our hook - CopyMem((VOID*)OriginalAddress, gHookTemplate, sizeof(gHookTemplate)); - *(UINTN*)((UINT8*)OriginalAddress + 2) = (UINTN)HookAddress; + CopyWpMem((VOID*)OriginalAddress, gHookTemplate, sizeof(gHookTemplate)); + CopyWpMem((UINT8*)OriginalAddress + gHookTemplateAddressOffset, (UINTN*)&HookAddress, sizeof(UINTN)); gBS->RestoreTPL(Tpl); diff --git a/EfiGuardDxe/PatchNtoskrnl.c b/EfiGuardDxe/PatchNtoskrnl.c index 1604f7a..fad6914 100644 --- a/EfiGuardDxe/PatchNtoskrnl.c +++ b/EfiGuardDxe/PatchNtoskrnl.c @@ -384,19 +384,19 @@ DisablePatchGuard( // We have all the addresses we need; now do the actual patching. CONST UINT32 Yes = 0xC301B0; // mov al, 1, ret CONST UINT32 No = 0xC3C033; // xor eax, eax, ret - *((UINT32*)KeInitAmd64SpecificState) = No; - *((UINT32*)CcInitializeBcbProfiler) = Yes; + CopyWpMem(KeInitAmd64SpecificState, &No, sizeof(No)); + CopyWpMem(CcInitializeBcbProfiler, &Yes, sizeof(Yes)); if (ExpLicenseWatchInitWorker != NULL) - *((UINT32*)ExpLicenseWatchInitWorker) = No; + CopyWpMem(ExpLicenseWatchInitWorker, &No, sizeof(No)); if (KiVerifyScopesExecute != NULL) - *(UINT32*)KiVerifyScopesExecute = No; + CopyWpMem(KiVerifyScopesExecute, &No, sizeof(No)); if (KiMcaDeferredRecoveryServiceCallers[0] != NULL && KiMcaDeferredRecoveryServiceCallers[1] != NULL) { - *(UINT32*)KiMcaDeferredRecoveryServiceCallers[0] = No; - *(UINT32*)KiMcaDeferredRecoveryServiceCallers[1] = No; + CopyWpMem(KiMcaDeferredRecoveryServiceCallers[0], &No, sizeof(No)); + CopyWpMem(KiMcaDeferredRecoveryServiceCallers[1], &No, sizeof(No)); } if (KiSwInterruptPatternAddress != NULL) - SetMem(KiSwInterruptPatternAddress, sizeof(SigKiSwInterrupt), 0x90); // 11 x nop + SetWpMem(KiSwInterruptPatternAddress, sizeof(SigKiSwInterrupt), 0x90); // 11 x nop // Print info PRINT_KERNEL_PATCH_MSG(L"\r\n Patched KeInitAmd64SpecificState [RVA: 0x%X].\r\n", @@ -704,14 +704,20 @@ DisableDSE( // We have all the addresses we need; now do the actual patching. // SepInitializeCodeIntegrity is only patched when using the 'nuke option' DSE_DISABLE_AT_BOOT. if (BypassType == DSE_DISABLE_AT_BOOT) - *((UINT16*)SepInitializeCodeIntegrityMovEcxAddress) = 0xC931; // xor ecx, ecx + { + CONST UINT16 ZeroEcx = 0xC931; + CopyWpMem(SepInitializeCodeIntegrityMovEcxAddress, &ZeroEcx, sizeof(ZeroEcx)); // xor ecx, ecx + } // SeValidateImageData *must* be patched on Windows Vista and 7 regardless of the DSE bypass method. // On Windows >= 8, again require DSE_DISABLE_AT_BOOT to do anything as it is otherwise harmless. if (BuildNumber < 9200) - *SeValidateImageDataJzAddress = 0xEB; // jmp + SetWpMem(SeValidateImageDataJzAddress, sizeof(UINT8), 0xEB); // jmp else if (BypassType == DSE_DISABLE_AT_BOOT) - *(UINT32*)(SeValidateImageDataMovEaxAddress + 1 /*skip existing mov opcode*/) = 0x0; // mov eax, 0 + { + CONST UINT32 Zero = 0; + CopyWpMem(SeValidateImageDataMovEaxAddress + 1 /*skip existing mov*/, &Zero, sizeof(Zero)); // mov eax, 0 + } if (BuildNumber >= 16299 && BypassType == DSE_DISABLE_AT_BOOT) { diff --git a/EfiGuardDxe/PatchWinload.c b/EfiGuardDxe/PatchWinload.c index edf15ad..baa28d7 100644 --- a/EfiGuardDxe/PatchWinload.c +++ b/EfiGuardDxe/PatchWinload.c @@ -128,7 +128,7 @@ HookedOslFwpKernelSetupPhase1( ) { // Restore the original function bytes that we replaced with our hook - CopyMem((VOID*)gOriginalOslFwpKernelSetupPhase1, gOslFwpKernelSetupPhase1Backup, sizeof(gOslFwpKernelSetupPhase1Backup)); + CopyWpMem((VOID*)gOriginalOslFwpKernelSetupPhase1, gOslFwpKernelSetupPhase1Backup, sizeof(gHookTemplate)); UINT8* LoadOrderListHeadAddress = (UINT8*)&LoaderBlock->LoadOrderListHead; if (gKernelPatchInfo.BuildNumber < 7600) @@ -238,7 +238,7 @@ PatchImgpValidateImageHash( } // Backtrack to function start - CONST UINT8* ImgpValidateImageHash = BacktrackToFunctionStart(ImageBase, NtHeaders, AndMinusFortyOneAddress); + UINT8* ImgpValidateImageHash = BacktrackToFunctionStart(ImageBase, NtHeaders, AndMinusFortyOneAddress); if (ImgpValidateImageHash == NULL) { Print(L" Failed to find %S!ImgpValidateImageHash%S.\r\n", @@ -247,7 +247,8 @@ PatchImgpValidateImageHash( } // Apply the patch - *((UINT32*)ImgpValidateImageHash) = 0xC3C033; // xor eax, eax, ret + CONST UINT32 Ok = 0xC3C033; // xor eax, eax, ret + CopyWpMem(ImgpValidateImageHash, &Ok, sizeof(Ok)); // Print info Print(L" Patched %S!ImgpValidateImageHash [RVA: 0x%X].\r\n", @@ -375,7 +376,7 @@ PatchImgpFilterValidationFailure( } // Backtrack to function start - CONST UINT8* ImgpFilterValidationFailure = BacktrackToFunctionStart(ImageBase, NtHeaders, LeaIntegrityFailureAddress); + UINT8* ImgpFilterValidationFailure = BacktrackToFunctionStart(ImageBase, NtHeaders, LeaIntegrityFailureAddress); if (ImgpFilterValidationFailure == NULL) { Print(L" Failed to find %S!ImgpFilterValidationFailure%S.\r\n", @@ -384,7 +385,8 @@ PatchImgpFilterValidationFailure( } // Apply the patch - *((UINT32*)ImgpFilterValidationFailure) = 0xC3C033; // xor eax, eax, ret + CONST UINT32 Ok = 0xC3C033; // xor eax, eax, ret + CopyWpMem(ImgpFilterValidationFailure, &Ok, sizeof(Ok)); // Print info Print(L" Patched %S!ImgpFilterValidationFailure [RVA: 0x%X].\r\n\r\n", @@ -679,16 +681,18 @@ PatchWinload( goto Exit; } - Print(L"HookedOslFwpKernelSetupPhase1 at 0x%p.\r\n", (VOID*)&HookedOslFwpKernelSetupPhase1); + CONST UINTN HookedOslFwpKernelSetupPhase1Address = (UINTN)&HookedOslFwpKernelSetupPhase1; + Print(L"HookedOslFwpKernelSetupPhase1 at 0x%p.\r\n", (VOID*)HookedOslFwpKernelSetupPhase1Address); CONST EFI_TPL Tpl = gBS->RaiseTPL(TPL_HIGH_LEVEL); // Note: implies cli // Backup original function prologue - CopyMem(gOslFwpKernelSetupPhase1Backup, (VOID*)gOriginalOslFwpKernelSetupPhase1, sizeof(gOslFwpKernelSetupPhase1Backup)); + CopyMem(gOslFwpKernelSetupPhase1Backup, (VOID*)gOriginalOslFwpKernelSetupPhase1, sizeof(gHookTemplate)); // Place faux call (push addr, ret) at the start of the function to transfer execution to our hook - CopyMem((VOID*)gOriginalOslFwpKernelSetupPhase1, gHookTemplate, sizeof(gHookTemplate)); - *(UINTN*)((UINT8*)gOriginalOslFwpKernelSetupPhase1 + 2) = (UINTN)&HookedOslFwpKernelSetupPhase1; + CopyWpMem((VOID*)gOriginalOslFwpKernelSetupPhase1, gHookTemplate, sizeof(gHookTemplate)); + CopyWpMem((UINT8*)gOriginalOslFwpKernelSetupPhase1 + gHookTemplateAddressOffset, + (UINTN*)&HookedOslFwpKernelSetupPhase1Address, sizeof(HookedOslFwpKernelSetupPhase1Address)); gBS->RestoreTPL(Tpl); |