#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include<stdlib.h>
#include<stdio.h>
#define FILE_PATH_IN "C:/Windows/System32/notepad.exe"
static const char* szResName[0x11]
{
0,
"Corsor",
"Bitmap",
"Icon",
"Menu",
"Dialog",
"StringTable",
"FontDir",
"Font",
"Accelerator",
"RCDATA",
"MessageTable",
"GroupCursor",
"zz",
"GroupIcon",
"xx",
"Version"
};
DWORD RVA2FOA(IN DWORD stRVA, IN LPVOID pFileBuffer)
{
//重置头指针
PIMAGE_DOS_HEADER pDosHeader = nullptr;
PIMAGE_NT_HEADERS pNTHeader = nullptr;
PIMAGE_FILE_HEADER pFileHeader = nullptr;
PIMAGE_OPTIONAL_HEADER pOptionalHeader = nullptr;
PIMAGE_SECTION_HEADER pSectionHeader = nullptr;
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + sizeof(pNTHeader->Signature));
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader);
//内存对齐
DWORD dwMemAlignCount = pOptionalHeader->FileAlignment;
//节区头个数
DWORD dwSectionCount = pFileHeader->NumberOfSections;
//距节区的偏移
DWORD dwDiffer = 0;
for (DWORD i = 0; i < dwSectionCount; i++,pSectionHeader++)
{
//在内存中对齐后的大小
DWORD dwBlockCount = 0;
dwBlockCount = pSectionHeader->SizeOfRawData / dwMemAlignCount;
dwBlockCount += (pSectionHeader->SizeOfRawData % dwMemAlignCount ? 1 : 0);
DWORD dwBeginRVA = pSectionHeader->VirtualAddress;
DWORD dwEndRVA = pSectionHeader->VirtualAddress + dwBlockCount * dwMemAlignCount;
if (stRVA >= dwBeginRVA && stRVA < dwEndRVA)
{
dwDiffer = stRVA - dwBeginRVA;
return dwDiffer + pSectionHeader->PointerToRawData;
}
else if (stRVA < dwBeginRVA)
{
return stRVA;
}
}
return 0;
}
DWORD ReadFile(OUT LPVOID* pFileBuffer,IN const char* lpszFile)
{
LPVOID pTempFileBuffer = nullptr;
FILE* pFile = nullptr;
DWORD FileSize = 0;
size_t n = 0;
//打开文件
pFile = fopen(lpszFile, "rb");
if (pFile == nullptr)
{
printf("文件打开失败");
return 0;
}
//计算文件长度
fseek(pFile, 0, SEEK_END);
FileSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
//分配缓冲区
pTempFileBuffer = calloc(FileSize, sizeof(char));
if (pTempFileBuffer == nullptr)
{
printf("缓冲区分配失败");
fclose(pFile);
return 0;
}
//初始化缓冲区
memset(pTempFileBuffer, 0, FileSize);
//读取文件
n = fread(pTempFileBuffer, FileSize, 1, pFile);
if (n == 0)
{
printf("读取文件失败");
fclose(pFile);
free(pTempFileBuffer);
pTempFileBuffer = nullptr;
return 0;
}
//关闭文件
fclose(pFile);
*pFileBuffer = pTempFileBuffer;
pTempFileBuffer = nullptr;
return n;
}
void PrintResourceTable()
{
PIMAGE_DOS_HEADER pDosHeader = nullptr;
PIMAGE_NT_HEADERS pNTHeader = nullptr;
PIMAGE_FILE_HEADER pFileHeader = nullptr;
PIMAGE_OPTIONAL_HEADER pOptionalHeader = nullptr;
PIMAGE_DATA_DIRECTORY pDataDirectory = nullptr;
PIMAGE_RESOURCE_DIRECTORY pResourceTable = nullptr;
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResourceEntry = nullptr;
LPVOID pFileBuffer = nullptr;
DWORD dwSize = 0;
dwSize = ReadFile(&pFileBuffer, FILE_PATH_IN);
if (dwSize == 0 || pFileBuffer == nullptr)
{
printf("读取文件失败");
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + sizeof(pNTHeader->Signature));
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
//定位资源表
pDataDirectory = (PIMAGE_DATA_DIRECTORY)(&pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
pResourceTable = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pFileBuffer + RVA2FOA(pDataDirectory->VirtualAddress, pFileBuffer));
pResourceEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResourceTable + 1);
//解析第一层
DWORD dwTypeCount = pResourceTable->NumberOfIdEntries + pResourceTable->NumberOfNamedEntries;
for (DWORD i = 0; i < dwTypeCount; i++)
{
//最高位为0
if (pResourceEntry[i].NameIsString == 0)
{
if (pResourceEntry[i].Id < 0x11)
{
printf("资源类型ID:%d %s\n", pResourceEntry[i].Id, szResName[pResourceEntry[i].Id]);
}
else
{
printf("资源类型ID:%d\n", pResourceEntry[i].Id);
}
}
//最高位为1
else if (pResourceEntry[i].NameIsString == 1)
{
PIMAGE_RESOURCE_DIR_STRING_U pStr = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResourceTable + pResourceEntry[i].NameOffset);
WCHAR szStr[MAX_PATH] = { 0 };
memcpy(szStr, pStr->NameString, pStr->Length * sizeof(WCHAR));
printf("资源类型名称:%ls\n", szStr);
}
//解析第二层
if (pResourceEntry[i].DataIsDirectory == 1)
{
printf("第二层目录偏移:%x\n", pResourceEntry[i].OffsetToDirectory);
PIMAGE_RESOURCE_DIRECTORY pRes2 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResourceTable + pResourceEntry[i].OffsetToDirectory);
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry2 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes2 + 1);
DWORD dwCount = pRes2->NumberOfIdEntries + pRes2->NumberOfNamedEntries;
for (DWORD i = 0; i < dwCount; i++)
{
//最高位为0
if (pResEntry2[i].NameIsString == 0)
{
printf(" ->资源标识ID:%d\n", pResEntry2[i].Id);
}
else
{
PIMAGE_RESOURCE_DIR_STRING_U pStr = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResourceTable + pResEntry2[i].NameOffset);
WCHAR szStr[MAX_PATH] = { 0 };
memcpy(szStr, pStr->NameString, pStr->Length * sizeof(WCHAR));
printf(" ->资源名称:%ls\n", szStr);
}
//解析第三层
if (pResEntry2[i].DataIsDirectory == 1)
{
PIMAGE_RESOURCE_DIRECTORY pRes3 = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResourceTable + pResEntry2[i].OffsetToDirectory);
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResEntry3 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pRes3 + 1);
printf(" -->代码页标号为:%x\n", pResEntry3->Id);
if (pResEntry3->DataIsDirectory == 0)
{
PIMAGE_RESOURCE_DATA_ENTRY pResDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pResourceTable+pResEntry3->OffsetToData);
printf(" --数据RVA:%x\n", pResDataEntry->OffsetToData);
printf(" --数据大小:%x\n", pResDataEntry->Size);
}
}
}
}
}
}
int main()
{
PrintResourceTable();
return 0;
}