Skip to content

MZ/PE: Parse and extract more information#2479

Merged
JeromeMartinez merged 5 commits intoMediaArea:masterfrom
cjee21:PE
Feb 8, 2026
Merged

MZ/PE: Parse and extract more information#2479
JeromeMartinez merged 5 commits intoMediaArea:masterfrom
cjee21:PE

Conversation

@cjee21
Copy link
Contributor

@cjee21 cjee21 commented Dec 10, 2025

Example (MediaInfo here is built in debug mode so no CFG flag in Dll_Characteristics):

>MediaInfo.exe MediaInfo.exe
General
Complete name                            : MediaInfo.exe
Format                                   : MZ
Format profile                           : Executable / AMD x86-64
File size                                : 15.8 MiB
Encoded date                             : 2025-12-10 15:49:07 UTC
Linker_Version                           : 14.50
Windows_Subsystem                        : Windows CUI
Subsystem_Version                        : 6.0
Dll_Characteristics                      : High Entropy VA, Dynamic Base, NX Compat, Terminal Server Aware
CompanyName                              : MediaArea.net
FileDescription                          : MediaInfo
FileVersion                              : 25.10.0.0
LegalCopyright                           : Copyright (C) 2002-2025 MediaArea.net SARL
ProductName                              : MediaInfo
ProductVersion                           : 25.10.0.0



>MediaInfo.exe MediaInfo.dll
General
Complete name                            : MediaInfo.dll
Format                                   : MZ
Format profile                           : DLL / AMD x86-64
File size                                : 20.0 MiB
Encoded date                             : 2025-12-10 15:49:06 UTC
Linker_Version                           : 14.50
Windows_Subsystem                        : Windows GUI
Subsystem_Version                        : 6.0
Dll_Characteristics                      : High Entropy VA, Dynamic Base, NX Compat
CompanyName                              : MediaArea.net
FileDescription                          : Most relevant technical and tag data for video and audio files
FileVersion                              : 25.10.0.0
LegalCopyright                           : Copyright (C) 2002-2025 MediaArea.net SARL
ProductName                              : MediaInfo
ProductVersion                           : 25.10.0.0



>MediaInfo.exe MediaInfo_GUI_25.09_Windows.exe
General
Complete name                            : MediaInfo_GUI_25.09_Windows.exe
Format                                   : MZ
Format profile                           : Executable / Intel i386
File size                                : 14.5 MiB
Encoded date                             : 2024-03-30 16:55:19 UTC
Linker_Version                           : 6.0
Windows_Subsystem                        : Windows GUI
Subsystem_Version                        : 4.0
Dll_Characteristics                      : Dynamic Base, NX Compat, No SEH, Terminal Server Aware
CompanyName                              : MediaArea.net
FileDescription                          : All about your audio and video files
FileVersion                              : 25.09.0.0
LegalCopyright                           : MediaArea.net
OriginalFilename                         : MediaInfo_GUI_25.09_Windows.exe
ProductName                              : MediaInfo
ProductVersion                           : 25.09.0.0



>MediaInfo.exe C:\Windows\Boot\EFI_EX\bootmgfw_EX.efi
General
Complete name                            : C:\Windows\Boot\EFI_EX\bootmgfw_EX.efi
Format                                   : MZ
Format profile                           : DLL / AMD x86-64
File size                                : 2.72 MiB
Encoded date                             : 2023-06-08 01:25:34 UTC
Linker_Version                           : 14.38
Windows_Subsystem                        : EFI Application
Subsystem_Version                        : 1.0
Dll_Characteristics                      : NX Compat
BootMgr_SVN                              : 7.0
CompanyName                              : Microsoft Corporation
FileDescription                          : Boot Manager
FileVersion                              : 10.0.26100.30227 (WinBuild.160101.0800)
InternalName                             : bootmgr.exe
LegalCopyright                           : © Microsoft Corporation. All rights reserved.
OriginalFilename                         : bootmgr.exe
ProductName                              : Microsoft® Windows® Operating System
ProductVersion                           : 10.0.26100.30227



