功能:
01:展示输出表信息
02: 展示输入表信息
03:资源表信息
04:重定位表信息
05:绑定导入表信息
难点:
01: 定义全局变量, 区别每个点击按钮, 使用一个对话框,分别对消息进行接收
02: 读取PE信息, 对每个表的信息进行展示
03: 字符串的使用方法 sprintf strcat 的用法
04 SendMessage
实例展示:
主要代码:
VOID SetPeFileInfo(HWND hwndDlg,LPSTR lpszFile) { HWND hInfoMation = GetDlgItem(hwndDlg,IDC_EDIT_INFOMATION); TCHAR InfoStr[200240]={0}; TCHAR rn[100] = {0}; LPVOID pFileBuffer = NULL; pFileBuffer= ReadPEFile(lpszFile); if(!pFileBuffer) { printf("文件读取失败\n"); return; } PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; PIMAGE_DATA_DIRECTORY DataDirectory=NULL; //Header信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader); //定位Directory_Data; DataDirectory = pOptionHeader->DataDirectory; DWORD FoA = 0; /* TCHAR rn[100] = TEXT("www.gyarmy.com"); sprintf(InfoStr,"\r\n%d\r\n%d\r\n%d",InfoNum,InfoNum,InfoNum); strcat(InfoStr,rn); SendMessage(hInfoMation,WM_SETTEXT,0,(long)InfoStr); */ switch(InfoNum) { case INFO_EXPORT: { //确定导出表信息 //printf("%x \n",FoA); DWORD Export_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; DWORD Export_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if(Export_Directory_Size == 0) { haveDirectory = FALSE; MessageBox(0,TEXT("没有输出表"),TEXT("错误"),0); return; }else{ haveDirectory = TRUE; } FoA = RVAToFileOffset(pFileBuffer,Export_Directory_Address); //定位导出表的位置 PIMAGE_EXPORT_DIRECTORY pExDirectory = NULL; pExDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + FoA); //基本信息 sprintf(rn,"输出表基本信息 : \r\n"); strcat(InfoStr,rn); sprintf(rn,"Characteristics: %08X\r\n",pExDirectory->Characteristics); strcat(InfoStr,rn); sprintf(rn,"TimeDateStamp: %08X\r\n",pExDirectory->TimeDateStamp); strcat(InfoStr,rn); sprintf(rn,"MajorVersion: %08X\r\n",pExDirectory->MajorVersion); strcat(InfoStr,rn); sprintf(rn,"MinorVersion: %08X\r\n",pExDirectory->MinorVersion); strcat(InfoStr,rn); sprintf(rn,"Name: %08X\r\n",pExDirectory->Name); strcat(InfoStr,rn); sprintf(rn,"Base: %08X\r\n",pExDirectory->Base); strcat(InfoStr,rn); sprintf(rn,"NumberOfFunctions: %08X\r\n",pExDirectory->NumberOfFunctions); strcat(InfoStr,rn); sprintf(rn,"NumberOfNames: %08X\r\n",pExDirectory->NumberOfNames); strcat(InfoStr,rn); sprintf(rn,"AddressOfFunctions: %08X\r\n",pExDirectory->AddressOfFunctions); strcat(InfoStr,rn); sprintf(rn,"AddressOfNames: %08X\r\n",pExDirectory->AddressOfNames); strcat(InfoStr,rn); sprintf(rn,"AddressOfNameOrdinals: %08X\r\n-------------\r\n",pExDirectory->AddressOfNameOrdinals); strcat(InfoStr,rn); //输出函数地址表信息 //AddressOfFunctions DWORD ExAddressOfFunctions = pExDirectory->AddressOfFunctions; DWORD ExAddressOfFunctionsFoA = RVAToFileOffset(pFileBuffer,ExAddressOfFunctions); DWORD ExNumberOfFunctions = pExDirectory->NumberOfFunctions; PDWORD pExAddressOfFunctions = NULL; pExAddressOfFunctions = (PDWORD)((DWORD)pFileBuffer + ExAddressOfFunctionsFoA); sprintf(rn,"每个函数地址表信息: \r\n"); strcat(InfoStr,rn); //输出每个函数地址表信息 DWORD k =0; for(k=0;k<ExNumberOfFunctions;k++) { //printf("%d : %x \n",k,); sprintf(rn,"%d : %08X\r\n",k,*pExAddressOfFunctions); strcat(InfoStr,rn); pExAddressOfFunctions++; } sprintf(rn,"-----------------\r\n"); strcat(InfoStr,rn); sprintf(rn,"函数名称表: \r\n"); strcat(InfoStr,rn); //函数名称表 DWORD ExAddressOfNames = pExDirectory->AddressOfNames; DWORD ExAddressOfNamesFoA = RVAToFileOffset(pFileBuffer,ExAddressOfNames); DWORD ExNumberOfNames = pExDirectory->NumberOfNames; PDWORD pExAddressOfNames = NULL; pExAddressOfNames = (PDWORD)((DWORD)pFileBuffer + ExAddressOfNamesFoA); for(k=0;k<ExNumberOfNames;k++) { //printf("%d : %x \n",k,*pExAddressOfNames); sprintf(rn,"%d : %08X\r\n",k,*pExAddressOfNames); strcat(InfoStr,rn); //函数名的地址转换为FoA ,输出函数名 PDWORD NameAddress = (PDWORD)RVAToFileOffset(pFileBuffer,*pExAddressOfNames); //输出函数名 printf("%s \n",(char*)((DWORD)pFileBuffer + (DWORD)NameAddress)); sprintf(rn,"%s \r\n",(char*)((DWORD)pFileBuffer + (DWORD)NameAddress)); strcat(InfoStr,rn); pExAddressOfNames++; } sprintf(rn,"-----------------\r\n"); strcat(InfoStr,rn); //函数序号表 sprintf(rn,"函数序号表: \r\n"); strcat(InfoStr,rn); DWORD ExAddressOfNameOrdinals = pExDirectory->AddressOfNameOrdinals; DWORD ExAddressOfNameOrdinalsFoA = RVAToFileOffset(pFileBuffer,ExAddressOfNameOrdinals); ExNumberOfNames = pExDirectory->NumberOfNames; PWORD pExAddressOfNameOrdinals = NULL; pExAddressOfNameOrdinals = (PWORD)((DWORD)pFileBuffer + ExAddressOfNameOrdinalsFoA); for(k=0;k<ExNumberOfNames;k++) { //printf("%d : %x \n",k,*pExAddressOfNameOrdinals); sprintf(rn,"%d : %08X \r\n",k,*pExAddressOfNameOrdinals); strcat(InfoStr,rn); pExAddressOfNameOrdinals++; } sprintf(rn,"-----------------\r\n"); strcat(InfoStr,rn); SendMessage(hInfoMation,WM_SETTEXT,0,(long)InfoStr); break; } case INFO_IMPORT: { //基本信息 //sprintf(rn,"%d : %08X \r\n",k,*pExAddressOfNameOrdinals); sprintf(rn,"输入表基本信息 : \r\n"); strcat(InfoStr,rn); //确定导入表 //pImportDirectory = NULL; IMAGE_DATA_DIRECTORY pImportDirectory = DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; DWORD ImportVirtualAddress = pImportDirectory.VirtualAddress; DWORD ImportFoa = RVAToFileOffset(pFileBuffer,ImportVirtualAddress); if(pImportDirectory.Size == 0) { haveDirectory = FALSE; MessageBox(0,TEXT("没有输入表"),TEXT("错误"),0); return; }else{ haveDirectory = TRUE; } sprintf(rn,"ImportVirtualAddress: %08X \r\n",ImportVirtualAddress); strcat(InfoStr,rn); sprintf(rn,"Size: %08X \r\n",pImportDirectory.Size); strcat(InfoStr,rn); sprintf(rn,"ImportFoa: %08X \r\n",ImportFoa); strcat(InfoStr,rn); //输出所有的导入表 //PIMAGE_THUNK_DATA32 pThunkData = NULL; //第一个导入表 PIMAGE_IMPORT_DESCRIPTOR pImportDes = NULL; pImportDes = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + ImportFoa); while(pImportDes->OriginalFirstThunk != 0x0 && pImportDes->FirstThunk != 0x0 ) { //输出所有的dll sprintf(rn,"OriginalFirstThunk: %08X \r\n",pImportDes->OriginalFirstThunk); strcat(InfoStr,rn); DWORD pNameAddress = RVAToFileOffset(pFileBuffer,pImportDes->Name); PSTR pDllName = (PSTR)((DWORD)pFileBuffer + pNameAddress); sprintf(rn,"name: %s \r\n",pDllName); strcat(InfoStr,rn); sprintf(rn,"------------------------------- : \r\n"); strcat(InfoStr,rn); //输出OriginalFirstThunk的信息 DWORD Thunk_Address = RVAToFileOffset(pFileBuffer,pImportDes->OriginalFirstThunk); PIMAGE_THUNK_DATA32 pThunkData = (PIMAGE_THUNK_DATA32)((DWORD)pFileBuffer + Thunk_Address); //根据pThunkData 的最高为来判断 DWORD ImportOrdinal = pThunkData->u1.Ordinal; while(ImportOrdinal) { //输出所有所有的信息 //#define IMAGE_ORDINAL_FLAG32 0x80000000 if(ImportOrdinal & IMAGE_ORDINAL_FLAG32) { sprintf(rn,"按序号导入: %08X \r\n",ImportOrdinal&0x0FFF); strcat(InfoStr,rn); }else { DWORD ImageNameAddress = RVAToFileOffset(pFileBuffer,ImportOrdinal); PIMAGE_IMPORT_BY_NAME pImageName = (PIMAGE_IMPORT_BY_NAME)(DWORD(pFileBuffer)+ImageNameAddress); //printf("按名字导入:%x - %s \n",pImageName->Hint,pImageName->Name); sprintf(rn,"按名字导入: %08X -- %s \r\n",pImageName->Hint,pImageName->Name); strcat(InfoStr,rn); } //向下移动 pThunkData = (PIMAGE_THUNK_DATA32)((DWORD)pThunkData + 4); ImportOrdinal = pThunkData->u1.Ordinal; } sprintf(rn,"------------------------------- : \r\n"); strcat(InfoStr,rn); //printf("FirstThunk:%x \n",pImportDes->FirstThunk); DWORD pFirstThunk = (DWORD)pImportDes->FirstThunk; printf("FirstThunk:%x \n",pImportDes->FirstThunk); sprintf(rn,"FirstThunk:%08X \r\n",pImportDes->FirstThunk); strcat(InfoStr,rn); sprintf(rn,"------------------------------- : \r\n"); strcat(InfoStr,rn); DWORD FirstThunk_Address = RVAToFileOffset(pFileBuffer,pFirstThunk); PIMAGE_THUNK_DATA32 pNewThunkData = (PIMAGE_THUNK_DATA32)((DWORD)pFileBuffer + FirstThunk_Address); DWORD newImportOrdinal = pNewThunkData->u1.Ordinal; while(newImportOrdinal) { //输出所有所有的信息 //#define IMAGE_ORDINAL_FLAG32 0x80000000 if(newImportOrdinal & IMAGE_ORDINAL_FLAG32) { //printf("按序号导入:%x\n",newImportOrdinal&0x0FFF); sprintf(rn,"按序号导入:%08X \r\n",newImportOrdinal&0x0FFF); strcat(InfoStr,rn); }else { DWORD newImageNameAddress = RVAToFileOffset(pFileBuffer,newImportOrdinal); PIMAGE_IMPORT_BY_NAME pNewImageName = (PIMAGE_IMPORT_BY_NAME)(DWORD(pFileBuffer)+newImageNameAddress); //printf("按名字导入:%x - %s \n",pNewImageName->Hint,pNewImageName->Name); sprintf(rn,"按名字导入::%08X - %s \r\n",pNewImageName->Hint,pNewImageName->Name); strcat(InfoStr,rn); } //向下移动 pNewThunkData = (PIMAGE_THUNK_DATA32)((DWORD)pNewThunkData + 4); newImportOrdinal = pNewThunkData->u1.Ordinal; } sprintf(rn,"------------------------------- \r\n"); strcat(InfoStr,rn); pImportDes = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImportDes + 20); //getchar(); } SendMessage(hInfoMation,WM_SETTEXT,0,(long)InfoStr); break; } case INFO_RES: { sprintf(rn,"资源表基本信息 : \r\n"); strcat(InfoStr,rn); IMAGE_DATA_DIRECTORY ResourceDirectory = DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]; DWORD ResourceVirtualAddress = ResourceDirectory.VirtualAddress; DWORD ResourceSize = ResourceDirectory.Size; if(ResourceSize== 0) { haveDirectory = FALSE; MessageBox(0,TEXT("没有资源表"),TEXT("错误"),0); return; }else{ haveDirectory = TRUE; } sprintf(rn,"ResourceVirtualAddress :%08X \r\n",ResourceVirtualAddress); strcat(InfoStr,rn); sprintf(rn,"ResourceSize :%08X \r\n",ResourceSize); strcat(InfoStr,rn); DWORD dwFoa = RVAToFileOffset(pFileBuffer,ResourceVirtualAddress); PIMAGE_RESOURCE_DIRECTORY pResource = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pFileBuffer + dwFoa); //输出PIMAGE_RESOURCE_DIRECTORY 的信息 sprintf(rn,"NumberOfNamedEntries :%08X \r\n",pResource->NumberOfNamedEntries); strcat(InfoStr,rn); sprintf(rn,"NumberOfIdEntries :%08X \r\n",pResource->NumberOfIdEntries); strcat(InfoStr,rn); //第一层类型的解析 //第一个资源表 PIMAGE_RESOURCE_DIRECTORY_ENTRY pResdirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResource + sizeof(IMAGE_RESOURCE_DIRECTORY)); DWORD NumberOfResType = pResource->NumberOfNamedEntries + pResource->NumberOfIdEntries; //找到图标资源 PIMAGE_RESOURCE_DIRECTORY pResICODir=NULL; for(DWORD i=0;i<NumberOfResType;i++) { //解析内容: DWORD NameIsString = pResdirectoryEntry->NameIsString; DWORD ResName = pResdirectoryEntry->Name; DWORD OffsetToData = pResdirectoryEntry->OffsetToData; DWORD DataIsDirectory = pResdirectoryEntry->DataIsDirectory; //printf("Info: %d -NameIsString: %d - Name: %x -- OffToDa: %x - IsD - %d \n",i+1, //NameIsString,ResName,OffsetToData,DataIsDirectory); sprintf(rn,"Info: %08X -NameIsString: %08X - Name: %08X -- OffToDa: %08X : IsD - %08X \r\n",i+1,NameIsString,ResName,OffsetToData,DataIsDirectory); strcat(InfoStr,rn); if(ResName == 0x3) { //PIMAGE_RESOURCE_DIRECTORY pResource = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pFileBuffer + dwFoa); pResICODir = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResource +pResdirectoryEntry->OffsetToDirectory); break; } pResdirectoryEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResdirectoryEntry + 8); } //确定图标的地址,找第二层 DWORD NumberOffICO = pResICODir->NumberOfIdEntries + pResICODir->NumberOfNamedEntries; //printf("NumberOffICO : %d \n",NumberOffICO); sprintf(rn,"NumberOffICO :%08X \r\n",NumberOffICO); strcat(InfoStr,rn); //第一个图标描述 PIMAGE_RESOURCE_DIRECTORY_ENTRY pICOEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResICODir + sizeof(IMAGE_RESOURCE_DIRECTORY)); PIMAGE_RESOURCE_DIRECTORY pICOContent = NULL; for(DWORD j = 0;j<NumberOffICO;j++) { //解析内容: DWORD NameIsString = pICOEntry->NameIsString; DWORD ResName = pICOEntry->Name; DWORD OffsetToData = pICOEntry->OffsetToData; DWORD DataIsDirectory = pICOEntry->DataIsDirectory; //printf("Info: %d -NameIsString: %d - Name: %x -- OffToDa: %x - IsD - %d \n",i+1, // NameIsString,ResName,OffsetToData,DataIsDirectory); sprintf(rn,"Info: %d -NameIsString: %d - Name: %08X -- OffToDa: %08X - IsD - %08X \n",i+1, NameIsString,ResName,OffsetToData,DataIsDirectory); strcat(InfoStr,rn); //依次解析页码表 pICOContent = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResource +pICOEntry->OffsetToDirectory); //页码表解析 DWORD NumberOfICOContent = pICOContent->NumberOfIdEntries + pICOContent->NumberOfNamedEntries; //printf("NumberOfICOContent: %d \n",NumberOfICOContent); sprintf(rn,"NumberOfICOContent :%08X \r\n",NumberOfICOContent); strcat(InfoStr,rn); //图标测试只有一个,不循环测试 //找到关键点: PIMAGE_RESOURCE_DIRECTORY_ENTRY pICOGetVS = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pICOContent + sizeof(IMAGE_RESOURCE_DIRECTORY)); //找到图标资源的VistrualAddress 和 Size PIMAGE_DATA_DIRECTORY pDataIco = (PIMAGE_DATA_DIRECTORY)((DWORD)pResource + pICOGetVS->OffsetToDirectory); //输出每个图标信息 //printf("VirtualAddress: %x, Size: %x \n",pDataIco->VirtualAddress,pDataIco->Size); sprintf(rn,"VirtualAddress: %08X, Size: %08X \n",pDataIco->VirtualAddress,pDataIco->Size); strcat(InfoStr,rn); pICOEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pICOEntry + 8); } SendMessage(hInfoMation,WM_SETTEXT,0,(long)InfoStr); break; } case INFO_RELOC: { sprintf(rn,"重定位表的基本信息 : \r\n"); strcat(InfoStr,rn); DWORD BaseReloc_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; DWORD BaseReloc_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; FoA = RVAToFileOffset(pFileBuffer,BaseReloc_Directory_Address); if(BaseReloc_Directory_Size == 0) { haveDirectory = FALSE; MessageBox(0,TEXT("没有重定位表"),TEXT("错误"),0); return; }else{ haveDirectory = TRUE; } //定位到第一个重定位块 PIMAGE_BASE_RELOCATION pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + FoA); //输出所有的标信息 while(pRelocData->VirtualAddress||pRelocData->SizeOfBlock) { DWORD RelocVirtualAddress = pRelocData->VirtualAddress; DWORD RelocSize = pRelocData->SizeOfBlock; sprintf(rn,"VirtualSize: %08X ,Size: %08X , Number: %08X \r\n",RelocVirtualAddress,RelocSize,(RelocSize-8)/2); strcat(InfoStr,rn); int k = (RelocSize-8)/2; PWORD pMyRelocAddress = NULL; pMyRelocAddress = (PWORD)((DWORD)pRelocData+8); for(int i=0;i<k;i++) { //printf(); sprintf(rn,"第%04X个 : 标志 : %08X 偏移 : %08X\r\n",i+1,pMyRelocAddress[i]&0xF000,RelocVirtualAddress+(pMyRelocAddress[i]&0x0FFF)); strcat(InfoStr,rn); } pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocData + RelocSize); } SendMessage(hInfoMation,WM_SETTEXT,0,(long)InfoStr); break; } case INFO_BIND: { sprintf(rn,"绑定导入表的基本信息 : \r\n"); strcat(InfoStr,rn); IMAGE_DATA_DIRECTORY pBindImportDirectory = DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]; DWORD BindImportVirtualAddress = pBindImportDirectory.VirtualAddress; DWORD BindImportFoa = BindImportVirtualAddress; PIMAGE_BOUND_IMPORT_DESCRIPTOR pBindImport = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + BindImportFoa); if(pBindImportDirectory.Size == 0) { haveDirectory = FALSE; MessageBox(0,TEXT("没有绑定导入表"),TEXT("错误"),0); return; }else{ haveDirectory = TRUE; } while(pBindImport->TimeDateStamp !=0x0) { //输出第一个绑定 DWORD bindTime = pBindImport->TimeDateStamp; WORD ModuleName = pBindImport->OffsetModuleName; WORD numberModule = pBindImport->NumberOfModuleForwarderRefs; //输出名字 PSTR pModuleName = (PSTR)((DWORD)pFileBuffer+(DWORD)BindImportVirtualAddress+ModuleName); sprintf(rn,"ModuleName:%s \r\n",pModuleName); strcat(InfoStr,rn); //printf("ModuleName:%s \n",pModuleName); //printf("--numberModule:%x \n",numberModule); sprintf(rn,"--numberModule:%08X \r\n",numberModule); strcat(InfoStr,rn); for(int i=0;i<numberModule;i++) { PIMAGE_BOUND_FORWARDER_REF pBoundRef = (PIMAGE_BOUND_FORWARDER_REF)((DWORD)pBindImport+i*8); pBindImport = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pBindImport+i*8); //输出名字 DWORD refTime = pBoundRef->TimeDateStamp; WORD refName = pBoundRef->OffsetModuleName; PSTR pRefName = (PSTR)((DWORD)pFileBuffer+(DWORD)BindImportVirtualAddress+refName); //printf(" RefName:%s \r\n",pRefName); sprintf(rn," RefName:%s \r\n",pRefName); strcat(InfoStr,rn); } pBindImport = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((DWORD)pBindImport+8); } SendMessage(hInfoMation,WM_SETTEXT,0,(long)InfoStr); break; } case INFO_IAT: { sprintf(rn,"绑定导入表的基本信息 : \r\n"); strcat(InfoStr,rn); sprintf(rn,"测试使用,未实现 : \r\n"); strcat(InfoStr,rn); SendMessage(hInfoMation,WM_SETTEXT,0,(long)InfoStr); break; } } //释放内存 free(pFileBuffer); }
0则评论给“PeTools开发(五)”