天天看点

PE 文件格之资源

PE 文件格之资源,是一个三级结构。

代码先放上:

#include "stdio.h"
#include "windows.h"
void GetDataAnd(DWORD RVA,int size,int type)//解析特定类型,自己添加
{
	
}
BOOL GetResour(DWORD nResoure,DWORD npose,DWORD nrfile,HANDLE file,int nType = -1)//nResoure 资源add npose 偏移 nrfile 段偏移 
{
	IMAGE_RESOURCE_DIRECTORY nmain={0};
	DWORD backdatenum;
	SetFilePointer(file,nResoure+npose,NULL,FILE_BEGIN);
	ReadFile(file,&nmain,sizeof(nmain),&backdatenum,0);//读取一个
	DWORD nmainnum=nResoure+sizeof(nmain)+npose;
	IMAGE_RESOURCE_DIRECTORY_ENTRY sundate={0};
	for (int i=0;i<nmain.NumberOfIdEntries+nmain.NumberOfNamedEntries;++i,nmainnum+=sizeof(sundate))
	{
		SetFilePointer(file,nmainnum,NULL,FILE_BEGIN);
		ReadFile(file,&sundate,sizeof(sundate),&backdatenum,NULL);
		if((sundate.OffsetToData&0x80000000)!=0)//最高位,如果是1,那就到第三层了
		{
			char ittoname[30]={0};
			if((sundate.Name&0x80000000)!=0)//最高位,如果是2,那就是一个自定义的类型,非系统的类型
			{
				//m_DrivesRoot=m_resourcetree.InsertItem("date", 0, 1,treepoint);
				printf("Date\n");
			}
			else
			{
				switch(sundate.Id)
				{
				case 1:
					strcpy(ittoname,"光标");
					break;
				case 2:
					strcpy(ittoname,"位图");
					break;
				case 3:
					strcpy(ittoname,"图标");
					break;
				case 4:
					strcpy(ittoname,"菜单");
					break;
				case 5:
					strcpy(ittoname,"对话框");
					break;
				case 6:
					strcpy(ittoname,"字符串");
					break;
				case 7:
					strcpy(ittoname,"字体目录");
					break;
				case 8:
					strcpy(ittoname,"字体");
					break;
				case 9:
					strcpy(ittoname,"加速键");
					break;
				case 10:
					strcpy(ittoname,"未格式化资源");
					break;
				case 11:
					strcpy(ittoname,"消息表");
					break;
				case 12:
					strcpy(ittoname,"光标组");
					break;
				case 13:
					strcpy(ittoname,"未知");
					break;
				case 14:
					strcpy(ittoname,"图标组");
					break;
				case 15:
					strcpy(ittoname,"未知");
					break;
				case 16:
					strcpy(ittoname,"版本信息");
					break;
				default:
					strcpy(ittoname,"其它");
						break;
				}
				if(nType<0)
				{
					printf("%s\n",ittoname);//第一层
					GetResour(nResoure,sundate.OffsetToData&0x7fffffff,nrfile,file,sundate.Id);
				}
				else
				{
					printf("%d\n",sundate.Id);//第二层
					GetResour(nResoure,sundate.OffsetToData&0x7fffffff,nrfile,file,nType);
				}
			}
			//去掉最高位
		}
		else//第三层
		{
			IMAGE_RESOURCE_DATA_ENTRY rdata={0};
			SetFilePointer(file,sundate.OffsetToData+nResoure,NULL,FILE_BEGIN);
			ReadFile(file,&rdata,sizeof(rdata),&backdatenum,NULL);
			//p->id=atoi(m_resourcetree.GetItemText(treepoint));
			int RVA=rdata.OffsetToData-nrfile;
			int size=rdata.Size;
			printf("  RVA :%08x Size:%d (文件位置:%08x)\n",RVA,size,RVA-nrfile);
			GetDataAnd(RVA,size,nType);//针对性,对某个类型进行解析
		}
	}
	return TRUE;
}

BOOL GetPEHeadFromFile(char *filePath,PIMAGE_DOS_HEADER nhead,PIMAGE_NT_HEADERS npe,PIMAGE_SECTION_HEADER *nSection)
{
	HANDLE file=INVALID_HANDLE_VALUE;
	try
	{
		file=CreateFile(filePath,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,0);//打开文件 
		if(file==INVALID_HANDLE_VALUE ) return FALSE;//如果错误
		DWORD backdatenum;
		ReadFile(file,nhead,sizeof(IMAGE_DOS_HEADER),&backdatenum,0);
		
		if(memcmp(&nhead->e_magic,"MZ",2)!=0) throw  (1);//判断DOS魔术字
		SetFilePointer(file,nhead->e_lfanew,0,FILE_BEGIN);
		ReadFile(file,npe,sizeof(IMAGE_NT_HEADERS),&backdatenum,0);
		if(npe->Signature != 0x00004550) throw  (2);
		*nSection =  new IMAGE_SECTION_HEADER[npe->FileHeader.NumberOfSections];
		PIMAGE_SECTION_HEADER Section = *nSection;
		for (int i = 0 ; i < npe->FileHeader.NumberOfSections ; ++i)
		{
			ReadFile(file,&Section[i],sizeof(Section[i]),&backdatenum,0);
			if(backdatenum!=sizeof(Section[i])) throw(3);
			printf("节点名:%s\n",Section[i].Name);
			
			printf("      虚拟偏移:%08X\n",Section[i].VirtualAddress);
			printf("      虚拟大小:%08X\n",Section[i].Misc.VirtualSize);
			printf("      实际偏移:%08X\n",Section[i].PointerToRawData);
			printf("      实际大小:%08X\n",Section[i].SizeOfRawData);
			printf("      文件特征:%08X\n",Section[i].Characteristics);
			
		}
		//printf("%x %x %d %d",IMAGE_Import.VirtualAddress,IMAGE_Export.VirtualAddress,IMAGE_Import_ID,IMAGE_Export_ID);
		CloseHandle(file);
	}
	catch (...)
	{
		printf("不是有效的PE");
		CloseHandle(file);
		return FALSE;
	}
	return TRUE;
}
BOOL DirInSecton(PIMAGE_DATA_DIRECTORY ndir,PIMAGE_SECTION_HEADER nsection)
{
	if(ndir->VirtualAddress>=nsection->VirtualAddress&&ndir->VirtualAddress<=nsection->VirtualAddress+nsection->Misc.VirtualSize)
	{
		return TRUE;
	}
	return FALSE;
}
void AnyResourcesFromFile(PIMAGE_SECTION_HEADER Section,PIMAGE_NT_HEADERS npe,char *filePath)
{
	IMAGE_DATA_DIRECTORY* IMAGE_Resources = &npe->OptionalHeader.DataDirectory[2];//资源在2号
	int IMAGE_Resources_ID = -1;
	
	for (int i = 0 ; i < npe->FileHeader.NumberOfSections ; ++i)
	{
		if(DirInSecton(IMAGE_Resources,Section+i))
		{
			IMAGE_Resources_ID = i;
			break;
		}
	}
	if(IMAGE_Resources_ID>=0)
	{
		int n_Resoure_file=Section[IMAGE_Resources_ID].VirtualAddress-Section[IMAGE_Resources_ID].PointerToRawData;
		int n_Resoure=IMAGE_Resources->VirtualAddress-n_Resoure_file;
		HANDLE file=INVALID_HANDLE_VALUE;
		file=CreateFile(filePath,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,0);
		if(file==INVALID_HANDLE_VALUE ) return ;
		GetResour(n_Resoure,0,n_Resoure_file,file,-1);//分析资源,最后一个参数必须为小于0,为处理方便
	}
	
}

int main(int argc, char* argv[])
{
	printf("Hello World!\n");
	IMAGE_DOS_HEADER head;
	IMAGE_NT_HEADERS pe;
	PIMAGE_SECTION_HEADER Section;
	char file[] = "C:\\windows\\notepad.exe";
	if(GetPEHeadFromFile(file,&head,&pe,&Section))
	{
		AnyResourcesFromFile(Section,&pe,file);
		
	}
	return 0;
}
           

这三层模式。类似

A代表:IMAGE_RESOURCE_DIRECTORY

B代表:IMAGE_RESOURCE_DIRECTORY_ENTRY 

A 指向多个B

B又指向一个A。

B中有结束标志。

如果 想从那些资源数据中保存可详见资源:http://download.csdn.net/download/he702477275/4972957

继续阅读