PE文件的导出表解析

版权声明:本文为YuanChuang文章,未经博主允许转载。 https://blog.csdn.net/zzy1448331580/article/details/90714368
typedef struct _IMAGE_EXPORT_DIRECTORY 
{
	DWORD   Characteristics;//保留,一直都是00000000
	DWORD   TimeDateStamp;//导出表创建的时间(GMT)
	WORD    MajorVersion;//导出表的主版本号
	WORD    MinorVersion;//导出表的次版本号
	DWORD   Name;//导出表的名字
	DWORD   Base;//函数索引=导出函数索引-Base
	DWORD   NumberOfFunctions;//EAT的数量
	DWORD   NumberOfNames;//ENA的数量
	DWORD   AddressOfFunctions;     // RVA from base of image
	DWORD   AddressOfNames;         // RVA from base of image
	DWORD   AddressOfNameOrdinals;  // RVA from base of image
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
#include <Windows.h>

#include <iostream>
#include <string>
#include <fstream>
#include <memory>
using namespace std;

int rva_to_file(PIMAGE_SECTION_HEADER pSection,int nSectionNum,int nRva)
{
	int nRet = 0;
	for (int nIndex = 0; nIndex < nSectionNum; nIndex++)
	{
		if (pSection[nIndex].VirtualAddress <= nRva && nRva < pSection[nIndex + 1].VirtualAddress)
		{
			nRet = nRva - pSection[nIndex].VirtualAddress + pSection[nIndex].PointerToRawData;
			break;
		}
	}
	return nRet;
}

void analizy_to_cout(const string& strFilePath)
{
	if (strFilePath.empty())
	{
		cout << "input file is null" << endl;
		return;
	}

	fstream cFile(strFilePath, ios::binary | ios::in);
	if (!cFile)
	{
		cout << "file open fail" << endl;
		return;
	}

	IMAGE_DOS_HEADER stDos;
	cFile.read((char*)&stDos,sizeof(IMAGE_DOS_HEADER));
	
	IMAGE_NT_HEADERS stNt;
	cFile.seekg(stDos.e_lfanew, ios::beg);
	cFile.read((char*)&stNt, sizeof(IMAGE_NT_HEADERS));

	if (!stNt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
	{
		cout << "the file has not export" << endl;
		cFile.close();
		return;
	}

	int nSectionNum = stNt.FileHeader.NumberOfSections;
	shared_ptr<IMAGE_SECTION_HEADER> pShareSection(new IMAGE_SECTION_HEADER[nSectionNum]);
	PIMAGE_SECTION_HEADER pSection = pShareSection.get();

	cFile.read((char*)pSection, sizeof(IMAGE_SECTION_HEADER)*nSectionNum);
	
	IMAGE_EXPORT_DIRECTORY stExport;
	int nExportOffset = rva_to_file(pSection, nSectionNum, stNt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	if (!nExportOffset)
	{
		cout << "export offset fail" << endl;
		cFile.close();
		return;
	}

	cFile.seekg(nExportOffset, ios::beg);
	cFile.read((char*)&stExport, sizeof(IMAGE_EXPORT_DIRECTORY));

	cFile.seekg(rva_to_file(pSection, nSectionNum, stExport.Name), ios::beg);
	char szExportName[50];
	cFile.get(szExportName,50);
	cout << "export name is " << szExportName << endl;

	int nAddressNum = stExport.NumberOfFunctions;

	shared_ptr<int> pShareName(new int[nAddressNum]);
	int* pName = pShareName.get();
	cFile.seekg(rva_to_file(pSection, nSectionNum, stExport.AddressOfNames), ios::beg);
	cFile.read((char*)pName, sizeof(int)*nAddressNum);

	shared_ptr<short> pShareOrder(new short[nAddressNum]);
	short* pOrder = pShareOrder.get();
	cFile.seekg(rva_to_file(pSection, nSectionNum, stExport.AddressOfNameOrdinals), ios::beg);
	cFile.read((char*)pOrder, sizeof(short)*nAddressNum);

	shared_ptr<int> pShareFunc(new int[nAddressNum]);
	int* pFunc = pShareFunc.get();
	cFile.seekg(rva_to_file(pSection, nSectionNum, stExport.AddressOfFunctions), ios::beg);
	cFile.read((char*)pFunc, sizeof(int)*nAddressNum);

	char szFuncName[50];
	for (int nIndex = 0; nIndex < nAddressNum; nIndex++)
	{
		cFile.seekg(rva_to_file(pSection, nSectionNum, pName[nIndex]), ios::beg);
		cFile.get(szFuncName, 50);

		cout << "[Index:" << dec << nIndex << "]\t"
			<< "[ID:" << hex << pOrder[nIndex] << "]\t"
			<< "[RVA:" << pFunc[nIndex] << "]\t"
			<< "[Name:" << szFuncName << "]\t"
			<< endl;
	}

	cFile.close();
}

int main(_In_ int argc, 
	_In_reads_(argc) _Pre_z_ char** argv, 
	_In_z_ char** envp)
{
	cout << "Please input target file" << endl;

	string strFilePath;
	cin >> strFilePath;
	analizy_to_cout(strFilePath);

	system("pause");
	return 0;
}

实际效果:

猜你喜欢

转载自blog.csdn.net/zzy1448331580/article/details/90714368