2021-06-07解析资源表

// Location_Res.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#define FilePath "D:\\NOTEPAD.EXE"



//功能:Rva转Foa

//参数1:FileBuffer

//参数2:dwRva,需要转换的Rva地址

DWORD RvaToFileOffset(IN LPVOID pFileBuffer, IN DWORD dwRva)

{

	//定义文件头

	PIMAGE_DOS_HEADER dosHeader = NULL;        //dos头指针

	PIMAGE_NT_HEADERS ntHeader = NULL;        //nt头指针

	PIMAGE_FILE_HEADER peHeader = NULL;        //pe头指针

	PIMAGE_OPTIONAL_HEADER32 opHeader = NULL;    //可选pe头指针

	PIMAGE_SECTION_HEADER sectionHeader = NULL;    //节表指针

												   //找到文件头

	dosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;

	ntHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + dosHeader->e_lfanew);

	peHeader = (PIMAGE_FILE_HEADER)((DWORD)ntHeader + 4);

	opHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)peHeader + IMAGE_SIZEOF_FILE_HEADER);

	sectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)opHeader + peHeader->SizeOfOptionalHeader);

	//1.判断是哪个节

	int sec = -1;

	for (int i = 0; i<peHeader->NumberOfSections; i++) {

		DWORD va = (sectionHeader + i)->VirtualAddress;

		DWORD size = (sectionHeader + i)->Misc.VirtualSize;

		if (dwRva >= va && dwRva <= (va + size)) {

			sec = i;

			//printf("在第%d个节\n", sec);

			break;

		}

	}

	if (sec<0) {

		printf("内存偏移不在任何一个节\n");

		return 0;

	}

	//2.转换

	DWORD secOffset = dwRva - (sectionHeader + sec)->VirtualAddress;

	DWORD foa = (sectionHeader + sec)->PointerToRawData + secOffset;

	return foa;

}



