您的位置:首页 > 编程语言 > C语言/C++

C++ 读取PE文件 工具类

2011-06-06 23:05 302 查看
#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息