栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

手工解析PE(节表)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

手工解析PE(节表)

上一篇文章解析了PE的前两个部分DOS头和NT头,这篇文章继续解析NT头的下一个部分 节表

首先我们需要算出第一个节表的地址,可以从PE标志开始算,

1.节表地址:PE标记[4字节]+标准PE头[20字节]+可选PE头[p_sizeofoptionalheader]

其中PE标记是固定的4字节,标准PE头是固定的20字节,可选PE头的大小不确定,但是在标准PE头中sizeofoptionalheader可以取到,所以最后还要加上sizeofoptionalheader的值

2.节表的个数:在标准PE头中numberofsections记录着

3.每个节表的大小:根据PE结构图可以看到,一个节表是40个字节

有了节表个数就可以确定循环次数了,每次循环结束后,节表的地址要增加40 到下一个节表地址

#include 
#include 
#include 
//获取文件大小
int get_file_size(char* filename)
{
	FILE* fp = fopen(filename,"r");
	int size;
	if( fp == NULL )
	{
		printf("open fail n");
		return -1;
	}
	fseek(fp,0,SEEK_END);
	size=ftell(fp);
	fclose(fp);
	return size;
}
 
int main()
{
	char* filename="D:\T\zx.exe"; 
	int file_size=get_file_size(filename);

	//申请空间
	char* ptr;
	ptr = (char*) malloc(file_size);
	if( ptr == NULL)
	{
		printf("空间不足n");
		return 0;
	}
	memset(ptr,0,file_size);
	printf("ptr:%x n",ptr);
	//将文件内容 读取到内存
	FILE* fp = fopen(filename,"rb+");
	fread(ptr,file_size,1,fp);
	fclose(fp);
	

	//找到PE偏移
	int* p_e_lfanew=(int*)ptr+15; 
	printf("PE偏移:ttt%x	n",*p_e_lfanew);
	//PE标志
	char* p_signature = ptr+(*p_e_lfanew);				
	//标准PE头中的 节数量
	short* p_numberofsections=(short*)(p_signature+6);	
	printf("节数量:ttt%x  n",*p_numberofsections);
	//可选PE头大小
	short* p_sizeofoptionalheader=(short*)(p_signature+20);	
	printf("可选PE头大小:tt%x -> %d	n",*p_sizeofoptionalheader,*p_sizeofoptionalheader);
	//内存镜像基址
	int* p_imagebase=(int*)(p_signature+52);				
	printf("内存镜像基址:tt%x n",*p_imagebase);
	//内存对齐字节数
	int* p_sectionalignment=(int*)(p_signature+56);	
	printf("内存对齐字节数:tt%x  n",*p_sectionalignment);
	//文件对齐字节数
	int* p_filealignment=(int*)(p_signature+60);	
	printf("文件对齐字节数:tt%x n",*p_filealignment);
 
	//节表地址:DOS头[64字节]+PE标记[4字节]+标准PE头[20字节]+可选PE头[p_sizeofoptionalheader] =312=0x138
	int varsize=*p_sizeofoptionalheader;
	//char* image_section_header_base=ptr+64+4+20+(*p_sizeofoptionalheader);
	char* image_section_header_base=p_signature+4+20+(*p_sizeofoptionalheader);
	printf("节表地址:tt%x n",image_section_header_base);
	
	

	int i=1;
	for(i;i<=*p_numberofsections;i++)
	{
		printf("第 %d 个节:n",i);
		//printf("image_section_header_base:%x n",image_section_header_base);
		char name[9];
		memcpy(name,image_section_header_base,8);
		name[8]='';

		int *pmisc=(int*)(image_section_header_base+8);
		int *pvirtualaddress=(int*)(image_section_header_base+12);
		int *psizeofrawdata=(int*)(image_section_header_base+16);
		int *ppointertorawdata=(int*)(image_section_header_base+20);
		int *ppointertorelocations=(int*)(image_section_header_base+24);
		int *ppointertolinenumbers=(int*)(image_section_header_base+28);
		short *pnumberofrelocations=(short*)(image_section_header_base+32);
		short *pnumberoflinenumbers=(short*)(image_section_header_base+34);
		int *pcharacteristics=(int*)(image_section_header_base+36);

		printf("t name:%s n",name);
		printf("t misc:%x n",*pmisc);
		printf("t virtualaddress:%x n",*pvirtualaddress);
		printf("t sizeofrawdata:%x n",*psizeofrawdata);
		printf("t pointertorawdata:%x n",*ppointertorawdata);
		printf("t pointertorelocations:%x n",*ppointertorelocations);
		printf("t pointertolinenumbers:%x n",*ppointertolinenumbers);
		printf("t numberofrelocations:%x n",*pnumberofrelocations);
		printf("t numberoflinenumbers:%x n",*pnumberoflinenumbers);
		printf("t characteristics:%x n",*pcharacteristics);
		

		image_section_header_base=image_section_header_base+40;
	}

 
	//释放内存
	free(ptr);
	ptr=NULL;
	return 0;
}
 
 

执行结果如图

拿PE程序解析一下  结果没有差异

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/949796.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号