PE 文件格式
PE. Portable Executable, 可移植的可执行文件, 是 MS WinNT, Win95, Win32中可执行的二进制文件
a.在 Win 中,驱动也是这种格式
b.这种文件格式由MS设计
1. DOS 头是这样的一个结构(也叫 'MZ' 头), 总共是 64 bytes
typedef struct _IMAGE_DOS_HEADER
{
WORD e_magic; // 必需为 4D 5A 'MZ' IMAGE_DOS_SIGNATURE
WORD e_cblp; // 文件最后页的字节数
WORD e_cp; // 文件页数
WORD e_crlc; // 重定义元素个数
WORD e_cparhdr; // 头部尽寸, 以段落为单位
WORD e_minalloc; // 所需的最小附加段
WORD e_maxalloc; // 所需的最大附加段
WORD e_ss; // 初始的SS值 (相对偏移量)
WORD e_sp; // 实始的SP值
WORD e_csum; // 校验和
WORD e_ip; // 初始的IP值
WORD e_cs; // 初始的CS值(相对偏移量)
WORD e_lfarlc; // 重分配表文件地址
WORD e_ovno; // 覆盖号
WORD e_res[4]; // 保留字
WORD e_oemid; // OEM标识符 (相对 e_oeminfo)
WORD e_oeminfo; // OEM 信息
WORD e_res2[10]; // 保留字
LONG e_lfanew; // PE头文件偏移量 , IMAGE_NT_HEADER32 结构所在的文件地址
}IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
(1). “MZ”是MS-DOS开发者之一的马克·茨柏克沃斯基(Mark Zbikowski)的姓名首字母缩写。
(2). e_lfanew定位到PE文件头
P: 1. 如何修改 DOS Stub
A: If you're compiling and linking the program yourself using MS compilers then the simplest approach would be to put in a custom DOS stub using the linkers /STUB[^] switch. Put in one which simply does nothing and returns immediately.
/STUB:filename
Remarks
where:
- filename
An MS-DOS application.
Remarks
The /STUB option attaches an MS-DOS stub program to a Win32 program.
A stub program is invoked if the file is executed in MS-DOS. It usually displays an appropriate message; however, any valid MS-DOS application can be a stub program.
Specify a filename for the stub program after a colon (:) on the command line. The linker checks filename and issues an error message if the file is not an executable. The program must be an .exe file; a .com file is invalid for a stub program.
If this option is not used, the linker attaches a default stub program that issues the following message:
When building a virtual device driver, filename allows the user to specify a file name that contains an IMAGE_DOS_HEADER structure (defined in WINNT.H) to be used in the VXD, rather than the default header.
To set this linker option in the Visual Studio development environment
Open the project's Property Pages dialog box. For details, see Setting Visual C++ Project Properties.
Click the Linker folder.
Click the Command Line property page.
Type the option into the Additional Options box.
To set this linker option programmatically
2. DOS 下的程序 与 (Win32下的程序 / VC6编译的DOS程序), MZ头的不同?
---------------------------------------------------------------------------------
Offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ?..........
00000010 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ?......@.......
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 F0 00 00 00 ............?..
---------------------------------------------------------------------------------
第一行:
(1). 4D 5A 对应 IMAGE_DOS_HEADER.e_magic 字段, 分别为 'MZ' 的 ASCII 码
(2). 90 00 对应 IMAGE_DOS_HEADER.e_cblp 字段,值为 0x0090,
(3). 03 00 对应 IMAGE_DOS_HEADER.e_cp 字段,值为 0x0003,
(4). 00 00 对应 IMAGE_DOS_HEADER.e_crlc 字段,值为 0x0000
(5). 04 00 对应 IMAGE_DOS_HEADER.e_cparhdr 0x0004; // 头部尽寸, 以段落为单位
(6). 00 00 对应 IMAGE_DOS_HEADER.e_minalloc 0x0000; // 所需的最小附加段
(7). FF FF 对应 IMAGE_DOS_HEADER.e_maxalloc 0xFFFF; // 所需的最大附加段
(8). 00 00 对应 IMAGE_DOS_HEADER.e_ss; 0x0000 // 初始的SS值 (相对偏移量)
第二行:
(9) . B8 00 对应 IMAGE_DOS_HEADER.e_sp; 0x00B8 // 实始的SP值
(10).00 00 对应 IMAGE_DOS_HEADER.e_csum; 0x0000 // 校验和
(11).00 00 对应 IMAGE_DOS_HEADER.e_ip; 0x00 // 初始的IP值
(12).00 00 对应 IMAGE_DOS_HEADER.e_cs; 0x00 // 初始的CS值(相对偏移量)
(13). 40 00 对应 IMAGE_DOS_HEADER.e_lfarlc; 0x0040 // 重分配表文件地址
(14). 00 00 对应 IMAGE_DOS_HEADER.e_ovno; 0x0000 // 覆盖号
(15). 00 00 对应 IMAGE_DOS_HEADER.e_res[4]; 0x0000 // 保留字
00 00
00 00
第三行:
(16). 00 00
(17). 00 00 对应 IMAGE_DOS_HEADER.e_oemid; // OEM标识符 (相对 e_oeminfo)
(18). 00 00 对应 IMAGE_DOS_HEADER.WORD e_oeminfo; // OEM 信息
(16). 00 00 对应 IMAGE_DOS_HEADER.WORD e_res2[10]; // 保留字
(17). 00 00
(18). 00 00
(19). 00 00
(20). 00 00
第四行:
(21). 00 00
(22). 00 00
(23). 00 00
(24). 00 00
(25). 00 00
(26). 00 00
(27). F0 00 对应 IMAGE_DOS_HEADER.LONG e_lfanew; 这里的地址为 0x000000F0 // PE头文件偏移量 , IMAGE_NT_HEADER32 结构所在的文件地址
(28). 00 00
2. DOS Stub (DOS实模式残余程序)
(1). 实模式残余程序 是一个在装载时能够被 MS-DOS运行的实际程序。
(2). Dos Stub 只是提供了 PE 文件在DOS下面执行时,DOS会把它当作有效的执行文件而顺利执行。
通常 Win32 的程序会在屏幕上输入"This Program cannot run in DOS mode"之类的提示语
(3). 可以随便改变 DOS Stub, 根据自己的意图实现完整的 DOS 代码
(4). DOS 下的EXE文件,长度不定
(5). 在 Win32下, MZ头 跟 DOS 加载模块 用不上, 加上这两个只为兼容性问题
P:
1. 只取 MZ 头与 DOS Stub
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ?..........
00000010 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ?......@.......
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 0F 00 00 ............?..
00000040 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 ..?.???L?Th
00000050 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F is program canno
00000060 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 t be run in DOS
00000070 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 mode....$.......
00000080 8D 44 CE 8E C9 25 A0 DD C9 25 A0 DD C9 25 A0 DD 岲螏?犦?犦?犦
00000090 AB 3A B3 DD CD 25 A0 DD 4A 39 AE DD C8 25 A0 DD ?齿?犦J9?犦
000000A0 A6 3A AA DD C2 25 A0 DD A6 3A A4 DD CB 25 A0 DD ??犦?ぽ?犦
000000B0 FF 03 A4 DD CA 25 A0 DD C9 25 A1 DD BA 25 A0 DD .ぽ?犦?≥?犦
000000C0 FF 03 AB DD CF 25 A0 DD 0E 23 A6 DD C8 25 A0 DD .?犦.#?犦
000000D0 52 69 63 68 C9 25 A0 DD 00 00 00 00 00 00 00 00 Rich?犦........
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
结果,
运行程序并没有显示 ' This program cannot be run in DOS mode ' ..........
在纯DOS下会显示 'Errror in exe file'
难道跟 MZ 头除了e_lfanew的字段有关?........
将开头的 4D 5A 90 00 03 00 改为
4D 5A 00 01 01 00
之后,在纯DOS下就会显示 ' This program cannot be run in DOS mode '
在 Win 下会一闪而过, 需要先 run cmd, 再run debug, -q 退出, 再执行,就会显示 ' This program cannot be run in DOS mode '
原因暂时未知.