手工解析PE(导出表)

本文档介绍了PE文件格式中的导出表结构,以及如何通过C++实现PE头、节表和导出表的解析。通过示例代码展示了如何获取PE文件的导出表地址、大小,并进行RVA到FOA的转换。此外,提供了读取文件到内存、释放内存等辅助函数。
摘要由CSDN通过智能技术生成

一个dll文件 静态库或者动态库编译完成之后 会生成一个导出表 用于告诉其他使用者 函数名以及对应的函数地址在哪里,具体导出表怎么使用我们下节再做详细解释,本次实验先把导出表的PE结构解析出来

头文件新增了导出表相关属性的计算,之前只计算了节表的相关内容,这次又丰富了一些,还完善了之前RVA转FOV的函数,因为导出表的PE结构中 记录的都是RVA 内存值,我们找到其对应的FOV更方便我们修改文件,解析过程还是跟之前解析节表、标准头一样,就是按照结构图 一个字节一个字节找,注意Directory中存的是导出表的内存地址,找到导出表地址后 需要加上基址才可以继续往下找

下面就是代码了

<mycode.h>

typedef struct _DIRECTORY
{
	int* pvirtualaddress;  //16个Directory
	int* psize;
}DIRECTORY;

typedef struct _PE
{
	//DOS头
	short* p_e_magic;	//MZ标记 用于判断是否为可执行文件
	short* p_e_cblp;
	short* p_e_cp;
	short* p_e_crlc;
	short* p_e_cparhdr;
	short* p_e_minalloc;
	short* p_e_maxalloc;
	short* p_e_ss;
	short* p_e_sp;
	short* p_e_csum;
	short* p_e_ip;
	short* p_e_cs;
	short* p_e_lfarlc;
	short* p_e_ovno;
	short* p_e_res;
	short* p_e_oemid;
	short* p_e_oeminfo;
	short* p_e_res2;
	int* p_e_lfanew;  //第60个字节  一行16个字节 第四行的最后四个字节就是 e_lfanew,从文件开始偏移 *p_e_lfanew 就是PE
	//PE标记
	char* p_signature;
	//标准PE头
	short* p_machine;	//程序运行的CPU型号   0x0任何处理器 0x14C 386及后续处理器
	short* p_numberofsections;	//节的总数
	int* p_timedatestamp;
	int* p_pointertosymboltable;
	int* p_numberofsymbols;
	short* p_sizeofoptionalheader;	//可选PE头的大小  32位默认E0 64位默认F0 可以自定义
	short* p_characteristics;
	//可选PE头
	short* p_magic;	//程序运行的CPU型号   0x0任何处理器 0x14C 386及后续处理器
	char* p_majorlinkerversion;
	char* p_minorlinkerversion;
	int* p_sizeofcode; //所有代码节的和 内存对齐字节数的整数倍
	int* p_sizeofinitializeddata;	//初始化的数据大小
	int* p_sizeofuninitializeddata;	//未初始化的数据的大小
	int* p_addressofentrypoint;		//程序入口
	int* p_baseofcode;
	int* p_baseofdata;
	int* p_imagebase;				//内存镜像基址
	int* p_sectionalignment;	//内存对齐字节数
	int* p_filealignment;	//文件对齐字节数
	short* p_majoroperatingsystemversion;
	short* p_minoroperatingsystemversion;
	short* p_majorimageversion;
	short* p_minorimageversion;
	short* p_majorsubsystemversion;
	short* p_minorsubsystemversion;
	int* p_win32versionvalue;
	int* p_sizeofimage;
	int* p_sizeofheaders;
	int* p_checksum;
	short* p_subsystem;
	short* p_dllcharacteristics;
	int* p_sizeofstackreserve;
	int* p_sizeofstackcommit;
	int* p_sizeofheapreserve;
	int* p_sizeofheapcommit;
	int* p_loaderflags;
	int* p_numberofrvaandsizes;
	char* p_datadirectory_base;
	//long long* p_datadirectory[16];
	DIRECTORY DIR[16];			//RVA内存地址     RVA from base of image
	int* pdirectory_entry_export_virtualaddress;  //导出表地址 相对于内存开始的偏移量
	int* pdirectory_entry_export_size;
	char* pexportdirectory_base;
	int* characteristics;
	int* timedatestamp;
	short* majorversion;
	short* minorversion;
	int* exportname;			//导出表文件名
	int* base;					//导出函数基址
	int* numberoffunctions;		//导出函数个数
	int* numberofnames;			//以函数名导出的函数个数
	int* addressoffunctions;	//导出函数地址表  RVA from base of image
	int* addressofnames;		//导出函数名称表  RVA from base of image
	int* addressofnameordinals;	//导出函数序号表  RVA from base of image

	//节表
	char* image_section_header_base;
	char name[9];
	int *pmisc;
	int *pvirtualaddress;
	int *psizeofrawdata;
	int *ppointertorawdata;
	int *ppointertorelocations;
	int *ppointertolinenumbers;
	short *pnumberofrelocations;
	short *pnumberoflinenumbers;
	int *pcharacteristics;
}PE;
 
 
//获取文件大小
int get_file_size(char* filename);
//将文件读取到内存中
char* read_file_to_file_buffer(char* filename);
//释放 将文件读取到内存
void read_file_to_file_buffer_free(char* ptr);
int trans_file_buffer_to_image_buffer(char* pfilebuffer,char* pimagebuffer);
int trans_image_buffe_to_file_buffer(char* pimagebuffer,char* pfilebuffer,int secno,int shellcodelength);
int trans_file_buffer_to_file(char* pfilebuffer,char* filename,int size);