>MediaInfo.exe C:\Windows\Boot\EFI\memtest.efi
General
Complete name                            : C:\Windows\Boot\EFI\memtest.efi
Format                                   : MZ
Format profile                           : Executable / AMD x86-64
File size                                : 2.49 MiB
Encoded date                             : 2090-12-12 08:44:11 UTC
Linker_Version                           : 14.38
Windows_Subsystem                        : Windows Boot Application
Subsystem_Version                        : 1.0
CompanyName                              : Microsoft Corporation
FileDescription                          : Memory Diagnostic
FileVersion                              : 10.0.26100.7309 (WinBuild.160101.0800)
InternalName                             : memdiag.exe
LegalCopyright                           : © Microsoft Corporation. All rights reserved.
OriginalFilename                         : memdiag.exe
ProductName                              : Microsoft® Windows® Operating System
ProductVersion                           : 10.0.26100.7309



>MediaInfo.exe D:\EFI\boot\grubx64.efi
General
Complete name                            : D:\EFI\boot\grubx64.efi
Format                                   : MZ
Format profile                           : Executable / AMD x86-64
File size                                : 2.26 MiB
Encoded date                             : 2015-01-01 00:00:00 UTC
Windows_Subsystem                        : EFI Application
Dll_Characteristics                      : NX Compat
SBAT                                     : sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md / grub,5,Free Software Foundation,grub,2.14~git20250718.0e36779,https://www.gnu.org/software/grub/ / grub.ubuntu,2,Ubuntu,grub2,2.14~git20250718.0e36779-1ubuntu4,https://www.ubuntu.com/ / grub.ubuntu26,1,Ubuntu,grub2,2.14~git20250718.0e36779-1ubuntu4,https://www.ubuntu.com/ / grub.peimage,2,Canonical,grub2,2.14~git20250718.0e36779-1ubuntu4,https://salsa.debian.org/grub-team/grub/-/blob/master/debian/patches/secure-boot/efi-use-peimage-shim.patch



@cjee21
Copy link
Contributor Author

cjee21 commented Dec 10, 2025

Some parts of the parsing are kind of messy since it is not simple but so far it worked fine with files I tested.


Oh it seems some issues parsing MediaInfo installer version info.


Fixed. Looks like the flag can be both binary or text.

@cjee21
Copy link
Contributor Author

cjee21 commented Dec 10, 2025

Have not found easy way to detect ARM64EC/ARM64X or the CETCOMPAT flag.

Copy link
Member

@JeromeMartinez JeromeMartinez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the hard work.

But a bit more work needed, especially for:

Have not found easy way to detect ARM64EC/ARM64X

Aren't they in the Machine Type?
IMAGE_FILE_MACHINE_ARM64EC | 0xA641 | ABI that enables interoperability between native ARM64 and emulated x64 code.
IMAGE_FILE_MACHINE_ARM64X | 0xA64E | Binary format that allows both native ARM64 and ARM64EC code to coexist in the same file.

(but I am a bit lost there, so not sure)

or the CETCOMPAT flag.

DllCharacteristics 0x4000 → either interpreted as Guard CF or CET_COMPAT, depending on OS version and SDK.
Load Config GuardFlags → actual runtime enforcement:
IMAGE_GUARD_CF_INSTRUMENTED → software CFG
IMAGE_GUARD_SHADOW_STACK → CET

