From 30e8570f9a3585572f60867166ac74f8951bf804 Mon Sep 17 00:00:00 2001 From: Matthijs Lavrijsen Date: Sun, 26 Mar 2023 01:49:12 +0100 Subject: Update Zydis to v4 --- EfiGuardDxe/EfiGuardDxe.inf | 13 +- EfiGuardDxe/EfiGuardDxe.vcxproj | 56 +++++-- EfiGuardDxe/EfiGuardDxe.vcxproj.filters | 87 +++++++---- EfiGuardDxe/PatchNtoskrnl.c | 254 ++++++++++++++++---------------- EfiGuardDxe/PatchWinload.c | 148 +++++++++---------- EfiGuardDxe/Zydis | 2 +- EfiGuardDxe/util.c | 19 +-- EfiGuardDxe/util.h | 32 +++- 8 files changed, 343 insertions(+), 268 deletions(-) (limited to 'EfiGuardDxe') diff --git a/EfiGuardDxe/EfiGuardDxe.inf b/EfiGuardDxe/EfiGuardDxe.inf index ca63724..67df756 100644 --- a/EfiGuardDxe/EfiGuardDxe.inf +++ b/EfiGuardDxe/EfiGuardDxe.inf @@ -20,6 +20,7 @@ Zydis/src/MetaInfo.c Zydis/src/Mnemonic.c Zydis/src/Register.c + Zydis/src/Segment.c Zydis/src/SharedData.c Zydis/src/String.c Zydis/src/Utils.c @@ -29,8 +30,6 @@ MdePkg/MdePkg.dec EfiGuardPkg/EfiGuardPkg.dec MdeModulePkg/MdeModulePkg.dec - # In EDK2 releases older than UDK2017, gEfiShellProtocolGuid is not in MdePkg but in ShellPkg. - # ShellPkg/ShellPkg.dec [LibraryClasses] UefiDriverEntryPoint @@ -69,7 +68,15 @@ [BuildOptions.Common] # Put Zydis on a diet - *_*_*_CC_FLAGS = -D ZYAN_UEFI -D ZYAN_NO_LIBC -D ZYCORE_STATIC_DEFINE -D ZYDIS_STATIC_DEFINE -D ZYDIS_DISABLE_AVX512 -D ZYDIS_DISABLE_KNC -D ZYDIS_DISABLE_FORMATTER + *_*_*_CC_FLAGS = -D ZYAN_NO_LIBC -D ZYCORE_STATIC_BUILD -D ZYDIS_STATIC_BUILD -D ZYDIS_DISABLE_ENCODER -D ZYDIS_DISABLE_FORMATTER -D ZYDIS_DISABLE_AVX512 -D ZYDIS_DISABLE_KNC + + # Zydis triggers this with MSVC and ICC on /W4. + # warning C4201: nonstandard extension used: nameless struct/union + MSFT:*_*_*_CC_FLAGS = /wd4201 + # ICC additionally generates about a million of these for Zydis on /W4, and then quits because of /WX. + # warning #188: enumerated type mixed with another type + # message #2415: variable "x" of static storage duration was declared but never referenced + INTEL:*_*_*_CC_FLAGS = -wd4201,188,2415 # This makes the decoder about twice as fast... sorry about the extra 5KB. Oh and usable PDBs please MSFT:RELEASE_*_*_CC_FLAGS = /O2 /Ot /Zi diff --git a/EfiGuardDxe/EfiGuardDxe.vcxproj b/EfiGuardDxe/EfiGuardDxe.vcxproj index bacd321..b0e2373 100644 --- a/EfiGuardDxe/EfiGuardDxe.vcxproj +++ b/EfiGuardDxe/EfiGuardDxe.vcxproj @@ -25,9 +25,10 @@ - ZYAN_UEFI;ZYAN_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;ZYDIS_DISABLE_AVX512;ZYDIS_DISABLE_KNC;ZYDIS_DISABLE_FORMATTER;%(PreprocessorDefinitions) + ZYAN_NO_LIBC;ZYCORE_STATIC_BUILD;ZYDIS_STATIC_BUILD;ZYDIS_DISABLE_ENCODER;ZYDIS_DISABLE_FORMATTER;ZYDIS_DISABLE_AVX512;ZYDIS_DISABLE_KNC;%(PreprocessorDefinitions) $(SolutionDir)Include;Zydis/dependencies/zycore/include;Zydis/include;Zydis/src;Zydis/msvc;%(AdditionalIncludeDirectories) MaxSpeed + 4201 UefiDriverEntryPoint.lib;BaseMemoryLib.lib;%(AdditionalDependencies) @@ -45,14 +46,28 @@ - - - - - + + true + + + true + + + true + + + true + + + true + + + true + + @@ -66,33 +81,46 @@ + + + - + - + + + true + + + true + + + true + + + + + + + + - - - - - - \ No newline at end of file diff --git a/EfiGuardDxe/EfiGuardDxe.vcxproj.filters b/EfiGuardDxe/EfiGuardDxe.vcxproj.filters index 9d4164d..ef7eb16 100644 --- a/EfiGuardDxe/EfiGuardDxe.vcxproj.filters +++ b/EfiGuardDxe/EfiGuardDxe.vcxproj.filters @@ -44,12 +44,18 @@ Source Files + + Source Files + Source Files\Zydis Source Files\Zydis + + Source Files\Zydis + Source Files\Zydis @@ -74,6 +80,9 @@ Source Files\Zydis + + Source Files\Zydis + Source Files\Zydis @@ -86,9 +95,6 @@ Source Files\Zydis - - Source Files - @@ -103,9 +109,21 @@ Header Files + + Header Files\Protocol + + + Header Files + Header Files\Zydis\Zycore + + Header Files\Zydis\Zycore + + + Header Files\Zydis\Zycore + Header Files\Zydis\Zycore @@ -121,6 +139,9 @@ Header Files\Zydis\Zycore + + Header Files\Zydis\Zycore + Header Files\Zydis\Zycore @@ -130,24 +151,51 @@ Header Files\Zydis\Zycore - - Header Files\Zydis\Zycore - Header Files\Zydis\Zycore Header Files\Zydis\Zycore + + Header Files\Zydis\Zycore + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + Header Files\Zydis Header Files\Zydis + + Header Files\Zydis + + + Header Files\Zydis + Header Files\Zydis + + Header Files\Zydis + Header Files\Zydis @@ -157,6 +205,9 @@ Header Files\Zydis + + Header Files\Zydis + Header Files\Zydis @@ -172,29 +223,5 @@ Header Files\Zydis - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Zydis\Internal - - - Header Files\Protocol - - - Header Files - \ No newline at end of file diff --git a/EfiGuardDxe/PatchNtoskrnl.c b/EfiGuardDxe/PatchNtoskrnl.c index 9dd3537..1604f7a 100644 --- a/EfiGuardDxe/PatchNtoskrnl.c +++ b/EfiGuardDxe/PatchNtoskrnl.c @@ -138,45 +138,44 @@ DisablePatchGuard( } // Initialize Zydis - ZydisDecoder Decoder; - ZyanStatus Status = ZydisInit(NtHeaders, &Decoder, NULL); + ZYDIS_CONTEXT Context; + ZyanStatus Status = ZydisInit(NtHeaders, &Context); if (!ZYAN_SUCCESS(Status)) { PRINT_KERNEL_PATCH_MSG(L"Failed to initialize disassembler engine.\r\n"); return EFI_LOAD_ERROR; } - UINTN Length = SizeOfRawData; - UINTN Offset = 0; - ZyanU64 InstructionAddress; - ZydisDecodedInstruction Instruction; + Context.Length = SizeOfRawData; + Context.Offset = 0; // Start decode loop - while ((InstructionAddress = (ZyanU64)(StartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + while ((Context.InstructionAddress = (ZyanU64)(StartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } if (BuildNumber < 9200) { // Windows Vista/7: check if this is 'call IMM' - if (Instruction.operand_count == 4 && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Instruction.operands[0].imm.is_relative == ZYAN_TRUE && - Instruction.mnemonic == ZYDIS_MNEMONIC_CALL) + if (Context.Instruction.operand_count == 4 && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Context.Operands[0].imm.is_relative == ZYAN_TRUE && + Context.Instruction.mnemonic == ZYDIS_MNEMONIC_CALL) { // Check if this is 'call RtlPcToFileHeader' ZyanU64 OperandAddress = 0; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[0], InstructionAddress, &OperandAddress)) && + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &OperandAddress)) && OperandAddress == RtlPcToFileHeader) { - CcInitializeBcbProfilerPatternAddress = (UINT8*)InstructionAddress; + CcInitializeBcbProfilerPatternAddress = (UINT8*)Context.InstructionAddress; PRINT_KERNEL_PATCH_MSG(L" Found 'call RtlPcToFileHeader' at 0x%llX.\r\n", (UINTN)CcInitializeBcbProfilerPatternAddress); break; } @@ -185,19 +184,19 @@ DisablePatchGuard( else { // Windows 8+: check if this is 'mov [al|rax], 0x0FFFFF780000002D4' ; SharedUserData->KdDebuggerEnabled - if ((Instruction.operand_count == 2 && Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER) && - ((Instruction.operands[0].reg.value == ZYDIS_REGISTER_AL && Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && - (UINT64)(Instruction.operands[1].mem.disp.value) == 0x0FFFFF780000002D4ULL) || - (Instruction.operands[0].reg.value == ZYDIS_REGISTER_RAX && Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - Instruction.operands[1].imm.value.u == 0x0FFFFF780000002D4ULL))) + if ((Context.Instruction.operand_count == 2 && Context.Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && Context.Operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER) && + ((Context.Operands[0].reg.value == ZYDIS_REGISTER_AL && Context.Operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && + (UINT64)(Context.Operands[1].mem.disp.value) == 0x0FFFFF780000002D4ULL) || + (Context.Operands[0].reg.value == ZYDIS_REGISTER_RAX && Context.Operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + Context.Operands[1].imm.value.u == 0x0FFFFF780000002D4ULL))) { - CcInitializeBcbProfilerPatternAddress = (UINT8*)InstructionAddress; + CcInitializeBcbProfilerPatternAddress = (UINT8*)Context.InstructionAddress; PRINT_KERNEL_PATCH_MSG(L" Found CcInitializeBcbProfiler pattern at 0x%llX.\r\n", (UINTN)CcInitializeBcbProfilerPatternAddress); break; } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } // Backtrack to function start @@ -217,33 +216,34 @@ DisablePatchGuard( UINT8* ExpLicenseWatchInitWorkerPatternAddress = NULL; // Start decode loop - Offset = 0; - while ((InstructionAddress = (ZyanU64)(StartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + Context.Offset = 0; + while ((Context.InstructionAddress = (ZyanU64)(StartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is 'mov al, ds:[0x0FFFFF780000002D4]' ; SharedUserData->KdDebuggerEnabled // The address must also obviously not be the CcInitializeBcbProfiler one we just found - if ((UINT8*)InstructionAddress != CcInitializeBcbProfilerPatternAddress && - Instruction.operand_count == 2 && Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && Instruction.operands[0].reg.value == ZYDIS_REGISTER_AL && - Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && Instruction.operands[1].mem.segment == ZYDIS_REGISTER_DS && - Instruction.operands[1].mem.disp.value == 0x0FFFFF780000002D4LL) + if ((UINT8*)Context.InstructionAddress != CcInitializeBcbProfilerPatternAddress && + Context.Instruction.operand_count == 2 && Context.Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && Context.Operands[0].reg.value == ZYDIS_REGISTER_AL && + Context.Operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && Context.Operands[1].mem.segment == ZYDIS_REGISTER_DS && + Context.Operands[1].mem.disp.value == 0x0FFFFF780000002D4LL) { - ExpLicenseWatchInitWorkerPatternAddress = (UINT8*)InstructionAddress; + ExpLicenseWatchInitWorkerPatternAddress = (UINT8*)Context.InstructionAddress; PRINT_KERNEL_PATCH_MSG(L" Found ExpLicenseWatchInitWorker pattern at 0x%llX.\r\n", (UINTN)ExpLicenseWatchInitWorkerPatternAddress); break; } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } // Backtrack to function start @@ -313,38 +313,39 @@ DisablePatchGuard( } // Start decode loop - Length = SizeOfRawData; - Offset = 0; - while ((InstructionAddress = (ZyanU64)(StartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + Context.Length = SizeOfRawData; + Context.Offset = 0; + while ((Context.InstructionAddress = (ZyanU64)(StartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is 'call KiMcaDeferredRecoveryService' ZyanU64 OperandAddress = 0; - if (Instruction.mnemonic == ZYDIS_MNEMONIC_CALL && - ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[0], InstructionAddress, &OperandAddress)) && + if (Context.Instruction.mnemonic == ZYDIS_MNEMONIC_CALL && + ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &OperandAddress)) && OperandAddress == (UINTN)KiMcaDeferredRecoveryService) { if (KiMcaDeferredRecoveryServiceCallers[0] == NULL) { - KiMcaDeferredRecoveryServiceCallers[0] = (UINT8*)InstructionAddress; + KiMcaDeferredRecoveryServiceCallers[0] = (UINT8*)Context.InstructionAddress; } else if (KiMcaDeferredRecoveryServiceCallers[1] == NULL) { - KiMcaDeferredRecoveryServiceCallers[1] = (UINT8*)InstructionAddress; + KiMcaDeferredRecoveryServiceCallers[1] = (UINT8*)Context.InstructionAddress; break; } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } // Backtrack to function start @@ -467,8 +468,8 @@ DisableDSE( PRINT_KERNEL_PATCH_MSG(L"\r\n== Disassembling PAGE to find nt!SepInitializeCodeIntegrity 'mov ecx, xxx' ==\r\n"); // Initialize Zydis - ZydisDecoder Decoder; - ZyanStatus Status = ZydisInit(NtHeaders, &Decoder, NULL); + ZYDIS_CONTEXT Context; + ZyanStatus Status = ZydisInit(NtHeaders, &Context); if (!ZYAN_SUCCESS(Status)) { PRINT_KERNEL_PATCH_MSG(L"Failed to initialize disassembler engine.\r\n"); @@ -476,9 +477,6 @@ DisableDSE( } UINT8* SepInitializeCodeIntegrityMovEcxAddress = NULL; - UINTN Length, Offset; - ZyanU64 InstructionAddress; - ZydisDecodedInstruction Instruction; if (BuildNumber < 9200) { @@ -486,37 +484,38 @@ DisableDSE( // SepInitializeCodeIntegrity will then call this thunk. What a waste CONST PEFI_IMAGE_SECTION_HEADER TextSection = IMAGE_FIRST_SECTION(NtHeaders); VOID* JmpCiInitializeAddress = NULL; - Length = TextSection->SizeOfRawData; - Offset = 0; + Context.Length = TextSection->SizeOfRawData; + Context.Offset = 0; // Start decode loop - while ((InstructionAddress = (ZyanU64)(ImageBase + TextSection->VirtualAddress + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + while ((Context.InstructionAddress = (ZyanU64)(ImageBase + TextSection->VirtualAddress + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } - if ((Instruction.operand_count == 2 && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Instruction.operands[0].mem.base == ZYDIS_REGISTER_RIP) && - Instruction.mnemonic == ZYDIS_MNEMONIC_JMP) + if ((Context.Instruction.operand_count == 2 && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Context.Operands[0].mem.base == ZYDIS_REGISTER_RIP) && + Context.Instruction.mnemonic == ZYDIS_MNEMONIC_JMP) { // Check if this is 'jmp qword ptr ds:[CiInitialize IAT RVA]' ZyanU64 OperandAddress = 0; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[0], InstructionAddress, &OperandAddress)) && + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &OperandAddress)) && OperandAddress == (UINTN)CiInitialize) { - JmpCiInitializeAddress = (VOID*)InstructionAddress; + JmpCiInitializeAddress = (VOID*)Context.InstructionAddress; break; } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } if (JmpCiInitializeAddress == NULL) @@ -530,38 +529,39 @@ DisableDSE( } UINT8* LastMovIntoEcx = NULL; // Keep track of 'mov ecx, xxx' - the last one before call/jmp cs:__imp_CiInitialize is the one we want to patch - Length = PageSizeOfRawData; - Offset = 0; + Context.Length = PageSizeOfRawData; + Context.Offset = 0; // Start decode loop - while ((InstructionAddress = (ZyanU64)(PageStartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + while ((Context.InstructionAddress = (ZyanU64)(PageStartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is a 2-byte (size of our patch) 'mov ecx, ' and store the instruction address if so - if (Instruction.operand_count == 2 && Instruction.length == 2 && Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && Instruction.operands[0].reg.value == ZYDIS_REGISTER_ECX) + if (Context.Instruction.operand_count == 2 && Context.Instruction.length == 2 && Context.Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && Context.Operands[0].reg.value == ZYDIS_REGISTER_ECX) { - LastMovIntoEcx = (UINT8*)InstructionAddress; + LastMovIntoEcx = (UINT8*)Context.InstructionAddress; } else if ((BuildNumber >= 9200 && - ((Instruction.operand_count == 2 || Instruction.operand_count == 4) && - (Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Instruction.operands[0].mem.base == ZYDIS_REGISTER_RIP) && - ((Instruction.mnemonic == ZYDIS_MNEMONIC_JMP && Instruction.operand_count == 2) || - (Instruction.mnemonic == ZYDIS_MNEMONIC_CALL && Instruction.operand_count == 4)))) + ((Context.Instruction.operand_count == 2 || Context.Instruction.operand_count == 4) && + (Context.Operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Context.Operands[0].mem.base == ZYDIS_REGISTER_RIP) && + ((Context.Instruction.mnemonic == ZYDIS_MNEMONIC_JMP && Context.Instruction.operand_count == 2) || + (Context.Instruction.mnemonic == ZYDIS_MNEMONIC_CALL && Context.Instruction.operand_count == 4)))) || (BuildNumber < 9200 && - (Instruction.operand_count == 4 && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Instruction.operands[0].imm.is_relative == ZYAN_TRUE && - Instruction.mnemonic == ZYDIS_MNEMONIC_CALL))) + (Context.Instruction.operand_count == 4 && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Context.Operands[0].imm.is_relative == ZYAN_TRUE && + Context.Instruction.mnemonic == ZYDIS_MNEMONIC_CALL))) { // Check if this is // 'call IMM:CiInitialize thunk' // E8 ?? ?? ?? ?? // Windows Vista/7 @@ -570,7 +570,7 @@ DisableDSE( // or // 'call qword ptr ds:[CiInitialize IAT RVA]' // FF 15 ?? ?? ?? ?? // Windows 10.0.16299.0+ ZyanU64 OperandAddress = 0; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[0], InstructionAddress, &OperandAddress)) && + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &OperandAddress)) && OperandAddress == (UINTN)CiInitialize) { SepInitializeCodeIntegrityMovEcxAddress = LastMovIntoEcx; // The last 'mov ecx, xxx' before the call/jmp is the instruction we want @@ -580,7 +580,7 @@ DisableDSE( } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } if (SepInitializeCodeIntegrityMovEcxAddress == NULL) @@ -593,35 +593,36 @@ DisableDSE( if (BuildNumber < 9200) { // On Windows Vista/7, find g_CiEnabled now because it's a few bytes away and we'll it need later - Length = 32; - Offset = 0; - - while ((InstructionAddress = (ZyanU64)(SepInitializeCodeIntegrityMovEcxAddress + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + Context.Length = 32; + Context.Offset = 0; + + while ((Context.InstructionAddress = (ZyanU64)(SepInitializeCodeIntegrityMovEcxAddress + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is 'mov g_CiEnabled, REG8' - if (Instruction.operand_count == 2 && - Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Instruction.operands[0].mem.base == ZYDIS_REGISTER_RIP && - Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) + if (Context.Instruction.operand_count == 2 && + Context.Instruction.mnemonic == ZYDIS_MNEMONIC_MOV && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Context.Operands[0].mem.base == ZYDIS_REGISTER_RIP && + Context.Operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) { - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[0], InstructionAddress, &gCiEnabled))) + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &gCiEnabled))) { PRINT_KERNEL_PATCH_MSG(L" Found g_CiEnabled at 0x%llX.\r\n", gCiEnabled); break; } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } if (gCiEnabled == 0) @@ -636,30 +637,31 @@ DisableDSE( UINT8 *SeValidateImageDataMovEaxAddress = NULL, *SeValidateImageDataJzAddress = NULL; // Start decode loop - Length = PageSizeOfRawData; - Offset = 0; - while ((InstructionAddress = (ZyanU64)(PageStartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + Context.Length = PageSizeOfRawData; + Context.Offset = 0; + while ((Context.InstructionAddress = (ZyanU64)(PageStartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // On Windows >= 8, check if this is 'mov eax, 0xC0000428' (STATUS_INVALID_IMAGE_HASH) in SeValidateImageData if ((BuildNumber >= 9200 && - (Instruction.operand_count == 2 && Instruction.mnemonic == ZYDIS_MNEMONIC_MOV) && - (Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && Instruction.operands[0].reg.value == ZYDIS_REGISTER_EAX) && - Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Instruction.operands[1].imm.value.s == 0xc0000428LL)) + (Context.Instruction.operand_count == 2 && Context.Instruction.mnemonic == ZYDIS_MNEMONIC_MOV) && + (Context.Operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && Context.Operands[0].reg.value == ZYDIS_REGISTER_EAX) && + Context.Operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && (Context.Operands[1].imm.value.s & 0xFFFFFFFFLL) == 0xc0000428LL)) { // Exclude false positives: next instruction must be jmp rel32 (Win 8), jmp rel8 (Win 8.1/10) or ret - CONST UINT8* Address = (UINT8*)InstructionAddress; + CONST UINT8* Address = (UINT8*)Context.InstructionAddress; CONST UINT8 JmpOpcode = BuildNumber >= 9600 ? 0xEB : 0xE9; - if (*(Address + Instruction.length) == JmpOpcode || *(Address + Instruction.length) == 0xC3) + if (*(Address + Context.Instruction.length) == JmpOpcode || *(Address + Context.Instruction.length) == 0xC3) { SeValidateImageDataMovEaxAddress = (UINT8*)Address; PRINT_KERNEL_PATCH_MSG(L" Found 'mov eax, 0xC0000428' in SeValidateImageData [RVA: 0x%X].\r\n", @@ -669,19 +671,19 @@ DisableDSE( } // On Windows Vista/7, check if this is 'cmp g_CiEnabled, al' in SeValidateImageData else if (BuildNumber < 9200 && - (Instruction.operand_count == 3 && Instruction.mnemonic == ZYDIS_MNEMONIC_CMP) && - (Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Instruction.operands[0].mem.base == ZYDIS_REGISTER_RIP) && - (Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && Instruction.operands[1].reg.value == ZYDIS_REGISTER_AL)) + (Context.Instruction.operand_count == 3 && Context.Instruction.mnemonic == ZYDIS_MNEMONIC_CMP) && + (Context.Operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY && Context.Operands[0].mem.base == ZYDIS_REGISTER_RIP) && + (Context.Operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER && Context.Operands[1].reg.value == ZYDIS_REGISTER_AL)) { ZyanU64 OperandAddress = 0; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[0], InstructionAddress, &OperandAddress)) && + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &OperandAddress)) && OperandAddress == gCiEnabled) { // Verify the next instruction is jz, and store its address instead of the cmp, as we will be patching the jz - CONST UINT8* Address = (UINT8*)InstructionAddress; - if (*(Address + Instruction.length) == 0x74) + CONST UINT8* Address = (UINT8*)Context.InstructionAddress; + if (*(Address + Context.Instruction.length) == 0x74) { - SeValidateImageDataJzAddress = (UINT8*)(Address + Instruction.length); + SeValidateImageDataJzAddress = (UINT8*)(Address + Context.Instruction.length); PRINT_KERNEL_PATCH_MSG(L" Found 'cmp g_CiEnabled, al' in SeValidateImageData [RVA: 0x%X].\r\n", (UINT32)(Address - ImageBase)); break; @@ -689,7 +691,7 @@ DisableDSE( } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } if (SeValidateImageDataMovEaxAddress == NULL && SeValidateImageDataJzAddress == NULL) diff --git a/EfiGuardDxe/PatchWinload.c b/EfiGuardDxe/PatchWinload.c index c231868..edf15ad 100644 --- a/EfiGuardDxe/PatchWinload.c +++ b/EfiGuardDxe/PatchWinload.c @@ -196,46 +196,45 @@ PatchImgpValidateImageHash( UINT8* AndMinusFortyOneAddress = NULL; // Initialize Zydis - ZydisDecoder Decoder; - ZyanStatus Status = ZydisInit(NtHeaders, &Decoder, NULL); + ZYDIS_CONTEXT Context; + ZyanStatus Status = ZydisInit(NtHeaders, &Context); if (!ZYAN_SUCCESS(Status)) { Print(L"Failed to initialize disassembler engine.\r\n"); return EFI_LOAD_ERROR; } - CONST UINTN Length = CodeSizeOfRawData; - UINTN Offset = 0; - ZyanU64 InstructionAddress; - ZydisDecodedInstruction Instruction; + Context.Length = CodeSizeOfRawData; + Context.Offset = 0; // Start decode loop - while ((InstructionAddress = (ZyanU64)(CodeStartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + while ((Context.InstructionAddress = (ZyanU64)(CodeStartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is 'and REG32, 0FFFFFFD7h' (only esi and r8d are used here really) - if (Instruction.operand_count == 3 && - (Instruction.length == 3 || Instruction.length == 4) && - Instruction.mnemonic == ZYDIS_MNEMONIC_AND && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && - Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && - Instruction.operands[1].imm.is_signed == ZYAN_TRUE && - Instruction.operands[1].imm.value.s == (ZyanI64)((ZyanI32)0xFFFFFFD7)) // Sign extend to 64 bits + if (Context.Instruction.operand_count == 3 && + (Context.Instruction.length == 3 || Context.Instruction.length == 4) && + Context.Instruction.mnemonic == ZYDIS_MNEMONIC_AND && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + Context.Operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && + Context.Operands[1].imm.is_signed == ZYAN_TRUE && + Context.Operands[1].imm.value.s == (ZyanI64)((ZyanI32)0xFFFFFFD7)) // Sign extend to 64 bits { - AndMinusFortyOneAddress = (UINT8*)InstructionAddress; + AndMinusFortyOneAddress = (UINT8*)Context.InstructionAddress; break; } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } // Backtrack to function start @@ -332,48 +331,47 @@ PatchImgpFilterValidationFailure( UINT8* LeaIntegrityFailureAddress = NULL; // Initialize Zydis - ZydisDecoder Decoder; - ZyanStatus Status = ZydisInit(NtHeaders, &Decoder, NULL); + ZYDIS_CONTEXT Context; + ZyanStatus Status = ZydisInit(NtHeaders, &Context); if (!ZYAN_SUCCESS(Status)) { Print(L"Failed to initialize disassembler engine.\r\n"); return EFI_LOAD_ERROR; } - CONST UINTN Length = CodeSizeOfRawData; - UINTN Offset = 0; - ZyanU64 InstructionAddress; - ZydisDecodedInstruction Instruction; + Context.Length = CodeSizeOfRawData; + Context.Offset = 0; // Start decode loop - while ((InstructionAddress = (ZyanU64)(CodeStartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + while ((Context.InstructionAddress = (ZyanU64)(CodeStartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is "lea REG, ds:[rip + offset_to_bsod_string]" - if (Instruction.operand_count == 2 && Instruction.mnemonic == ZYDIS_MNEMONIC_LEA && - Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && - Instruction.operands[1].mem.base == ZYDIS_REGISTER_RIP) + if (Context.Instruction.operand_count == 2 && Context.Instruction.mnemonic == ZYDIS_MNEMONIC_LEA && + Context.Operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && + Context.Operands[1].mem.base == ZYDIS_REGISTER_RIP) { ZyanU64 OperandAddress = 0; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[1], InstructionAddress, &OperandAddress)) && + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[1], Context.InstructionAddress, &OperandAddress)) && OperandAddress == (UINTN)IntegrityFailureStringAddress) { - LeaIntegrityFailureAddress = (UINT8*)InstructionAddress; + LeaIntegrityFailureAddress = (UINT8*)Context.InstructionAddress; Print(L" Found load instruction for load failure string at 0x%llx.\r\n", (UINTN)LeaIntegrityFailureAddress); break; } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } // Backtrack to function start @@ -470,55 +468,54 @@ FindOslFwpKernelSetupPhase1( UINT8* LeaEfiAcpiTableGuidAddress = NULL; // Initialize Zydis - ZydisDecoder Decoder; - ZyanStatus Status = ZydisInit(NtHeaders, &Decoder, NULL); + ZYDIS_CONTEXT Context; + ZyanStatus Status = ZydisInit(NtHeaders, &Context); if (!ZYAN_SUCCESS(Status)) { Print(L"Failed to initialize disassembler engine.\r\n"); return EFI_LOAD_ERROR; } - CONST UINTN Length = CodeSizeOfRawData; - UINTN Offset = 0; - ZyanU64 InstructionAddress; - ZydisDecodedInstruction Instruction; + Context.Length = CodeSizeOfRawData; + Context.Offset = 0; // Start decode loop - while ((InstructionAddress = (ZyanU64)(CodeStartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + while ((Context.InstructionAddress = (ZyanU64)(CodeStartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is "lea rcx, ds:[rip + offset_to_acpi20_guid]" - if (Instruction.operand_count == 2 && Instruction.mnemonic == ZYDIS_MNEMONIC_LEA && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && - Instruction.operands[0].reg.value == ZYDIS_REGISTER_RCX && - Instruction.operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && - Instruction.operands[1].mem.base == ZYDIS_REGISTER_RIP) + if (Context.Instruction.operand_count == 2 && Context.Instruction.mnemonic == ZYDIS_MNEMONIC_LEA && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER && + Context.Operands[0].reg.value == ZYDIS_REGISTER_RCX && + Context.Operands[1].type == ZYDIS_OPERAND_TYPE_MEMORY && + Context.Operands[1].mem.base == ZYDIS_REGISTER_RIP) { ZyanU64 OperandAddress = 0; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[1], InstructionAddress, &OperandAddress)) && + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[1], Context.InstructionAddress, &OperandAddress)) && OperandAddress == (UINTN)PatternAddress) { // Check for false positives (BlFwGetSystemTable) - CONST UINT8* Check = (UINT8*)(CodeStartVa + Offset - 4); // 4 = length of 'lea rdx, [r11+18h]' which precedes this instruction in EfipGetRsdt + CONST UINT8* Check = (UINT8*)(CodeStartVa + Context.Offset - 4); // 4 = length of 'lea rdx, [r11+18h]' which precedes this instruction in EfipGetRsdt if (Check[0] == 0x49 && Check[1] == 0x8D && Check[2] == 0x53) // If no match, this is not EfipGetRsdt { - LeaEfiAcpiTableGuidAddress = (UINT8*)InstructionAddress; + LeaEfiAcpiTableGuidAddress = (UINT8*)Context.InstructionAddress; Print(L" Found load instruction for EFI ACPI 2.0 GUID at 0x%llX.\r\n", (UINTN)LeaEfiAcpiTableGuidAddress); break; } } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } if (LeaEfiAcpiTableGuidAddress == NULL) @@ -539,42 +536,43 @@ FindOslFwpKernelSetupPhase1( UINT8* CallEfipGetRsdtAddress = NULL; // Start decode loop - Offset = 0; + Context.Offset = 0; UINTN ShortestDistanceToCall = MAX_UINTN; - while ((InstructionAddress = (ZyanU64)(CodeStartVa + Offset), - Status = ZydisDecoderDecodeBuffer(&Decoder, - (VOID*)InstructionAddress, - Length - Offset, - &Instruction)) != ZYDIS_STATUS_NO_MORE_DATA) + while ((Context.InstructionAddress = (ZyanU64)(CodeStartVa + Context.Offset), + Status = ZydisDecoderDecodeFull(&Context.Decoder, + (VOID*)Context.InstructionAddress, + Context.Length - Context.Offset, + &Context.Instruction, + Context.Operands)) != ZYDIS_STATUS_NO_MORE_DATA) { if (!ZYAN_SUCCESS(Status)) { - Offset++; + Context.Offset++; continue; } // Check if this is 'call IMM' - if (Instruction.operand_count == 4 && - Instruction.operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Instruction.operands[0].imm.is_relative == ZYAN_TRUE && - Instruction.mnemonic == ZYDIS_MNEMONIC_CALL) + if (Context.Instruction.operand_count == 4 && + Context.Operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE && Context.Operands[0].imm.is_relative == ZYAN_TRUE && + Context.Instruction.mnemonic == ZYDIS_MNEMONIC_CALL) { // Check if this is 'call EfipGetRsdt' ZyanU64 OperandAddress = 0; - if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Instruction, &Instruction.operands[0], InstructionAddress, &OperandAddress)) && + if (ZYAN_SUCCESS(ZydisCalcAbsoluteAddress(&Context.Instruction, &Context.Operands[0], Context.InstructionAddress, &OperandAddress)) && OperandAddress == (UINTN)EfipGetRsdt) { // Calculate the distance from the start of the function to the instruction. OslFwpKernelSetupPhase1 will always have the shortest distance - CONST UINTN StartOfFunction = (UINTN)BacktrackToFunctionStart(ImageBase, NtHeaders, (UINT8*)InstructionAddress); - CONST UINTN Distance = InstructionAddress - StartOfFunction; + CONST UINTN StartOfFunction = (UINTN)BacktrackToFunctionStart(ImageBase, NtHeaders, (UINT8*)Context.InstructionAddress); + CONST UINTN Distance = Context.InstructionAddress - StartOfFunction; if (Distance < ShortestDistanceToCall) { - CallEfipGetRsdtAddress = (UINT8*)InstructionAddress; + CallEfipGetRsdtAddress = (UINT8*)Context.InstructionAddress; ShortestDistanceToCall = Distance; } } } - Offset += Instruction.length; + Context.Offset += Context.Instruction.length; } if (CallEfipGetRsdtAddress == NULL) diff --git a/EfiGuardDxe/Zydis b/EfiGuardDxe/Zydis index ba9431c..aeb1b9a 160000 --- a/EfiGuardDxe/Zydis +++ b/EfiGuardDxe/Zydis @@ -1 +1 @@ -Subproject commit ba9431cf143f89f29343d0c3d737935545627367 +Subproject commit aeb1b9acf0703fd56dae879c99b05704ea955511 diff --git a/EfiGuardDxe/util.c b/EfiGuardDxe/util.c index 2bb406f..c1ad213 100644 --- a/EfiGuardDxe/util.c +++ b/EfiGuardDxe/util.c @@ -337,26 +337,23 @@ ZyanStatus EFIAPI ZydisInit( IN PEFI_IMAGE_NT_HEADERS NtHeaders, - OUT ZydisDecoder *Decoder, - OUT ZydisFormatter *Formatter OPTIONAL + OUT PZYDIS_CONTEXT Context ) { ZyanStatus Status; - if (!ZYAN_SUCCESS((Status = ZydisDecoderInit(Decoder, + if (!ZYAN_SUCCESS((Status = ZydisDecoderInit(&Context->Decoder, IMAGE64(NtHeaders) ? ZYDIS_MACHINE_MODE_LONG_64 : ZYDIS_MACHINE_MODE_LONG_COMPAT_32, - IMAGE64(NtHeaders) ? ZYDIS_ADDRESS_WIDTH_64 : ZYDIS_ADDRESS_WIDTH_32)))) + IMAGE64(NtHeaders) ? ZYDIS_STACK_WIDTH_64 : ZYDIS_STACK_WIDTH_32)))) return Status; -#ifdef ZYDIS_DISABLE_FORMATTER - ASSERT(Formatter == NULL); -#else - if (!ZYAN_SUCCESS((Status = ZydisFormatterInit(Formatter, ZYDIS_FORMATTER_STYLE_INTEL)))) +#ifndef ZYDIS_DISABLE_FORMATTER + if (!ZYAN_SUCCESS((Status = ZydisFormatterInit(&Context->Formatter, ZYDIS_FORMATTER_STYLE_INTEL)))) return Status; - if (!ZYAN_SUCCESS((Status = ZydisFormatterSetProperty(Formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE)))) + if (!ZYAN_SUCCESS((Status = ZydisFormatterSetProperty(&Context->Formatter, ZYDIS_FORMATTER_PROP_FORCE_SIZE, ZYAN_TRUE)))) return Status; - DefaultInstructionFormatter = (ZydisFormatterFunc)&ZydisInstructionBytesFormatter; - if (!ZYAN_SUCCESS((Status = ZydisFormatterSetHook(Formatter, + DefaultInstructionFormatter = &ZydisInstructionBytesFormatter; + if (!ZYAN_SUCCESS((Status = ZydisFormatterSetHook(&Context->Formatter, ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION, (CONST VOID**)&DefaultInstructionFormatter)))) return Status; diff --git a/EfiGuardDxe/util.h b/EfiGuardDxe/util.h index 4565c79..d69fc89 100644 --- a/EfiGuardDxe/util.h +++ b/EfiGuardDxe/util.h @@ -1,9 +1,11 @@ #pragma once -#include "EfiGuardDxe.h" - #include +#ifndef ZYDIS_DISABLE_FORMATTER +#include +#endif + // // Stalls CPU for N milliseconds // @@ -105,19 +107,33 @@ FindPatternVerbose( OUT VOID **Found ); -typedef struct ZydisFormatter_ ZydisFormatter; +// +// Zydis instruction decoder context. +// +typedef struct _ZYDIS_CONTEXT +{ + ZydisDecoder Decoder; + ZydisDecodedInstruction Instruction; + ZydisDecodedOperand Operands[ZYDIS_MAX_OPERAND_COUNT]; + + ZyanU64 InstructionAddress; + UINTN Length; + UINTN Offset; + +#ifndef ZYDIS_DISABLE_FORMATTER + ZydisFormatter Formatter; + CHAR8 InstructionText[256]; +#endif +} ZYDIS_CONTEXT, *PZYDIS_CONTEXT; // -// Initializes a ZydisDecoder instance. -// If ZYDIS_DISABLE_FORMATTER is defined, Formatter must be NULL. -// Otherwise it is a required argument. +// Initializes a decoder context. // ZyanStatus EFIAPI ZydisInit( IN PEFI_IMAGE_NT_HEADERS NtHeaders, - OUT ZydisDecoder *Decoder, - OUT ZydisFormatter *Formatter OPTIONAL + OUT PZYDIS_CONTEXT Context ); // -- cgit v1.2.3