PE第一课——MS-DOS头解析

课堂笔记

PE文件的全称是Portable Executable,意为可移植的可执行的文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)

PE 文件的结构大约是这样的

用 010 随便打开一个 exe 文件,可以看到它的文件结构组成。

被标红高亮的部分就是 MS-DOS 头,他就是防止 PE 文件运行在 MS-DOS 系统下出现问题。

在 visual studio 当中可以去查看 _IMAGE_DOS_HEADER 结构体去查看 MS-DOS 头结构,结构体定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

这里比较重要的就是第一个和最后一个字段,第一个就是魔术字,最后一个就是 PE 头的地址,中间的字段就到时候看看情况学学吧。

然后这里写一个代码去读取指定文件的 MS-DOS 头去分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<windows.h>
#include<stdio.h>
int main() {
FILE* fd = fopen("C:\\Users\\xia0ji233\\Desktop\\Home\\C++\\test.exe","rb");
char* buffer=(char *)malloc(0x10000);
if (buffer == NULL) {
perror("malloc fail");
exit(0);
}
if (fd == NULL) {
perror("NO such File");
exit(0);
}
fread(buffer, 1, 0x100, fd);
PIMAGE_DOS_HEADER pheader=(PIMAGE_DOS_HEADER)buffer;
system("pause");
}

运行结果