PE 资源表
唯一坑点:在找IMAGE_RESOURCE_DIRECTORY或者是IMAGE_RESOURCE_DATA_ENTRY,用OffsetToDirectory加的永远是以第一个IMAGE_RESOURCE_DIRECTORY来作为基址,也就是如下所示:
实现代码如下:
void PrintResourceTable(PVOID pFileBuffer){ PIMAGE_DOS_HEADER pImageDosHeader = NULL; PIMAGE_FILE_HEADER pImageFileHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pImageOptionalHeader = NULL; PIMAGE_SECTION_HEADER pImageSectionHeaderGroup = NULL; PIMAGE_SECTION_HEADER NewSec = NULL; PIMAGE_RESOURCE_DIRECTORY pImageResourceDireOne = NULL; PIMAGE_RESOURCE_DIRECTORY_ENTRY pImageResourceEntryOne = NULL; PIMAGE_RESOURCE_DIRECTORY pImageResourceDireTwo = NULL; PIMAGE_RESOURCE_DIRECTORY_ENTRY pImageResourceEntryTwo = NULL; PIMAGE_RESOURCE_DIRECTORY pImageResourceDireThree = NULL; PIMAGE_RESOURCE_DIRECTORY_ENTRY pImageResourceEntryThree = NULL; PIMAGE_DATA_DIRECTORY pImageDataDire = NULL; PIMAGE_RESOURCE_DIR_STRING_U pDirString = NULL; DWORD RVA = 0; DWORD FOA = 0; DWORD dwEntryNumOne = 0; DWORD dwEntryNumTwo = 0; DWORD dwEntryNumThree = 0; DWORD i=0; DWORD j=0; DWORD k=0; DWORD m=0; pImageDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pImageFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pImageDosHeader + pImageDosHeader->e_lfanew + 4); pImageOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pImageFileHeader + sizeof(IMAGE_FILE_HEADER)); pImageSectionHeaderGroup = (PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader + pImageFileHeader->SizeOfOptionalHeader); RVA_TO_FOA(pFileBuffer,pImageOptionalHeader->DataDirectory[2].VirtualAddress,&FOA); /* typedef struct _IMAGE_RESOURCE_DIRECTORY { DWORD Characteristics; //资源属性 保留 0 DWORD TimeDateStamp; //资源创建的时间 WORD MajorVersion; //资源版本号 未使用 0 WORD MinorVersion; //资源版本号 未使用 0 WORD NumberOfNamedEntries; //以名称命名的资源数量 WORD NumberOfIdEntries; //以ID命名的资源数量 // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; } IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; */ pImageResourceDireOne = (DWORD)pFileBuffer + (DWORD)FOA; dwEntryNumOne = pImageResourceDireOne->NumberOfIdEntries + pImageResourceDireOne->NumberOfNamedEntries; pImageResourceEntryOne = (DWORD)pImageResourceDireOne + 16; for(i=0;i<dwEntryNumOne;i++){ if(pImageResourceEntryOne[i].NameIsString == 1){ // 1 pDirString = (PIMAGE_RESOURCE_DIR_STRING_U)pImageResourceEntryOne[i].NameOffset; wprintf(L"第一层资源类型: %s\n", pDirString->NameString); // 第一层资源类型 }else{ //0 printf("第一层资源类型: %d\n",pImageResourceEntryOne[i].NameOffset); // 第一层资源类型 } //======================pImageResourceDireTwo========================= pImageResourceDireTwo = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pImageResourceDireOne + (DWORD)pImageResourceEntryOne[i].OffsetToDirectory); dwEntryNumTwo = pImageResourceDireTwo->NumberOfIdEntries + pImageResourceDireTwo->NumberOfNamedEntries; pImageResourceEntryTwo = (DWORD)pImageResourceDireTwo + 16; for(j=0;j<dwEntryNumTwo;j++){ if(pImageResourceEntryTwo[j].NameIsString == 1){ // 1 pDirString = (PIMAGE_RESOURCE_DIR_STRING_U)pImageResourceEntryTwo[j].NameOffset; wprintf(L"\t第二层资源名称: %s\n", pDirString->NameString); // 第二层资源名称 }else{ //0 printf("\t第二层资源名称: %d\n",pImageResourceEntryTwo[j].NameOffset); // 第二层资源名称 } //======================pImageResourceDireThree========================= pImageResourceDireThree = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pImageResourceDireOne + (DWORD)pImageResourceEntryTwo[j].OffsetToDirectory); dwEntryNumThree = pImageResourceDireThree->NumberOfIdEntries + pImageResourceDireThree->NumberOfNamedEntries; pImageResourceEntryThree = (DWORD)pImageResourceDireThree + 16; for(k=0;k<dwEntryNumThree;k++){ if(pImageResourceEntryThree[k].NameIsString == 1){ // 1 pDirString = (PIMAGE_RESOURCE_DIR_STRING_U)pImageResourceEntryThree[k].NameOffset; wprintf(L"\t\t第三层代码页编号: %s\n", pDirString->NameString); // 第三层代码页编号 }else{ //0 printf("\t\t第三层代码页编号: %d\n",pImageResourceEntryThree[k].NameOffset); // 第三层代码页编号 } //======================IMAGE_RESOURCE_DATA_ENTRY========================= //pImageDataDire IMAGE_RESOURCE_DATA_ENTRY pImageDataDire = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pImageResourceDireOne + (DWORD)pImageResourceEntryThree[k].OffsetToDirectory); printf("\t\t\t VirtualAddress: 0x%X, Size: 0x%X\n", pImageDataDire->VirtualAddress, pImageDataDire->Size); } } printf("==================================\n"); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY