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