zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C++ 获取 PE 文件导出表

C++文件导出 获取 pe
2023-09-11 14:14:01 时间
// 内存偏移转文件偏移
int rva_to_raw(PIMAGE_SECTION_HEADER pSection,int nSectionNum,int nRva)
{
	int nRet = 0;

	// 遍历节区
	for (int i=0;i<nSectionNum;i++){
		// 导出表地址在这个节区内
		if (pSection[i].VirtualAddress <= nRva && nRva < pSection[i+1].VirtualAddress){
			// 文件偏移 = 该段的 PointerToRawData + (内存偏移 - 该段起始的RVA(VirtualAddress))
			nRet = nRva - pSection[i].VirtualAddress + pSection[i].PointerToRawData;
			break;
		}
	}

	return nRet;
}

void printExpTable(const string& strFilePath)
{
	// 二进制方式读文件
	fstream cFile(strFilePath, ios::binary | ios::in);
	if (!cFile){cout << "打开文件失败" << endl; return;}

	// 读 dos 头
	IMAGE_DOS_HEADER dosHeader; 
	cFile.read((char*)&dosHeader,sizeof(IMAGE_DOS_HEADER));
	
	// 读 nt 头(64位)
	IMAGE_NT_HEADERS64 ntHeader;
	cFile.seekg(dosHeader.e_lfanew, ios::beg);
	cFile.read((char*)&ntHeader, sizeof(IMAGE_NT_HEADERS64));
	if (!ntHeader.OptionalHeader.DataDirectory[0].VirtualAddress){
		cout << "文件没有导出函数" << endl;
		cFile.close(); return;
	}

	// 读节区头
	int nSectionNum = ntHeader.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);
	
	// 计算导出表 RAW
	IMAGE_EXPORT_DIRECTORY expDir;
	int nExportOffset = rva_to_raw(pSection,nSectionNum,ntHeader.OptionalHeader.DataDirectory[0].VirtualAddress);
	if (!nExportOffset){
		cout << "RAW 获取失败" << endl;
		cFile.close(); return;
	}

	// 读导出表
	cFile.seekg(nExportOffset, ios::beg);
	cFile.read((char*)&expDir, sizeof(IMAGE_EXPORT_DIRECTORY));

	// 读导出表头
	cFile.seekg(rva_to_raw(pSection, nSectionNum, expDir.Name), ios::beg);
	char szExportName[50];
	cFile.get(szExportName,50);
	cout << "IMAGE_EXPORT_DIRECTORY.Name = " << szExportName << endl;

	// 获取到处函数个数
	int nAddressNum = expDir.NumberOfFunctions;

	// 获取导出表函数名
	shared_ptr<int> pShareName(new int[nAddressNum]);
	int* pName = pShareName.get();
	cFile.seekg(rva_to_raw(pSection, nSectionNum, expDir.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_raw(pSection, nSectionNum, expDir.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_raw(pSection, nSectionNum, expDir.AddressOfFunctions), ios::beg);
	cFile.read((char*)pFunc, sizeof(int)*nAddressNum);
	
	// 遍历导出表
	char szFuncName[50];
	for (int i=0;i<nAddressNum;i++){
		cFile.seekg(rva_to_raw(pSection, nSectionNum, pName[i]), ios::beg);
		cFile.get(szFuncName, 50);
		cout << "[Index:" << dec << i << "]\t"
			<< "[ID:" << hex << pOrder[i] << "]\t"
			<< "[RVA:" << pFunc[i] << "]\t"
			<< "[Name:" << szFuncName << "]\t"
			<< endl;
	}

	cFile.close();
}

效果图:
在这里插入图片描述