aboutsummaryrefslogtreecommitdiff
path: root/EfiGuardDxe
diff options
context:
space:
mode:
authorMatthijs Lavrijsen <mattiwatti@gmail.com>2023-03-26 01:49:12 +0100
committerMatthijs Lavrijsen <mattiwatti@gmail.com>2023-03-26 09:05:03 +0200
commit30e8570f9a3585572f60867166ac74f8951bf804 (patch)
tree2e446eef754d577bf37802a014066a9392cc8e14 /EfiGuardDxe
parent513c08bc0073a04b07041fd1c08a288069b31302 (diff)
Update Zydis to v4
Diffstat (limited to 'EfiGuardDxe')
-rw-r--r--EfiGuardDxe/EfiGuardDxe.inf13
-rw-r--r--EfiGuardDxe/EfiGuardDxe.vcxproj56
-rw-r--r--EfiGuardDxe/EfiGuardDxe.vcxproj.filters87
-rw-r--r--EfiGuardDxe/PatchNtoskrnl.c254
-rw-r--r--EfiGuardDxe/PatchWinload.c148
m---------EfiGuardDxe/Zydis0
-rw-r--r--EfiGuardDxe/util.c19
-rw-r--r--EfiGuardDxe/util.h32
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
);
//