pe格式从入门到图形化显示(二)-文件头



前言

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


一、什么是Windows PE格式文件头?

Windows PE格式文件头(Portable Executable file format header)是Windows操作系统中可执行文件的一部分,用于存储有关文件结构和属性的信息。它位于可执行文件的开头部分,包含了许多字段,用于描述文件的类型、机器体系结构、节表、入口点等。

二、解析文件头并显示

1.数据结构

IMAGE_FILE_HEADER是一个结构体,它位于PE文件的IMAGE_NT_HEADERS结构中,用于描述PE文件的基本属性和结构。那么IMAGE_NT_HEADERS又是一个什么结构呢?

typedef struct _IMAGE_NT_HEADERS
{
    DWORD Signature;                            
    IMAGE_FILE_HEADER FileHeader;               
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

以下是_IMAGE_NT_HEADERS结构的主要字段及其含义:
Signature:用于标识文件的开头部分,通常为"PE"(即0x50 0x45)。
FileHeader:表示PE文件的文件头信息,这对于加载和执行PE文件非常重要。例如,FileHeader.Machine字段告诉操作系统PE文件的目标机器类型,以便正确地加载和执行该文件。
OptionalHeader:表示PE文件的可选头信息,这些信息对于加载和执行PE文件非常重要。例如,OptionalHeader.Magic字段告诉操作系统PE文件的目标机器类型,以便正确地加载和执行该文件。OptionalHeader.AddressOfEntryPoint字段表示PE文件的入口点地址,这有助于操作系统了解PE文件的入口点。OptionalHeader.Subsystem字段表示PE文件所需的子系统类型,如GUI、CUI等。

以下是IMAGE_FILE_HEADER结构的主要字段:
Machine:指定PE文件的目标机器类型,如I386、AMD64、ARM等。
NumberOfSections:表示PE文件中的节(Section)数量。
TimeDateStamp:表示PE文件的创建时间戳。
PointerToSymbolTable:指向符号表(Symbol Table)的指针。
NumberOfSymbols:表示符号表中的符号数量。
SizeOfOptionalHeader:表示PE文件的可选头(Optional Header)的大小。
Characteristics字段是一个位掩码(bitmask),用于表示PE文件的特性。以下是一些常见的Characteristics字段的值及其含义:
IMAGE_FILE_RELOCS_STRIPPED (0x0001):表示PE文件中的重定位表已被删除。
IMAGE_FILE_EXECUTABLE_IMAGE (0x0002):表示PE文件是一个可执行文件。
IMAGE_FILE_LINE_NUMS_STRIPPED (0x0004):表示PE文件中的行号信息已被删除。
IMAGE_FILE_LOCAL_SYMS_STRIPPED (0x0008):表示PE文件中的本地符号信息已被删除。
IMAGE_FILE_AGGRESIVE_WS_TRIM (0x0010):表示PE文件中的工作集大小已被优化。
IMAGE_FILE_LARGE_ADDRESS_AWARE (0x0020):表示PE文件支持大于2GB的地址空间。
IMAGE_FILE_BYTES_REVERSED_LO (0x0080):表示PE文件中的字节顺序已被反转(低位)。
IMAGE_FILE_32BIT_MACHINE (0x0100):表示PE文件是一个32位机器的可执行文件。
IMAGE_FILE_DEBUG_STRIPPED (0x0200):表示PE文件中的调试信息已被删除。
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP (0x0400):表示PE文件可以从交换文件中运行。
IMAGE_FILE_NET_RUN_FROM_SWAP (0x0800):表示PE文件可以从网络交换文件中运行。
IMAGE_FILE_SYSTEM (0x1000):表示PE文件是一个系统文件。
IMAGE_FILE_DLL (0x2000):表示PE文件是一个动态链接库(DLL)文件。
IMAGE_FILE_UP_SYSTEM_ONLY (0x4000):表示PE文件只能在单处理器系统上运行。
IMAGE_FILE_BYTES_REVERSED_HI (0x8000):表示PE文件中的字节顺序已被反转(高位)。
Characteristics字段的值可以通过位运算(如按位与、按位或等)进行组合,以表示PE文件的多种特性。例如,如果Characteristics字段的值为0x0002(即IMAGE_FILE_EXECUTABLE_IMAGE),则表示PE文件是一个可执行文件。

struct IMAGE_FILE_HEADER
{
    enum FILECharacteristics
    {
        IMAGE_FILE_RELOCS_STRIPPED = 0x0001,
        IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
        IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004,
        IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0004,
        IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010,
        IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
        IMAGE_FILE_BYTES_REVERSED_LO = 0x0080,
        IMAGE_FILE_32BIT_MACHINE = 0x0100,
        IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
        IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
        IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800,
        IMAGE_FILE_SYSTEM = 0x1000,
        IMAGE_FILE_DLL = 0x2000,
        IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000,
        IMAGE_FILE_BYTES_REVERSED_HI = 0x8000
    };
    WORD Machine;
    WORD NumberOfSections;
    DWORD TimeDateStamp;
    DWORD PointerToSymbolTable;
    DWORD NumberOfSymbols;
    WORD SizeOfOptionalHeader;
    WORD Characteristics;
};

2.解析

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)));
    return true;
}

void PEParser::paserFileHeader(const QByteArray &peFileHeaderData)
{
    const IMAGE_FILE_HEADER *fileHeader = reinterpret_cast<const IMAGE_FILE_HEADER *>(peFileHeaderData.data());
    emit sendPEFileHeader(*fileHeader);
    m_fileHeader = *fileHeader;
}

3.显示

void MainWindow::showPEFileHeader(const IMAGE_FILE_HEADER &header)
{
    ui->lineEdit_optionalSize->setText(QString::asprintf("%08X", header.SizeOfOptionalHeader));
    ui->lineEdit_timeDateStamp->setText(QString::asprintf("%08lX", header.TimeDateStamp));
    ui->lineEdit_numberOfSections->setText(QString::asprintf("%08X", header.NumberOfSections));
    ui->lineEdit_characteristics->setText(QString::asprintf("%08X", header.Characteristics));
}

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mrack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值