Skip to content

Commit 5195ae9

Browse files
committed
Add updated decode search for OslFwpKernelSetupPhase1
1 parent b94b82d commit 5195ae9

File tree

1 file changed

+67
-24
lines changed

1 file changed

+67
-24
lines changed

EfiGuardDxe/PatchWinload.c

+67-24
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ UINT8 gOslFwpKernelSetupPhase1Backup[sizeof(gHookTemplate)] = { 0 };
88

99

1010
// Signature for winload!OslFwpKernelSetupPhase1+XX, where the value of XX needs to be determined by backtracking.
11-
// Windows 10 only. On older OSes, and on Windows 10 as fallback, OslFwpKernelSetupPhase1 is found via xrefs to EfipGetRsdt
11+
// Windows 10 RS4 and later only. On older OSes, and on Windows 10 as fallback, OslFwpKernelSetupPhase1 is found via xrefs to EfipGetRsdt
1212
STATIC CONST UINT8 SigOslFwpKernelSetupPhase1[] = {
13-
0xE8, 0xCC, 0xCC, 0xCC, 0xCC, // call BlpArchSwitchContext
14-
0x48, 0x8B, 0x05, 0xCC, 0xCC, 0xCC, 0xCC, // mov rax, gBS
15-
0xCC, 0x8B, 0xCC, // mov rdx, XX
16-
0x48, 0x8B, 0x0D, 0xCC, 0xCC, 0xCC, 0xCC // mov rcx, EfiImageHandle
13+
0x89, 0xCC, 0x24, 0x01, 0x00, 0x00, // mov [REG+124h], r32
14+
0xE8, 0xCC, 0xCC, 0xCC, 0xCC, // call BlBdStop
15+
0xCC, 0x8B, 0xCC // mov r32, r/m32
1716
};
1817

