【问题标题】:How to differentiate 16 bit MZ and 32 bit MZ如何区分 16 位 MZ 和 32 位 MZ
【发布时间】:2015-05-02 11:43:31
【问题描述】:

我需要区分 32 位 PE 和 16 位 DOS MZ。 正确的方法是什么? 我可以使用诸如寻找 PE 标头之类的启发式方法,但我觉得它不一定是确定性的

【问题讨论】:

  • 这不仅仅是“启发式”。所有可执行文件都有一个 16 位的加载器,对于 32 位(也可以是 LE),标头提供了准确的必要信息。操作系统怎么会知道?

标签: c windows 32-bit portable-executable


【解决方案1】:

所有 DOS 风格的可执行文件都有一个“MZ”作为前两个字节。
要识别 MSDOS 可执行文件与众多其他变体,最好的办法似乎是读取文件中偏移量 0x0018 处的重定位表的位置,如果该位置大于 0x0040(进入文件),则不仅仅是普通的 DOS .

为了将可执行文件明确标识为“PE”可执行文件,文件中的偏移量为 0x003C 处有一个指针。这是文件中的偏移量,将包含字节“PE”和两个 nuls。其他 MSDOS 'MZ' 变体将使用相同的位置来放置其他代码,例如:'NE'、'W3'、'LE' 等。

“PE”风格的可执行文件也有多种形式,我希望您至少会对 32 位和 64 位感兴趣。

这类事情的最终权威可能是 Unix 的“文件”命令,它旨在通过调查其内容来可靠地识别任何文件类型。 MSDOS 部分在here 中列出。 Microsoft 在这方面不是可靠的权威,因为他们忽略了非 Microsoft 信息。

【讨论】:

    【解决方案2】:

    普通的 DOS EXE 标头只有 28 (0x1C) 字节长,如果存在,通常后跟 DOS 重定位表。 NT PE 标头的IMAGE_DOS_HEADERstruct 在64 (0x40) 字节处要大得多,因为它已针对各种其他Windows 可执行格式进行了扩展。这个标头大小差异是为什么来自@user3710044 的答案不仅是最快的而且是可靠的:如果重定位表 [e_lfarlc]

    只要你意识到e_lfanew 成员(对许多可能的“扩展”头文件的偏移)在普通的 DOS 可执行文件中不存在,你也可以使用以下逻辑来区分各种 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)
      

    更多晦涩的签名(引用自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
    

    【讨论】:

    • LE表示文件包含16位代码是不正确的。例如,文件 VIPX.386 (Windows 3.1) 包含 32 位代码,如目标操作系统 LE 标头字段 (Windows 386) 和对象表条目的标志字段的第 13 位所示。有关 LE 和 LX 标头的更多信息:program-transformation.org/Transform/PcExeFormat
    • 关于 LE 的正确陈述:通常是 Windows 3.x、Windows 95、Windows 98 和 Windows Me 上的 32 位虚拟设备驱动程序 (VxD),或 32 位 DOS 可执行文件(通常已编译并由 Watcom C/C++ 编译器链接)。 LE 文件可以包含 16 位和 32 位代码(即使在同一个文件中),但带有任何 16 位代码的 LE 文件极为罕见,我找不到。
    • 关于 LX 的正确陈述:通常是 32 位 OS/2 2.x 可执行文件。 LX 文件可以包含 16 位和 32 位代码(即使在同一个文件中),但是具有任何 16 位代码的 LX 文件非常罕见,我找不到任何代码。 LXLE 非常相似,program-transformation.org/Transform/PcExeFormat 包含一些差异。
    猜你喜欢
    • 2021-08-26
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    相关资源
    最近更新 更多