pe格式从入门到图形化显示(四)-节表



前言

通过分析和解析Windows PE格式,并使用qt进行图形化显示


一、什么是Windows PE格式节表?

PE格式的节表(Section Table)是一个数组,它包含了PE文件中各个节(Section)的信息。每个节表项都是一个IMAGE_SECTION_HEADER结构体,它包含了关于节的名称、大小、属性等信息。

二、解析节表并显示

1.节表数据结构以及字段描述

Name:节的名称,最多8个字符,以空字符填充。
VirtualSize:节在内存中的大小,以字节为单位。
VirtualAddress:节在内存中的起始RVA(相对虚拟地址)。
SizeOfRawData:节在文件中的大小,以字节为单位。
PointerToRawData:节在文件中的起始偏移量,以字节为单位。
PointerToRelocations:节的重定位表在文件中的起始偏移量,以字节为单位。
PointerToLinenumbers:节的行号表在文件中的起始偏移量,以字节为单位。
NumberOfRelocations:节的重定位表中的项数。
NumberOfLinenumbers:节的行号表中的项数。
Characteristics:节的属性,如可读、可写、可执行等。

struct IMAGE_SECTION_HEADER
{
    BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
        DWORD PhysicalAddress;
        DWORD VirtualSize;
    } Misc;
    DWORD VirtualAddress;
    DWORD SizeOfRawData;
    DWORD PointerToRawData;

    DWORD PointerToRelocations;
    DWORD PointerToLinenumbers;
    WORD NumberOfRelocations;
    WORD NumberOfLinenumbers;
    DWORD Characteristics;
};

2.节表的属性

PE格式的节表中的每个节都有一个属性字段(Characteristics),它是一个位掩码,用于指定节的各种属性。以下是一些常见的节属性及其具体值:
IMAGE_SCN_CNT_CODE:表示节包含可执行代码。具体值为0x00000020。
IMAGE_SCN_CNT_INITIALIZED_DATA:表示节包含初始化的数据。具体值为0x00000040。
IMAGE_SCN_CNT_UNINITIALIZED_DATA:表示节包含未初始化的数据。具体值为0x00000080。
IMAGE_SCN_MEM_EXECUTE:表示节可以执行。具体值为0x20000000。
IMAGE_SCN_MEM_READ:表示节可以读取。具体值为0x40000000。
IMAGE_SCN_MEM_WRITE:表示节可以写入。具体值为0x80000000。
IMAGE_SCN_MEM_SHARED:表示节可以在多个进程之间共享。具体值为0x10000000。
IMAGE_SCN_MEM_DISCARDABLE:表示节可以被丢弃,以释放内存。具体值为0x02000000。
IMAGE_SCN_MEM_NOT_CACHED:表示节不应被缓存。具体值为0x04000000。
IMAGE_SCN_MEM_NOT_PAGED:表示节不应被分页。具体值为0x08000000。
这些属性可以组合使用,以指定节的具体属性。例如,如果一个节同时包含可执行代码和可读数据,那么它的属性字段将包含IMAGE_SCN_CNT_CODE和IMAGE_SCN_MEM_READ标志。在处理PE文件时,可以通过检查节的属性字段来确定节的具体用途和行为。

3.解析

bool PEParser::parserFileData(const QByteArray &fileData)
{
    //判断是否是MZ开头的文件
    if (fileData.left(2) != "MZ")
    {
        return false;
    }
    //解析DOS头
    parserDOSHeader(fileData.left(sizeof(IMAGE_DOS_HEADER)));
    //DOSStub数据
    m_dosStubData = fileData.mid(sizeof(IMAGE_DOS_HEADER), m_dosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER));
    long peAddress = m_dosHeader.e_lfanew;
    if (fileData.mid(peAddress, 2) != "PE")
    {
        return false;
    }
    m_fileData = fileData;
    //去除前4个字节的PE头标识
    long fileHeaderIndex = peAddress + 4;
    //记录文件头索引
    m_fileHeaderIndex = fileHeaderIndex;
    //解析标准PE文件头
    paserFileHeader(fileData.mid(fileHeaderIndex, sizeof(IMAGE_FILE_HEADER)));
    //解析扩展PE文件头
    long optionHeaderIndex = fileHeaderIndex + sizeof(IMAGE_FILE_HEADER);
    //记录扩展PE文件头索引
    m_optionHeaderIndex = optionHeaderIndex;
    //解析扩展PE文件头
    parserOptionHeader(fileData.mid(optionHeaderIndex, m_fileHeader.SizeOfOptionalHeader));
    //解析节表
    long sectionHeaderIndex = optionHeaderIndex + m_fileHeader.SizeOfOptionalHeader;
    //节表结构在文件中开始的偏移
    m_sectionHeaderIndex = sectionHeaderIndex;
    //解析节表
    parserSectionHeader(fileData.mid(sectionHeaderIndex,
                                     m_fileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)));
    return true;
}


void PEParser::parserSectionHeader(const QByteArray &sectionHeader)
{
    m_sections.clear();
    for (int i = 0; i < m_fileHeader.NumberOfSections; ++i)
    {
        int index = i * sizeof(IMAGE_SECTION_HEADER);
        QByteArray sectionData = sectionHeader.mid(index, sizeof(IMAGE_SECTION_HEADER));
        const IMAGE_SECTION_HEADER *header = reinterpret_cast<const IMAGE_SECTION_HEADER *>(sectionData.data());
        m_sections.append(*header);
    }
    emit sendSectionHeader(m_sections);
}

4.显示

void MainWindow::showSectionHeader(const QList<IMAGE_SECTION_HEADER> &sections)
{
    ui->tableWidget_sections->clearContents();
    ui->tableWidget_dataDirectories->setRowCount(0);
    for (int i = 0; i < sections.size(); ++i)
    {
        ui->tableWidget_sections->insertRow(i);
        ui->tableWidget_sections->setItem(i, 0, new QTableWidgetItem(QString::asprintf("%s", sections[i].Name)));
        ui->tableWidget_sections->setItem(i, 1, new QTableWidgetItem(QString::asprintf("%08lX", sections[i].VirtualAddress)));
        ui->tableWidget_sections->setItem(i, 2, new QTableWidgetItem(QString::asprintf("%08lX", sections[i].Misc.VirtualSize)));

        ui->tableWidget_sections->setItem(i, 3, new QTableWidgetItem(QString::asprintf("%08lX", sections[i].PointerToRawData)));
        ui->tableWidget_sections->setItem(i, 4, new QTableWidgetItem(QString::asprintf("%08lX", sections[i].SizeOfRawData)));
        ui->tableWidget_sections->setItem(i, 5, new QTableWidgetItem(QString::asprintf("%08lX", sections[i].Characteristics)));
    }
}

相关推荐

  1. pe格式入门图形显示)-

    2024-04-12 22:18:02       38 阅读
  2. pe格式入门图形显示(五)-RVA和FOA

    2024-04-12 22:18:02       36 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-12 22:18:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-12 22:18:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-12 22:18:02       82 阅读
  4. Python语言-面向对象

    2024-04-12 22:18:02       91 阅读

热门阅读

  1. C语言入门算法——拼数

    2024-04-12 22:18:02       37 阅读
  2. 代码随想录算法训练营day36

    2024-04-12 22:18:02       38 阅读
  3. 机器人的基本概念

    2024-04-12 22:18:02       44 阅读
  4. MybatisPlus快速入门

    2024-04-12 22:18:02       36 阅读
  5. python django mvc

    2024-04-12 22:18:02       41 阅读
  6. 从零开始精通RTSP之请求与响应详解2

    2024-04-12 22:18:02       44 阅读