//设置PE
void set_pe(char* ptr,PE* p_PE );

//RVA --> FOA   这次把这里封装了一下  详细解法可以参考前面内容
int trans_RVA_to_FOA(int pRVA,char* filename);

<mycode.cpp>

有些函数已经出现过很多次了 可以删掉的 不用在意 

主要修改了这两个函数 set_pe() 、trans_RVA_to_FOA()

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "mycode.h"
 
//获取文件大小
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;
}
 
 
//将文件读取到内存中 返回读取到哪个内存地址
char* read_file_to_file_buffer(char* filename)
{
	//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("文件读取到:%x \n",ptr);
	//将文件内容 读取到内存
	FILE* fp = fopen(filename,"rb+");
	fread(ptr,file_size,1,fp);
	fclose(fp);
	return ptr;
}
//释放内存
void read_file_to_file_buffer_free(char* ptr)
{
	free(ptr);
	ptr=NULL;
}
 
 
//FileBuffer 转化到 ImageBuffer
int trans_file_buffer_to_image_buffer(char* pfilebuffer,char* pimagebuffer)
{
	//找到PE偏移
	int* p_e_lfanew=(int*)pfilebuffer+15; 
	//PE标志
	char* p_signature = pfilebuffer+(*p_e_lfanew);	
	//节数
	short* p_numberofsections=(short*)(p_signature+6);	
 
	//DOS头-节表  这段可以直接复制过去 不用做内存转换  大小在sizeofheaders 记录着
	int* p_sizeofheaders=(int*)(p_signature+84);
	memcpy(pimagebuffer,pfilebuffer,*p_sizeofheaders);
	
	//节区 复制到 ImageBuffer  每节大小为 sizeofrawdata
	//遍历节表  复制每一节
	short* p_sizeofoptionalheader=(short*)(p_signature+20);	
	char* image_section_header_base=p_signature+4+20+(*p_sizeofoptionalheader);
 
	int i=1;
	for(i;i<=*p_numberofsections;i++)
	{
		int *pvirtualaddress=(int*)(image_section_header_base+12);		//节内存中的偏移
		int *psizeofrawdata=(int*)(image_section_header_base+16);		//节文件中的大小
		int *ppointertorawdata=(int*)(image_section_header_base+20);	//节文件中的偏移
 
	//	printf("复制第 %d 个节	起始地址:%x \t 结束地址:%x \n",i,pfilebuffer + (*ppointertorawdata),pfilebuffer + (*ppointertorawdata)+ *psizeofrawdata);
		
	//								    偏移	                                
		memcpy( pimagebuffer  +  (*pvirtualaddress)      //Image中 节的位置
			   ,pfilebuffer   +  (*ppointertorawdata)    //文件中  节的位置 
			   ,*psizeofrawdata);						 //节大小
	
		image_section_header_base=image_section_header_base+40;
	}
	return 0;
}
 
