【C++源码】PE文件结构中导出表的解析

#include<iostream>  
#include<fstream>  
#include<Windows.h>  
#include<cstring>  
#include"RVAToFOA.h"  
using namespace std;  
//函数声明  
unsigned int GetFunctionAddressByName(char *functionName);  
long GetFileSize(char *fileName);  
unsigned int GetFunctionAddressByOrdinals(int n);  
void PrintExportTable();  

char* buffer;  
long fileSize = GetFileSize("D:\\Notepad++\\plugins\\mimeTools.dll");  

//获取各结构的地址  
IMAGE_DOS_HEADER* pDOSHeader = (IMAGE_DOS_HEADER*)(buffer);  
IMAGE_NT_HEADERS* pNTHeaders = (IMAGE_NT_HEADERS*)(&buffer[0] + pDOSHeader->e_lfanew);  
IMAGE_FILE_HEADER* pFileHeader = (IMAGE_FILE_HEADER*)((int)(pNTHeaders)+4);  
IMAGE_OPTIONAL_HEADER* pOptionalHeader = (IMAGE_OPTIONAL_HEADER*)((int)(pFileHeader)+sizeof(IMAGE_FILE_HEADER));  
IMAGE_SECTION_HEADER* pSectionHeader[10];  
IMAGE_EXPORT_DIRECTORY* pExportTable = (IMAGE_EXPORT_DIRECTORY*)  
(&buffer[0] + RVAToFOA(buffer, pOptionalHeader->DataDirectory[0].VirtualAddress));  

//导出函数名称表  
unsigned char* addressOfNames[1000];  
unsigned char** pAddressOfNames;//定义unsigned char** pAddressOfNames,利用pAddressOfNames来存贮导入函数名称表的地址  

//导出函数地址表  
unsigned int* addressOfFunctions[1000];  
unsigned int** pAddressOfFunctions;//学会用二级指针  

//导出函数序号表  
unsigned short nameOrdinals[1000];  
unsigned short* pNameOrdinals;  

int main()  
{  
	//先获取第一个节区头的地址  
	pSectionHeader[0] = (IMAGE_SECTION_HEADER*)((unsigned int)(pOptionalHeader)+sizeof(IMAGE_OPTIONAL_HEADER));  
	for (int i = 0;i < pFileHeader->NumberOfSections - 1;i++)  
		pSectionHeader[i + 1] = (IMAGE_SECTION_HEADER*)((unsigned int)(pSectionHeader[i]) + sizeof(IMAGE_SECTION_HEADER));  

	//给导出函数地址表赋值  
	for (int i = 0;i < pExportTable->NumberOfFunctions;i++)  
	{  
		pAddressOfFunctions = (unsigned int**)(buffer + RVAToFOA(buffer, pExportTable->AddressOfFunctions));  
		addressOfFunctions[i] = *(pAddressOfFunctions + i);  
	}  

	//给导出函数名称表赋值  
	for (int i = 0;i < pExportTable->NumberOfNames;i++)  
	{  
		pAddressOfNames = (unsigned char**)(buffer + RVAToFOA(buffer, pExportTable->AddressOfNames));  
		addressOfNames[i] = *(pAddressOfNames+i);  
	}  

	//给导出函数序号表赋值  
	for (int i = 0;i < pExportTable->NumberOfNames;i++)  
	{  
		pNameOrdinals = (unsigned short*)(buffer + RVAToFOA(buffer, pExportTable->AddressOfNameOrdinals));  
		nameOrdinals[i] = *(pNameOrdinals + i);  
	}  

	PrintExportTable();  
}  

unsigned int GetFunctionAddressByName(char *functionName)  
{  
	int i;  
	for (i = 0;i < pExportTable->NumberOfNames;i++)//两字符串相等返回0  
		if (strcmp(functionName, (const char*)(buffer + RVAToFOA(buffer, (unsigned int)addressOfNames[i])))==0)  
			return (unsigned int)addressOfFunctions[nameOrdinals[i]]+pOptionalHeader->ImageBase;  


	if (i == pExportTable->NumberOfNames)  
	{  
		cout << "找不到此函数" << endl;  
		return 0;  
	}  
}  

unsigned int GetFunctionAddressByOrdinals(int n)  
{  
	if(n<= pExportTable->Base+ pExportTable->NumberOfFunctions)  
		return (unsigned int)addressOfFunctions[n-pExportTable->Base] + pOptionalHeader->ImageBase;  
	else  
	{  
		cout << "无此函数" << endl;  
		return 0;  
	}  
}  

