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


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

    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:初始化上面定义的结构
    下面来一一说明这两个函数

    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文件头的地址 + 文件头的大小也一样可以获取到区块表的地址

    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成员获取区块表的个数,然后在循环中以这个个数作为条件,以此往后寻址,将信息写入到对应的数组中,最后在输出的时候只需要根据需求输出我们感兴趣的内容即可

  • 相关阅读:
    linux查看端口命令 lsof netstat
    基于神经网络集成学习的研究论文推荐
    在没有训练数据的情况下通过领域知识利用弱监督方法生成NLP大型标记数据集
    旷视MegEngine是如何将31*31的大核卷积计算速度提高10倍的
    LAB03:升级K8S版本
    LAB01:权限控制RBAC
    LAB04:备份还原ETCD
    LAB02:指定节点不可用
    vue2.0增删改查 关键词检索怎么做
    【Vue实例实战】商城后台管理系统——增删改查
  • 原文地址:https://www.cnblogs.com/lanuage/p/7725693.html
Copyright © 2020-2023  润新知