//将ImageBuffer还原到FileBuffer内存
int trans_image_buffe_to_file_buffer(char* pimagebuffer,char* pfilebuffer,int secno,int shellcodelength)
{
	//找到PE偏移
	int* p_e_lfanew=(int*)pimagebuffer+15; 
	//PE标志
	char* p_signature = pimagebuffer+(*p_e_lfanew);	
	//节数
	short* p_numberofsections=(short*)(p_signature+6);	
 
	//DOS头-节表  这段可以直接复制过去 不用做内存转换  大小在sizeofheaders 记录着
	int* p_sizeofheaders=(int*)(p_signature+84);
	memcpy(pfilebuffer,pimagebuffer,*p_sizeofheaders);
	
	//节区 复制到 ImageBuffer  每节大小为 sizeofrawdata
	//遍历节表  复制每一节
	short* p_sizeofoptionalheader=(short*)(p_signature+20);	
	char* image_section_header_base=p_signature+4+20+(*p_sizeofoptionalheader);
 
	int i=1;
	for(i;i<=*p_numberofsections;i++)
	{
		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);	//节文件中的偏移
		//printf("复制第 %d 个节	起始地址:%x \t 结束地址:%x \n",i,pimagebuffer + (*pvirtualaddress),pimagebuffer + (*pvirtualaddress)+ *pmisc);
		//当 节为 代码追加节时  复制的内容 要多复制一些
		if( i == secno)
		{
		//								    偏移	                                
			memcpy( pfilebuffer    +  (*ppointertorawdata)      //FileBuffer中   节的位置
				   ,pimagebuffer   +  (*pvirtualaddress)	    //ImageBuffer中  节的位置 
				   ,*pmisc+shellcodelength);				    //节大小 +  shellcode大小
		}
		else
		{
			//								    偏移	                                
			memcpy( pfilebuffer    +  (*ppointertorawdata)      //FileBuffer中   节的位置
				   ,pimagebuffer   +  (*pvirtualaddress)	    //ImageBuffer中  节的位置 
				   ,*pmisc);									//节大小
		}

		image_section_header_base=image_section_header_base+40;
	}
	return 0;
}
 
 
//将 NewFileBuffer内容  写到文件
int trans_file_buffer_to_file(char* pfilebuffer,char* filename,int size)
{
 
	printf("将 %x 写入到 %s ",pfilebuffer,filename);
	FILE *fp;
	fp = fopen(filename,"wb+" );
	fwrite(pfilebuffer, size , 1, fp );
	fclose(fp);
	return 0;
}
 

 
void set_pe(char* ptr,PE* p_PE )
{
	//DOS头
	p_PE->p_e_magic=(short*)ptr;	//MZ标记 用于判断是否为可执行文件
	p_PE->p_e_cblp=(short*)ptr+1;
	p_PE->p_e_cp=(short*)ptr+2;
	p_PE->p_e_crlc=(short*)ptr+3;
	p_PE->p_e_cparhdr=(short*)ptr+4;
	p_PE->p_e_minalloc=(short*)ptr+5;
	p_PE->p_e_maxalloc=(short*)ptr+6;
	p_PE->p_e_ss=(short*)ptr+7;
	p_PE->p_e_sp=(short*)ptr+8;
	p_PE->p_e_csum=(short*)ptr+9;
	p_PE->p_e_ip=(short*)ptr+10;
	p_PE->p_e_cs=(short*)ptr+11;
	p_PE->p_e_lfarlc=(short*)ptr+12;
	p_PE->p_e_ovno=(short*)ptr+13;
	p_PE->p_e_res=(short*)ptr+17;
	p_PE->p_e_oemid=(short*)ptr+18;
	p_PE->p_e_oeminfo=(short*)ptr+19;
	p_PE->p_e_res2=(short*)ptr+20;
	p_PE->p_e_lfanew=(int*)ptr+15;  //第60个字节  一行16个字节 第四行的最后四个字节就是 e_lfanew,从文件开始偏移 *p_e_lfanew 就是PE
	//PE标记
	p_PE->p_signature = ptr+(*(p_PE->p_e_lfanew));
	//标准PE头
	p_PE->p_machine=(short*)(p_PE->p_signature+4);	//程序运行的CPU型号   0x0任何处理器 0x14C 386及后续处理器
	p_PE->p_numberofsections=(short*)(p_PE->p_signature+6);	//节的总数
	p_PE->p_timedatestamp=(int*)(p_PE->p_signature+8);
	p_PE->p_pointertosymboltable=(int*)(p_PE->p_signature+12);
	p_PE->p_numberofsymbols=(int*)(p_PE->p_signature+16);
	p_PE->p_sizeofoptionalheader=(short*)(p_PE->p_signature+20);	//可选PE头的大小  32位默认E0 64位默认F0 可以自定义
	p_PE->p_characteristics=(short*)(p_PE->p_signature+22);
	//可选PE头
	p_PE->p_magic=(short*)(p_PE->p_signature+24);	//程序运行的CPU型号   0x0任何处理器 0x14C 386及后续处理器
	p_PE->p_majorlinkerversion=(char*)(p_PE->p_signature+26);
	p_PE->p_minorlinkerversion=(char*)(p_PE->p_signature+27);
	p_PE->p_sizeofcode=(int*)(p_PE->p_signature+28); //所有代码节的和 内存对齐字节数的整数倍
	p_PE->p_sizeofinitializeddata=(int*)(p_PE->p_signature+32);	//初始化的数据大小
	p_PE->p_sizeofuninitializeddata=(int*)(p_PE->p_signature+36);	//未初始化的数据的大小
	p_PE->p_addressofentrypoint=(int*)(p_PE->p_signature+40);		//程序入口
	p_PE->p_baseofcode=(int*)(p_PE->p_signature+44);
	p_PE->p_baseofdata=(int*)(p_PE->p_signature+48);
	p_PE->p_imagebase=(int*)(p_PE->p_signature+52);				//内存镜像基址
	p_PE->p_sectionalignment=(int*)(p_PE->p_signature+56);	//内存对齐字节数
	p_PE->p_filealignment=(int*)(p_PE->p_signature+60);	//文件对齐字节数
	p_PE->p_majoroperatingsystemversion=(short*)(p_PE->p_signature+64);
	p_PE->p_minoroperatingsystemversion=(short*)(p_PE->p_signature+66);
	p_PE->p_majorimageversion=(short*)(p_PE->p_signature+68);
	p_PE->p_minorimageversion=(short*)(p_PE->p_signature+70);
	p_PE->p_majorsubsystemversion=(short*)(p_PE->p_signature+72);
	p_PE->p_minorsubsystemversion=(short*)(p_PE->p_signature+74);
	p_PE->p_win32versionvalue=(int*)(p_PE->p_signature+76);
	p_PE->p_sizeofimage=(int*)(p_PE->p_signature+80);
	p_PE->p_sizeofheaders=(int*)(p_PE->p_signature+84);
	p_PE->p_checksum=(int*)(p_PE->p_signature+88);
	p_PE->p_subsystem=(short*)(p_PE->p_signature+92);
	p_PE->p_dllcharacteristics=(short*)(p_PE->p_signature+94);
	p_PE->p_sizeofstackreserve=(int*)(p_PE->p_signature+96);
	p_PE->p_sizeofstackcommit=(int*)(p_PE->p_signature+100);
	p_PE->p_sizeofheapreserve=(int*)(p_PE->p_signature+104);
	p_PE->p_sizeofheapcommit=(int*)(p_PE->p_signature+108);
	p_PE->p_loaderflags=(int*)(p_PE->p_signature+112);
	p_PE->p_numberofrvaandsizes=(int*)(p_PE->p_signature+116);
	p_PE->p_datadirectory_base=(char*)(p_PE->p_signature+120);
	//节表
	p_PE->image_section_header_base=(p_PE->p_signature)+4+20+ *(p_PE->p_sizeofoptionalheader);
	memcpy(p_PE->name,p_PE->image_section_header_base,8);
	p_PE->name[8]='\0';
	p_PE->pmisc=(int*)(p_PE->image_section_header_base+8);
	p_PE->pvirtualaddress=(int*)(p_PE->image_section_header_base+12);
	p_PE->psizeofrawdata=(int*)(p_PE->image_section_header_base+16);
	p_PE->ppointertorawdata=(int*)(p_PE->image_section_header_base+20);
	p_PE->ppointertorelocations=(int*)(p_PE->image_section_header_base+24);
	p_PE->ppointertolinenumbers=(int*)(p_PE->image_section_header_base+28);
	p_PE->pnumberofrelocations=(short*)(p_PE->image_section_header_base+32);
	p_PE->pnumberoflinenumbers=(short*)(p_PE->image_section_header_base+34);
	p_PE->pcharacteristics=(int*)(p_PE->image_section_header_base+36);

	p_PE->DIR[0].pvirtualaddress=(int*)(p_PE->p_signature+120);		//导出表地址
	p_PE->DIR[1].pvirtualaddress=(int*)(p_PE->p_signature+128);
	p_PE->DIR[2].pvirtualaddress=(int*)(p_PE->p_signature+136);
	p_PE->DIR[3].pvirtualaddress=(int*)(p_PE->p_signature+144);
	p_PE->DIR[4].pvirtualaddress=(int*)(p_PE->p_signature+152);
	p_PE->DIR[5].pvirtualaddress=(int*)(p_PE->p_signature+160);
	p_PE->DIR[6].pvirtualaddress=(int*)(p_PE->p_signature+168);
	p_PE->DIR[7].pvirtualaddress=(int*)(p_PE->p_signature+176);
	p_PE->DIR[8].pvirtualaddress=(int*)(p_PE->p_signature+184);
	p_PE->DIR[9].pvirtualaddress=(int*)(p_PE->p_signature+192);
	p_PE->DIR[10].pvirtualaddress=(int*)(p_PE->p_signature+200);
	p_PE->DIR[11].pvirtualaddress=(int*)(p_PE->p_signature+208);
	p_PE->DIR[12].pvirtualaddress=(int*)(p_PE->p_signature+216);
	p_PE->DIR[13].pvirtualaddress=(int*)(p_PE->p_signature+224);
	p_PE->DIR[14].pvirtualaddress=(int*)(p_PE->p_signature+232);
	p_PE->DIR[15].pvirtualaddress=(int*)(p_PE->p_signature+240);

	p_PE->DIR[0].psize=(int*)(p_PE->p_signature+120+4);		//导出表地址
	p_PE->DIR[1].psize=(int*)(p_PE->p_signature+128+4);
	p_PE->DIR[2].psize=(int*)(p_PE->p_signature+136+4);
	p_PE->DIR[3].psize=(int*)(p_PE->p_signature+144+4);
	p_PE->DIR[4].psize=(int*)(p_PE->p_signature+152+4);
	p_PE->DIR[5].psize=(int*)(p_PE->p_signature+160+4);
	p_PE->DIR[6].psize=(int*)(p_PE->p_signature+168+4);
	p_PE->DIR[7].psize=(int*)(p_PE->p_signature+176+4);
	p_PE->DIR[8].psize=(int*)(p_PE->p_signature+184+4);
	p_PE->DIR[9].psize=(int*)(p_PE->p_signature+192+4);
	p_PE->DIR[10].psize=(int*)(p_PE->p_signature+200+4);
	p_PE->DIR[11].psize=(int*)(p_PE->p_signature+208+4);
	p_PE->DIR[12].psize=(int*)(p_PE->p_signature+216+4);
	p_PE->DIR[13].psize=(int*)(p_PE->p_signature+224+4);
	p_PE->DIR[14].psize=(int*)(p_PE->p_signature+232+4);
	p_PE->DIR[15].psize=(int*)(p_PE->p_signature+240+4);

	//导出表
	p_PE->p_datadirectory_base=(char*)(p_PE->p_signature+120);
	p_PE->pdirectory_entry_export_virtualaddress=(int*)(p_PE->p_signature+120);  //导出表地址 RVA内存地址
	p_PE->pdirectory_entry_export_size=(int*)(p_PE->p_signature+124);
	//导出表属性
	p_PE->pexportdirectory_base= ptr + *p_PE->pdirectory_entry_export_virtualaddress;    //RVA from base of image          这里注意要加上内存的开始位置 ptr    
	p_PE->characteristics=(int*)(p_PE->pexportdirectory_base);
	p_PE->timedatestamp=(int*)(p_PE->pexportdirectory_base+4);
	p_PE->majorversion=(short*)(p_PE->pexportdirectory_base+8);
	p_PE->minorversion=(short*)(p_PE->pexportdirectory_base+10);
	p_PE->exportname=(int*)(p_PE->pexportdirectory_base+12);			//导出表文件名
	p_PE->base=(int*)(p_PE->pexportdirectory_base+16);					//导出函数基址
	p_PE->numberoffunctions=(int*)(p_PE->pexportdirectory_base+20);		//导出函数个数
	p_PE->numberofnames=(int*)(p_PE->pexportdirectory_base+24);			//以函数名导出的函数个数
	p_PE->addressoffunctions=(int*)(p_PE->pexportdirectory_base+28);	//导出函数表地址
	p_PE->addressofnames=(int*)(p_PE->pexportdirectory_base+32);		//导出函数名称地址表
	p_PE->addressofnameordinals=(int*)(p_PE->pexportdirectory_base+36);	//导出函数序号地址表


}