//获取文件大小  
long GetFileSize(char *fileName)  
{  
	filebuf *pbuf;  
	ifstream fileStr;  
	long size;  
	//采用二进制模式打开  
	fileStr.open(fileName, ios::binary);  

	//获取fileStr对应buffer对象的指针  
	pbuf = fileStr.rdbuf();  

	// 调用buffer对象方法获取文件大小    
	size = pbuf->pubseekoff(0, ios::end, ios::in);  
	pbuf->pubseekpos(0, ios::in);  
	// 分配内存空间    
	buffer = new char[size];  
	// 获取文件内容    
	pbuf->sgetn(buffer, size);  
	fileStr.close();  

	return size;  
}  

//打印导出表  
void PrintExportTable()  
{  
	cout << "Name:" << (char*)(buffer + RVAToFOA(buffer, pExportTable->Name)) << endl;  
	cout << "Base:" << hex << pExportTable->Base << endl;  
	cout << "NumberOfFunctions:" << hex << pExportTable->NumberOfFunctions << "<所有导出的函数的个数>" << endl;  
	cout << "NumberOfFunctions:" << hex << pExportTable->NumberOfFunctions << "<所有导出的函数的个数>" << endl;  
	cout << "NumberOfFunctions:" << hex << pExportTable->NumberOfNames << "<以函数名导出的函数的个数>" << endl;  
	cout << "AddressOfFunctions:" << hex << pExportTable->AddressOfFunctions << "<导出函数地址表偏移>" << endl;  
	cout << "AddressOfNameOrdinals:" << hex << pExportTable->AddressOfNameOrdinals << "<导出函数序号表偏移>" << endl;  

	cout << "****函数地址表****" << endl;  
	for (int i = 0;i < pExportTable->NumberOfFunctions;i++)  
		cout << "函数地址:" << hex << (unsigned int)(pAddressOfFunctions[i]) << endl;  

	cout << "****函数名称表****" << endl;  
	for (int i = 0;i < pExportTable->NumberOfNames;i++)  
		cout << "函数--" << hex << (unsigned int)(addressOfNames[i]) << endl  
		<< "函数名称:" << (char*)(buffer+RVAToFOA(buffer,(unsigned int)(addressOfNames[i]))) << endl;  

	cout << "****函数序号表****" << endl;  
	for (int i = 0;i < pExportTable->NumberOfNames;i++)  
		cout << "函数序号:" << hex << nameOrdinals[i] << endl;</span>  
}  



//RVAToFOA.cpp的内容

#include<Windows.h>  
#include"RVAToFOA.h"  
unsigned int RVAToFOA(char* buffer, unsigned int address)  
{  
	IMAGE_DOS_HEADER* pDOSHeader = (IMAGE_DOS_HEADER*)(buffer);  
	IMAGE_NT_HEADERS* pNTHeaders = (IMAGE_NT_HEADERS*)(&buffer[0] + pDOSHeader->e_lfanew);  
	IMAGE_FILE_HEADER* pFileHeader = (IMAGE_FILE_HEADER*)((int)(pNTHeaders)+4);  
	IMAGE_OPTIONAL_HEADER* pOptionalHeader = (IMAGE_OPTIONAL_HEADER*)((int)(pFileHeader)+sizeof(IMAGE_FILE_HEADER));  
	IMAGE_SECTION_HEADER* pSectionHeader[10];  

	pSectionHeader[0] = (IMAGE_SECTION_HEADER*)((int)(pOptionalHeader)+sizeof(IMAGE_OPTIONAL_HEADER));  
	for (int i = 0;i < pFileHeader->NumberOfSections - 1;i++)  
	{  
		pSectionHeader[i + 1] = (IMAGE_SECTION_HEADER*)((int)(pSectionHeader[i]) + sizeof(IMAGE_SECTION_HEADER));  
	}  

	//if(address<pSectionHeader[0]->VirtualAddress) return  
	for (int i = 0;i < pFileHeader->NumberOfSections - 1;i++)  
	{  
		if (address >= pSectionHeader[i]->VirtualAddress&&address <= pSectionHeader[i + 1]->VirtualAddress)  
			return address - pSectionHeader[i]->VirtualAddress + pSectionHeader[i]->PointerToRawData;  
	}  
}



以任意dll文件为例


解析结果与DIE分析出的相同



过程中主要学会的指针的灵活运用,其他表的解析后续学习中再贴上,欢迎私信交流,指导不足


猜你喜欢

转载自blog.csdn.net/jiangqin115/article/details/79742750