昨天看了fengmk2一篇博文:PE文件格式小炒
http://www.cnblogs.com/fengmk2/archive/2008/06/23/1228393.html
这篇博客里用实例分析了,PE文件格式,看得我心里痒痒,也说几句吧,不过我是初学者,水平可能不够,呵呵,大家一起讨论吧。
我将fengmk2画的结构图加了几个定位说明。
![](https://pic002.cnblogs.com/img/CUCmehp/200903/2009032818120190.gif)
Dos_stub由Dos头和一小段Dos程序组成,Dos头的长度为64字节,即从0x00000000处到0x0000003Fh处。而Dos程序的长度不定,因此在Dos头中用偏移量e_lfanew记录file-header的偏移量。下面是Dos头的定义:
通过e_lfanew可以定位到file_header:下面这两种方法均可:
方法1:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
unsigned char dt[2];
fp=(FILE *)fopen("filename","rb");
fseek(fp,(long)0x3c,SEEK_SET);
fread(dt,1,2,fp);
fseek(fp,(long)(dt[0]|(dt[1]<<8)),SEEK_SET);
0x3c即是e_lfanew的起始地址。
方法2:
列出NT头的定义,可以看出包列文件头和可选文件头两部分
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
HANDLE hFile=CreateFile("filename",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISITING,FILE_ATTRIBUTE_NORMAL,NULL);
IMAGE_DOS_HEADER dosHeader;
IMAGE_NT_HEADERS32 ntHeader;
DWORD dwRead
if(hFile!=INVALID_HANDLE_VALUE){
::ReadFile(hFile,&dosHeader,sizeof(dosHeader),&dwRead,NULL);
}
if(dwRead==sizeof(dosHeader)){
if(dosHeader.e_magic==IMAGE_DOS_SIGNATURE){
if(SetFilePointer(hFile,dosHeader.e_lfanew,NULL,FILE_BEGIN)!=-1){
//读取NT头
ReadFile(hFile,&ntHeader,sizeof(ntHeader),&dwRead,NULL);
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
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;
下面我详细分析一下可选文件头,可选文件头非常重要,因此它绝对不是可选的。它包含了模块基地址、代码和数据的大小和基地址、线程堆栈和进程堆的配置等信息。最后一个成员DataDirectory数据表中,含有导入表、导出表、资源和重定位表等等重要的表项,其详细的定义如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage)
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor
太长了,不想写了,估计也没有人愿意看了,下回再写吧。(^_^)