首页
社区
课程
招聘
[原创]C++11标准的PE信息读取类
发表于: 2016-2-11 23:31 6340

[原创]C++11标准的PE信息读取类

2016-2-11 23:31
6340
第一次发贴,现在还是临时会员

这几天用C++11的语法写了一个读取PE32文件信息的类,目前还不支持PE64(PE32+)格式。因为大量使用新语法,可能老版本编译器无法编译程序。


    PEInfor类是主要功能类,读取PE文件头的几个主要信息,以及区块表、输入表、输出表和重定位表。

    MD5类是一个附带的计算字符串和文件MD5值的“静态类”(通过=delete删除类的构造函数实现,有待商榷),PEInfor类使用MD5类计算PE文件的MD5校验值。


我没做过啥项目,不是很会写代码注释。这次的注释写的比较多,主要集中在类头文件里,可能显得有些罗嗦,大家有精力看的话提点建议也行


类的封装程度比较高,所有的字段都是只读的,只能通过接口读取,而不能修改。在区块表、输入表这部分,提供了一些我认为比较常用的操作。比如通过区块名称获取区块表指针从而读取信息,获取某个动态链接库所有的输入函数名称等。如果类提供的操作不能满足用户需要,还可以获取指向类中文件信息存储区的常量指针,但只能读取自己所需要的信息,无法修改。

下面把一些主要信息说明一下
private:
  bool IsOpening = false;        // 文件的打开状态
  std::string FileName = "";        // 文件名称
  std::string MD5 = "";          // MD5值
  std::size_t FileSize = 0;        // 文件大小
  std::size_t ImageSize = 0;        // 映像大小
  DWORD ImageBase = NULL;      // 默认载入基址
  DWORD EntryPoint = NULL;      // 代码入口点
  std::size_t ExtraDataSize = 0;      // 额外数据大小
  std::size_t FileAlignment = 0;      // 磁盘对齐值
  std::size_t SectionAlignment = 0;    // 内存对齐值
  std::size_t SectionNum = 0;      // 区块个数

这几个是默认存储的PE字段。可以用公有接口获取每个字段的值。

private:
  std::shared_ptr<const BYTE> FileData = nullptr;        // 文件数据指针
  std::shared_ptr<const IMAGE_DOS_HEADER> DosHeader = nullptr;        //IMAGE_DOS_HEADER指针
  std::shared_ptr<const IMAGE_NT_HEADERS> NtHeader = nullptr;  // IMAGE_NT_HEADERS指针

这几个指针也可以通过公有接口获取,为了防止文件信息被修改,返回的指针类型为指向常量的指针。如果需要一些冷门字段,可以使用该指针自行获取。

private:
// 区块表信息
  //
  //            存储结构
  // 区块名称:std::string  区块表:IMAGE_SECTION_HEADER
  // 区块名称:std::string  区块表:IMAGE_SECTION_HEADER
  // ……
  std::shared_ptr<const std::vector<std::pair<std::string, IMAGE_SECTION_HEADER>>> SecHeader = nullptr;

  // 输入表信息
  //
  //            存储结构
  // 动态链接库名称:std::string  输入函数名称:std::string
  //                输入函数名称:std::string    
  //                ……
  // 动态链接库名称:std::string  输入函数名称:std::string
  //                输入函数名称:std::string    
  //                ……
  // ……
  std::shared_ptr<const std::vector<std::pair<std::string, std::vector<std::string>>>> ImpFunc = nullptr; 
  
  // 输出表信息
  //
  //      存储结构
  // 输出函数名称:std::string
  // 输出函数名称:std::string
  // ……
  std::shared_ptr<const std::vector<std::string>> ExpFunc = nullptr;
  
  // 重定位表信息
  //
  //        存储结构
  // 内存页起始RVA:DWORD  重定位表项:WORD
  //            重定位表项:WORD
  //            ……
  // 内存页起始RVA:DWORD  重定位表项:WORD
  //            重定位表项:WORD
  //            ……
  // ……
  std::shared_ptr<const std::vector<std::pair<DWORD, std::vector<WORD>>>> Reloc = nullptr;

上面几个指针指向的容器用来存储输入表、输出表、区块表和重定位表信息。也都是常量指针。如果类提供的操作不能满足用户需求,可以自行获取指针读取信息。

类接口部分
构造函数:

  // 功能:
  //  打开文件
  // 输入参数:
  //  FilePath:文件路径
  // 其他:
  //  若文件打开失败,对象默认初始化
  explicit PEInfor(const std::string & FilePath);

  PEInfor() = default;

其他拷贝操作:
  PEInfor(const PEInfor &) = default;          // 拷贝构造
  PEInfor & operator=(const PEInfor &) = default;    // 拷贝赋值
  PEInfor(PEInfor &&) noexcept;            // 移动构造
  PEInfor & operator=(PEInfor &&) noexcept;      // 移动赋值
  ~PEInfor() = default;

