欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]一个C++的PE文件操作类

[原创]一个C++的PE文件操作类

最近也研究了一波PE文件结构,自己写了一个PE结构的类,不敢私藏,分享给大家了。
只写了一个基类,如果有需要扩展的同学自己继承基类,还是挺方便的。

//PeReadWrite.h 文件

#pragma once

class PeReadWrite

{

private:

  HANDLE hFile;

  HANDLE hMapping;

  PVOID pBaseAddr;

public:

  

  //构造函数

  PeReadWrite();

  //加载文件

  bool loadFile(CString filePath);

  //返回载入的地址

  DWORD getBaseAddr();

  //判断是否是PE文件

  bool isPeFile();

  //获取DOS头

  IMAGE_DOS_HEADER *getDosHeader();

  //获取NT头

  IMAGE_NT_HEADERS *getNtHeader();

  //获取节表起始

  IMAGE_SECTION_HEADER *getSectionStart();

  //获取导入表

  IMAGE_IMPORT_DESCRIPTOR *getImport();

  //获取导出表

  IMAGE_EXPORT_DIRECTORY *getExport();

  //获取重定位

  IMAGE_BASE_RELOCATION *getReLocation();

  //获取资源

  IMAGE_RESOURCE_DIRECTORY *getResource();

  //计算RvaToVa

  DWORD RvaToVa(DWORD rva);

  //关闭一系列操作

  void UnFile();

};


cpp文件
//PeReadWrite.cpp 文件

#include "stdafx.h"

#include "PeReadWrite.h"

#include "windows.h"

//默认构造函数

PeReadWrite::PeReadWrite(){}

bool PeReadWrite::loadFile(CString filePath){

  hFile = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);

  if (hFile == INVALID_HANDLE_VALUE)

  {

    return FALSE;

  }

    //创建内存映射文件  

  if (!(hMapping = CreateFileMapping(hFile, 0, PAGE_READWRITE | SEC_COMMIT, 0, 0, 0)))

  {

    CloseHandle(hFile);

    return FALSE;

  }

  //把文件映像存入pBaseAddr  

  if (!(pBaseAddr = MapViewOfFile(hMapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 0)))

  {

    CloseHandle(hMapping);

    CloseHandle(hFile);

    return FALSE;

  }

  return TRUE;

}

//返回载入地址

DWORD PeReadWrite::getBaseAddr(){

  return (DWORD)pBaseAddr;

}

//获取NT头

IMAGE_NT_HEADERS* PeReadWrite::getNtHeader(){

  IMAGE_DOS_HEADER* dosHead = (IMAGE_DOS_HEADER*)pBaseAddr;

  return (IMAGE_NT_HEADERS *)((DWORD)pBaseAddr + dosHead->e_lfanew);

}

//获取DOS头

IMAGE_DOS_HEADER* PeReadWrite::getDosHeader(){

  return (IMAGE_DOS_HEADER *)pBaseAddr;

}

//获取节表起始

IMAGE_SECTION_HEADER* PeReadWrite::getSectionStart(){

  return (IMAGE_SECTION_HEADER*)((DWORD)getNtHeader() + sizeof(IMAGE_NT_HEADERS));

}

//获取导入表

IMAGE_IMPORT_DESCRIPTOR* PeReadWrite::getImport(){

  DWORD importTable = RvaToVa(getNtHeader()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

  return (IMAGE_IMPORT_DESCRIPTOR *)importTable;

}

//获取导出表

IMAGE_EXPORT_DIRECTORY* PeReadWrite::getExport(){

  DWORD exportTable = RvaToVa(getNtHeader()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

  return (IMAGE_EXPORT_DIRECTORY*)exportTable;

}

//获取重定位

IMAGE_BASE_RELOCATION* PeReadWrite::getReLocation(){

  DWORD reLocation = RvaToVa(getNtHeader()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

  return (IMAGE_BASE_RELOCATION*)reLocation;

}

//获取资源表

IMAGE_RESOURCE_DIRECTORY *PeReadWrite::getResource(){

  DWORD source = RvaToVa(getNtHeader()->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);

  return (IMAGE_RESOURCE_DIRECTORY *)source;

}

//计算 RvaToVa

DWORD PeReadWrite::RvaToVa(DWORD rva){

  IMAGE_SECTION_HEADER *sectionHeader;

  int secNum = getNtHeader()->FileHeader.NumberOfSections;

  sectionHeader = getSectionStart();

  for (int i = 0; i<secNum; i++)

  {

    if ((sectionHeader->VirtualAddress <= rva)&& rva<(sectionHeader->VirtualAddress + sectionHeader->SizeOfRawData))

      return (rva - sectionHeader->VirtualAddress + sectionHeader->PointerToRawData) + (DWORD)pBaseAddr;

    sectionHeader++;

  }

  return 0;

}

//清除内存映射和关闭文件 

void PeReadWrite::UnFile(){

  if (pBaseAddr!=NULL)

  {

    UnmapViewOfFile(pBaseAddr);

  }

  if (hMapping!=NULL)

  {

    CloseHandle(hMapping);

  }

  if (hFile!=NULL)

  {

    CloseHandle(hFile);

  }

  

  

}

//验证是否是PE文件

bool PeReadWrite::isPeFile(){

  if (getDosHeader()->e_magic != IMAGE_DOS_SIGNATURE)

  {

    return FALSE;

  }

  if (getNtHeader()->Signature != IMAGE_NT_SIGNATURE)

  {

    return FALSE;

  }   

  return TRUE;

}

本人水平有限,如果代码有误,欢迎指正。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功