/* * 近日学习pe文件格式,写了一个简单的分析程序 * 个人网站:http://ggg82.126.com * 电子邮件:ggg82@163.com * QQ:358416653 * * 本程序在win2000+vc6平台编译通过 * 学习参考:看学论坛 */ #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> void help() { printf("Usage:Pedir <exefile>/n"); printf("Press any key to exit this program./n"); getch(); } //IMAGE_DOS_SIGNATURE int main(int argc,char *argv[]) { IMAGE_DOS_HEADER *pDosHead; IMAGE_NT_HEADERS *pPeHead; IMAGE_SECTION_HEADER *pSectionHead; HANDLE hFile,hMapping; char *pBasePoint; // char buffer[MAX_PATH]; int i; if(argc<2) { help(); exit(1); } hFile=CreateFile(argv[1],GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0); //Create the File handle if (hFile==INVALID_HANDLE_VALUE) { //test File Handle GetLastError(); return 0; } if (!(hMapping=CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0))) { //Create the File Map and test CloseHandle(hFile); return 0; } if (!(pBasePoint=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0))) { CloseHandle(hFile); CloseHandle(hMapping); return 0; } // GetShortPathName(argv[1],buffer,sizeof buffer); //判断是否是pe文件 pDosHead=(IMAGE_DOS_HEADER *)pBasePoint; if(IMAGE_DOS_SIGNATURE!=pDosHead->e_magic) { printf("DOS文件头出错!/n"); exit(1); } //通过Dos头找到pe头 pPeHead=(IMAGE_NT_HEADERS *)(pBasePoint+pDosHead->e_lfanew); //判断pe头 if(IMAGE_NT_SIGNATURE!=pPeHead->Signature) { printf("PE文件头错误!/n"); exit(1); } //列出pe filehead的信息 printf("运行平台:/t"); if(IMAGE_FILE_MACHINE_I386==pPeHead->FileHeader.Machine) printf("%s/n","X86CPU"); else printf("未知(%X)/n",pPeHead->FileHeader.Machine); printf("节数目:/t%d/n",pPeHead->FileHeader.NumberOfSections); printf("创建时间:/t%X/n",pPeHead->FileHeader.TimeDateStamp); printf("PointerToSymbolTable:/t%X/n",pPeHead->FileHeader.PointerToSymbolTable); printf("NumberOfSymbols:/t%X/n",pPeHead->FileHeader.NumberOfSymbols); printf("SizeOfOptionalHeader:/t%X/n",pPeHead->FileHeader.SizeOfOptionalHeader); printf("Characteristics:/t%X/n",pPeHead->FileHeader.Characteristics); //列出Optional Header信息 printf("进入点:/t%x/n",pPeHead->OptionalHeader.AddressOfEntryPoint); printf("载入地址:/t%x/n",pPeHead->OptionalHeader.ImageBase); printf("内存对齐:/t%x/n",pPeHead->OptionalHeader.SectionAlignment); printf("文件对齐:/t%x/n",pPeHead->OptionalHeader.FileAlignment); printf("MajorSubsystemVersion:/t%x/n",pPeHead->OptionalHeader.MajorSubsystemVersion); printf("MinorSubsystemVersion:/t%x/n",pPeHead->OptionalHeader.MinorSubsystemVersion); printf("映像大小:/t%x/n",pPeHead->OptionalHeader.SizeOfImage); printf("头大小:/t%x/n",pPeHead->OptionalHeader.SizeOfHeaders); printf("界面:/t%x/n",pPeHead->OptionalHeader.Subsystem); //DataDirectory //Section Table //fseet应该不用定位了吧 for(i=0;i<pPeHead->FileHeader.NumberOfSections;i++) { int j; pSectionHead=(IMAGE_SECTION_HEADER *)((char *)pPeHead+sizeof *pPeHead+i*sizeof *pSectionHead); printf("/n节名称:/t"); for(j=0;j<sizeof pSectionHead->Name;j++) { if(0==pSectionHead->Name[j]) break; putchar(pSectionHead->Name[j]); } printf("/n本节的RVA:/t%X/n",pSectionHead->VirtualAddress); printf("映射尺寸:/t%X/n",pSectionHead->SizeOfRawData); printf("文件数据偏移:/t%X/n",pSectionHead->PointerToRawData); printf("节属性:/t%X/n",pSectionHead->Characteristics); } #define addr(rva) (void *)((char *)((char *)pBasePoint+pSectionHead->PointerToRawData)+((DWORD)(rva)-pSectionHead->VirtualAddress)) //导入表//遍历节表查找导入表的位置 for(i=0;i<pPeHead->FileHeader.NumberOfSections;i++) { IMAGE_DATA_DIRECTORY *pData=&pPeHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; pSectionHead=(IMAGE_SECTION_HEADER *)((char *)pPeHead+sizeof *pPeHead+i*sizeof *pSectionHead); //查看导入表是否在该节内 if(pData->VirtualAddress>=pSectionHead->VirtualAddress &&pData->VirtualAddress+pData->Size<=pSectionHead->VirtualAddress+pSectionHead->SizeOfRawData) { //定位地址 IMAGE_IMPORT_DESCRIPTOR *pImport=addr(pData->VirtualAddress); while(pImport->Name) { IMAGE_THUNK_DATA *imThunk_data=addr(pImport->Characteristics); //输出模块名称 printf("/n导入模块:%s/n/n",(char *)addr(pImport->Name)); //输出引入函数表 while(imThunk_data->u1 .Ordinal) { if(IMAGE_SNAP_BY_ORDINAL(imThunk_data->u1.Ordinal)) { printf("/t导入ID:/t%d/n",IMAGE_ORDINAL(imThunk_data->u1 .Ordinal )); } else { IMAGE_IMPORT_BY_NAME *imImport_Name=(IMAGE_IMPORT_BY_NAME *) addr(imThunk_data->u1.AddressOfData); printf("/t导入函数:/t%s/n",(char *)imImport_Name->Name); } imThunk_data++; }//*/ pImport++; } break; } } //导出表//和导入标实现方法类似 CloseHandle(hFile); CloseHandle(hMapping); return 0; }
学习PE文件格式后编写的简单代码(C代码)
最新推荐文章于 2024-03-31 15:31:19 发布