zoukankan      html  css  js  c++  java
  • C/C++ 获取 PE 文件导出表

    // 内存偏移转文件偏移
    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 << "]	"
    			<< "[ID:" << hex << pOrder[i] << "]	"
    			<< "[RVA:" << pFunc[i] << "]	"
    			<< "[Name:" << szFuncName << "]	"
    			<< endl;
    	}
    
    	cFile.close();
    }
    

    效果图:


    版权声明: 本博客,文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!

    警告:如果您恶意转载本人文章,则您的整站文章,将会变为我的原创作品,请相互尊重!
  • 相关阅读:
    iOS- 优化与封装 APP音效的播放
    iOS- iPhone App 如何运营?
    iOS- 封装单例宏
    iOS- 详解文本属性Attributes
    iOS- 如何将应用集成发短信、发邮件、打电话
    iOS- <项目笔记> UIApplication常见属性与方法总结
    iOS- <项目笔记>iOS6 & iOS7屏幕图片适配
    iOS- <项目笔记>项目配置常见文件
    iOS- <项目笔记>UI控件常见属性总结
    iOS- UIPickerView餐厅点餐系统
  • 原文地址:https://www.cnblogs.com/LyShark/p/15019654.html
Copyright © 2011-2022 走看看