通过观察可以发现,程序是以MZ标识开头的。下面是DOS加载模块标识字段“This is program cannot be run in DOS mode.”。这两个字段基本是不变的,基本上Windows程序的开头都是这两个字段。接下来是 PE 开头的文件头。再后面是.text(代码)、.data(数据)、.rsrc(资源)等组成的区段表。区段表主要作用是让PE加载器快速地加载对应的区段如图2所示。
图2 区段表
相对虚拟地址。PE 文件主要是 DLL 加载到进程虚拟内存的某些位置时,该位置可能已经加载了其他 PE 文件。如果使用虚拟内存就会发生冲突,这时候必须通过重定位(Relocation)到其他位置才行。因为相对基地址的相对地址没有改变,所以可以通过相对虚拟地址进行访问。
文件偏移地址。文件偏移地址是指数据在 PE 文件中的地址,是文件在磁盘上存放时相对于文件开头的偏移。WinHex打开文件所显示的地址就是文件偏移地址。
3. PE文件结构
PE文件头结构的定义都在winnt.h中。
(1)DOS头
在winnt.h中DOS头的结构如下。
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 PE
} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 //Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 //File is executable (i.e.no unresolved externel references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 //Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 //Lo cal symbols stripped from file.
#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 //Agressively trim working set
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 //App can handle>2gb addresses
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 //Bytes of machine word are reversed.
#define IMAGE_FILE_32BIT_MACHINE 0x0100 //32 bit word machine.
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 //Debugging info stripped from file in.DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 //If Image is on removable media,copy and run from the swap file.
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 //If Image is on Net,copy and run from the swap file.
#define IMAGE_FILE_SYSTEM 0x1000 //System File.
#define IMAGE_FILE_DLL 0x2000 //File is a DLL.
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 //File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 //Bytes of machine word are reversed.