DWORD FoaToImageOffset(PVOID pBuffer, DWORD dwFoa)
{
	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;

	if (!pBuffer)
	{
		printf("(FoaToImageOffset)Can't open file!\n");
		return 0;
	}

	if (*((PWORD)pBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(FoaToImageOffset)No MZ flag, not exe file!\n");
		return 0;
	}

	pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
	if (*((PDWORD)((DWORD)pBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(FoaToImageOffset)Not a valid PE flag!\n");
		return 0;
	}
	printf("FileOffset: %#x\n", dwFoa);

	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pBuffer + 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);

	PIMAGE_SECTION_HEADER pSectionTemp = pSectionHeader;

	if (dwFoa <= pOptionHeader->SizeOfHeaders)
		return (DWORD)dwFoa;
	else
	{
		for (int n = 0; n < pPEHeader->NumberOfSections; n++, pSectionTemp++)
		{	//判断 :   文件对齐+文件偏移>file_panyi>文件偏移  (即是在文件的哪个节中)
			if ((dwFoa >= pSectionTemp->PointerToRawData) && (dwFoa < pSectionTemp->PointerToRawData + pSectionTemp->SizeOfRawData))
			{
				return dwFoa - pSectionTemp->PointerToRawData + pSectionTemp->VirtualAddress;
			}
		}
	}
	printf("FoaToRva failed!\n");
	return 0;
}





//读到文件中
FILE* ReadFile_own(LPSTR Path) {
	FILE* FileAddress = NULL;
	if (!(FileAddress=fopen(Path, "rb"))) {//如果FileAdd为空
		printf("读取文件失败");
		fclose(FileAddress);
		return 0;
	}
	return FileAddress;//返回文件流指针
}

//获取文件大小
int File_Size(FILE* File) {
	int len = 0;
	fseek(File, 0, SEEK_END);
	len = ftell(File);
	fseek(File, 0, SEEK_SET);
	return len;
}

//把文件读到FileBuffer
LPVOID FileToFilebuffer(FILE* FileAddress, int len) {
	if (!len) {
		printf("读取的长度为空");
		fclose(FileAddress);
		return 0;
	}

	LPVOID FileMem = (char*)malloc(len);
	memset(FileMem, 0, len);
	fread(FileMem, 1, len, FileAddress);
	
	//memcpy(FileMem, FileAddress, len);
	return FileMem;
}


//读取资源表
void Location_Res(LPVOID FileMem){

	//资源的类型
	PCHAR lpszResType[17] = { "未定义", "光标", "位图", "图标", "菜单",
		"对话框", "字符串","字体目录", "字体",
		"加速键", "非格式化资源", "消息列表", "光标组",
		"未定义", "图标组","未定义", "版本信息" };

	PIMAGE_DOS_HEADER pDos = NULL;
	PIMAGE_NT_HEADERS pNt = NULL;
	PIMAGE_FILE_HEADER pFile = NULL;
	PIMAGE_OPTIONAL_HEADER pOpt = NULL;
	PIMAGE_DATA_DIRECTORY pDataDir = NULL;
	PIMAGE_RESOURCE_DIRECTORY pRes = NULL;
	PIMAGE_RESOURCE_DIRECTORY_ENTRY pRes_Entry = NULL;
	if (!FileMem) {

		printf("读取dll文件失败\n");

		return;

	}

	pDos = (PIMAGE_DOS_HEADER)FileMem;
	pNt = (PIMAGE_NT_HEADERS)((DWORD)pDos+pDos->e_lfanew);
	pFile = (PIMAGE_FILE_HEADER)((DWORD)pNt + 4);
	pOpt = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER);

	pDataDir = (PIMAGE_DATA_DIRECTORY)(pOpt->DataDirectory);
	//pDataDir = (PIMAGE_DATA_DIRECTORY)(&(pOpt->NumberOfRvaAndSizes)+1);
	//pDataDir = (PIMAGE_DATA_DIRECTORY)pOpt->DataDirectory;



	pRes = PIMAGE_RESOURCE_DIRECTORY(pDataDir[2].VirtualAddress);  //资源目录Rva
	PIMAGE_RESOURCE_DIRECTORY  pResource = NULL;
	//转FOA
	pResource = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)FileMem+RvaToFileOffset(FileMem, (DWORD)pRes));//资源目录Foa

	//找到资源数量
	int Res_count = 0;
	Res_count = (int)(pResource->NumberOfIdEntries + pResource->NumberOfNamedEntries);
	pRes_Entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pResource + sizeof(IMAGE_RESOURCE_DIRECTORY));
	for (int i = 0; i < Res_count; i++) {
		//第一层
		if ((pRes_Entry + i)->NameIsString == 1) {//=1,低31位是一个指向UNICODE的指针
			PIMAGE_RESOURCE_DIR_STRING_U Unicd = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResource + (pRes_Entry + i)->NameOffset);
			WCHAR szStr[MAX_PATH] = { 0 };
			memcpy(szStr, Unicd->NameString, Unicd->Length*sizeof(WCHAR));
			printf("图标类型:%ls \n", szStr);
		}
		else {
			if ((pRes_Entry + i)->NameOffset < 17) {
				printf("\n\n=====图标类型:%s=====\n\n", lpszResType[((pRes_Entry + i)->NameOffset)]);//系统预定义类型
			}

			else {
				printf("\n\n=====图标类型(ID)=====\n\n图标自定义类型:%d \n", (pRes_Entry + i)->NameOffset);
			}
			
		}
		//第二层//地址

		PIMAGE_RESOURCE_DIRECTORY pNext = (PIMAGE_RESOURCE_DIRECTORY)((DWORD)pResource + (pRes_Entry + i)->OffsetToDirectory);//低31位 + 资源地址(foa) == 下一层目录节点的起始位置
		PIMAGE_RESOURCE_DIRECTORY_ENTRY pNext_Entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)pNext + sizeof(IMAGE_RESOURCE_DIRECTORY));
		int pNext_count = pNext->NumberOfIdEntries + pNext->NumberOfNamedEntries;
		if ((pRes_Entry + i)->DataIsDirectory == 1) //DataIsDirectory是OffsetToData的最高位,低31位 + 资源地址 == 下一层目录节点的起始位置
		{
			
			for (int i = 0; i < pNext_count; i++) 
			
			
			{
				if ((pNext_Entry + i)->NameIsString == 1) 
				{//第二层编号,如果NameIsString=1,低31位是一个指向UNICODE的指针
					PIMAGE_RESOURCE_DIR_STRING_U Unicd_2 = (PIMAGE_RESOURCE_DIR_STRING_U)((DWORD)pResource + (pNext_Entry + i)->NameOffset);//& 0x7FFFFFFF
					WCHAR szStr[MAX_PATH] = { 0 };
					memcpy(szStr, Unicd_2->NameString, Unicd_2->Length*sizeof(WCHAR));
					printf("\n图标资源编号字符串:%ls \t", szStr);
					//
				}
				else {

						printf("\n图标资源编号:");
						printf("%d\t", (pNext_Entry + i)->NameOffset);
						//

					}

				//第三层
				PIMAGE_RESOURCE_DIRECTORY p3 = (PIMAGE_RESOURCE_DIRECTORY)(((DWORD)pResource) + (pNext_Entry+i)->OffsetToDirectory);
				PIMAGE_RESOURCE_DIRECTORY_ENTRY p3_entry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)p3 + sizeof(IMAGE_RESOURCE_DIRECTORY));
				int p3C = p3->NumberOfIdEntries + p3->NumberOfNamedEntries;

				for (int n = 0; n < p3C; n++)

				{

					if ((p3_entry + n)->NameIsString == 1) {
						PIMAGE_RESOURCE_DIR_STRING_U Unicd_3 = PIMAGE_RESOURCE_DIR_STRING_U((p3_entry + n)->NameOffset);
						WCHAR szStr[MAX_PATH] = { 0 };
						memcpy(szStr, Unicd_3->NameString, Unicd_3->Length);
						printf("代码页编号字符串:%ls ", szStr);
						if ((p3_entry + n)->DataIsDirectory == 0) {
							PIMAGE_RESOURCE_DATA_ENTRY DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pResource + (p3_entry + n)->OffsetToDirectory);
							printf("代码页Rva:%x ", DataEntry->OffsetToData);
							printf("代码页大小:%x \n", DataEntry->Size);
						}
					}
					else {
						printf("代码页编号ID:%d ", (p3_entry + n)->NameOffset);
						if ((p3_entry + n)->DataIsDirectory == 0) {
							PIMAGE_RESOURCE_DATA_ENTRY DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((DWORD)pResource + (p3_entry + n)->OffsetToDirectory);
							printf("代码页Rva:%x ", DataEntry->OffsetToData);
							printf("代码页大小:%x \n", DataEntry->Size);
						}
					}
				}
			}
		}
	}
}
	
	
int main()
{
	LPVOID P = NULL;
	FILE* file = NULL;
	file = ReadFile_own(FilePath);
	int len = File_Size(file);
	P = FileToFilebuffer(file, len);

	Location_Res(P);
	getchar();
    return 0;
}


在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值