//RVA转化为FOA
int trans_RVA_to_FOA(int pRVA,char* pfilename)
{
    //用于存放硬盘中 和 内存中的PE结构
	PE PE_file;
	PE PE_memory;
	//找出文件中的PE结构
	char* ptr=read_file_to_file_buffer(pfilename);
	set_pe(ptr,&PE_file);
	//为ImageBuffer申请空间
	char* p_imagebuffer;
	p_imagebuffer = (char*) malloc(*PE_file.p_sizeofimage);
	//找出内存中的PE结构
	if( p_imagebuffer == NULL)
	{
		printf("空间不足\n");
		return 0;
	}
	else
	{	
		memset(p_imagebuffer,0,*PE_file.p_sizeofimage);
		//这里一定要注意 p_imagebuffer里面有数据之后 才能set_pe 
		//FileBuffer内容 复制到 ImageBuffer
		trans_file_buffer_to_image_buffer(ptr,p_imagebuffer);
		set_pe(p_imagebuffer,&PE_memory);
		//printf("ImageBuffer范围:%x --> %x \n",p_imagebuffer,p_imagebuffer+(*PE_file.p_sizeofimage));
	}
	//节表大小
	int sectablesize = *PE_file.p_numberofsections*40;
	//节表结束位置
	int sectableend = (int)(PE_memory.image_section_header_base + sectablesize);
	//printf("节表范围:%x --> %x \n",PE_memory.image_section_header_base,sectableend);

	int RVA = pRVA + (int)p_imagebuffer; 
	int FOA = 0x99999999;
	int section_no;			//RVA属于第几节
	int section_offset;				//RVA节偏移
	//printf("请输入RVA值\n");
	//scanf("%p",&RVA);
	//printf("RVA = %x \n",RVA);
	
	//如果RVA在节表结束之前 那么不用转换 直接减去基址就是FOA
	if( RVA < sectableend )
	{
		FOA = RVA - (int)p_imagebuffer;
		//printf("节表之前 无需转化 FOA = %x \n",FOA);
	}
	else
	{
	//找出 RVA在内存中节数 和 节偏移量
	int rva_offset = (char*)RVA - p_imagebuffer;
	//判断是第几个节
	int i=1;
	for(i;i<=*PE_memory.p_numberofsections;i++)
	{
		// RVA的偏移量  在 两点之间 此时的节数才是我们要的
		if(     rva_offset >=    *PE_memory.pvirtualaddress 
			&&  rva_offset <   ( *PE_memory.pvirtualaddress + (*PE_memory.pmisc) ) )
		{ 
			section_no=i;
			section_offset = rva_offset - *PE_memory.pvirtualaddress ;
			//printf("RVA是第%d个节   节偏移量为%d \n",section_no,section_offset);
			break;
		}
		//image_section_header_base=image_section_header_base+40;
		//这里注意 pvirtualaddress 要往下走40个字节(一个节表的大小),
		//因为pvirtualaddress 是int 所以指针需要加10 即可 
		PE_memory.pvirtualaddress=PE_memory.pvirtualaddress+10;	
        PE_memory.pmisc=PE_memory.pmisc+10;
	}
	//根据 节数  找出文件中节的位置  第n节 需要遍历n-1次
	for(i=1;i<section_no;i++)
	{
		PE_file.ppointertorawdata=PE_file.ppointertorawdata+10;	
	}
	//加上 节偏移量 得出最终在文件中的位置
	FOA=*PE_file.ppointertorawdata+section_offset;
	//printf("FOA = %x \n",*PE_file.ppointertorawdata+section_offset);
	}
	//释放内存
	free(p_imagebuffer);
	p_imagebuffer=NULL;
	read_file_to_file_buffer_free(ptr);
	return FOA;
}

main函数

只打印了16个Director的地址信息,导出表的属性信息是在监控视图看的

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "mycode.h"

int main()
{
	char* sourcefile="D:\\CODE\\DLL\\TestDll.dll";
	char* ptr=read_file_to_file_buffer(sourcefile);
	PE filePE;
	set_pe(ptr,&filePE);
	printf("导出表地址:%x \n",*filePE.pdirectory_entry_export_virtualaddress);
	int FOA=0x99999999;
	for(int i=0;i<16;i++)
	{
		FOA=trans_RVA_to_FOA(*filePE.DIR[i].pvirtualaddress,sourcefile);
		printf("第%d个表:\n",i+1);
		printf("RVA地址:%x\t\t",*filePE.DIR[i].pvirtualaddress);
		printf("FOA地址:%x\t\t",FOA);
		printf("大小:%x\n",*filePE.DIR[i].psize);
	}

	return 0;
}

运行结果如下

用PE工具比对 一切正常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值