static const char* Mz_Windows_Subsystem(int16u Subsystem)
{
switch (Subsystem) {
case 0: return "Unknown";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: I prefer just a static const char* [] + test on the size of the array, like Mz_Directories.

Copy link
Contributor Author

@cjee21 cjee21 Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The values that have strings are not continuous though.

I'll change to array and put empty strings for the missing ones.

};
mz_dllcharacteristics_data Mz_DLLCharacteristics_Data[] =
{
{ 0x0020, "High Entropy VA" },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: I prefer just a static const char* [] and the line number of the list is the bit offset. From doc it is "reserved" but still has a name (bit 4 is just "") and this function iterates over the bitfield.

Fill(Stream_General, 0, "Windows_Subsystem", Mz_Windows_Subsystem(Subsystem));
if (MajorSubsystemVersion)
Fill(Stream_General, 0, "Subsystem_Version", std::to_string(MajorSubsystemVersion) + "." + std::to_string(MinorSubsystemVersion));
Fill(Stream_General, 0, "Dll_Characteristics", Mz_DLL_Characteristics(DllCharacteristics));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fill(Stream_General, 0, "Dll_Characteristics", Mz_DLL_Characteristics(DllCharacteristics));
Fill(Stream_General, 0, "Format_Settings", Mz_DLL_Characteristics(DllCharacteristics));

}
if (MajorLinkerVersion)
Fill(Stream_General, 0, "Linker_Version", std::to_string(MajorLinkerVersion) + "." + std::to_string(MinorLinkerVersion));
Fill(Stream_General, 0, "Windows_Subsystem", Mz_Windows_Subsystem(Subsystem));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fill(Stream_General, 0, "Windows_Subsystem", Mz_Windows_Subsystem(Subsystem));
Fill(Stream_General, 0, "Subsystem_Name", Mz_Windows_Subsystem(Subsystem));

Get_L2(majorver, "MajorVersion");

FILLING_BEGIN();
Fill(Stream_General, 0, "BootMgr_SVN", std::to_string(majorver) + "." + std::to_string(minorver));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Fill(Stream_General, 0, "BootMgr_SVN", std::to_string(majorver) + "." + std::to_string(minorver));
Fill(Stream_General, 0, "BootMgrSecurity_Version", std::to_string(majorver) + "." + std::to_string(minorver));


FILLING_BEGIN();
if (level == 2) {
Fill(Stream_General, 0, szKey.To_UTF8().c_str(), Value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to add a mapping of "known names" with e.g.
LegalCopyright --> Copyright
CompanytName --> Software_CompanyName
FileVersion --> Software_Version
FileName --> Software_Name
(I try to have something like what we have with EXIF "Encoded_Application_*" stuff so I'll do something similar with one line default display)

@cjee21
Copy link
Contributor Author

cjee21 commented Feb 8, 2026

A rebase first...

@cjee21
Copy link
Contributor Author

cjee21 commented Feb 8, 2026

DllCharacteristics 0x4000 → either interpreted as Guard CF or CET_COMPAT, depending on OS version and SDK.

CETCOMPAT is in Extended DLL Characteristics. Not sure how to get/parse there.


Looks like it is in Mz_Directories == "Debug".

@cjee21
Copy link
Contributor Author

cjee21 commented Feb 8, 2026

Aren't they in the Machine Type?

Not so simple. Look at MediaInfo.dll ARM64X:

0000114   Machine:                              43620 (0xAA64) - ARM64

but peview can identify that it is ARM64X, not ARM64 or ARM64EC. It also seems it may be able to determine whether the ARM64X defaults to ARM64 or ARM64EC.

or an ARM64EC file:

000114   Machine:                              34404 (0x8664) - AMD x86-64

It is not simple because for compatibility, the ARM64X binary has to appear like a usual ARM64 or x64 binary and ARM64EC like a x64 if I remember correctly.


Looks like we have to get to IMAGE_LOAD_CONFIG_DIRECTORY from Mz_Directories[10] == "Load Config Table".

Then parse if 64-bits -> https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_load_config_directory64.

DynamicValueRelocTable and CHPEMetadataPointer supposedly will be able to give us what is needed to determine if it is ARM64EC or ARM64X.


More info: https://ffri.github.io/ProjectChameleon/new_reloc_chpev2/


I see Section Header - .a64xrm which may be hint of ARM64X/ARM64EC.

@cjee21
Copy link
Contributor Author

cjee21 commented Feb 8, 2026

CET compat detection done. The way I jump around the file for the various elements looks like a hack and does not seem scalable. May need a good "infrastructure" for navigating if we are to parse more stuff.

Copy link
Member

@JeromeMartinez JeromeMartinez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go with that for now and we see what can be improved step by step.

@JeromeMartinez JeromeMartinez merged commit 3a336d7 into MediaArea:master Feb 8, 2026
15 checks passed
@cjee21 cjee21 deleted the PE branch February 8, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants