(二) PE文件结构概述

时间:2022-09-14 11:52:38

上面文章说了一些有关PE中会常用到的术语,接下来咱们就能从宏观的角度观察伟大的PE结构了:D

老规矩,说话前先看图:

 

 

 

(二) PE文件结构概述  

为了兼容16位的MS-DOS程序,MS在PE结构中包含了MS-DOS程序必须的结构(DOS MZ Header和DOS Stub),接下来会详细描述这部分内容.

1.DOS MZ Header

在PE文件中,DOS MZ Header的结构如下定义:

IMAGE_DOS_HEADER STRUCT
e_magic        WORD        ?    ;EXE标志,"MZ"
e_cblp             WORD        ?      
e_cp                 WORD        ?
e_crlc        WORD        ?
e_cparhdr    WORD        ?
e_minalloc    WORD        ?
e_maxalloc    WORD        ?
e_ss        WORD        ?    ;初始的SS值
e_sp        WORD        ?    ;初始的SP值
e_csum        WORD        ?
e_ip        WORD        ?    ;初始的IP值
e_cs        WORD        ?    ;初始的CS值
e_lfarlc        WORD        ?
e_ovno        WORD        ?
e_res        WORD    4 dup      (?)
e_oemid        WORD        ?
e_oeminfo    WORD        ?
e_res2        WORD    10 dup    (?)
e_ifanew        WORD        ?    ;PE头的FOA
IMAGE_DOS_HEADER ENDS

DOS MZ Header结构的大小为64btytes,结构的最后一个成员指定了PE文件头起始的FOA,紧跟着此结构后面的便是DOS Stub.

 

2.DOS Stub

既然兼容MS-DOS程序,那么一定有地方存放代码,毫无疑问,就是此处.

先写一段简单的代码:

(二) PE文件结构概述(二) PE文件结构概述MSGBOX
 1     .386
 2     .model flat,stdcall
 3     option casemap:none
 4 
 5 include    windows.inc
 6 include    kernel32.inc
 7 include    user32.inc
 8 
 9 includelib    kernel32.lib
10 includelib    user32.lib
11 
12 .const
13 szTitle        db    'test',0
14 szContext    db    'hello,msgbox',0
15 
16 .code
17 
18 start:
19     invoke    MessageBox,NULL,offset szTitle,offset szContext,MB_OK
20     invoke    ExitProcess,NULL
21 end start
22     

 编译链接,生成了最终的PE文件,msgbox.exe.将其载入16进制编辑器(我使用的UltraEdit),看到如下:

(二) PE文件结构概述

红色方框内为MZ DOS Header,蓝色方框则为DOS Stub,紫色箭头便是MZ DOS Header的最后一个成员e_ifanew所指向PE头所在的FOA.

现在将这个程序放入cmd中,运行debug msgbox.exe:

(二) PE文件结构概述

debug下键入d命令,会查看cs:ip处的起始字节码,同时也发现了与UltraEdit蓝色部分,即DOS stub中的字节码完全一样.

现在再使用u命令,则会查看cs:ip处的机器码翻译成汇编的语句,如下:

(二) PE文件结构概述

很明显,是16位汇编,这段汇编的功能很简单,就是通过21号中断的9号功能(mov ah,09  int 21)来实现对ds:dx指向的字符串(This program cannot be run in DOS mode.)进行输出.

最后输入g命令,运行程序进行测试,查看结果如下:

(二) PE文件结构概述

 

综上所述,只要在DOS Stub中添加了正确的代码,便可以在MS-DOS中看到我们期望的结果. :D