PE结构的节表解析

本文详细介绍了PE文件格式中节表的解析过程,包括节表的每个成员解释,如Name、Misc、VirtualAddress等,并提供了具体的C语言实现代码示例,通过Xshell7进行测试,展示了如何遍历并打印节表信息。
摘要由CSDN通过智能技术生成

目录

前言

过程


前言

本文章用于学习,如有错误还望指出。

上篇文章写了关于PE文件头(DOS头,标准PE头,可选PE头的解析),今天这篇文件是关于节表的解析。
首先介绍一下节表的每个成员:

typedef struct _IMAGE_SECTION_HEADER

{

        0x00 BYTE Name[IMAGE_SIZEOF_SHORT_NAME];//描述了此节区的名称,八个字节,这个名字是可以改的,如果你没有指定,编译器会生成固定的名字。

要注意的是:这一串是ASCII字符,需要以0结尾,编译器生成的名字长度如果小于8个字节还行,余下补0,但是如果正好8个字节,你在进行打印的时候就会越界了,在下面会写出处理办法。

        union {

                0x08 DWORD PhysicalAddress;

                0x08 DWORD VirtualSize;

                } Misc;//这个节表(有几个节,就有几个节表)指向的节真实的大小(没有经过对齐的)。

        0x0c DWORD VirtualAddress; //当程序载入内存时,相对于ImageBase的偏移,指向节的第一个字节。

        0x10 DWORD SizeOfRawData; //节进行文件对齐之后的长度。

        0x14 DWORD PointerToRawData; //节在硬盘中,或者通过16位文本编辑器打开时,相对于起始地址的偏移,指向节的第一个字节。

        0x18 DWORD PointerToRelocations;

        0x1c DWORD PointerToLinenumbers;

        0x20 WORD NumberOfRelocations;

        0x22 WORD NumberOfLinenumbers;

        0x24 DWORD Characteristics;//节的属性,例如:可读可写可执行。

};

 

过程

具体的实现过程:

这里是以Xshell 7版本做为测试的。

对于PE头部分的解析就不放出来了,在之前的文章里面有提及到,下面写的是关于节表解析

//首先根据节表的特征,使用数组记录
const BYTE* _IMAGE_SECTION_HEADER[10]
{
	"Name[IMAGE_SIZEOF_SHORT_NAME]",
	"Misc",
	"VirtualAddress",
	"SizeOfRawData",
	"PointerToRawData",
	"PointerToRelocations",
	"PointerToLinenumbers",
	"NumberOfRelocations",
	"NumberOfLinenumbers",
	"Characteristics"
};
//每一个成员的长度
int Section_LENGTH[10]
{
	8,4,4,4,4,4,4,2,2,4
};
//节表
	//节表的数量
    /*
        BufBackUp是文件读入内存的起始值,也就是0
        Turn是dos头中最后一个成员,存着NT头的起始位置的偏移
        +4,+2,是为了索引到标准PE头中的第二个成员:NumberOfSection,节的个数,后面循环的时候需                      要用到
    */
	WORD * P_Section_num = (WORD*)(BufBackUp + Turn + 4 + 2);
	//定位节表
	WORD* P_Size_Optioanal_Header = (WORD *)(BufBackUp + Turn + 0x4 + 0x10);
    //让Buf指向第一个节表的开始位置,节表和节表之间是贴着的,而且长度相同,很好理解,因为节表就是描述节的概要性信息的嘛。
	Buf = (BufBackUp + Turn + 0x4 + 20 + (*P_Size_Optioanal_Header));
	i = 0;
	DWORD j = 0;

    //以节表的个数做为外层循环次数
	while(j < (*P_Section_num))
	{ 
        //内存循环每个节表的成员,一共10个
		while (i < 10)
		{
			printf("%s:", _IMAGE_SECTION_HEADER[i]);
			if (Section_LENGTH[i] == 8)
			{
				int TempCount = 0;
				BYTE TempArr[9] = {0};

                //这个地方大家注意一下,我验证的时候通过strcpy_s复制,但是一直在报越界问题,我//验证觉的是因为strcpy_s是以源字符串直到0结尾做为源字符串的长度,不是根据第二个参数来的。
				while (TempCount< 8 && (*(Buf + TempCount)) != 0)
				{
					TempArr[TempCount] = Buf[TempCount];
					TempCount ++;
				}
				printf("%s\n", TempArr);
				Buf += 8;
			}
			else if(Section_LENGTH[i] == 4)
			{
				DWORD* PTemp = (DWORD*)Buf;
				printf("%x\n", (*PTemp));
				Buf += 4;
			}
			else
			{
				WORD* PTemp = (WORD*)Buf;
				printf("%x\n", (*PTemp));
				Buf += 2;
			}
			i++;
		}
		printf("\n");
		i = 0;
		j++;
	}

这是跑出来的结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值