1918
STATIC UNICODE_STRING ImgpFilterValidationFailureMessage = RTL_CONSTANT_STRING(L"*** Windows is unable to verify the signature of"); // newline, etc etc...
@@ -405,7 +404,7 @@ FindOslFwpKernelSetupPhase1(
405404
IN PEFI_IMAGE_NT_HEADERS NtHeaders,
406405
IN PEFI_IMAGE_SECTION_HEADER CodeSection,
407406
IN PEFI_IMAGE_SECTION_HEADER PatternSection,
408-
IN BOOLEAN TryPatternMatch,
407+
IN UINT16 BuildNumber,
409408
OUT UINT8** OslFwpKernelSetupPhase1Address
410409
)
411410
{
@@ -415,9 +414,9 @@ FindOslFwpKernelSetupPhase1(
415414
CONST UINT32 CodeSizeOfRawData = CodeSection->SizeOfRawData;
416415
CONST UINT8* PatternStartVa = ImageBase + PatternSection->VirtualAddress;
417416

418-
if (TryPatternMatch)
417+
if (BuildNumber >= 17134)
419418
{
420-
// On Windows 10, try simple pattern matching first since it will most likely work
419+
// On Windows 10 RS4 and later, try simple pattern matching first since it will most likely work
421420
UINT8* Found = NULL;
422421
CONST EFI_STATUS Status = FindPattern(SigOslFwpKernelSetupPhase1,
423422
0xCC,
@@ -437,14 +436,69 @@ FindOslFwpKernelSetupPhase1(
437436
}
438437
}
439438

439+
// Initialize Zydis
440+
Print(L"\r\n== Disassembling .text to find OslFwpKernelSetupPhase1 ==\r\n");
441+
ZYDIS_CONTEXT Context;
442+
ZyanStatus Status = ZydisInit(NtHeaders, &Context);
443+
if (!ZYAN_SUCCESS(Status))
444+
{
445+
Print(L"Failed to initialize disassembler engine.\r\n");
446+
return EFI_LOAD_ERROR;
447+
}
448+
449+
CONST VOID* BlBdStop = GetProcedureAddress((UINTN)ImageBase, NtHeaders, "BlBdStop");
450+
if (BuildNumber >= 17134 && BlBdStop != NULL)
451+
{
452+
Context.Length = CodeSizeOfRawData;
453+
Context.Offset = 6;
454+
455+
// Start decode loop
456+
while ((Context.InstructionAddress = (ZyanU64)(CodeStartVa + Context.Offset),
457+
Status = ZydisDecoderDecodeFull(&Context.Decoder,
458+
(VOID*)Context.InstructionAddress,
459+
Context.Length - Context.Offset,
460+
&Context.Instruction,
461+
Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA)
462+
{
463+
if (!ZYAN_SUCCESS(Status))
464+
{
465+
Context.Offset++;
466+
continue;
467+
}
468+
469+
// Check if this is 'call BlBdStop'
470+
if (Context.Instruction.operand_count == 4 &&
471+
Context.Operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Context.Operands[0].imm.is_relative == ZYAN_TRUE &&
472+
Context.Instruction.mnemonic == ZYDIS_MNEMONIC_CALL)
473+
{
474+
ZyanU64 OperandAddress = 0;
475+
if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &OperandAddress)) &&
476+
OperandAddress == (UINTN)BlBdStop)
477+
{
478+
// Check if the preceding instruction is 'mov [REG+124h], r32'
479+
CONST UINT8* CallBlBdStopAddress = (UINT8*)Context.InstructionAddress;
480+
if ((CallBlBdStopAddress[-6] == 0x89 || CallBlBdStopAddress[-6] == 0x8B) &&
481+
*(UINT32*)(&CallBlBdStopAddress[-4]) == 0x124 &&
482+
(*OslFwpKernelSetupPhase1Address = BacktrackToFunctionStart(ImageBase, NtHeaders, CallBlBdStopAddress)) != NULL)
483+
{
484+
Print(L" Found OslFwpKernelSetupPhase1 at 0x%llX.\r\n\r\n", (UINTN)(*OslFwpKernelSetupPhase1Address));
485+
return EFI_SUCCESS;
486+
}
487+
}
488+
}
489+
490+
Context.Offset += Context.Instruction.length;
491+
}
492+
}
493+
494+
// On RS4 and later, the previous method really should have worked
495+
ASSERT(BuildNumber < 17134);
496+
440497
// On older versions, use some convoluted but robust logic to find OslFwpKernelSetupPhase1 by matching xrefs to EfipGetRsdt.
441498
// This of course implies finding EfipGetRsdt first. After that, find all calls to this function, and for each, calculate
442499
// the distance from the start of the function to the call. OslFwpKernelSetupPhase1 is reliably (Vista through 10)
443500
// the function that has the smallest value for this distance, i.e. the call happens very early in the function.
444-
CHAR8 SectionName[EFI_IMAGE_SIZEOF_SHORT_NAME + 1];
445-
CopyMem(SectionName, PatternSection->Name, EFI_IMAGE_SIZEOF_SHORT_NAME);
446-
SectionName[EFI_IMAGE_SIZEOF_SHORT_NAME] = '\0';
447-
Print(L"\r\n== Searching for EfipGetRsdt pattern in %a ==\r\n", SectionName);
501+
Print(L"\r\n== Searching for EfipGetRsdt pattern in .text ==\r\n");
448502

449503
// Search for EFI ACPI 2.0 table GUID: { 8868e871-e4f1-11d3-bc22-0080c73c8881 }
450504
UINT8* PatternAddress = NULL;
@@ -468,16 +522,6 @@ FindOslFwpKernelSetupPhase1(
468522

469523
Print(L"\r\n== Disassembling .text to find EfipGetRsdt ==\r\n");
470524
UINT8* LeaEfiAcpiTableGuidAddress = NULL;
471-
472-
// Initialize Zydis
473-
ZYDIS_CONTEXT Context;
474-
ZyanStatus Status = ZydisInit(NtHeaders, &Context);
475-
if (!ZYAN_SUCCESS(Status))
476-
{
477-
Print(L"Failed to initialize disassembler engine.\r\n");
478-
return EFI_LOAD_ERROR;
479-
}
480-
481525
Context.Length = CodeSizeOfRawData;
482526
Context.Offset = 0;
483527

@@ -534,7 +578,6 @@ FindOslFwpKernelSetupPhase1(
534578
}
535579

536580
Print(L" Found EfipGetRsdt at 0x%llX.\r\n", (UINTN)EfipGetRsdt);
537-
Print(L"\r\n== Disassembling .text to find OslFwpKernelSetupPhase1 ==\r\n");
538581
UINT8* CallEfipGetRsdtAddress = NULL;
539582

540583
// Start decode loop
@@ -673,7 +716,7 @@ PatchWinload(
673716
NtHeaders,
674717
CodeSection,
675718
PatternSection,
676-
BuildNumber >= 10240,
719+
BuildNumber,
677720
(UINT8**)&gOriginalOslFwpKernelSetupPhase1);
678721
if (EFI_ERROR(Status))
679722
{

0 commit comments

Comments
 (0)