erocarrera / pefile

pefile is a Python module to read and work with PE (Portable Executable) files
MIT License
1.86k stars 519 forks source link

Update new dvrt type and Load Config filed adapt to Windows11 #374

Closed zjgcjy closed 1 year ago

zjgcjy commented 1 year ago

https://github.com/erocarrera/pefile/pull/353 is a great pr as it parses the dvrt structure.

However, here is the problem that it didn't deal with.

  1. Load Config is still updating when it comes to Windows 11 22H2, so I add some fields copied from winnt.h
  2. A mistake at 18050fe (#353) missing a comma may cause problems when paring pe32
  3. Type mismatch at 18b71ea (#353) with declaration in winnt.h, which leads to the array half missing

The most important thing is win11 introduces a new dvrt type called function override as one part of retpoline. As mentioned in https://github.com/erocarrera/pefile/pull/353, retpoline is the policy that Microsoft use it to mitigate Spectre v2. In fact, retpoline uses the relocations stored in dvrt and the new type function override describes the function needed to be overridden when the image is loading. Here follows the brief code snippet in winnt.h (WDK ver.10.0.22621.0)

#define IMAGE_DYNAMIC_RELOCATION_FUNCTION_OVERRIDE              0x00000007

typedef struct _IMAGE_FUNCTION_OVERRIDE_HEADER {
    DWORD FuncOverrideSize;
 // IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION  FuncOverrideInfo[ANYSIZE_ARRAY]; // FuncOverrideSize bytes in size
 // IMAGE_BDD_INFO BDDInfo; // BDD region, size in bytes: DVRTEntrySize - sizeof(IMAGE_FUNCTION_OVERRIDE_HEADER) - FuncOverrideSize
} IMAGE_FUNCTION_OVERRIDE_HEADER;
typedef IMAGE_FUNCTION_OVERRIDE_HEADER UNALIGNED * PIMAGE_FUNCTION_OVERRIDE_HEADER;

typedef struct _IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION {
    DWORD OriginalRva;          // RVA of original function
    DWORD BDDOffset;            // Offset into the BDD region
    DWORD RvaSize;              // Size in bytes taken by RVAs. Must be multiple of sizeof(DWORD).
    DWORD BaseRelocSize;        // Size in bytes taken by BaseRelocs

    // DWORD RVAs[RvaSize / sizeof(DWORD)];     // Array containing overriding func RVAs. 

    // IMAGE_BASE_RELOCATION  BaseRelocs[ANYSIZE_ARRAY]; // Base relocations (RVA + Size + TO)
                                                         //  Padded with extra TOs for 4B alignment
                                                         // BaseRelocSize size in bytes
} IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION;
typedef IMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION * PIMAGE_FUNCTION_OVERRIDE_DYNAMIC_RELOCATION;

typedef struct _IMAGE_BDD_INFO {
    DWORD         Version;      // decides the semantics of serialized BDD
    DWORD         BDDSize;
    // IMAGE_BDD_DYNAMIC_RELOCATION BDDNodes[ANYSIZE_ARRAY]; // BDDSize size in bytes.
} IMAGE_BDD_INFO;
typedef IMAGE_BDD_INFO * PIMAGE_BDD_INFO;

typedef struct _IMAGE_BDD_DYNAMIC_RELOCATION {
    WORD   Left;                // Index of FALSE edge in BDD array
    WORD   Right;               // Index of TRUE edge in BDD array
    DWORD  Value;               // Either FeatureNumber or Index into RVAs array
} IMAGE_BDD_DYNAMIC_RELOCATION;
typedef IMAGE_BDD_DYNAMIC_RELOCATION * PIMAGE_BDD_DYNAMIC_RELOCATION;

// Function override relocation types in DVRT records.

#define IMAGE_FUNCTION_OVERRIDE_INVALID         0
#define IMAGE_FUNCTION_OVERRIDE_X64_REL32       1  // 32-bit relative address from byte following reloc
#define IMAGE_FUNCTION_OVERRIDE_ARM64_BRANCH26  2  // 26 bit offset << 2 & sign ext. for B & BL
#define IMAGE_FUNCTION_OVERRIDE_ARM64_THUNK     3

For more testing, here I give two cases that both are official drivers in win11 which can be downloaded from msdl directly:

  1. dxgkrnl.sys,10.0.22621.580
  2. dxgkrnl.sys,10.0.25127.1000