[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 GMT 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.html>


More information about the vbox-dev mailing list