通过读取PE头Magic字段判断位数:0x0107为16位NE(罕见),0x010B为32位PE32,0x020B为64位PE32+;需先从DOS头0x3C处获取PE头偏移,再读该位置+0x00处2字节Magic值。

怎么看PE文件头的Magic字段判断位数
Windows可执行文件(.exe、.dll)是否为16位、32位或64位,关键在PE头开头的Magic字段——它不依赖加载,只靠读取文件前几十字节就能确定。
实际操作就是:打开文件 → 跳到偏移0x3C处读DWORD得到PE头起始位置 → 再跳到该位置+0x00处读2字节Magic值。
-
0x5A4D(即ASCII "MZ")只是DOS头标识,不能用于判断位数 - 真正有效的是PE头里的
Magic:0x010B表示32位PE32,0x020B表示64位PE32+,0x0107才是16位PE(极罕见,多见于NE格式老程序) - 注意:纯16位Windows程序(如Win16 .exe)通常用NE(New Executable)格式,不是PE,其Magic是
0x0000或0x0001,需额外检查DOS头后第0x0E字节的ne_magic
为什么不能只看文件扩展名或图标
扩展名(.exe)、资源图标、甚至文件描述都可能被伪造或误标。真实位数必须从结构体字段中提取。
比如一个32位程序可以被重命名为foo.16.exe,图标也可能复用旧资源;而某些打包器(如UPX)会修改节表但保留原始Magic,此时仅靠file命令或属性页可能误判。
立即学习“C++免费学习笔记(深入)”;
- Windows资源管理器“属性→兼容性”里显示的“以兼容模式运行”选项,和实际PE位数无关
-
dumpbin /headers能看,但它本质也是读Magic字段,只是封装了逻辑 - 用
GetBinaryType()API虽快,但对64位系统上的32位程序可能返回SCS_32BIT_BINARY,无法区分原生32位和WoW64环境下的模拟,且不支持16位NE文件
代码片段:用fread快速提取Magic而不加载
以下C++片段只做最小IO,不调用任何PE解析库,也不触发系统加载行为:
FILE* f = fopen("target.exe", "rb");
if (!f) return -1;
// 读DOS头,定位PE头偏移
uint32_t pe_header_offset;
fseek(f, 0x3C, SEEK_SET);
fread(&pe_header_offset, sizeof(pe_header_offset), 1, f);
<p>// 读PE Magic
uint16_t magic;
fseek(f, pe_header_offset + 0x00, SEEK_SET);
fread(&magic, sizeof(magic), 1, f);
fclose(f);</p><p>switch (magic) {
case 0x0107: printf("16-bit NE (rare)\n"); break;
case 0x010B: printf("32-bit PE32\n"); break;
case 0x020B: printf("64-bit PE32+\n"); break;
default: printf("not PE or unknown format\n");
}注意:这段代码没做错误检查和字节序处理(x86/x64小端,无需转换),但已足够应对绝大多数场景。
- 不要用
std::ifstream默认构造+seekg,某些标准库实现会在seek时预读缓冲区,导致读到非预期位置 - 若要支持NE格式,需在
magic != 0x010B && != 0x020B时,再查DOS头偏移0x0E处是否为0x454E("NE") - Linux/macOS下可用
read()替代fread(),逻辑完全一致
容易忽略的边界情况
真正实战中,几个细节常导致误判:
- 有些加壳程序(如ASPack)会把原始PE头加密并覆盖,此时读出的Magic可能是
0x0000或乱码——这不是位数问题,而是文件已被改写 - 驱动程序(.sys)也用PE格式,但Magic同样是
0x010B或0x020B,和普通exe无区别;不能因后缀不同就跳过检查 - 64位系统上用
sizeof(void*) == 8判断当前进程位数,和目标文件位数毫无关系——这是最常见的混淆点 - 部分嵌入式PE变种(如ARM64 Windows驱动)仍用
0x020B,不额外标记架构,需结合可选头中的Machine字段(0x8664vs0xAA64)进一步确认
位数判断本身很简单,难的是识别哪些文件根本就不是标准PE,以及如何在不触发系统加载策略的前提下安全读取——这两点比Magic值本身更影响结果可信度。



















