前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PE解析器的编写(三)——区块表的解析

PE解析器的编写(三)——区块表的解析

作者头像
Masimaro
发布2018-08-31 15:47:35
6580
发布2018-08-31 15:47:35
举报

PE文件中所有节的属性都被定义在节表中,节表由一系列的IMAGE_SECTION_HEADER结构排列而成,每个结构用来描述一个节,结构的排列顺序和它们描述的节在文件中的排列顺序是一致的。 具有相同属性的数据被安排到同一个区块中。 区块表的结构为IMAGE_SECTION_HEADER,在PE文件中存在一个该结构的数组,用来保存各个区块的信息,这个数组的大小在PE头的结构 IMAGE_NT_HEADERS 的成员NumberOfSections描述。 区块表结构IMAGE_SECTION_HEADER结构如下:

代码语言:javascript
复制
typedef struct _IMAGE_SECTION_HEADER 
{
       BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 节表名称,如“.text”
        //IMAGE_SIZEOF_SHORT_NAME=8
        union
         {
                DWORD PhysicalAddress;      // 物理地址
                DWORD VirtualSize;          // 真实长度,这两个值是一个联合结构,可以使用其中的任何一个,一般是取后一个
        } Misc;
        DWORD VirtualAddress;               // 节区的 RVA 地址        
        DWORD SizeOfRawData;                // 在文件中对齐后的尺寸     
        DWORD PointerToRawData;             // 在文件中的偏移量        
        DWORD PointerToRelocations;         // 在OBJ文件中使用,重定位的偏移  
        DWORD PointerToLinenumbers;         // 行号表的偏移(供调试使用地)
        WORD NumberOfRelocations;           // 在OBJ文件中使用,重定位项数目
        WORD NumberOfLinenumbers;           // 行号表中行号的数目
        DWORD Characteristics;              // 节属性如可读,可写,可执行等
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

在程序中我们主要列出了,区块名称、RVA、在进行内存对齐后的尺寸,在磁盘中的大小,在文件中的偏移,节属性。 在界面中,定义了一个listctrl来显示这些信息。 在CPeFileInfo类中定义了一个vector m_SectionTable;专门用来存储区块表的属性信息。获取这个信息。 在这个类中与区块表有关的函数主要有两个: GetSectionHeader : 用来获取指向表的指针 InitSectionTable:初始化上面定义的结构 下面来一一说明这两个函数

代码语言:javascript
复制
PIMAGE_SECTION_HEADER CPeFileInfo::GetSectionHeader()
{
    PIMAGE_FILE_HEADER pFileHeader = GetFileHeader();
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    if (NULL == pFileHeader)
    {
        return NULL;
    }
    PIMAGE_OPTIONAL_HEADER pOptionHeader = GetOptionalHeader();
    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)(pOptionHeader) + pFileHeader->SizeOfOptionalHeader);
    return pSectionHeader;

//  PIMAGE_NT_HEADERS pNtHeader = GetNtHeaders();
//  return (PIMAGE_SECTION_HEADER)((DWORD)pNtHeader + sizeof(IMAGE_NT_HEADERS));
}

在PE文件中区块表的属性信息是紧密排列在PE头结构后面的,所以我们只要知道OptionHeader结构的指针,然后加上这个结构的大小就可以获取到区块表的地址,上面的代码也是这样做的,首先获取了FileHeader的指针,这个结构中的SizeOfOptionalHeader定义了OptionHeader这个结构的大小,我们利用FileHeader + SizeOfOptionalHeader这样就偏移到了区块表所在的位置。 或者更简单的方式是利用PE文件头的地址 + 文件头的大小也一样可以获取到区块表的地址

代码语言:javascript
复制
void CPeFileInfo::InitSectionTable()
{
    if (!m_SectionTable.empty())
    {
        return ;
    }
    PIMAGE_SECTION_HEADER pSectionHeader = GetSectionHeader();
    PIMAGE_FILE_HEADER pFileHeader = GetFileHeader();
    if (NULL != pSectionHeader && NULL != pFileHeader)
    {
        DWORD dwCountOfSection = pFileHeader->NumberOfSections;
        int nCount = 0;
        while (nCount < dwCountOfSection)
        {
            IMAGE_SECTION_HEADER ImageSec = pSectionHeader[nCount];
            m_SectionTable.push_back(ImageSec);
            nCount++;
        }
    }
}

后面就是循环遍历将所有信息写入m_SectionTable这个动态数组中。在这份代码中我们首先利用FileHeader的NumberOfSections成员获取区块表的个数,然后在循环中以这个个数作为条件,以此往后寻址,将信息写入到对应的数组中,最后在输出的时候只需要根据需求输出我们感兴趣的内容即可

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-10-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档