如何区分16位MZ和32位MZ

时间:2015-03-02 07:14:00

标签: c windows 32-bit portable-executable

我需要将32位PE与16位DOS MZ区分开来。 这样做的正确方法是什么? 我可以像寻找PE头一样使用启发式方法,但我觉得它不一定是确定性的

2 个答案:

答案 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风格的格式:

  1. 如果文件的开头不是以“MZ”或“ZM”开头,则它不是DOS或Windows可执行映像。否则,您可能具有以下类型的可执行格式之一:普通DOS,NE(Windows 16位),LE(16位VXD),PE32或PE32 +(PE64)。

  2. 通过查看e_lfanew值确定您是否具有纯DOS可执行文件。普通的DOS可执行文件将超出范围e_lfanew指向文件的限制之外,为零,或者如果偏移恰好在范围内,则其偏移处的签名将不匹配任何签名下方。

  3. 尝试将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)
    
  4. 更加模糊的签名(引自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