// 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;
}
2021-06-07解析资源表
最新推荐文章于 2021-10-24 16:33:55 发布