[vbox-dev] Fix PE loader problems with Windows 11 SDK 10.0.22621
Bien Pham
phamnnb at sea.com
Wed Jun 29 19:23:22 UTC 2022
Greetings,
The latest `IMAGE_LOAD_CONFIG_DIRECTORY(32|64)` structures added a new
`GuardMemcpyFunctionPointer` member. On the current trunk (r95063), V13
structures don't have this field, so VMs will not be able to start because
of the `VERR_LDRPE_LOAD_CONFIG_SIZE` check.
Struct references can be found on MSDN or in `winnt.h` of Windows 11 SDK,
version 10.0.22621.
This patch introduces V14 structures with the added field.
I'm submitting this patch under the MIT license.
Best regards,
Bien Pham - Sea Security Team
Index: include/iprt/formats/pecoff.h
===================================================================
--- include/iprt/formats/pecoff.h (revision 95063)
+++ include/iprt/formats/pecoff.h (working copy)
@@ -1375,11 +1375,68 @@
typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V13
*PIMAGE_LOAD_CONFIG_DIRECTORY32_V13;
typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V13 const
*PCIMAGE_LOAD_CONFIG_DIRECTORY32_V13;
-typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V13 IMAGE_LOAD_CONFIG_DIRECTORY32;
-typedef PIMAGE_LOAD_CONFIG_DIRECTORY32_V13 PIMAGE_LOAD_CONFIG_DIRECTORY32;
-typedef PCIMAGE_LOAD_CONFIG_DIRECTORY32_V13
PCIMAGE_LOAD_CONFIG_DIRECTORY32;
+/** @since Windows 11 SDK (found in 10.0.22621.0) /
IMAGE_LOAD_CONFIG_DIRECTORY32. */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V14
+{
+ uint32_t Size; /**< 0x00 - virtual
address */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 - virtual
address */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c - virtual
address */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 - virtual
address of pointer variable */
+ uint32_t ProcessHeapFlags; /**< 0x2c - virtual
address of pointer variable */
+ uint32_t ProcessAffinityMask; /**< 0x30 - virtual
address */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c - virtual
address */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 - virtual
address */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c - virtual
address */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 - virtual
address */
+ uint32_t GuardFlags; /**< 0x58 - virtual
address of pointer variable */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 - virtual
address */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 - virtual
address */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 - virtual
address */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure
when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 - virtual
address */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 - virtual
address of pointer variable */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+ uint32_t GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 -
virtual address of pointer variable */
+ uint32_t HotPatchTableOffset; /**< 0x94 */
+ uint32_t Reserved3; /**< 0x98 */
+ uint32_t EnclaveConfigurationPointer; /**< 0x9c - virtual
address of pointer variable */
+ uint32_t VolatileMetadataPointer; /**< 0xa0 - virtual
address of pointer variable */
+ uint32_t GuardEHContinuationTable; /**< 0xa4 - virtual
address */
+ uint32_t GuardEHContinuationCount; /**< 0xa8 */
+ uint32_t GuardXFGCheckFunctionPointer; /**< 0xac - virtual
address of pointer variable */
+ uint32_t GuardXFGDispatchFunctionPointer; /**< 0xb0 - virtual
address of pointer variable */
+ uint32_t GuardXFGTableDispatchFunctionPointer; /**< 0xb4 - virtual
address of pointer variable */
+ uint32_t CastGuardOsDeterminedFailureMode; /**< 0xb8 - virtual
address */
+ uint32_t GuardMemcpyFunctionPointer; /**< 0xbc - virtual
address of pointer variable */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V14;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V14, 0xc0);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V14
*PIMAGE_LOAD_CONFIG_DIRECTORY32_V14;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V14 const
*PCIMAGE_LOAD_CONFIG_DIRECTORY32_V14;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V14 IMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY32_V14 PIMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY32_V14
PCIMAGE_LOAD_CONFIG_DIRECTORY32;
+
/* No _IMAGE_LOAD_CONFIG_DIRECTORY64_V1 exists. */
typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V2
@@ -1911,10 +1968,67 @@
typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V13
*PIMAGE_LOAD_CONFIG_DIRECTORY64_V13;
typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V13 const
*PCIMAGE_LOAD_CONFIG_DIRECTORY64_V13;
-typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V13 IMAGE_LOAD_CONFIG_DIRECTORY64;
-typedef PIMAGE_LOAD_CONFIG_DIRECTORY64_V13 PIMAGE_LOAD_CONFIG_DIRECTORY64;
-typedef PCIMAGE_LOAD_CONFIG_DIRECTORY64_V13
PCIMAGE_LOAD_CONFIG_DIRECTORY64;
+/** @since Windows 11 SDK (found in 10.0.22621.0) /
IMAGE_LOAD_CONFIG_DIRECTORY64. */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V14
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 - virtual
address */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 - virtual
address */
+ uint64_t SecurityCookie; /**< 0x58 - virtual
address */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 - virtual
address of pointer variable */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 - virtual
address of pointer variable */
+ uint64_t GuardCFFunctionTable; /**< 0x80 - virtual
address */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 - virtual
address */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 - virtual
address */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 - virtual
address */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 - virtual
address */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 - virtual
address of pointer variable */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+ uint64_t GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 -
virtual address of pointer variable */
+ uint32_t HotPatchTableOffset; /**< 0xf0 */
+ uint32_t Reserved3; /**< 0xf4 */
+ uint64_t EnclaveConfigurationPointer; /**< 0xf8 - seen in
bcrypt and bcryptprimitives pointing to the string "L". */
+ uint64_t VolatileMetadataPointer; /**< 0x100 - virtual
address of pointer variable */
+ uint64_t GuardEHContinuationTable; /**< 0x108 - virtual
address */
+ uint64_t GuardEHContinuationCount; /**< 0x110 */
+ uint64_t GuardXFGCheckFunctionPointer; /**< 0x118 - virtual
address of pointer variable */
+ uint64_t GuardXFGDispatchFunctionPointer; /**< 0x120 - virtual
address of pointer variable */
+ uint64_t GuardXFGTableDispatchFunctionPointer; /**< 0x128 - virtual
address of pointer variable */
+ uint64_t CastGuardOsDeterminedFailureMode; /**< 0x130 - virtual
address */
+ uint64_t GuardMemcpyFunctionPointer; /**< 0x138 - virtual
address of pointer variable */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V14;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V14, 0x140);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V14
*PIMAGE_LOAD_CONFIG_DIRECTORY64_V14;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V14 const
*PCIMAGE_LOAD_CONFIG_DIRECTORY64_V14;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V14 IMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY64_V14 PIMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY64_V14
PCIMAGE_LOAD_CONFIG_DIRECTORY64;
+
/** @} */
Index: src/VBox/Runtime/common/ldr/ldrPE.cpp
===================================================================
--- src/VBox/Runtime/common/ldr/ldrPE.cpp (revision 95063)
+++ src/VBox/Runtime/common/ldr/ldrPE.cpp (working copy)
@@ -3824,9 +3824,10 @@
/*
* volatile everywhere! Trying to prevent the compiler being a
smarta$$ and reorder stuff.
*/
- IMAGE_LOAD_CONFIG_DIRECTORY32_V13 volatile *pLoadCfg32 =
(IMAGE_LOAD_CONFIG_DIRECTORY32_V13 volatile *)pLoadCfg;
- IMAGE_LOAD_CONFIG_DIRECTORY64_V13 volatile *pLoadCfg64 = pLoadCfg;
+ IMAGE_LOAD_CONFIG_DIRECTORY32_V14 volatile *pLoadCfg32 =
(IMAGE_LOAD_CONFIG_DIRECTORY32_V14 volatile *)pLoadCfg;
+ IMAGE_LOAD_CONFIG_DIRECTORY64_V14 volatile *pLoadCfg64 = pLoadCfg;
+ pLoadCfg64->GuardMemcpyFunctionPointer =
pLoadCfg32->GuardMemcpyFunctionPointer;
pLoadCfg64->CastGuardOsDeterminedFailureMode =
pLoadCfg32->CastGuardOsDeterminedFailureMode;
pLoadCfg64->GuardXFGTableDispatchFunctionPointer =
pLoadCfg32->GuardXFGTableDispatchFunctionPointer;
pLoadCfg64->GuardXFGDispatchFunctionPointer =
pLoadCfg32->GuardXFGDispatchFunctionPointer;
@@ -4455,6 +4456,9 @@
IMAGE_DATA_DIRECTORY Dir =
pOptHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
if (Dir.Size)
{
+ const size_t cbExpectV14 = !pModPe->f64Bit
+ ?
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V14)
+ :
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V14);
const size_t cbExpectV13 = !pModPe->f64Bit
?
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V13)
:
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V13);
@@ -4495,10 +4499,11 @@
? sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_V1)
: sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64_V2)
/*No V1*/;
const size_t cbNewHack = cbExpectV5; /* Playing safe here since
there might've been revisions between V5 and V6 we don't know about . */
- const size_t cbMaxKnown = cbExpectV12;
+ const size_t cbMaxKnown = cbExpectV14;
bool fNewerStructureHack = false;
- if ( Dir.Size != cbExpectV13
+ if ( Dir.Size != cbExpectV14
+ && Dir.Size != cbExpectV13
&& Dir.Size != cbExpectV12
&& Dir.Size != cbExpectV11
&& Dir.Size != cbExpectV10
@@ -4514,13 +4519,13 @@
{
fNewerStructureHack = Dir.Size > cbNewHack /* These structure
changes are slowly getting to us! More futher down. */
&& Dir.Size <= sizeof(u);
- Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u
bytes, expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu,
or %zu.%s\n",
- pszLogName, Dir.Size, cbExpectV13, cbExpectV12,
cbExpectV11, cbExpectV10, cbExpectV9, cbExpectV8, cbExpectV7, cbExpectV6,
cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1,
+ Log(("rtldrPEOpen: %s: load cfg dir: unexpected dir size of %u
bytes, expected %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu,
%zu, or %zu.%s\n",
+ pszLogName, Dir.Size, cbExpectV14, cbExpectV13,
cbExpectV12, cbExpectV11, cbExpectV10, cbExpectV9, cbExpectV8, cbExpectV7,
cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1,
fNewerStructureHack ? " Will try ignore extra bytes if
all zero." : ""));
if (!fNewerStructureHack)
return RTErrInfoSetF(pErrInfo, VERR_LDRPE_LOAD_CONFIG_SIZE,
- "Unexpected load config dir size of
%u bytes; supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu,
%zu, %zu, %zu, or %zu",
- Dir.Size, cbExpectV13, cbExpectV12,
cbExpectV11, cbExpectV10, cbExpectV9, cbExpectV8, cbExpectV7, cbExpectV6,
cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
+ "Unexpected load config dir size of
%u bytes; supported sized: %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu, %zu,
%zu, %zu, %zu, %zu, or %zu",
+ Dir.Size, cbExpectV14, cbExpectV13,
cbExpectV12, cbExpectV11, cbExpectV10, cbExpectV9, cbExpectV8, cbExpectV7,
cbExpectV6, cbExpectV5, cbExpectV4, cbExpectV3, cbExpectV2, cbExpectV1);
}
/*
@@ -4559,7 +4564,8 @@
}
/* Kludge #2: This happens a lot. Structure changes, but the
linker doesn't get
updated and stores some old size in the directory. Use the
header size. */
- else if ( u.Cfg64.Size == cbExpectV13
+ else if ( u.Cfg64.Size == cbExpectV14
+ || u.Cfg64.Size == cbExpectV13
|| u.Cfg64.Size == cbExpectV12
|| u.Cfg64.Size == cbExpectV11
|| u.Cfg64.Size == cbExpectV10
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.virtualbox.org/pipermail/vbox-dev/attachments/20220630/1bf738cf/attachment-0001.html>
More information about the vbox-dev
mailing list