PE总结13 --PE文件结构之 解析资源表

来源:互联网 发布:teamview linux命令行 编辑:程序博客网 时间:2024/06/05 01:17
// 资源表2.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <stdlib.h>#include <string.h>#include <windows.h>DWORD RVA2Offset(DWORD dwRva, PIMAGE_NT_HEADERS32 pNt){  DWORD dwOffset = 0;  PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);  //获取区段的数量  DWORD dwCount = pNt->FileHeader.NumberOfSections;  //判断在哪个区段 并且进行转换  for (DWORD i = 0; i < dwCount;i++)  {     if (dwRva >= pSection[i].VirtualAddress &&       dwRva <( pSection[i].Misc.VirtualSize + pSection[i].VirtualAddress)       )     {       dwOffset = dwRva - pSection[i].VirtualAddress + pSection[i].PointerToRawData;       return dwOffset;     }  }  return dwOffset;}static char* szResName[0x11] = { 0, "鼠标指针", "位图", "图标", "菜单", "对话框", "字符串列表","字体目录", "字体", "快捷键", "非格式化资源", "消息列表", "鼠标指针组","zz", "图标组","xx", "版本信息"};void ShowRes(PVOID lpImg, DWORD dwSize){  //获取DOS头  PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpImg;  if (IMAGE_DOS_SIGNATURE != pDos->e_magic)  {     return;  }  //Nt头  PIMAGE_NT_HEADERS32  pNt = (PIMAGE_NT_HEADERS32)( (DWORD)lpImg + pDos->e_lfanew );  if (IMAGE_NT_SIGNATURE != pNt->Signature)  {     return;  }  //获取数据目录表  PIMAGE_DATA_DIRECTORY   pData = pNt->OptionalHeader.DataDirectory;  //获取到资源目录表  pData = &(pData[IMAGE_DIRECTORY_ENTRY_RESOURCE]);  //获取资源目录表的偏移  DWORD dwResOffset = RVA2Offset(pData->VirtualAddress, pNt);  //获取到资源目录表  PIMAGE_RESOURCE_DIRECTORY  pRes = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)lpImg + dwResOffset);  //获取紧跟着的IMAGE_RESOURCE_DIRECTORY_ENTRY的个数  DWORD dwResSize = pRes->NumberOfNamedEntries + pRes->NumberOfIdEntries;  //获取到PIMAGE_RESOURCE_DIRECTORY_ENTRY   PIMAGE_RESOURCE_DIRECTORY_ENTRY  pResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)     ( pRes + 1);    for (DWORD i = 0; i < dwResSize; i++)  {          if (!pResEntry[i].NameIsString)//0     {       if (pResEntry[i].Id<0x11)       {          printf("资源类型ID:%p %s\n", pResEntry[i].Id, szResName[pResEntry[i].Id]);       }       else{          char  type[20];          sprintf_s(type,"%d",  pResEntry[i].Id);          printf("资源类型ID:%p %s\n", pResEntry[i].Id, type);       }     }     else //1     {       PIMAGE_RESOURCE_DIR_STRING_U pstcString = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pRes + pResEntry[i].NameOffset);       WCHAR szStr[MAX_PATH] = { 0 };       memcpy_s(szStr, MAX_PATH,          pstcString->NameString,          pstcString->Length*sizeof(WCHAR)          );       printf("资源字符串:%ls\n", szStr);     }      // 获取第二层目录的偏移     if (pResEntry[i].DataIsDirectory) //1     {       printf("资源第二层目录偏移:%p\n", pResEntry[i].OffsetToDirectory);       PIMAGE_RESOURCE_DIRECTORY pRes2 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pRes + pResEntry[i].OffsetToDirectory);       DWORD dwCount = pRes2->NumberOfIdEntries + pRes2->NumberOfNamedEntries;       PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry2 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(           pRes2 + 1);       for (DWORD i = 0; i < dwCount; i++)       {          if (!pResEntry2[i].NameIsString)          {            printf("->资源标识ID:%d\n", pResEntry2[i].Id);          }          else          {            // 显示资源字符串            // NameOffset为相对资源的文件偏移            // 字符串偏移为 资源基地址+NameOffset            PIMAGE_RESOURCE_DIR_STRING_U pstcString = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pRes + pResEntry2[i].NameOffset);            WCHAR szStr[MAX_PATH] = { 0 };            memcpy(szStr,               pstcString->NameString,               pstcString->Length*sizeof(WCHAR)               );            printf("->资源字符串:%ls\n", szStr);          }       }            // 解析第三层目录       PIMAGE_RESOURCE_DIRECTORY pRes3 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pRes + pResEntry2[i].OffsetToDirectory);       printf("->->第三层目录:%d\n", pRes3->NumberOfIdEntries);       PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry3 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes3 + 1);       if (!pResEntry3[i].DataIsDirectory)       {          // 取数据偏移,显示数据          PIMAGE_RESOURCE_DATA_ENTRY pResData = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pRes + pResEntry3->OffsetToData);          printf("->->->数据RVA:%p 数据大小:%p\n", pResData->OffsetToData, pResData->Size);       }       printf("\n\n");     }  }}int _tmain(int argc, _TCHAR* argv[]){  HANDLE hFile = nullptr;  //文件的路径  //LPCTSTR lpPath = L"D:\\Users\\PE\\pe01\\Debug\\HelloWorld.exe";  LPCTSTR lpPath = L"C:\\Users\\Denny\\Desktop\\(手动查找导入导出表)\\(手动查找导入导出表)\\MFCLibrary1Dll.dll";  //读取文件内容获取到文件句柄 和 大小 用来创建内存      if (INVALID_HANDLE_VALUE == (hFile = CreateFile(lpPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL)))  {     return 0;  }  DWORD dwSize = 0;  if (INVALID_FILE_SIZE == (dwSize = GetFileSize(hFile, NULL)))  {     CloseHandle(hFile);     return 0;  }  PVOID lpImg = nullptr;  if (!(lpImg = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE)))  {     CloseHandle(hFile);     return 0;  }  DWORD dwRet = 0;  //将文件的内容读取都开辟的内存中  if (!(ReadFile(hFile, lpImg, dwSize, &dwRet, NULL)))  {     CloseHandle(hFile);     VirtualFree(lpImg, dwSize, MEM_RELEASE);     return 0;  }  //调用函数  ShowRes(lpImg, dwSize);  system("pause");  return 0;} 

0 0