diff options
author | Matthijs Lavrijsen <mattiwatti@gmail.com> | 2023-03-26 01:49:12 +0100 |
---|---|---|
committer | Matthijs Lavrijsen <mattiwatti@gmail.com> | 2023-03-26 09:05:03 +0200 |
commit | 30e8570f9a3585572f60867166ac74f8951bf804 (patch) | |
tree | 2e446eef754d577bf37802a014066a9392cc8e14 /EfiGuardDxe | |
parent | 513c08bc0073a04b07041fd1c08a288069b31302 (diff) |
Update Zydis to v4
Diffstat (limited to 'EfiGuardDxe')
-rw-r--r-- | EfiGuardDxe/EfiGuardDxe.inf | 13 | ||||
-rw-r--r-- | EfiGuardDxe/EfiGuardDxe.vcxproj | 56 | ||||
-rw-r--r-- | EfiGuardDxe/EfiGuardDxe.vcxproj.filters | 87 | ||||
-rw-r--r-- | EfiGuardDxe/PatchNtoskrnl.c | 254 | ||||
-rw-r--r-- | EfiGuardDxe/PatchWinload.c | 148 | ||||
m--------- | EfiGuardDxe/Zydis | 0 | ||||
-rw-r--r-- | EfiGuardDxe/util.c | 19 | ||||
-rw-r--r-- | EfiGuardDxe/util.h | 32 |
8 files changed, 342 insertions, 267 deletions
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 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ItemDefinitionGroup> <ClCompile> - <PreprocessorDefinitions>ZYAN_UEFI;ZYAN_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;ZYDIS_DISABLE_AVX512;ZYDIS_DISABLE_KNC;ZYDIS_DISABLE_FORMATTER;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>ZYAN_NO_LIBC;ZYCORE_STATIC_BUILD;ZYDIS_STATIC_BUILD;ZYDIS_DISABLE_ENCODER;ZYDIS_DISABLE_FORMATTER;ZYDIS_DISABLE_AVX512;ZYDIS_DISABLE_KNC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <AdditionalIncludeDirectories>$(SolutionDir)Include;Zydis/dependencies/zycore/include;Zydis/include;Zydis/src;Zydis/msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <Optimization>MaxSpeed</Optimization> + <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4201</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>UefiDriverEntryPoint.lib;BaseMemoryLib.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -45,14 +46,28 @@ <ClCompile Include="VisualUefi.c" /> <ClCompile Include="Zydis\src\Decoder.c" /> <ClCompile Include="Zydis\src\DecoderData.c" /> - <ClCompile Include="Zydis\src\Formatter.c" /> - <ClCompile Include="Zydis\src\FormatterATT.c" /> - <ClCompile Include="Zydis\src\FormatterBase.c" /> - <ClCompile Include="Zydis\src\FormatterBuffer.c" /> - <ClCompile Include="Zydis\src\FormatterIntel.c" /> + <ClCompile Include="Zydis\src\Disassembler.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="Zydis\src\Formatter.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="Zydis\src\FormatterATT.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="Zydis\src\FormatterBase.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="Zydis\src\FormatterBuffer.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> + <ClCompile Include="Zydis\src\FormatterIntel.c"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClCompile> <ClCompile Include="Zydis\src\MetaInfo.c" /> <ClCompile Include="Zydis\src\Mnemonic.c" /> <ClCompile Include="Zydis\src\Register.c" /> + <ClCompile Include="Zydis\src\Segment.c" /> <ClCompile Include="Zydis\src\SharedData.c" /> <ClCompile Include="Zydis\src\String.c" /> <ClCompile Include="Zydis\src\Utils.c" /> @@ -66,33 +81,46 @@ <ClInclude Include="pe.h" /> <ClInclude Include="util.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Allocator.h" /> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\ArgParse.h" /> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Atomic.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Bitset.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Comparison.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Defines.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Format.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\LibC.h" /> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\List.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Object.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Status.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\String.h" /> - <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Terminal.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Types.h" /> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Vector.h" /> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Zycore.h" /> <ClInclude Include="Zydis\include\Zydis\Decoder.h" /> <ClInclude Include="Zydis\include\Zydis\DecoderTypes.h" /> - <ClInclude Include="Zydis\include\Zydis\Formatter.h" /> + <ClInclude Include="Zydis\include\Zydis\Defines.h" /> + <ClInclude Include="Zydis\include\Zydis\Disassembler.h"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Formatter.h"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\FormatterBuffer.h"> + <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Internal\DecoderData.h" /> + <ClInclude Include="Zydis\include\Zydis\Internal\FormatterATT.h" /> + <ClInclude Include="Zydis\include\Zydis\Internal\FormatterBase.h" /> + <ClInclude Include="Zydis\include\Zydis\Internal\FormatterIntel.h" /> + <ClInclude Include="Zydis\include\Zydis\Internal\SharedData.h" /> + <ClInclude Include="Zydis\include\Zydis\Internal\String.h" /> <ClInclude Include="Zydis\include\Zydis\MetaInfo.h" /> <ClInclude Include="Zydis\include\Zydis\Mnemonic.h" /> <ClInclude Include="Zydis\include\Zydis\Register.h" /> + <ClInclude Include="Zydis\include\Zydis\Segment.h" /> <ClInclude Include="Zydis\include\Zydis\SharedTypes.h" /> <ClInclude Include="Zydis\include\Zydis\ShortString.h" /> <ClInclude Include="Zydis\include\Zydis\Status.h" /> <ClInclude Include="Zydis\include\Zydis\Utils.h" /> <ClInclude Include="Zydis\include\Zydis\Zydis.h" /> - <ClInclude Include="Zydis\include\Zydis\Internal\DecoderData.h" /> - <ClInclude Include="Zydis\include\Zydis\Internal\FormatterATT.h" /> - <ClInclude Include="Zydis\include\Zydis\Internal\FormatterBase.h" /> - <ClInclude Include="Zydis\include\Zydis\Internal\FormatterIntel.h" /> - <ClInclude Include="Zydis\include\Zydis\Internal\SharedData.h" /> - <ClInclude Include="Zydis\include\Zydis\Internal\String.h" /> </ItemGroup> </Project>
\ 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 @@ <ClCompile Include="PatchNtoskrnl.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="VisualUefi.c"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="Zydis\src\Decoder.c"> <Filter>Source Files\Zydis</Filter> </ClCompile> <ClCompile Include="Zydis\src\DecoderData.c"> <Filter>Source Files\Zydis</Filter> </ClCompile> + <ClCompile Include="Zydis\src\Disassembler.c"> + <Filter>Source Files\Zydis</Filter> + </ClCompile> <ClCompile Include="Zydis\src\Formatter.c"> <Filter>Source Files\Zydis</Filter> </ClCompile> @@ -74,6 +80,9 @@ <ClCompile Include="Zydis\src\Register.c"> <Filter>Source Files\Zydis</Filter> </ClCompile> + <ClCompile Include="Zydis\src\Segment.c"> + <Filter>Source Files\Zydis</Filter> + </ClCompile> <ClCompile Include="Zydis\src\SharedData.c"> <Filter>Source Files\Zydis</Filter> </ClCompile> @@ -86,9 +95,6 @@ <ClCompile Include="Zydis\src\Zydis.c"> <Filter>Source Files\Zydis</Filter> </ClCompile> - <ClCompile Include="VisualUefi.c"> - <Filter>Source Files</Filter> - </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="EfiGuardDxe.h"> @@ -103,9 +109,21 @@ <ClInclude Include="util.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\Include\Protocol\EfiGuard.h"> + <Filter>Header Files\Protocol</Filter> + </ClInclude> + <ClInclude Include="ntdef.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Allocator.h"> <Filter>Header Files\Zydis\Zycore</Filter> </ClInclude> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\ArgParse.h"> + <Filter>Header Files\Zydis\Zycore</Filter> + </ClInclude> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Atomic.h"> + <Filter>Header Files\Zydis\Zycore</Filter> + </ClInclude> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Bitset.h"> <Filter>Header Files\Zydis\Zycore</Filter> </ClInclude> @@ -121,6 +139,9 @@ <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\LibC.h"> <Filter>Header Files\Zydis\Zycore</Filter> </ClInclude> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\List.h"> + <Filter>Header Files\Zydis\Zycore</Filter> + </ClInclude> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Object.h"> <Filter>Header Files\Zydis\Zycore</Filter> </ClInclude> @@ -130,24 +151,51 @@ <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\String.h"> <Filter>Header Files\Zydis\Zycore</Filter> </ClInclude> - <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Terminal.h"> - <Filter>Header Files\Zydis\Zycore</Filter> - </ClInclude> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Types.h"> <Filter>Header Files\Zydis\Zycore</Filter> </ClInclude> <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Vector.h"> <Filter>Header Files\Zydis\Zycore</Filter> </ClInclude> + <ClInclude Include="Zydis\dependencies\zycore\include\Zycore\Zycore.h"> + <Filter>Header Files\Zydis\Zycore</Filter> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Internal\DecoderData.h"> + <Filter>Header Files\Zydis\Internal</Filter> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Internal\FormatterATT.h"> + <Filter>Header Files\Zydis\Internal</Filter> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Internal\FormatterBase.h"> + <Filter>Header Files\Zydis\Internal</Filter> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Internal\FormatterIntel.h"> + <Filter>Header Files\Zydis\Internal</Filter> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Internal\SharedData.h"> + <Filter>Header Files\Zydis\Internal</Filter> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Internal\String.h"> + <Filter>Header Files\Zydis\Internal</Filter> + </ClInclude> <ClInclude Include="Zydis\include\Zydis\Decoder.h"> <Filter>Header Files\Zydis</Filter> </ClInclude> <ClInclude Include="Zydis\include\Zydis\DecoderTypes.h"> <Filter>Header Files\Zydis</Filter> </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Defines.h"> + <Filter>Header Files\Zydis</Filter> + </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Disassembler.h"> + <Filter>Header Files\Zydis</Filter> + </ClInclude> <ClInclude Include="Zydis\include\Zydis\Formatter.h"> <Filter>Header Files\Zydis</Filter> </ClInclude> + <ClInclude Include="Zydis\include\Zydis\FormatterBuffer.h"> + <Filter>Header Files\Zydis</Filter> + </ClInclude> <ClInclude Include="Zydis\include\Zydis\MetaInfo.h"> <Filter>Header Files\Zydis</Filter> </ClInclude> @@ -157,6 +205,9 @@ <ClInclude Include="Zydis\include\Zydis\Register.h"> <Filter>Header Files\Zydis</Filter> </ClInclude> + <ClInclude Include="Zydis\include\Zydis\Segment.h"> + <Filter>Header Files\Zydis</Filter> + </ClInclude> <ClInclude Include="Zydis\include\Zydis\SharedTypes.h"> <Filter>Header Files\Zydis</Filter> </ClInclude> @@ -172,29 +223,5 @@ <ClInclude Include="Zydis\include\Zydis\Zydis.h"> <Filter>Header Files\Zydis</Filter> </ClInclude> - <ClInclude Include="Zydis\include\Zydis\Internal\DecoderData.h"> - <Filter>Header Files\Zydis\Internal</Filter> - </ClInclude> - <ClInclude Include="Zydis\include\Zydis\Internal\FormatterATT.h"> - <Filter>Header Files\Zydis\Internal</Filter> - </ClInclude> - <ClInclude Include="Zydis\include\Zydis\Internal\FormatterBase.h"> - <Filter>Header Files\Zydis\Internal</Filter> - </ClInclude> - <ClInclude Include="Zydis\include\Zydis\Internal\FormatterIntel.h"> - <Filter>Header Files\Zydis\Internal</Filter> - </ClInclude> - <ClInclude Include="Zydis\include\Zydis\Internal\SharedData.h"> - <Filter>Header Files\Zydis\Internal</Filter> - </ClInclude> - <ClInclude Include="Zydis\include\Zydis\Internal\String.h"> - <Filter>Header Files\Zydis\Internal</Filter> - </ClInclude> - <ClInclude Include="..\Include\Protocol\EfiGuard.h"> - <Filter>Header Files\Protocol</Filter> - </ClInclude> - <ClInclude Include="ntdef.h"> - <Filter>Header Files</Filter> - </ClInclude> </ItemGroup> </Project>
\ 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, <anything>' 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 -Subproject ba9431cf143f89f29343d0c3d73793554562736 +Subproject aeb1b9acf0703fd56dae879c99b05704ea95551 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 <Protocol/LoadedImage.h> +#ifndef ZYDIS_DISABLE_FORMATTER +#include <Zydis/Formatter.h> +#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 ); // |