我需要将32位PE与16位DOS MZ区分开来。 这样做的正确方法是什么? 我可以像寻找PE头一样使用启发式方法,但我觉得它不一定是确定性的
答案 0 :(得分:6)
所有DOS风格的可执行文件都有一个' MZ'作为前两个字节 要识别MSDOS可执行文件与众多其他变体,最好的选择似乎是读取文件中偏移量0x0018处的重定位表的位置,如果这大于0x0040(进入文件)它不仅仅是普通的DOS
要将可执行文件明确标识为' PE'可执行文件中有一个偏移量为0x003C的指针。这是文件中的偏移量,它将具有字节' PE'和两个人。其他MSDOS' MZ'变体将使用相同的位置来放置其他代码,例如:' NE'' W3'' LE'等
' PE'样式可执行文件也有多种形式,我希望你至少对32位和64位感兴趣。
这种事情的最终权威可能是Unix'文件'命令,它旨在通过调查它的内容可靠地识别任何文件类型。 MSDOS部分列出here。 Microsoft不是这方面的可靠权威,因为他们忽略了非Microsoft信息。
答案 1 :(得分:2)
普通的DOS EXE标头只有28(0x1C
)个字节长,如果存在,通常会跟着DOS重定位表。 NT PE标头的IMAGE_DOS_HEADER
struct
在64(0x40)字节处大得多,因为它已针对各种其他Windows可执行格式进行了扩展。这个标题大小差异是为什么来自@ user3710044的答案不仅是最快但是可靠的:如果重定位表[e_lfarlc]< EXE是普通的DOS。 0x40的)。
只要您意识到普通DOS可执行文件中不存在e_lfanew
成员(对多个可能的“扩展”标头的偏移),您还可以使用以下逻辑来区分各种MZ风格的格式:
如果文件的开头不是以“MZ”或“ZM”开头,则它不是DOS或Windows可执行映像。否则,您可能具有以下类型的可执行格式之一:普通DOS,NE(Windows 16位),LE(16位VXD),PE32或PE32 +(PE64)。
通过查看e_lfanew
值确定您是否具有纯DOS可执行文件。普通的DOS可执行文件将超出范围e_lfanew
指向文件的限制之外,为零,或者如果偏移恰好在范围内,则其偏移处的签名将不匹配任何签名下方。
尝试将e_lfanew
指向的“范围内”偏移的签名与以下WORD或DWORD值匹配:
"PE" followed by two zero bytes if the image is a PE32 or PE32+ (PE64) and is further determined by the "magic" in the NT Optional Header
"NE" indicates the image is a 16-bit Windows executable
"LE" indicates the image is a 16-bit Virtual Device Driver (VXD)
更加模糊的签名(引自Ralph Brown's INT 21/AH=4Bh):
LX variant of LE used in OS/2 2.x
W3 Windows WIN386.EXE file; a collection of LE files
W4 Windows95 VMM32.VXD file
DL HP 100LX/200LX system manager compliant executable (.EXM)
MP old PharLap .EXP
P2 PharLap 286 .EXP
P3 PharLap 386 .EXP