第一次发贴,现在还是临时会员
这几天用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直播授课