如何识别内置的Windows二进制是32位还是64位?

时间:2018-09-05 09:11:58

标签: file-format portable-executable

我使用go build为不同的操作系统和不同的拱门构建一些二进制文件。

在linux上,我可以使用类似以下的方法来了解64位或32位二进制文​​件:

# file try
try: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
# file newtry
newtry: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped

如何在Windows上获取此信息?

1 个答案:

答案 0 :(得分:0)

file工具通过查看某些“魔术”模式的预定义位置来工作。这些位置在magic file中进行了描述。

使用简单的Go程序可以很容易地复制此行为; Microsoft网站上有一个good description of the WinPE file format

下面的程序正是这样做的,但有一些限制:

  • 假定该文件是WinPE文件。
  • 它简单地按字节搜索COFF文件头的位置;最好找到合适的字节偏移量:

      

    在位置0x3c,存根具有与PE签名相对应的文件偏移。此信息使Windows能够正确执行映像文件,即使它具有MS-DOS存根。在链接期间,此文件偏移量位于位置0x3c。   签名(仅图像)

         

    在MS-DOS存根之后,在偏移量为0x3c处指定的文件偏移量处是一个4字节的签名,它将文件标识为PE格式的图像文件。此签名为“ PE \ 0 \ 0”(字母“ P”和“ E”,后跟两个空字节)。

实现这一点留给读者练习;-)

package main

import (
    "bytes"
    "fmt"
    "log"
    "os"
)

func main() {
    fp, err := os.Open(os.Args[1])
    if err != nil {
        log.Fatal(err)
    }
    defer fp.Close()


    data := make([]byte, 8192)
    _, err = fp.Read(data)
    if err != nil {
        log.Fatal(err)
    }

    h := bytes.Index(data, []byte("PE\x00\x00"))
    if h == -1 {
        log.Fatal("could not find COFF header")
    }

    // First two bytes is machine type.
    mach := fmt.Sprintf("0x%x%x", data[h+5:h+6], data[h+4:h+5])
    if err != nil {
        log.Fatal(err)
    }

    desc, ok := machineTypes[mach]
    if !ok {
        log.Fatalf("unknown machine type %s", mach)
    }

    fmt.Printf("%s %s\n", mach, desc)
}

var machineTypes = map[string]string{
    "0x0000": "The contents of this field are assumed to be applicable to any machine type",
    "0x01d3": "Matsushita AM33",
    "0x8664": "x64",
    "0x01c0": "ARM little endian",
    "0xaa64": "ARM64 little endian",
    "0x01c4": "ARM Thumb-2 little endian",
    "0x0ebc": "EFI byte code",
    "0x014c": "Intel 386 or later processors and compatible processors",
    "0x0200": "Intel Itanium processor family",
    "0x9041": "Mitsubishi M32R little endian",
    "0x0266": "MIPS16",
    "0x0366": "MIPS with FPU",
    "0x0466": "MIPS16 with FPU",
    "0x01f0": "Power PC little endian",
    "0x01f1": "Power PC with floating point support",
    "0x0166": "MIPS little endian",
    "0x5032": "RISC-V 32-bit address space",
    "0x5064": "RISC-V 64-bit address space",
    "0x5128": "RISC-V 128-bit address space",
    "0x01a2": "Hitachi SH3",
    "0x01a3": "Hitachi SH3 DSP",
    "0x01a6": "Hitachi SH4",
    "0x01a8": "Hitachi SH5",
    "0x01c2": "Thumb",
    "0x0169": "MIPS little-endian WCE v2 ",
}