#ifndef PEFile_h__ #define PEFile_h__ //************************************ // 作者: 吴奇凡 // 编写时间: 2011-6-6 // 模块: 读取PE文件 // 博客地址:http://blog.csdn.net/fan_mvp //************************************ #pragma once #include <windows.h> #include <functional> #include <map> using namespace std; struct StrCompare : public std::binary_function<PSTR, PSTR, bool> { public: bool operator() (const PSTR str1, PSTR str2) const { return strcmp(str1, str2) < 0; } }; typedef map<PSTR,void*,StrCompare> FunctionMap; class ImportEntry{ public: PSTR dllName; FunctionMap functions; }; typedef map<PSTR,ImportEntry*,StrCompare> ImportMap; class PEFile { private: unsigned char* m_ImageBase; void* GetRVAOffset(DWORD rva); ImportMap m_imports; FunctionMap m_exports; public: PEFile(void* pImageBase); IMAGE_DOS_HEADER* GetDosHeader(); IMAGE_NT_HEADERS* GetNtHeader(); IMAGE_SECTION_HEADER* GetSectionHeader(); IMAGE_OPTIONAL_HEADER GetOptionalHeader(); IMAGE_IMPORT_DESCRIPTOR* GetImportDescriptor(); IMAGE_EXPORT_DIRECTORY* GetExportDirectory(); ImportMap GetImportTable(); FunctionMap GetExportTable(); public: ~PEFile(void); }; #endif // PEFile_h__ #include "StdAfx.h" #include "PEFile.h" //************************************ // 作者: 吴奇凡 // 编写时间: 2011-6-6 // 模块: 读取PE文件 // 博客地址:http://blog.csdn.net/fan_mvp //************************************ PEFile::PEFile( void* pImageBase) { m_ImageBase = (unsigned char*)pImageBase; } PEFile::~PEFile(void) { for (ImportMap::iterator it = m_imports.begin();it!=m_imports.end();++it) { delete (*it).second; } } IMAGE_DOS_HEADER* PEFile::GetDosHeader() { return (IMAGE_DOS_HEADER*)m_ImageBase; } IMAGE_NT_HEADERS* PEFile::GetNtHeader() { return (IMAGE_NT_HEADERS*)(m_ImageBase+GetDosHeader()->e_lfanew); } IMAGE_SECTION_HEADER* PEFile::GetSectionHeader() { return (IMAGE_SECTION_HEADER*)(m_ImageBase+sizeof(IMAGE_NT_HEADERS)+GetDosHeader()->e_lfanew); } IMAGE_OPTIONAL_HEADER PEFile::GetOptionalHeader() { return ( IMAGE_OPTIONAL_HEADER)GetNtHeader()->OptionalHeader; } IMAGE_IMPORT_DESCRIPTOR* PEFile::GetImportDescriptor() { return (IMAGE_IMPORT_DESCRIPTOR*)GetRVAOffset(GetOptionalHeader().DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); } void* PEFile::GetRVAOffset( DWORD rva) { IMAGE_SECTION_HEADER* pSection = GetSectionHeader(); int maxSectionNumber = GetNtHeader()->FileHeader.NumberOfSections; for (int i=0;i<maxSectionNumber;i++,pSection++) { DWORD sectionAddress = pSection->VirtualAddress; if(sectionAddress<=rva&&rva<sectionAddress+pSection->SizeOfRawData){ return m_ImageBase+pSection->PointerToRawData +(rva-sectionAddress); } } return 0; } ImportMap PEFile::GetImportTable() { //获取导入表 PIMAGE_IMPORT_DESCRIPTOR import_descriptor = GetImportDescriptor(); //循环获取每个导入库 //如果循环到所有数据为NULL时证明已经没有导入数据了 for (;import_descriptor->FirstThunk==NULL&& import_descriptor->ForwarderChain==NULL&& import_descriptor->OriginalFirstThunk == NULL&& import_descriptor->TimeDateStamp == NULL&& import_descriptor->Name==NULL;import_descriptor++) { //获取导入的dll名称如user32.dll PSTR dllName = (char*)GetRVAOffset(import_descriptor->Name); ImportEntry *entry = new ImportEntry();//创建一个导入项 entry->dllName = dllName;//设置导入项的名称 //获取导入函数项 //函数项地址为OriginalFirstThunk指向的地址 IMAGE_THUNK_DATA* thunk = (IMAGE_THUNK_DATA*)GetRVAOffset(import_descriptor->OriginalFirstThunk); //循环获取导入的函数 //当thunkOrdinal为NULL时表示已经没有函数了 for (DWORD thunkOrdinal = thunk->u1.Ordinal;thunkOrdinal!=NULL;thunkOrdinal=(++thunk)->u1.Ordinal) { //获取该项的函数名称 IMAGE_IMPORT_BY_NAME* functionName = (IMAGE_IMPORT_BY_NAME*)GetRVAOffset(thunk->u1.AddressOfData); //获取函数地址 entry->functions[(PSTR)functionName->Name] = GetRVAOffset(thunk->u1.Function); } m_imports[dllName] = entry; } return m_imports; } IMAGE_EXPORT_DIRECTORY* PEFile::GetExportDirectory() { return (IMAGE_EXPORT_DIRECTORY*)GetRVAOffset(GetOptionalHeader().DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); } FunctionMap PEFile::GetExportTable() { PIMAGE_EXPORT_DIRECTORY export_directory = GetExportDirectory(); //获取名称表的虚拟地址 PINT nameOffset = (PINT)GetRVAOffset(export_directory->AddressOfNames); //获取函数地址表的虚拟地址 PINT functionOffset = (PINT)GetRVAOffset(export_directory->AddressOfFunctions); for (int i=0;i<export_directory->NumberOfNames;i++) { //利用表项+索引找到函数名称的地址指针 再加上偏移获取实际名称 PSTR functionName = (PSTR)GetRVAOffset(*(nameOffset+i)); m_exports[functionName] = GetRVAOffset(*(functionOffset+i)); } return m_exports; } void CPEFileViewDlg::LoadPEFile(CString fileName) { CFile file(fileName,CFile::modeRead); int len =(int)file.GetLength(); unsigned char * buffer =new unsigned char[len]; file.Read(buffer,len); file.Close(); PEFile pe(buffer); pe.GetExportTable(); } 使用请著名出处谢谢:http://blog.csdn.net/fan_mvp