pe文件结构:
IMAGE_DOS_HEADER+IMAGE_NT_HEADERS +IMAGE_SECTION_HEADER+数据
三个结构构成文件头。
资源段为IMAGE_DIRECTORY_ENTRY_RESOURCE
IMAGE_SECTION_HEADER为段描述结构
以上过程通过get_section_header 解析
资源结构表有四层,前三层的偏移地址从本段基地址开始,前三层结构相同,为IMAGE_RESOURCE_DIRECTORY+IMAGE_RESOURCE_DIRECTORY_ENTRY组成
第一层 ID为资源类型
第二层 ID为资源ID,字串ID=真实ID/16+1;
第三层 ID为格式编码,0x804="gbk";0x409="utf-8"
第四层结构为IMAGE_SECTION_HEADER 该结构中的VirtualAddress指向资源数据:
具体代码如下:
PIMAGE_SECTION_HEADER get_section_header(void * pFileBuffer, DWORD section) {
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeaders;
PIMAGE_DATA_DIRECTORY pdd;
PIMAGE_SECTION_HEADER psh = NULL;
pDosHeader = (PIMAGE_DOS_HEADER) pFileBuffer;
if (!pDosHeader) {
KPrintf("get_section_header fail file \n");
return NULL;
}
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
KPrintf("not a mz header!\n");
return NULL;
}
pNtHeaders =
(PIMAGE_NT_HEADERS) ((DWORD) pDosHeader + pDosHeader->e_lfanew);
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
KPrintf("not a PE header!\n");
return NULL;
}
//资源表在文件中的偏移
pdd = (void *) (&pNtHeaders->OptionalHeader.DataDirectory[section]);
// KPrintf("资源表地址,%x!\n",pdd);
if (!pdd->VirtualAddress) {
return NULL;
} else {
//节表后
psh =
(PIMAGE_SECTION_HEADER) &(pNtHeaders->OptionalHeader.DataDirectory[pNtHeaders->OptionalHeader.NumberOfRvaAndSizes]);
for (int i = 0; i < pNtHeaders->FileHeader.NumberOfSections; i++) {
//KPrintf("sect:%x,%s!\n", psh->SizeOfRawData, psh->Name);
if (psh->VirtualAddress == pdd->VirtualAddress) {
return psh;
}
psh++;
}
//运行到这时则出错
return NULL;
}
}
PIMAGE_RESOURCE_DIR_STRING_U get_resource_string(
PIMAGE_RESOURCE_DIR_STRING_U pUStr, int uID) {
uID %= 16;
int i;
// 每16个字符串为一个串组,字符串的排序以字符串的资源ID号为依据,
// 0 - 15为第一串组,16 - 31位第二串组,32 - 47位第三串组,...。
// 串组ID号从1开始,字符串ID号从0开始。由此可以得到如下公式:
// 串组ID = (取整)(字符串ID / 16) + 1
// 串组ID = pParam->dwResID
for (i = 0; i < 16; i++) {
if (i == uID) {
return pUStr;
}
if (pUStr->Length <= 0) {
//空字串占两个字节
pUStr++;
} else {
//结尾占两节
pUStr = (DWORD) pUStr + 2 + 2 + pUStr->Length * 2;
}
}
return NULL;
}
DWORD resource_from_id(PIMAGE_RESOURCE_DIRECTORY pResDir, int uID) {
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry;
DWORD dwSize;
//KPrintf("resource_from_id %x,%x\n",pResDir,uID);
pResDirEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) pResDir
+ sizeof(IMAGE_RESOURCE_DIRECTORY));
dwSize = pResDir->NumberOfIdEntries + pResDir->NumberOfNamedEntries;
//第一层查找相应类型
for (int i = 0; i < dwSize; i++) {
if ((pResDirEntry->DUMMYUNIONNAME.Id == uID) | (uID == 0)) {
return pResDirEntry->DUMMYUNIONNAME2.DUMMYSTRUCTNAME2.OffsetToDirectory;
}
pResDirEntry++;
}
return 0;
}
//返回的地址是偏移地址
DWORD find_resource_offset(void * dwResourceAddr, int mode, int uID) {
PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry = NULL;
PIMAGE_RESOURCE_DATA_ENTRY pResDataEntry = NULL;
DWORD dwSize, dwSize2, dwSize3, dwResDataSize;
DWORD offset, uID2;
//第一层iD为资源类型
offset = resource_from_id(dwResourceAddr, mode);
if (!offset) {
return 0;
}
if (mode == RT_STRING) {
uID = uID / 16 + 1;
}
//第二层ID,如果字串则需转换,其他可直接使用
offset = resource_from_id(offset + (DWORD) dwResourceAddr, uID);
if (!offset) {
return 0;
}
//第三层id与编译语言有关,0x804为中文
offset = resource_from_id(offset + (DWORD) dwResourceAddr, 0);
if (!offset) {
return NULL;
}
pResDataEntry = (PIMAGE_RESOURCE_DATA_ENTRY) (offset
+ (DWORD) dwResourceAddr);
return pResDataEntry->OffsetToData;
}
EXPORT WINAPI
HRSRC FindResourceW(HMODULE hModule, LPCWSTR lpName, LPCWSTR lpType) {
DWORD pResDataEntry = 0;
if (!hModule) {
hModule = GetModuleHandleA(NULL);
}
//找到资源段入口
PIMAGE_SECTION_HEADER psh = get_section_header((void *) hModule,
IMAGE_DIRECTORY_ENTRY_RESOURCE);
if (psh) {
//资源数据偏移
pResDataEntry = find_resource_offset(
(void*) (psh->VirtualAddress + (DWORD) hModule), (int) lpType,
lpName);
}
KPrintf(" API FindResourceW %x \n", pResDataEntry);
return pResDataEntry;
}