开篇语:
本文只是我学习PE过程中的一些学习笔记,没有什么技术含量。:)
PE格式是WINDOWS下最常用的可执行文件格式。本文将用win32汇编进行描述。
------------------------------
| IMAGE_DOS_HEADER | <-------DOS MZ 文件头
------------------------------
| DOS STUB | <-------DOS可分行代码块
------------------------------
| IMAGE_NT_HEADERS | <-------PE文件头
------------------------------
| SECTION TABLE | <-------节表
------------------------------
| SECTION | <-------节
------------------------------
| SECTION |
------------------------------
| ... |
------------------------------
PE文件格式一览
上图就是PE文件的基本结构,在PE文件中,代码、数据、资源什么的依据不同的属性而被存放到不同的SECTION(节)中,而每个SECTION的属性和位置等信息用一个IMAGE_SECTION_HEADER结构来描述,所有的IMAGE_SECTION_HEADER结构组成一个SECTION TABLE(节表)。
纵观PE格式,我们可以发现一个PE文件分为两大块:DOS部分(DOS文件头+DOS块)+WIN32部分(PE文件头+节表+节)
DOS部分
MZ格式的文件头(IMAGE_DOS_HEADER)和可执行代码(DOS STUB)组成了DOS部分。MZ格式的DOS文件头是由IMAGE_DOS_HEADER结构定义的:
IMAGE_DOS_HEADER STRUCT
e_magic word ? ;00000000 DOS可执行文件标记,为"MZ",在Windows.inc中预定义为IMAGE_DOS_SIGNATURE。
e_cblp word ?
e_cp word ?
e_crlc word ?
e_cparhdr word ?
e_minalloc word ?
e_maxalloc word ?
e_ss word ?
e_sp word ?
e_csum word ?
e_ip word ?
e_cs word ?
e_lfarlc word ?
e_ovno word ?
e_res word 4 dup(?)
e_oemid word ?
e_oeminfo word ?
e_res2 word 10 dup(?)
e_lfanew dword ? ;0000003ch 指向PE文件头,以此来引出PE文件头
一般我们只关心e_magic和e_lfanew这两个字段的值。而e_lfanew这个字段的值在这个结构中是最重要的。DOS的可执行代码部分(DOS STUB)一般只是简单的显示一句"This program connot be run in DOS mode."有的是"This program requires win32."这些代码一般是编译器自动完成的,当然我们也可以定制DOS STUB部分,只要在link时使用/stub:dos_file_name.exe选项进行链接就可以了。
:) 实践是检验真理的标准。
-----------------------------cut-----------------------------------
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
szCaption db 'wensir!',0
szText db 'Hello World!',0
.code
start:
invoke MessageBox,NULL,offset szText,offset szCaption,MB_OK
invoke ExitProcess,NULL
end start
---------------------------cut---------------------------------------
保存为*.asm,我这里保存为wensir.asm,然后编译之:
ml /c /coff wensir.asm
link /subsystem:windows wensir.obj
现在我们得到一个简单的"Hello World"的win32程序wensir.exe,当然,它是PE格式的。随便到哪里DOWN一个16进制编辑器来,我用的是UltraEdit,将wensir.exe用16进制编辑器打开:
----------------------------------------------------------------------------
0 1 2 3 4 5 6 7 8 9 A B C D E F
00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 ; MZ?........��..
00000010h: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ; ?......@.......
00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 B0 00 00 00 ; ............?..
00000040h: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 ; ..?.???L?Th
00000050h: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F ; is program canno
00000060h: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 ; t be run in DOS
00000070h: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 ; mode....$.......
00000080h: 5D 65 FD C8 19 04 93 9B 19 04 93 9B 19 04 93 9B ; ]e..摏..摏..摏
00000090h: 97 1B 80 9B 11 04 93 9B E5 24 81 9B 18 04 93 9B ; ??.摏?仜..摏
000000a0h: 52 69 63 68 19 04 93 9B 00 00 00 00 00 00 00 00 ; Rich..摏........
000000b0h: 50 45 00 00 4C 01 03 00 1C 8C 45 42 00 00 00 00 ; PE..L....孍B....
........
-----------------------------------------------------------------------------
00000000h处的5A4D便是IMAGE_DOS_HEADER中e_magic字段的值"MZ",0000003ch处的值0000000bh值是e_lfanew,它指向PE文件头的位置。从00000040h-000000a0便是DOS STUB块,从上图中我们可以看到"This program cannot be run in dos mode"字样。
重头戏在WIN32部分。:) 欲知后事如何,请听下回分解。

|