文件读取:
  // 功能:
  //  打开文件
  // 输入参数:
  //  FilePath:文件路径
  // 返回值:
  //  true表示文件打开成功。
  // 其他:
  //  打开文件前不需要考虑当前对象的状态。若操作失败,对象保持原始状态
  bool OpenFile(const std::string & FilePath);

  // 功能:
  //  判断文件是否处于打开状态
  // 返回值:
  //  true表示文件处于打开状态
  bool Is_Open() const;

  // 功能:
  //  RVA转换文件偏移值
  // 输入参数:
  //  RVA:RVA值
  // 返回值:
  //  RVA对应的文件偏移,转换失败返回NULL
  DWORD RVAToOffset(const DWORD RVA) const;

获取常用字段:
  // 功能:
  //  获取文件的MD5值
  // 返回值:
  //  文件的MD5值
  std::string GetFileMD5() const;

  // 功能:
  //  获取文件数据指针
  // 返回值:
  //  指向文件数据的常量指针
  const BYTE* GetFileData() const;
  
  // 功能:
  //  获取IMAGE_DOS_HEADER指针
  // 返回值:
  //  指向IMAGE_DOS_HEADER的常量指针
  std::shared_ptr<const IMAGE_DOS_HEADER> GetDosHeader() const;

  // 功能:
  //  获取IMAGE_NT_HEADERS指针
  // 返回值:
  //  指向IMAGE_NT_HEADERS的常量指针
  std::shared_ptr<const IMAGE_NT_HEADERS> GetNtHeader() const;
剩余类似函数省略……

区块表相关操作:

  // 功能:
  //  获取所有区块的名称
  // 返回值:
  //  所有区块的名称
  std::vector<std::string> GetSecName() const;

  // 功能:
  //  获取指定区块表指针
  // 输入参数:
  //  SecIndex:区块索引
  // 返回值:
  //  指向指定区块表的常量指针或nullptr
  // 其他:
  //  若索引超出范围,抛出std::out_of_range异常
  const IMAGE_SECTION_HEADER* GetSecHeader(const std::size_t SecIndex) const;

  // 功能:
  //  获取指定区块表指针
  // 输入参数:
  //  SecName:区块名称
  // 返回值:
  //  指向指定区块表的常量指针或nullptr
  const IMAGE_SECTION_HEADER* GetSecHeader(const std::string & SecName) const;

  // 功能:
  //  获取区块信息
  // 返回值:
  //  指向区块信息存储区的常量指针
  // 其他:
  //            存储结构
  // 区块名称:std::string  区块表:IMAGE_SECTION_HEADER
  // 区块名称:std::string  区块表:IMAGE_SECTION_HEADER
  // ……
  std::shared_ptr<const std::vector<std::pair<std::string, IMAGE_SECTION_HEADER>>> GetSecHeader() const;

输入表相关操作:
  // 功能:
  //  获取导入的动态链接库列表
  // 返回值:
  //  导入的动态链接库列表
  std::vector<std::string> GetImpDll() const;

  // 功能:
  //  获取指定动态链接库的输入函数列表
  // 输入参数:
  //  DllName:动态链接库名称
  // 返回值:
  //  指定动态链接库的输入函数列表
  std::vector<std::string> GetImpFunc(const std::string & DllName) const;

  // 功能:
  //  获取输入表信息
  // 返回值:
  //  指向输入表信息存储区的常量指针
  // 其他:
  //            存储结构
  // 动态链接库名称:std::string  输入函数名称:std::string
  //            输入函数名称:std::string    
  //            ……
  // 动态链接库名称:std::string  输入函数名称:std::string
  //            输入函数名称:std::string    
  //            ……
  // ……
  std::shared_ptr<const std::vector<std::pair<std::string, std::vector<std::string>>>> GetImpFunc() const;

输出表相关操作:
  // 功能:
  //  获取输出的函数列表
  // 返回值:
  //  输出的函数列表
  std::vector<std::string> GetExpFunc() const;

重定位表相关操作:
  // 功能:
  //  获取重定位信息
  // 返回值:
  //  指向重定位信息存储区的常量指针
  // 其他:
  //        存储结构
  // 内存页起始RVA:DWORD  重定位表项:WORD
  //          重定位表项:WORD
  //          ……
  // 内存页起始RVA:DWORD  重定位表项:WORD
  //          重定位表项:WORD
  //          ……
  // ……
  std::shared_ptr<const std::vector<std::pair<DWORD, std::vector<WORD>>>> GetReloc() const;

具体细节还是看代码文件吧

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 3
支持
分享
最新回复 (7)
雪    币: 438
活跃值: (228)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
2
mark一下,学习一下C++11
2016-2-14 12:33
0
雪    币: 59
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
看懂一些,很好
2016-2-15 23:39
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
支持一下小白熊
2016-2-17 17:40
0
雪    币: 112
活跃值: (293)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
c++11引进lambda挺好玩的
2016-2-19 17:05
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
原来在学校学的都还给老师了。
2016-2-20 19:27
0
雪    币: 222
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
但是这个lambda表达式最好少用,据说很多人看不懂,不方便交流
2016-2-21 20:32
0
雪    币: 19
活跃值: (32)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
以后还会有c++14pe信息读取,, 还有c++17pe信息读取...
拉姆打如果真是让大部分人头晕目眩我想是不会成为世界主流计算机语言的特性的...
2016-2-22 07:59
0
游客
登录 | 注册 方可回帖
返回
//