PE文件和COFF文件格式分析――签名、COFF文件头和可选文件头2(二)

2014-11-24 10:40:02 · 作者: · 浏览: 1
EADER32);
lpOpHeaderStart = &m_OptionalHeader32;
}
else if ( IMAGE_NT_OPTIONAL_HDR64_MAGIC== dwOptionHeader ) {
m_eFileOpType = EOp32Plus;
unImgOpHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER64);
lpOpHeaderStart = &m_OptionalHeader64;
}
else {
_ASSERT(FALSE);
return FALSE;
}

memset( lpOpHeaderStart, 0 , unImgOpHeaderSize);

// 根据镜像文件头中可选文件头大小拷贝数据
BOOL bSuc = SafeCopy( lpOpHeaderStart, lpImgOpHeaderAddr, m_FileHeader.SizeOfOptionalHeader );

if ( bSuc ) {
m_dwInfoMask |= OPHEADER;
}
else {
_ASSERT(FALSE);
}

if ( EOp32 == m_eFileOpType ) {
m_dwFileAlignment = m_OptionalHeader32.FileAlignment;
}
else {
m_dwFileAlignment = m_OptionalHeader64.FileAlignment;
}
return bSuc;
}
现在我们将重心放到IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];这个数组元素,我在《可选文件头1》中对此有了点描述,而且我还说可选文件头大小要看这个数组元素的“位置”(而不是个数)来决定的。现在我来细说下。先看下微软的声明
[cpp]
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16

#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
DataDirectory保存了指向“块信息”的目录信息,其中包括偏移(除了IMAGE_DIRECTORY_ENTRY_SECURITY元素是相对文件偏移RA,其他都是相对虚拟首地址偏移RVA)和大小。如果某文件只包含IMAGE_DIRECTORY_ENTRY_EXPORT(0) 、IMAGE_DIRECTORY_ENTRY_IMPORT(1) 和IMAGE_DIRECTORY_ENTRY_BASERELOC(5)等三个目录,则IMAGE_DIRECTORY_ENTRY_EXCEPTION(2)、IMAGE_DIRECTORY_ENTRY_SECURITY(3)和IMAGE_DIRECTORY_ENTRY_SECURITY(4)的信息都要被填充0。于是IMAGE_FILE_HEADER::SizeOfOptionalHeader所指定的可选文件头大小为DataDirectory之前的元素总大小加上6(最后一个目录IMAGE_DIRECTORY_ENTRY_BASERELOC所在的位置5+1)*sizeof(IMAGE_DATA_DIRECTORY)。这就说明了为什么可选文件头大小是根据目录的位置而不是数量来决定的。

下篇博文我们将详细说一下IMAGE_OPTIONAL_HEADER32和IMAGE_OPTIONAL_HEADER64中其他元素的意义。