当前位置:编程学习 > C/C++ >>

PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2

     之前的博文中介绍了IMAGE_FILE_HEADER结构,现在来讨论比较复杂的“可选文件头”结构体。(转载请指明来自breaksoftware的csdn博客)先看下其声明

[cpp] 
typedef struct _IMAGE_OPTIONAL_HEADER { 
    // 
    // Standard fields. 
    // 
    WORD    Magic; 
    . 
    . 
    . 
    DWORD   BaseOfData;    // not exist in PE32+ 
    // 
    // NT additional fields. 
    // 
    DWORD   ImageBase; 
    . 
    . 
    . 
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; 
        看一下64位版本该结构体www.zzzyk.com

[cpp] 
typedef struct _IMAGE_OPTIONAL_HEADER64 { 
    WORD        Magic; 
    . 
    . 
    . 
    DWORD       BaseOfCode; 
    ULONGLONG   ImageBase; 
    . 
    . 
    . 
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; 
         我们观察这个32位版本结构体,可以看到该结构体包含两块数据:Standard fields和NT additional fields。我们可以猜想到,该结构体应该在第一个NT操作系统之前就存在了,只是当时其内容只有Standard fields(以后称为标准域)下的内容,后来NT系统增加了NT additional fields(以后称为扩展域)下元素。

        此处需要特别注意一点,我们看两个在WinNT.h中定义的结构体

[cpp] 
typedef struct _IMAGE_NT_HEADERS64 { 
    DWORD Signature; 
    IMAGE_FILE_HEADER FileHeader; 
    IMAGE_OPTIONAL_HEADER64 OptionalHeader; 
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; 
 
typedef struct _IMAGE_NT_HEADERS { 
    DWORD Signature; 
    IMAGE_FILE_HEADER FileHeader; 
    IMAGE_OPTIONAL_HEADER32 OptionalHeader; 
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; 
        该结构给出了PE文件头的结构体布局,但是切记,这仅仅是布局。我们千万不要想当然的认为直接从PE头部开始将IMAGE_NT_HEADERS32(64)结构体大小的数据拷贝到该结构体对象中。

[cpp] 
memcpy( &ImageNTHeader32,lpPEStart,sizeof(IMAGE_NT_HEADERS32 );// 这是错误的!! 
        为什么?因为一个文件中不一定有完整的IMAGE_OPTIONAL_HEADER32(64)结构体对象信息。原因在《可选文件头1》做了介绍,IMAGE_FILE_HEADER中字段SizeOfOptionalHeader指定了该文件中保存的“可选文件头”真实长度,我们应该根据该元素来给IMAGE_OPTIONAL_HEADER32(64)对象赋值。

        我们的文件是使用IMAGE_OPTIONAL_HEADER32还是IMAGE_OPTIONAL_HEADER64结构体呢?可能有人会记起,我们在《可选文件头1》中介绍了判断文件是32位还是64位的方法,我们是否可以通过该判断的结果来判断是哪种结构体呢?最开始我也是这么想的,后来我发现我电脑上Microsoft Visual Studio 10.0\VC\lib\amd64\Microsoft.VisualC.STLCLR.dll文件是个64位文件但是使用了IMAGE_OPTIONAL_HEADER32结构体!!!是不是很惊讶!我不知道微软这么设计的原因,但是我知道了通过之前判断是否为64位文件来决定可选文件头结构体类型是错误的。那如何判断呢?

        其实是有标记的。紧跟着IMAGE_FILE_HEADER结构体的肯定是IMAGE_OPTIONAL_HEADER32(64)的Magic字段。如果该字段是0x010B,则是使用了IMAGE_OPTIONAL_HEADER32(称为PE32);如果是0x020B,则使用了IMAGE_OPTIONAL_HEADER32(称为PE32+)。切记PE32和PE32+和这个文件是32为文件还是64位文件是没有关系的!它们是两种不同的概念!切记要分清。

[cpp]
BOOL CGetPEInfo::GetOptionalHeader(){ 
     
    CHECKOPHEADER(); 
    GETFILETYPE(); 
 
    size_t unDwordSize = sizeof(DWORD); 
    size_t unImgFileHeaderSize = sizeof(IMAGE_FILE_HEADER); 
    size_t unImgOpHeaderSize = 0; 
     
    LPBYTE lpImgOpHeaderAddr = m_lpPEStart + unDwordSize + unImgFileHeaderSize; 
     
    LPVOID lpOpHeaderStart= NULL; 
 
    WORD dwOptionHeader = 0; 
     
    if ( FALSE == SafeCopy( &dwOptionHeader, lpImgOpHeaderAddr, sizeof(WORD) ) ) { 
        return FALSE; 
    } 
 
    if ( E64Bit == m_eFileType && PE32MAGICNUM == dwOptionHeader ) { 
        // D:\Microsoft Visual Studio 10.0\VC\lib\amd64\Microsoft.VisualC.STLCLR.dll 
        //_ASSERT(FALSE); 
    } 
 
    if ( IMAGE_NT_OPTIONAL_HDR32_MAGIC == dwOptionHeader ) { 
        // 64位系统文件也存在该格式可选头 
        m_eFileOpType  = EOp32; 
        unImgOpHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER32); 
        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; 

&nbs

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,