头文件CpeUtil.h的内容:
#pragma once
#include<Windows.h>
class CPeUtil
{
public:
CPeUtil();
~CPeUtil();
BOOL LoadFile(const char* path);
BOOL InitPeInfo();
void PrintSectionHeaders();
void GetExportTable();
private:
char* fileBuff;
DWORD FileSize;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader;
PIMAGE_FILE_HEADER pFileHeader;
PIMAGE_OPTIONAL_HEADER pOptionHeader;
DWORD Rva2Foa(DWORD rva);
};
源文件CPeUtil.cpp内容:
#include "CPeUtil.h"
#include "stdio.h"
CPeUtil::CPeUtil()
{
fileBuff = NULL;
FileSize = 0;
pDosHeader = NULL;
pNtHeader = NULL;;
pFileHeader = NULL;
pOptionHeader = NULL;
}
CPeUtil::~CPeUtil()
{
if (NULL != fileBuff)
{
delete[] fileBuff;
}
}
BOOL CPeUtil::LoadFile(const char* path)
{
HANDLE hFile = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == 0)
{
return FALSE;
}
FileSize = GetFileSize(hFile, 0);
fileBuff = new char[FileSize] {0};
DWORD realReadBytes = 0;
BOOL readSuccess = ReadFile(hFile, fileBuff, FileSize, &realReadBytes, 0);
if (0 == readSuccess)
{
return FALSE;
}
if (this->InitPeInfo())
{
return TRUE;
}
return FALSE;
}
BOOL CPeUtil::InitPeInfo()
{
pDosHeader = (PIMAGE_DOS_HEADER)fileBuff;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return FALSE;
}
pNtHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + fileBuff);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
return FALSE;
}
pFileHeader = &pNtHeader->FileHeader;
pOptionHeader = &pNtHeader->OptionalHeader;
return TRUE;
}
void CPeUtil::PrintSectionHeaders()
{
PIMAGE_SECTION_HEADER pSectionHeaders = IMAGE_FIRST_SECTION(pNtHeader);
for (int i = 0; i < pFileHeader->NumberOfSections; ++i)
{
char name[9] = { 0 };
memcpy_s(name, 9, pSectionHeaders->Name, 8);
printf("区段名称=%s\n", name);
pSectionHeaders++;
}
}
///< 解析导出表
void CPeUtil::GetExportTable()
{
IMAGE_DATA_DIRECTORY directory = pOptionHeader->DataDirectory[0];
///< 得到导出表的位置
PIMAGE_EXPORT_DIRECTORY pexport = (PIMAGE_EXPORT_DIRECTORY)(Rva2Foa(directory.VirtualAddress) + fileBuff);
char* dllName = Rva2Foa(pexport->Name) + fileBuff;
printf("文件名称:%s\n", dllName);
DWORD * funcAddr = (DWORD*)(Rva2Foa(pexport->AddressOfFunctions) + fileBuff);
WORD * peot = (WORD*)(Rva2Foa(pexport->AddressOfNameOrdinals) + fileBuff); ///<序号表的地址
DWORD * pent = (DWORD*)(Rva2Foa(pexport->AddressOfNames) + fileBuff);
for (int i = 0; i < pexport->NumberOfFunctions; ++i)
{
printf("函数地址为:%x **** ", *funcAddr);
for (int j = 0; j < pexport->NumberOfNames; ++j)
{
if (peot[j] == i)
{
char* funName =(char*)(Rva2Foa(pent[j]) + fileBuff);
printf("函数名称为: %s\n", funName);
}
}
funcAddr++;
}
}
DWORD CPeUtil::Rva2Foa(DWORD rva)
{
PIMAGE_SECTION_HEADER pSectionHeaders = IMAGE_FIRST_SECTION(pNtHeader);
for (int i = 0; i < pFileHeader->NumberOfSections; ++i)
{
if (rva >= pSectionHeaders->VirtualAddress && rva < pSectionHeaders->VirtualAddress + pSectionHeaders->Misc.VirtualSize)
{
///< FOA = 数据的RVA - 区段的RVA + 数据的FOA
return rva - pSectionHeaders->VirtualAddress + pSectionHeaders->PointerToRawData;
}
pSectionHeaders++;
}
return 0;
}
main.cpp的内容
#include<iostream>
#include "CPeUtil.h"
int main()
{
CPeUtil peUtil;
BOOL success = peUtil.LoadFile("./7z.dll");
if (success)
{
//peUtil.PrintSectionHeaders();
peUtil.GetExportTable();
return 0;
}
printf("加载PE文件失败\n");
return 0;
}