PE文件格式,是Win32环境自带的执行体文件格式。个人理解主要是指.exe文件和.dll文件,不知道是否正确,若不对还望大侠们指正,不多说了,风飘雪大哥在加密解密中说的很详细,先写一个vc编写的基于控制台的PE文件格式分析程序,通过内存映射实现。^_^ ^_^ ^_^
先创建一个PE格式分析类:
头文件:PeLook.h
#pragma once
#include <windows.h>
#include <fstream>
#include <iostream>
using namespace std;
class PeLook
{
private:
HANDLE hFile;
HANDLE hFileMap;
void *pvFile;
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeader;
IMAGE_SECTION_HEADER * sectionTable;
IMAGE_IMPORT_DESCRIPTOR *importTable;
public:
int LoadHeader(char *fileName);
int LoadSectionTable();
int SearchSection(unsigned long rva, unsigned long *virAddr, unsigned long *virOffset, unsigned long *offset);
int LoadImportTable();
int LoadFunction(IMAGE_IMPORT_DESCRIPTOR importDesc);
PeLook(void);
PeLook(char *fileName);
~PeLook(void);
};
类的实现 PeLook.cpp
#include "./pelook.h"
PeLook::PeLook(void)
{
}
PeLook::~PeLook(void)
{
}
PeLook::PeLook(char *fileName)
{
}
/*******************************************************************************
*函数介绍: 获取指定.exe/.dll的头信息,包括IMAGE_DOS_HEADER和IMAGE_NT_HEADERS
*输入参数: char *fileName 需要分析的文件名
*输出参数: 无
*返回值: 获取头信息是否成功,成功返回0,否则返回-1,-2,-3
*******************************************************************************/
int PeLook::LoadHeader(char *fileName)
{
//创建内存映射文件
hFile = CreateFile(fileName, GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
cout << "create file false !" << endl;
return -1;
}
hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
if(hFileMap == NULL)
{
cout << "create file mapping false !" << endl;
return -2;
}
pvFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
if(pvFile == NULL)
{
cout << "view view of file is filse!" << endl;
return -3;
}
dosHeader = (IMAGE_DOS_HEADER *)pvFile;
ntHeader = (IMAGE_NT_HEADERS *)((char *)pvFile + dosHeader->e_lfanew);
cout << "" << ntHeader->Signature << endl;
return 0;
}
/************************************************************************
*函数介绍: 获取指定.exe/.dll的节表信息
*输入参数: 无
*输出参数: 无
*返回值: 获取节表信息是否成功,成功返回0
************************************************************************/
int PeLook::LoadSectionTable()
{
sectionTable = (IMAGE_SECTION_HEADER *)((char *)pvFile + dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
for(int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++)
{
cout << "-----------------------------------" << endl;
cout << "name : " << sectionTable[i].Name << endl;
cout << "VirtualSize : " << sectionTable[i].Misc.VirtualSize << endl;
cout << "VirtualAddress : " << sectionTable[i].VirtualAddress << endl;
cout << "PointerToRawData : " << sectionTable[i].PointerToRawData << endl;
cout << "SizeOfRawData : " << sectionTable[i].SizeOfRawData << endl;
cout << "Characteristics : " << sectionTable[i].Characteristics << endl;
}
return 0;
}
/************************************************************************
*函数介绍: 根据给出的虚拟地址,查找该地址在文件中的偏移地址
*输入参数: unsigned long rva 需要查找偏移地址的虚拟地址
*输出参数: unsigned long *virAddr 所查虚拟地址所在的节的虚拟地址
* unsigned long offset 所查虚拟地址所在的节在文中的偏移地址
*返回值: 所查虚拟地址所在的节号,小于0(-1)时表示查找失败
************************************************************************/
int PeLook::SearchSection(unsigned long rva, unsigned long *virAddr, unsigned long *virOffset, unsigned long *offset)
{
for(int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++)
{
if(rva >= sectionTable[i].VirtualAddress && rva < sectionTable[i].VirtualAddress + sectionTable[i].Misc.VirtualSize)
{
*virAddr = sectionTable[i].VirtualAddress;
*virOffset = sectionTable[i].PointerToRawData;
*offset = *virOffset + rva - *virAddr;
return i;
}
}
return -1;
}
/************************************************************************
*函数介绍: 获取指定.exe/.dll文件的输入表信息
*输入参数: 无
*输出参数: 无
*返回值: 获取节表信息是否成功,成功返回0
************************************************************************/
int PeLook::LoadImportTable()
{
unsigned long localVir, virAddr, virOffset, offset;
localVir = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
int sectionNumber = SearchSection(localVir, &virAddr, &virOffset, &offset);
IMAGE_IMPORT_DESCRIPTOR *p = (IMAGE_IMPORT_DESCRIPTOR *)((char *)pvFile + offset);
for(; p->Name; p++)
{
cout << "-------------------------------" << endl;
localVir = p->Name;
sectionNumber = SearchSection(localVir, &virAddr, &virOffset, &offset);
cout << "name : " << (char *)pvFile + offset << endl;
cout << "OriginalFirstThunk : " << p->OriginalFirstThunk << endl;
cout << "TimeDateStamp : " << p->TimeDateStamp << endl;
cout << "ForwarderChain : " << p->ForwarderChain << endl;
cout << "Characteristics : " << p->Characteristics << endl;
cout << "FirstThunk : " << p->FirstThunk << endl;
LoadFunction(*p);
}
return 0;
}
/************************************************************************
*函数介绍: 获取.exe/.dll文件使用指定.dll文件时引入的函数
*输入参数: IMAGE_IMPORT_DESCRIPTOR importDesc 一个引用节,代表一个引
* 用的dll
*输出参数: 无
*返回值: 从该.dll文件中引用的函数的个数
************************************************************************/
int PeLook::LoadFunction(IMAGE_IMPORT_DESCRIPTOR importDesc)
{
unsigned long localVir, virAddr, virOffset, offset;
localVir = importDesc.FirstThunk;
int sectionNumber = SearchSection(localVir, &virAddr, &virOffset, &offset);
IMAGE_THUNK_DATA *thunkTable = (IMAGE_THUNK_DATA *)((char *)pvFile + offset);
IMAGE_IMPORT_BY_NAME *p;
int funNum = 0;
for(; thunkTable->u1.Function; thunkTable++)
{
localVir = thunkTable->u1.Function;
sectionNumber = SearchSection(localVir, &virAddr, &virOffset, &offset);
p = (IMAGE_IMPORT_BY_NAME *)((char *)pvFile + offset);
cout << p->Hint << "/t" << p->Name << endl;
funNum++;
}
return funNum;
}
主函数文件 PeAnalyse.cpp
#include "PeLook.h"
void main()
{
PeLook mype;
mype.LoadHeader("c://MySocket.dll");
mype.LoadSectionTable();
mype.LoadImportTable();
char ch;
cin >> ch;
}