PE文件格式分析之一

        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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值