文章总结: …
综合评分: 86
文章分类: …,score:0}。无markdown代码块,无解释,无额外文本。>>**起草Summary:**该文章介绍了如何使用C++实现一个PE解析器。它涵盖了解析DOS头、Rich头、NT头、节头、导入表和重定位表等结构。代码支持PE32和PE32+格式。文章提供了结构体定义和解析逻辑,并输出文件详情,包括节信息和导入函数。它还包含了指向GitHub仓库的链接。>>_草稿1:_本文介绍了使用C++实现PE32和PE32+文件解析器的过程,涵盖DOS头、Rich头、NT头、节头、导入表及重定位表的解析。文章详细定义了所需的数据结构,通过读取二进制文件并校验签名来判断架构,最终输出文件的各种元数据和依赖信息。代码示例完整,适合逆向工程初学者深入理解PE格式。(约140字符-有点长,需要删减)。>>_草稿2:_文章介绍了使用C++实现PE32及PE32+解析器的方法,涵盖DOS头、Rich头、NT头、节表、导入表与重定位表的解析。文中提供了完整的数据结构定义与解析逻辑,通过读取二进制数据并校验签名来识别文件架构,最终输出文件详细结构信息。代码示例有助于理解PE文件格式底层原理。(约128字符-长度合适,涵盖关键点)。>>_检查约束:_无双引号,无换行符。>>**起草Type:**相关类别:>>*逆向分析-这是关于解析二进制文件结构。>*二进制安全-PE格式是二进制安全的核心。>*代码审计-严格来说不是审计,而是理解二进制结构,通常属于该领域。>*安全工具-它是一个工具。>*安全开发-开发安全工具。>>选择:“逆向分析”是最强的。“二进制安全”很宽泛但正确。“安全工具”也适用。让我们从列表中精确匹配:列表:渗透测试,代码审计,应急响应,漏洞分析,威胁情报,恶意软件,安全意识,实战经验,SRC活动,软文广告,产品介绍,AI安全,二进制安全,CTF,WEB安全,红队,内网渗透,IoT安全,移动安全,安全建设,安全工具,技术标准,政策法规,供应链安全,漏洞预警,解决方案,数据安全,应用安全,网络安全,办公安全,终端安全,云安全,区块链安全,安全培训,安全运营,社会工程学,安全招聘,数据泄露,车联网安全,逆向分析,爬虫,免杀,安全开发,漏洞POC,安全大事件,娱乐吃瓜,其他。>>匹配:>>1.逆向分析-直接匹配。>2.二进制安全-广泛的类别。>3.安全工具-它是一个工具。>4.代码审计-较弱,但相关。>5.安全开发-开发工具。>>顺序:逆向分析,二进制安全,安全工具,安全开发。>>**起草Score:**>>*准确性(20):代码看起来基于标准PE定义是正确的。20/20。>*深度/洞见(35):它涵盖了Rich头和标准表,这是不错的,但它是一个基础实现。对于一篇教程来说,它没有提供高深的洞见。25/35。>*结构/可读性(20):组织良好(头文件、cpp文件、解释)。18/20。>*可操作性(15):代码可直接复制粘贴/编译。15/15。>*原创性(10):PE解析器是标准练习,但实现是作者自己的。8/10。>>总计:20+25+18+15+8=86。四舍五入到86。>>**优化JSON:**Summary:文章介绍了使用C++实现PE32及PE32+解析器的方法,涵盖DOS头、Rich头、NT头、节表、导入表与重定位表的解析。文中提供了完整的数据结构定义与解析逻辑,通过读取二进制数据并校验签名来识别文件架构,最终输出文件详细结构信息。代码示例有助于理解PE文件格式底层原理。Type:逆向分析,二进制安全,安全工具,安全开发Score:86>>**最终验证:**>>*Summary长度:\~130字符。很好。>*无双引号?已检查。>*无换行符?已检查。>*Type来自列表?是。>*最多5个类型?是(4个)。>*Score是整数?是。>>让我们把Summary稍微缩短一点,以确保其更接近100字符的要求(100+/-20%->80-120)。当前长度:\~130。缩短后:文章介绍使用C++实现PE32及PE32+解析器,涵盖DOS头、Rich头、NT头、节表、导入表与重定位表解析。文中提供完整结构体定义与解析逻辑,通过读取二进制数据校验签名识别架构并输出详情。该代码示例有助于深入理解PE文件格式底层原理。长度:115字符。完美。>>Type:逆向分析,二进制安全,安全工具,安全开发Score:86>>构建JSON。{summary:文章介绍使用C++实现PE32及PE32+解析器,涵盖DOS头、Rich头、NT头、节表、导入表与重定位表解析。文中提供完整结构体定义与解析逻辑,通过读取二进制数据校验签名识别架构并输出详情。该代码示例有助于深入理解PE文件格式底层原理。,type:逆向分析,二进制安全,安全工具,安全开发
深入学习PE文件结构系列五自己实现一个PE解析器
原创
ybdt ybdt
卡卡罗特取西经
2026年2月9日 21:33 吉林
0x1 前言
之前几篇文章讲述了Windows PE结构的各个部分,本篇文章会应用前文中的知识,借助C++实现一个PE Parser,可以解析PE32和PE32+,可以解析PE文件中的下列部分
- • DOS Header
- • Rich Header
- • NT Headers
- • Data Directory
- • Section Headers
- • Import Table
- • Relocation Table
0x2 PE Parser Readme
- 1. 以二进制形式读取一个PE文件
- 2. 通过校验DOS头中的Signature和NT头中的Signature这两个固定值,判断它是否有效的PE文件
- 3. 通过PE可选头中的字段判断它是32位PE还是64位PE
- 4. 解析下列结构
- • DOS Header
- • Rich Header
- • NT Headers
- • Section Headers
- • Import Data Directory
- • Relocation Data Directory
- 5. 输出下列信息
- • 文件名和类型
- • DOS头中的签名以及PE文件的实际起始地址
- • 富有头中的每一项
- • PE文件Signature
- • PE文件头中节的数量、PE可选头的大小
- • PE可选头中代码节的大小、初始化数据节的大小、未初始化数据节的大小、入口点的地址、代码节的起始RVA、期望的映像基址、节对齐、文件对齐、映像文件大小、各类头的大小
- • 数据目录中每一项的名字、RVA、大小
- • 节头中节的名字、节在文件中的起始地址和大小、节在内存中的起始地址和大小、节的属性
- • 导入表中每个DLL的名字、ILT和IAT、是否使用绑定导入、使用名称还是需要搜索函数、函数名称表的RVA
- • 重定位表中每个块对应的页面RVA、块大小、块项的数量
0x3 整理用到的结构体
代码实现中会用到定义在winnt.h中的类型、常量、结构体,整理后放到winntdef.h中,代码如下
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef unsigned long long QWORD;
typedef unsigned long LONG;
typedef __int64 LONGLONG;
typedef unsigned __int64 ULONGLONG;
#define ___IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define ___IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define ___IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
#define ___IMAGE_DOS_SIGNATURE 0x5A4D
#define ___IMAGE_DIRECTORY_ENTRY_EXPORT 0
#define ___IMAGE_DIRECTORY_ENTRY_IMPORT 1
#define ___IMAGE_DIRECTORY_ENTRY_RESOURCE 2
#define ___IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
#define ___IMAGE_DIRECTORY_ENTRY_SECURITY 4
#define ___IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define ___IMAGE_DIRECTORY_ENTRY_DEBUG 6
#define ___IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7
#define ___IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
#define ___IMAGE_DIRECTORY_ENTRY_TLS 9
#define ___IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
#define ___IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
#define ___IMAGE_DIRECTORY_ENTRY_IAT 12
#define ___IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
#define ___IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
#define ___IMAGE_SIZEOF_SHORT_NAME 8
#define ___IMAGE_SIZEOF_SECTION_HEADER 40
typedef struct __IMAGE_DOS_HEADER {
WORD e_magic;
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew;
} ___IMAGE_DOS_HEADER, * ___PIMAGE_DOS_HEADER;
typedef struct __IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} ___IMAGE_DATA_DIRECTORY, * ___PIMAGE_DATA_DIRECTORY;
typedef struct __IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
___IMAGE_DATA_DIRECTORY DataDirectory[___IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} ___IMAGE_OPTIONAL_HEADER32, * ___PIMAGE_OPTIONAL_HEADER32;
typedef struct __IMAGE_OPTIONAL_HEADER64 {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
ULONGLONG ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
ULONGLONG SizeOfStackReserve;
ULONGLONG SizeOfStackCommit;
ULONGLONG SizeOfHeapReserve;
ULONGLONG SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
___IMAGE_DATA_DIRECTORY DataDirectory[___IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} ___IMAGE_OPTIONAL_HEADER64, * ___PIMAGE_OPTIONAL_HEADER64;
typedef struct __IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} ___IMAGE_FILE_HEADER, * ___PIMAGE_FILE_HEADER;
typedef struct __IMAGE_NT_HEADERS64 {
DWORD Signature;
___IMAGE_FILE_HEADER FileHeader;
___IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} ___IMAGE_NT_HEADERS64, * ___PIMAGE_NT_HEADERS64;
typedef struct __IMAGE_NT_HEADERS {
DWORD Signature;
___IMAGE_FILE_HEADER FileHeader;
___IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} ___IMAGE_NT_HEADERS32, * ___PIMAGE_NT_HEADERS32;
typedef struct __IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics;
DWORD OriginalFirstThunk;
} DUMMYUNIONNAME;
DWORD TimeDateStamp;
DWORD ForwarderChain;
DWORD Name;
DWORD FirstThunk;
} ___IMAGE_IMPORT_DESCRIPTOR, * ___PIMAGE_IMPORT_DESCRIPTOR;
typedef struct __IMAGE_IMPORT_BY_NAME {
WORD Hint;
char Name[100];
} ___IMAGE_IMPORT_BY_NAME, * ___PIMAGE_IMPORT_BY_NAME;
typedef struct __IMAGE_BASE_RELOCATION {
DWORD VirtualAddress;
DWORD SizeOfBlock;
} ___IMAGE_BASE_RELOCATION, * ___PIMAGE_BASE_RELOCATION;
typedef struct __IMAGE_SECTION_HEADER {
BYTE Name[___IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} ___IMAGE_SECTION_HEADER, * ___PIMAGE_SECTION_HEADER;
0x4 自定义结构体
自定义一些结构体,方便解析PE文件,放到PEFILE_CUSTOM_STRUCTS.h中
#pragma once
#include "winntdef.h"
typedef struct __RICH_HEADER_INFO {
int size;
char* ptrToBuffer;
int entries;
} RICH_HEADER_INFO, * PRICH_HEADER_INFO;
typedef struct __RICH_HEADER_ENTRY {
WORD prodID;
WORD buildID;
DWORD useCount;
} RICH_HEADER_ENTRY, * PRICH_HEADER_ENTRY;
typedef struct __RICH_HEADER {
PRICH_HEADER_ENTRY entries;
} RICH_HEADER, * PRICH_HEADER;
typedef struct __ILT_ENTRY_64 {
union {
DWORD ORDINAL : 16;
DWORD HINT_NAME_TABE : 32;
} FIELD_2;
DWORD ORDINAL_NAME_FLAG : 1;
} ILT_ENTRY_64, * PILT_ENTRY_64;
typedef struct __ILT_ENTRY_32 {
union {
DWORD ORDINAL : 16;
DWORD HINT_NAME_TABE : 32;
DWORD ORDINAL_NAME_FLAG : 1;
} FIELD_1;
} ILT_ENTRY_32, * PILT_ENTRY_32;
typedef struct __BASE_RELOC_ENTRY {
WORD OFFSET : 12;
WORD TYPE : 4;
} BASE_RELOC_ENTRY, * PBASE_RELOC_ENTRY;
0x5 代码实现
整理逻辑是PE-Parser.cpp调用PEFILE,PEFILE根据PE文件是32位还是64位,传给PE32FILE还是PE64FILE,定义在.h文件中,实现在.cpp文件中
PE-Parser.cpp
#include <iostream>
#include <fstream>
#include "PEFILE.h"
int main(int argc, char* argv[])
{
if (argc != 2) {
printf("Usage: %s [path to executable]\n", argv[0]);
return 1;
}
FILE* PpeFile;
fopen_s(&PpeFile, argv[1], "rb");
if (PpeFile == NULL) {
printf("Can't open file.\n");
return 1;
}
if (INITPARSE(PpeFile) == 1) {
exit(1);
}
else if (INITPARSE(PpeFile) == 32) {
PE32FILE PeFile_1(argv[1], PpeFile);
PeFile_1.PrintInfo();
fclose(PpeFile);
exit(0);
}
else if (INITPARSE(PpeFile) == 64) {
PE64FILE PeFile_1(argv[1], PpeFile);
PeFile_1.PrintInfo();
fclose(PpeFile);
exit(0);
}
return 0;
}
PEFILE.h
#pragma once
#include "PE32FILE.h"
#include "PE64FILE.h"
int INITPARSE(FILE* PpeFile);
PEFILE.cpp
#include "PEFILE.h"
// INITIAL PARSE //
int INITPARSE(FILE* PpeFile) {
___IMAGE_DOS_HEADER TMP_DOS_HEADER;
WORD PEFILE_TYPE;
fseek(PpeFile, 0, SEEK_SET);
fread(&TMP_DOS_HEADER, sizeof(___IMAGE_DOS_HEADER), 1, PpeFile);
if (TMP_DOS_HEADER.e_magic != ___IMAGE_DOS_SIGNATURE) {
printf("Error. Not a PE file.\n");
return 1;
}
fseek(PpeFile, (TMP_DOS_HEADER.e_lfanew + sizeof(DWORD) + sizeof(___IMAGE_FILE_HEADER)), SEEK_SET);
fread(&PEFILE_TYPE, sizeof(WORD), 1, PpeFile);
if (PEFILE_TYPE == ___IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
return 32;
}
else if (PEFILE_TYPE == ___IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
return 64;
}
else {
printf("Error while parsing IMAGE_OPTIONAL_HEADER.Magic. Unknown Type.\n");
return 1;
}
}
PE32FILE.h
#pragma once
#include "winntdef.h"
#include "PEFILE_CUSTOM_STRUCTS.h"
#include <string>
class PE32FILE
{
public:
PE32FILE(char* _NAME, FILE* Ppefile);
void PrintInfo();
private:
char* NAME;
FILE* Ppefile;
int _import_directory_count, _import_directory_size;
int _basreloc_directory_count;
// HEADERS
___IMAGE_DOS_HEADER PEFILE_DOS_HEADER;
___IMAGE_NT_HEADERS32 PEFILE_NT_HEADERS;
// DOS HEADER
DWORD PEFILE_DOS_HEADER_EMAGIC;
LONG PEFILE_DOS_HEADER_LFANEW;
// RICH HEADER
RICH_HEADER_INFO PEFILE_RICH_HEADER_INFO;
RICH_HEADER PEFILE_RICH_HEADER;
// NT_HEADERS.Signature
DWORD PEFILE_NT_HEADERS_SIGNATURE;
// NT_HEADERS.FileHeader
WORD PEFILE_NT_HEADERS_FILE_HEADER_MACHINE;
WORD PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS;
WORD PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER;
// NT_HEADERS.OptionalHeader
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE;
ULONGLONG PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS;
___IMAGE_DATA_DIRECTORY PEFILE_EXPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_RESOURCE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_EXCEPTION_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_SECURITY_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BASERELOC_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DEBUG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_ARCHITECTURE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_GLOBALPTR_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_TLS_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_LOAD_CONFIG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BOUND_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IAT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DELAY_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_COM_DESCRIPTOR_DIRECTORY;
// SECTION HEADERS
___PIMAGE_SECTION_HEADER PEFILE_SECTION_HEADERS;
// IMPORT TABLE
___PIMAGE_IMPORT_DESCRIPTOR PEFILE_IMPORT_TABLE;
// BASE RELOCATION TABLE
___PIMAGE_BASE_RELOCATION PEFILE_BASERELOC_TABLE;
// FUNCTIONS
// ADDRESS RESOLVERS
int locate(DWORD VA);
DWORD resolve(DWORD VA, int index);
// PARSERS
void ParseFile();
void ParseDOSHeader();
void ParseNTHeaders();
void ParseSectionHeaders();
void ParseImportDirectory();
void ParseBaseReloc();
void ParseRichHeader();
// PRINT INFO
void PrintFileInfo();
void PrintDOSHeaderInfo();
void PrintRichHeaderInfo();
void PrintNTHeadersInfo();
void PrintSectionHeadersInfo();
void PrintImportTableInfo();
void PrintBaseRelocationsInfo();
};
PE32FILE.cpp
#include "PE32FILE.h"
// CONSTRUCTOR
PE32FILE::PE32FILE(char* _NAME, FILE* _Ppefile) {
NAME = _NAME;
Ppefile = _Ppefile;
ParseFile();
}
// ADDRESS RESOLVERS
int PE32FILE::locate(DWORD VA) {
int index;
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
if (VA >= PEFILE_SECTION_HEADERS[i].VirtualAddress
&& VA < (PEFILE_SECTION_HEADERS[i].VirtualAddress + PEFILE_SECTION_HEADERS[i].Misc.VirtualSize)) {
index = i;
break;
}
}
return index;
}
DWORD PE32FILE::resolve(DWORD VA, int index) {
return (VA - PEFILE_SECTION_HEADERS[index].VirtualAddress) + PEFILE_SECTION_HEADERS[index].PointerToRawData;
}
// PARSERS
void PE32FILE::ParseDOSHeader() {
fseek(Ppefile, 0, SEEK_SET);
fread(&PEFILE_DOS_HEADER, sizeof(___IMAGE_DOS_HEADER), 1, Ppefile);
PEFILE_DOS_HEADER_EMAGIC = PEFILE_DOS_HEADER.e_magic;
PEFILE_DOS_HEADER_LFANEW = PEFILE_DOS_HEADER.e_lfanew;
}
void PE32FILE::ParseNTHeaders() {
fseek(Ppefile, PEFILE_DOS_HEADER.e_lfanew, SEEK_SET);
fread(&PEFILE_NT_HEADERS, sizeof(PEFILE_NT_HEADERS), 1, Ppefile);
PEFILE_NT_HEADERS_SIGNATURE = PEFILE_NT_HEADERS.Signature;
PEFILE_NT_HEADERS_FILE_HEADER_MACHINE = PEFILE_NT_HEADERS.FileHeader.Machine;
PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS = PEFILE_NT_HEADERS.FileHeader.NumberOfSections;
PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER = PEFILE_NT_HEADERS.FileHeader.SizeOfOptionalHeader;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC = PEFILE_NT_HEADERS.OptionalHeader.Magic;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfInitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfUninitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT = PEFILE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.BaseOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE = PEFILE_NT_HEADERS.OptionalHeader.ImageBase;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.SectionAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.FileAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfImage;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS = PEFILE_NT_HEADERS.OptionalHeader.SizeOfHeaders;
PEFILE_EXPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXPORT];
PEFILE_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IMPORT];
PEFILE_RESOURCE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_RESOURCE];
PEFILE_EXCEPTION_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXCEPTION];
PEFILE_SECURITY_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_SECURITY];
PEFILE_BASERELOC_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BASERELOC];
PEFILE_DEBUG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DEBUG];
PEFILE_ARCHITECTURE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_ARCHITECTURE];
PEFILE_GLOBALPTR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_GLOBALPTR];
PEFILE_TLS_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_TLS];
PEFILE_LOAD_CONFIG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
PEFILE_BOUND_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
PEFILE_IAT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IAT];
PEFILE_DELAY_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
PEFILE_COM_DESCRIPTOR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
}
void PE32FILE::ParseSectionHeaders() {
PEFILE_SECTION_HEADERS = new ___IMAGE_SECTION_HEADER[PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS];
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
int offset = (PEFILE_DOS_HEADER.e_lfanew + sizeof(PEFILE_NT_HEADERS)) + (i * ___IMAGE_SIZEOF_SECTION_HEADER);
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_SECTION_HEADERS[i], ___IMAGE_SIZEOF_SECTION_HEADER, 1, Ppefile);
}
}
void PE32FILE::ParseImportDirectory() {
DWORD _import_directory_address = resolve(PEFILE_IMPORT_DIRECTORY.VirtualAddress, locate(PEFILE_IMPORT_DIRECTORY.VirtualAddress));
_import_directory_count = 0;
while (true) {
___IMAGE_IMPORT_DESCRIPTOR tmp;
int offset = (_import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);
if (tmp.Name == 0x00000000 && tmp.FirstThunk == 0x00000000) {
_import_directory_count -= 1;
_import_directory_size = _import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR);
break;
}
_import_directory_count++;
}
PEFILE_IMPORT_TABLE = new ___IMAGE_IMPORT_DESCRIPTOR[_import_directory_count];
for (int i = 0; i < _import_directory_count; i++) {
int offset = (i * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_IMPORT_TABLE[i], sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);
}
}
void PE32FILE::ParseBaseReloc() {
DWORD _basereloc_directory_address = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
_basreloc_directory_count = 0;
int _basereloc_size_counter = 0;
while (true) {
___IMAGE_BASE_RELOCATION tmp;
int offset = (_basereloc_size_counter + _basereloc_directory_address);
fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);
if (tmp.VirtualAddress == 0x00000000 &&
tmp.SizeOfBlock == 0x00000000) {
break;
}
_basreloc_directory_count++;
_basereloc_size_counter += tmp.SizeOfBlock;
}
PEFILE_BASERELOC_TABLE = new ___IMAGE_BASE_RELOCATION[_basreloc_directory_count];
_basereloc_size_counter = 0;
for (int i = 0; i < _basreloc_directory_count; i++) {
int offset = _basereloc_directory_address + _basereloc_size_counter;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_BASERELOC_TABLE[i], sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);
_basereloc_size_counter += PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
}
}
void PE32FILE::ParseRichHeader() {
char* dataPtr = new char[PEFILE_DOS_HEADER_LFANEW];
fseek(Ppefile, 0, SEEK_SET);
fread(dataPtr, PEFILE_DOS_HEADER_LFANEW, 1, Ppefile);
int index_ = 0;
for (int i = 0; i <= PEFILE_DOS_HEADER_LFANEW; i++) {
if (dataPtr[i] == 0x52 && dataPtr[i + 1] == 0x69) {
index_ = i;
break;
}
}
if (index_ == 0) {
printf("Error while parsing Rich Header.");
PEFILE_RICH_HEADER_INFO.entries = 0;
return;
}
char key[4];
memcpy(key, dataPtr + (index_ + 4), 4);
int indexpointer = index_ - 4;
int RichHeaderSize = 0;
while (true) {
char tmpchar[4];
memcpy(tmpchar, dataPtr + indexpointer, 4);
for (int i = 0; i < 4; i++) {
tmpchar[i] = tmpchar[i] ^ key[i];
}
indexpointer -= 4;
RichHeaderSize += 4;
if (tmpchar[1] = 0x61 && tmpchar[0] == 0x44) {
break;
}
}
char* RichHeaderPtr = new char[RichHeaderSize];
memcpy(RichHeaderPtr, dataPtr + (index_ - RichHeaderSize), RichHeaderSize);
for (int i = 0; i < RichHeaderSize; i += 4) {
for (int x = 0; x < 4; x++) {
RichHeaderPtr[i + x] = RichHeaderPtr[i + x] ^ key[x];
}
}
PEFILE_RICH_HEADER_INFO.size = RichHeaderSize;
PEFILE_RICH_HEADER_INFO.ptrToBuffer = RichHeaderPtr;
PEFILE_RICH_HEADER_INFO.entries = (RichHeaderSize - 16) / 8;
delete[] dataPtr;
PEFILE_RICH_HEADER.entries = new RICH_HEADER_ENTRY[PEFILE_RICH_HEADER_INFO.entries];
for (int i = 16; i < RichHeaderSize; i += 8) {
WORD PRODID = (uint16_t)((unsigned char)RichHeaderPtr[i + 3] << 8) | (unsigned char)RichHeaderPtr[i + 2];
WORD BUILDID = (uint16_t)((unsigned char)RichHeaderPtr[i + 1] << 8) | (unsigned char)RichHeaderPtr[i];
DWORD USECOUNT = (uint32_t)((unsigned char)RichHeaderPtr[i + 7] << 24) | (unsigned char)RichHeaderPtr[i + 6] << 16 | (unsigned char)RichHeaderPtr[i + 5] << 8 | (unsigned char)RichHeaderPtr[i + 4];
PEFILE_RICH_HEADER.entries[(i / 8) - 2] = {
PRODID,
BUILDID,
USECOUNT
};
if (i + 8 >= RichHeaderSize) {
PEFILE_RICH_HEADER.entries[(i / 8) - 1] = { 0x0000, 0x0000, 0x00000000 };
}
}
delete[] PEFILE_RICH_HEADER_INFO.ptrToBuffer;
}
// PRINT INFO
void PE32FILE::PrintFileInfo() {
printf(" FILE: %s\n", NAME);
printf(" TYPE: 0x%X (PE32)\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);
}
void PE32FILE::PrintDOSHeaderInfo() {
printf(" DOS HEADER:\n");
printf(" -----------\n\n");
printf(" Magic: 0x%X\n", PEFILE_DOS_HEADER_EMAGIC);
printf(" File address of new exe header: 0x%X\n", PEFILE_DOS_HEADER_LFANEW);
}
void PE32FILE::PrintRichHeaderInfo() {
printf(" RICH HEADER:\n");
printf(" ------------\n\n");
for (int i = 0; i < PEFILE_RICH_HEADER_INFO.entries; i++) {
printf(" 0x%X 0x%X 0x%X: %d.%d.%d\n",
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount,
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount);
}
}
void PE32FILE::PrintNTHeadersInfo() {
printf(" NT HEADERS:\n");
printf(" -----------\n\n");
printf(" PE Signature: 0x%X\n", PEFILE_NT_HEADERS_SIGNATURE);
printf("\n File Header:\n\n");
printf(" Machine: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_MACHINE);
printf(" Number of sections: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS);
printf(" Size of optional header: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER);
printf("\n Optional Header:\n\n");
printf(" Magic: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);
printf(" Size of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE);
printf(" Size of initialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA);
printf(" Size of uninitialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA);
printf(" Address of entry point: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT);
printf(" RVA of start of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE);
printf(" Desired image base: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE);
printf(" Section alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT);
printf(" File alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT);
printf(" Size of image: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE);
printf(" Size of headers: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS);
printf("\n Data Directories:\n");
printf("\n * Export Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXPORT_DIRECTORY.Size);
printf("\n * Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IMPORT_DIRECTORY.Size);
printf("\n * Resource Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.Size);
printf("\n * Exception Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.Size);
printf("\n * Security Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_SECURITY_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_SECURITY_DIRECTORY.Size);
printf("\n * Base Relocation Table:\n");
printf(" RVA: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.Size);
printf("\n * Debug Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_DEBUG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DEBUG_DIRECTORY.Size);
printf("\n * Architecture Specific Data:\n");
printf(" RVA: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.Size);
printf("\n * RVA of GlobalPtr:\n");
printf(" RVA: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.Size);
printf("\n * TLS Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_TLS_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_TLS_DIRECTORY.Size);
printf("\n * Load Configuration Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.Size);
printf("\n * Bound Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.Size);
printf("\n * Import Address Table:\n");
printf(" RVA: 0x%X\n", PEFILE_IAT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IAT_DIRECTORY.Size);
printf("\n * Delay Load Import Descriptors:\n");
printf(" RVA: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.Size);
printf("\n * COM Runtime Descriptor:\n");
printf(" RVA: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.Size);
}
void PE32FILE::PrintSectionHeadersInfo() {
printf(" SECTION HEADERS:\n");
printf(" ----------------\n\n");
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
printf(" * %.8s:\n", PEFILE_SECTION_HEADERS[i].Name);
printf(" VirtualAddress: 0x%X\n", PEFILE_SECTION_HEADERS[i].VirtualAddress);
printf(" VirtualSize: 0x%X\n", PEFILE_SECTION_HEADERS[i].Misc.VirtualSize);
printf(" PointerToRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].PointerToRawData);
printf(" SizeOfRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].SizeOfRawData);
printf(" Characteristics: 0x%X\n\n", PEFILE_SECTION_HEADERS[i].Characteristics);
}
}
void PE32FILE::PrintImportTableInfo() {
printf(" IMPORT TABLE:\n");
printf(" ----------------\n\n");
for (int i = 0; i < _import_directory_count; i++) {
DWORD NameAddr = resolve(PEFILE_IMPORT_TABLE[i].Name, locate(PEFILE_IMPORT_TABLE[i].Name));
int NameSize = 0;
while (true) {
char tmp;
fseek(Ppefile, (NameAddr + NameSize), SEEK_SET);
fread(&tmp, sizeof(char), 1, Ppefile);
if (tmp == 0x00) {
break;
}
NameSize++;
}
char* Name = new char[NameSize + 2];
fseek(Ppefile, NameAddr, SEEK_SET);
fread(Name, (NameSize * sizeof(char)) + 1, 1, Ppefile);
printf(" * %s:\n", Name);
delete[] Name;
printf(" ILT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk);
printf(" IAT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].FirstThunk);
if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == 0) {
printf(" Bound: FALSE\n");
}
else if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == -1) {
printf(" Bound: TRUE\n");
}
printf("\n");
DWORD ILTAddr = resolve(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk, locate(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk));
int entrycounter = 0;
while (true) {
ILT_ENTRY_32 entry;
fseek(Ppefile, (ILTAddr + (entrycounter * sizeof(DWORD))), SEEK_SET);
fread(&entry, sizeof(ILT_ENTRY_32), 1, Ppefile);
BYTE flag = entry.FIELD_1.ORDINAL_NAME_FLAG;
DWORD HintRVA = 0x0;
WORD ordinal = 0x0;
if (flag == 0x0) {
HintRVA = entry.FIELD_1.HINT_NAME_TABE;
}
else if (flag == 0x01) {
ordinal = entry.FIELD_1.ORDINAL;
}
if (flag == 0x0 && HintRVA == 0x0 && ordinal == 0x0) {
break;
}
printf("\n Entry:\n");
if (flag == 0x0) {
___IMAGE_IMPORT_BY_NAME hint;
DWORD HintAddr = resolve(HintRVA, locate(HintRVA));
fseek(Ppefile, HintAddr, SEEK_SET);
fread(&hint, sizeof(___IMAGE_IMPORT_BY_NAME), 1, Ppefile);
printf(" Name: %s\n", hint.Name);
printf(" Hint RVA: 0x%X\n", HintRVA);
printf(" Hint: 0x%X\n", hint.Hint);
}
else if (flag == 1) {
printf(" Ordinal: 0x%X\n", ordinal);
}
entrycounter++;
}
printf("\n ----------------------\n\n");
}
}
void PE32FILE::PrintBaseRelocationsInfo() {
printf(" BASE RELOCATIONS TABLE:\n");
printf(" -----------------------\n");
int szCounter = sizeof(___IMAGE_BASE_RELOCATION);
for (int i = 0; i < _basreloc_directory_count; i++) {
DWORD PAGERVA, BLOCKSIZE, BASE_RELOC_ADDR;
int ENTRIES;
BASE_RELOC_ADDR = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
PAGERVA = PEFILE_BASERELOC_TABLE[i].VirtualAddress;
BLOCKSIZE = PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
ENTRIES = (BLOCKSIZE - sizeof(___IMAGE_BASE_RELOCATION)) / sizeof(WORD);
printf("\n Block 0x%X: \n", i);
printf(" Page RVA: 0x%X\n", PAGERVA);
printf(" Block size: 0x%X\n", BLOCKSIZE);
printf(" Number of entries: 0x%X\n", ENTRIES);
printf("\n Entries:\n");
for (int i = 0; i < ENTRIES; i++) {
BASE_RELOC_ENTRY entry;
int offset = (BASE_RELOC_ADDR + szCounter + (i * sizeof(WORD)));
fseek(Ppefile, offset, SEEK_SET);
fread(&entry, sizeof(WORD), 1, Ppefile);
printf("\n * Value: 0x%X\n", entry);
printf(" Relocation Type: 0x%X\n", entry.TYPE);
printf(" Offset: 0x%X\n", entry.OFFSET);
}
printf("\n ----------------------\n\n");
szCounter += BLOCKSIZE;
}
}
// MAIN
void PE32FILE::ParseFile() {
// PARSE DOS HEADER
ParseDOSHeader();
// PARSE RICH HEADER
ParseRichHeader();
//PARSE NT HEADERS
ParseNTHeaders();
// PARSE SECTION HEADERS
ParseSectionHeaders();
// PARSE IMPORT DIRECTORY
ParseImportDirectory();
// PARSE BASE RELOCATIONS
ParseBaseReloc();
}
void PE32FILE::PrintInfo() {
printf("\n\n");
PrintFileInfo();
printf("\n ----------------------------------\n\n");
PrintDOSHeaderInfo();
printf("\n ----------------------------------\n\n");
PrintRichHeaderInfo();
printf("\n ----------------------------------\n\n");
PrintNTHeadersInfo();
printf("\n ----------------------------------\n\n");
PrintSectionHeadersInfo();
printf("\n ----------------------------------\n\n");
PrintImportTableInfo();
printf("\n ----------------------------------\n\n");
PrintBaseRelocationsInfo();
printf("\n ----------------------------------\n\n");
return;
}
PE64FILE.h
#pragma once
#include "winntdef.h"
#include "PEFILE_CUSTOM_STRUCTS.h"
#include <string>
class PE64FILE
{
public:
PE64FILE(char* _NAME, FILE* Ppefile);
void PrintInfo();
private:
char* NAME;
FILE* Ppefile;
int _import_directory_count, _import_directory_size;
int _basreloc_directory_count;
// HEADERS
___IMAGE_DOS_HEADER PEFILE_DOS_HEADER;
___IMAGE_NT_HEADERS64 PEFILE_NT_HEADERS;
// DOS HEADER
DWORD PEFILE_DOS_HEADER_EMAGIC;
LONG PEFILE_DOS_HEADER_LFANEW;
// RICH HEADER
RICH_HEADER_INFO PEFILE_RICH_HEADER_INFO;
RICH_HEADER PEFILE_RICH_HEADER;
// NT_HEADERS.Signature
DWORD PEFILE_NT_HEADERS_SIGNATURE;
// NT_HEADERS.FileHeader
WORD PEFILE_NT_HEADERS_FILE_HEADER_MACHINE;
WORD PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS;
WORD PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER;
// NT_HEADERS.OptionalHeader
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE;
ULONGLONG PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE;
DWORD PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS;
___IMAGE_DATA_DIRECTORY PEFILE_EXPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_RESOURCE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_EXCEPTION_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_SECURITY_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BASERELOC_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DEBUG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_ARCHITECTURE_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_GLOBALPTR_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_TLS_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_LOAD_CONFIG_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_BOUND_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_IAT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_DELAY_IMPORT_DIRECTORY;
___IMAGE_DATA_DIRECTORY PEFILE_COM_DESCRIPTOR_DIRECTORY;
// SECTION HEADERS
___PIMAGE_SECTION_HEADER PEFILE_SECTION_HEADERS;
// IMPORT TABLE
___PIMAGE_IMPORT_DESCRIPTOR PEFILE_IMPORT_TABLE;
// BASE RELOCATION TABLE
___PIMAGE_BASE_RELOCATION PEFILE_BASERELOC_TABLE;
// FUNCTIONS
// ADDRESS RESOLVERS
int locate(DWORD VA);
DWORD resolve(DWORD VA, int index);
// PARSERS
void ParseFile();
void ParseDOSHeader();
void ParseNTHeaders();
void ParseSectionHeaders();
void ParseImportDirectory();
void ParseBaseReloc();
void ParseRichHeader();
// PRINT INFO
void PrintFileInfo();
void PrintDOSHeaderInfo();
void PrintRichHeaderInfo();
void PrintNTHeadersInfo();
void PrintSectionHeadersInfo();
void PrintImportTableInfo();
void PrintBaseRelocationsInfo();
};
PE64FILE.cpp
#include "PE64FILE.h"
// CONSTRUCTOR
PE64FILE::PE64FILE(char* _NAME, FILE* _Ppefile) {
NAME = _NAME;
Ppefile = _Ppefile;
ParseFile();
}
// ADDRESS RESOLVERS
int PE64FILE::locate(DWORD VA) {
int index;
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
if (VA >= PEFILE_SECTION_HEADERS[i].VirtualAddress
&& VA < (PEFILE_SECTION_HEADERS[i].VirtualAddress + PEFILE_SECTION_HEADERS[i].Misc.VirtualSize)) {
index = i;
break;
}
}
return index;
}
DWORD PE64FILE::resolve(DWORD VA, int index) {
return (VA - PEFILE_SECTION_HEADERS[index].VirtualAddress) + PEFILE_SECTION_HEADERS[index].PointerToRawData;
}
// PARSERS
void PE64FILE::ParseDOSHeader() {
fseek(Ppefile, 0, SEEK_SET);
fread(&PEFILE_DOS_HEADER, sizeof(___IMAGE_DOS_HEADER), 1, Ppefile);
PEFILE_DOS_HEADER_EMAGIC = PEFILE_DOS_HEADER.e_magic;
PEFILE_DOS_HEADER_LFANEW = PEFILE_DOS_HEADER.e_lfanew;
}
void PE64FILE::ParseNTHeaders() {
fseek(Ppefile, PEFILE_DOS_HEADER.e_lfanew, SEEK_SET);
fread(&PEFILE_NT_HEADERS, sizeof(PEFILE_NT_HEADERS), 1, Ppefile);
PEFILE_NT_HEADERS_SIGNATURE = PEFILE_NT_HEADERS.Signature;
PEFILE_NT_HEADERS_FILE_HEADER_MACHINE = PEFILE_NT_HEADERS.FileHeader.Machine;
PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS = PEFILE_NT_HEADERS.FileHeader.NumberOfSections;
PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER = PEFILE_NT_HEADERS.FileHeader.SizeOfOptionalHeader;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC = PEFILE_NT_HEADERS.OptionalHeader.Magic;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfInitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA = PEFILE_NT_HEADERS.OptionalHeader.SizeOfUninitializedData;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT = PEFILE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE = PEFILE_NT_HEADERS.OptionalHeader.BaseOfCode;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE = PEFILE_NT_HEADERS.OptionalHeader.ImageBase;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.SectionAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT = PEFILE_NT_HEADERS.OptionalHeader.FileAlignment;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE = PEFILE_NT_HEADERS.OptionalHeader.SizeOfImage;
PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS = PEFILE_NT_HEADERS.OptionalHeader.SizeOfHeaders;
PEFILE_EXPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXPORT];
PEFILE_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IMPORT];
PEFILE_RESOURCE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_RESOURCE];
PEFILE_EXCEPTION_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_EXCEPTION];
PEFILE_SECURITY_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_SECURITY];
PEFILE_BASERELOC_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BASERELOC];
PEFILE_DEBUG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DEBUG];
PEFILE_ARCHITECTURE_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_ARCHITECTURE];
PEFILE_GLOBALPTR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_GLOBALPTR];
PEFILE_TLS_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_TLS];
PEFILE_LOAD_CONFIG_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG];
PEFILE_BOUND_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT];
PEFILE_IAT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_IAT];
PEFILE_DELAY_IMPORT_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];
PEFILE_COM_DESCRIPTOR_DIRECTORY = PEFILE_NT_HEADERS.OptionalHeader.DataDirectory[___IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
}
void PE64FILE::ParseSectionHeaders() {
PEFILE_SECTION_HEADERS = new ___IMAGE_SECTION_HEADER[PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS];
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
int offset = (PEFILE_DOS_HEADER.e_lfanew + sizeof(PEFILE_NT_HEADERS)) + (i * ___IMAGE_SIZEOF_SECTION_HEADER);
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_SECTION_HEADERS[i], ___IMAGE_SIZEOF_SECTION_HEADER, 1, Ppefile);
}
}
void PE64FILE::ParseImportDirectory() {
DWORD _import_directory_address = resolve(PEFILE_IMPORT_DIRECTORY.VirtualAddress, locate(PEFILE_IMPORT_DIRECTORY.VirtualAddress));
_import_directory_count = 0;
while (true) {
___IMAGE_IMPORT_DESCRIPTOR tmp;
int offset = (_import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);
if (tmp.Name == 0x00000000 && tmp.FirstThunk == 0x00000000) {
_import_directory_count -= 1;
_import_directory_size = _import_directory_count * sizeof(___IMAGE_IMPORT_DESCRIPTOR);
break;
}
_import_directory_count++;
}
PEFILE_IMPORT_TABLE = new ___IMAGE_IMPORT_DESCRIPTOR[_import_directory_count];
for (int i = 0; i < _import_directory_count; i++) {
int offset = (i * sizeof(___IMAGE_IMPORT_DESCRIPTOR)) + _import_directory_address;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_IMPORT_TABLE[i], sizeof(___IMAGE_IMPORT_DESCRIPTOR), 1, Ppefile);
}
}
void PE64FILE::ParseBaseReloc() {
DWORD _basereloc_directory_address = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
_basreloc_directory_count = 0;
int _basereloc_size_counter = 0;
while (true) {
___IMAGE_BASE_RELOCATION tmp;
int offset = (_basereloc_size_counter + _basereloc_directory_address);
fseek(Ppefile, offset, SEEK_SET);
fread(&tmp, sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);
if (tmp.VirtualAddress == 0x00000000 &&
tmp.SizeOfBlock == 0x00000000) {
break;
}
_basreloc_directory_count++;
_basereloc_size_counter += tmp.SizeOfBlock;
}
PEFILE_BASERELOC_TABLE = new ___IMAGE_BASE_RELOCATION[_basreloc_directory_count];
_basereloc_size_counter = 0;
for (int i = 0; i < _basreloc_directory_count; i++) {
int offset = _basereloc_directory_address + _basereloc_size_counter;
fseek(Ppefile, offset, SEEK_SET);
fread(&PEFILE_BASERELOC_TABLE[i], sizeof(___IMAGE_BASE_RELOCATION), 1, Ppefile);
_basereloc_size_counter += PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
}
}
void PE64FILE::ParseRichHeader() {
char* dataPtr = new char[PEFILE_DOS_HEADER_LFANEW];
fseek(Ppefile, 0, SEEK_SET);
fread(dataPtr, PEFILE_DOS_HEADER_LFANEW, 1, Ppefile);
int index_ = 0;
for (int i = 0; i <= PEFILE_DOS_HEADER_LFANEW; i++) {
if (dataPtr[i] == 0x52 && dataPtr[i + 1] == 0x69) {
index_ = i;
break;
}
}
if (index_ == 0) {
printf("Error while parsing Rich Header.");
PEFILE_RICH_HEADER_INFO.entries = 0;
return;
}
char key[4];
memcpy(key, dataPtr + (index_ + 4), 4);
int indexpointer = index_ - 4;
int RichHeaderSize = 0;
while (true) {
char tmpchar[4];
memcpy(tmpchar, dataPtr + indexpointer, 4);
for (int i = 0; i < 4; i++) {
tmpchar[i] = tmpchar[i] ^ key[i];
}
indexpointer -= 4;
RichHeaderSize += 4;
if (tmpchar[1] = 0x61 && tmpchar[0] == 0x44) {
break;
}
}
char* RichHeaderPtr = new char[RichHeaderSize];
memcpy(RichHeaderPtr, dataPtr + (index_ - RichHeaderSize), RichHeaderSize);
for (int i = 0; i < RichHeaderSize; i += 4) {
for (int x = 0; x < 4; x++) {
RichHeaderPtr[i + x] = RichHeaderPtr[i + x] ^ key[x];
}
}
PEFILE_RICH_HEADER_INFO.size = RichHeaderSize;
PEFILE_RICH_HEADER_INFO.ptrToBuffer = RichHeaderPtr;
PEFILE_RICH_HEADER_INFO.entries = (RichHeaderSize - 16) / 8;
delete[] dataPtr;
PEFILE_RICH_HEADER.entries = new RICH_HEADER_ENTRY[PEFILE_RICH_HEADER_INFO.entries];
for (int i = 16; i < RichHeaderSize; i += 8) {
WORD PRODID = (uint16_t)((unsigned char)RichHeaderPtr[i + 3] << 8) | (unsigned char)RichHeaderPtr[i + 2];
WORD BUILDID = (uint16_t)((unsigned char)RichHeaderPtr[i + 1] << 8) | (unsigned char)RichHeaderPtr[i];
DWORD USECOUNT = (uint32_t)((unsigned char)RichHeaderPtr[i + 7] << 24) | (unsigned char)RichHeaderPtr[i + 6] << 16 | (unsigned char)RichHeaderPtr[i + 5] << 8 | (unsigned char)RichHeaderPtr[i + 4];
PEFILE_RICH_HEADER.entries[(i / 8) - 2] = {
PRODID,
BUILDID,
USECOUNT
};
if (i + 8 >= RichHeaderSize) {
PEFILE_RICH_HEADER.entries[(i / 8) - 1] = { 0x0000, 0x0000, 0x00000000 };
}
}
delete[] PEFILE_RICH_HEADER_INFO.ptrToBuffer;
}
// PRINT INFO
void PE64FILE::PrintFileInfo() {
printf(" FILE: %s\n", NAME);
printf(" TYPE: 0x%X (PE32+)\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);
}
void PE64FILE::PrintDOSHeaderInfo() {
printf(" DOS HEADER:\n");
printf(" -----------\n\n");
printf(" Magic: 0x%X\n", PEFILE_DOS_HEADER_EMAGIC);
printf(" File address of new exe header: 0x%X\n", PEFILE_DOS_HEADER_LFANEW);
}
void PE64FILE::PrintRichHeaderInfo() {
printf(" RICH HEADER:\n");
printf(" ------------\n\n");
for (int i = 0; i < PEFILE_RICH_HEADER_INFO.entries; i++) {
printf(" 0x%X 0x%X 0x%X: %d.%d.%d\n",
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount,
PEFILE_RICH_HEADER.entries[i].buildID,
PEFILE_RICH_HEADER.entries[i].prodID,
PEFILE_RICH_HEADER.entries[i].useCount);
}
}
void PE64FILE::PrintNTHeadersInfo() {
printf(" NT HEADERS:\n");
printf(" -----------\n\n");
printf(" PE Signature: 0x%X\n", PEFILE_NT_HEADERS_SIGNATURE);
printf("\n File Header:\n\n");
printf(" Machine: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_MACHINE);
printf(" Number of sections: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS);
printf(" Size of optional header: 0x%X\n", PEFILE_NT_HEADERS_FILE_HEADER_SIZEOF_OPTIONAL_HEADER);
printf("\n Optional Header:\n\n");
printf(" Magic: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_MAGIC);
printf(" Size of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_CODE);
printf(" Size of initialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_INITIALIZED_DATA);
printf(" Size of uninitialized data: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_UNINITIALIZED_DATA);
printf(" Address of entry point: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_ADDRESSOF_ENTRYPOINT);
printf(" RVA of start of code section: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_BASEOF_CODE);
printf(" Desired image base: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_IMAGEBASE);
printf(" Section alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SECTION_ALIGNMENT);
printf(" File alignment: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_FILE_ALIGNMENT);
printf(" Size of image: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_IMAGE);
printf(" Size of headers: 0x%X\n", PEFILE_NT_HEADERS_OPTIONAL_HEADER_SIZEOF_HEADERS);
printf("\n Data Directories:\n");
printf("\n * Export Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXPORT_DIRECTORY.Size);
printf("\n * Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IMPORT_DIRECTORY.Size);
printf("\n * Resource Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_RESOURCE_DIRECTORY.Size);
printf("\n * Exception Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_EXCEPTION_DIRECTORY.Size);
printf("\n * Security Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_SECURITY_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_SECURITY_DIRECTORY.Size);
printf("\n * Base Relocation Table:\n");
printf(" RVA: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BASERELOC_DIRECTORY.Size);
printf("\n * Debug Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_DEBUG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DEBUG_DIRECTORY.Size);
printf("\n * Architecture Specific Data:\n");
printf(" RVA: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_ARCHITECTURE_DIRECTORY.Size);
printf("\n * RVA of GlobalPtr:\n");
printf(" RVA: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_GLOBALPTR_DIRECTORY.Size);
printf("\n * TLS Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_TLS_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_TLS_DIRECTORY.Size);
printf("\n * Load Configuration Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_LOAD_CONFIG_DIRECTORY.Size);
printf("\n * Bound Import Directory:\n");
printf(" RVA: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_BOUND_IMPORT_DIRECTORY.Size);
printf("\n * Import Address Table:\n");
printf(" RVA: 0x%X\n", PEFILE_IAT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_IAT_DIRECTORY.Size);
printf("\n * Delay Load Import Descriptors:\n");
printf(" RVA: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_DELAY_IMPORT_DIRECTORY.Size);
printf("\n * COM Runtime Descriptor:\n");
printf(" RVA: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.VirtualAddress);
printf(" Size: 0x%X\n", PEFILE_COM_DESCRIPTOR_DIRECTORY.Size);
}
void PE64FILE::PrintSectionHeadersInfo() {
printf(" SECTION HEADERS:\n");
printf(" ----------------\n\n");
for (int i = 0; i < PEFILE_NT_HEADERS_FILE_HEADER_NUMBER0F_SECTIONS; i++) {
printf(" * %.8s:\n", PEFILE_SECTION_HEADERS[i].Name);
printf(" VirtualAddress: 0x%X\n", PEFILE_SECTION_HEADERS[i].VirtualAddress);
printf(" VirtualSize: 0x%X\n", PEFILE_SECTION_HEADERS[i].Misc.VirtualSize);
printf(" PointerToRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].PointerToRawData);
printf(" SizeOfRawData: 0x%X\n", PEFILE_SECTION_HEADERS[i].SizeOfRawData);
printf(" Characteristics: 0x%X\n\n", PEFILE_SECTION_HEADERS[i].Characteristics);
}
}
void PE64FILE::PrintImportTableInfo() {
printf(" IMPORT TABLE:\n");
printf(" ----------------\n\n");
for (int i = 0; i < _import_directory_count; i++) {
DWORD NameAddr = resolve(PEFILE_IMPORT_TABLE[i].Name, locate(PEFILE_IMPORT_TABLE[i].Name));
int NameSize = 0;
while (true) {
char tmp;
fseek(Ppefile, (NameAddr + NameSize), SEEK_SET);
fread(&tmp, sizeof(char), 1, Ppefile);
if (tmp == 0x00) {
break;
}
NameSize++;
}
char* Name = new char[NameSize + 2];
fseek(Ppefile, NameAddr, SEEK_SET);
fread(Name, (NameSize * sizeof(char)) + 1, 1, Ppefile);
printf(" * %s:\n", Name);
delete[] Name;
printf(" ILT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk);
printf(" IAT RVA: 0x%X\n", PEFILE_IMPORT_TABLE[i].FirstThunk);
if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == 0) {
printf(" Bound: FALSE\n");
}
else if (PEFILE_IMPORT_TABLE[i].TimeDateStamp == -1) {
printf(" Bound: TRUE\n");
}
printf("\n");
DWORD ILTAddr = resolve(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk, locate(PEFILE_IMPORT_TABLE[i].DUMMYUNIONNAME.OriginalFirstThunk));
int entrycounter = 0;
while (true) {
ILT_ENTRY_64 entry;
fseek(Ppefile, (ILTAddr + (entrycounter * sizeof(QWORD))), SEEK_SET);
fread(&entry, sizeof(ILT_ENTRY_64), 1, Ppefile);
BYTE flag = entry.ORDINAL_NAME_FLAG;
DWORD HintRVA = 0x0;
WORD ordinal = 0x0;
if (flag == 0x0) {
HintRVA = entry.FIELD_2.HINT_NAME_TABE;
}
else if (flag == 0x01) {
ordinal = entry.FIELD_2.ORDINAL;
}
if (flag == 0x0 && HintRVA == 0x0 && ordinal == 0x0) {
break;
}
printf("\n Entry:\n");
if (flag == 0x0) {
___IMAGE_IMPORT_BY_NAME hint;
DWORD HintAddr = resolve(HintRVA, locate(HintRVA));
fseek(Ppefile, HintAddr, SEEK_SET);
fread(&hint, sizeof(___IMAGE_IMPORT_BY_NAME), 1, Ppefile);
printf(" Name: %s\n", hint.Name);
printf(" Hint RVA: 0x%X\n", HintRVA);
printf(" Hint: 0x%X\n", hint.Hint);
}
else if (flag == 1) {
printf(" Ordinal: 0x%X\n", ordinal);
}
entrycounter++;
}
printf("\n ----------------------\n\n");
}
}
void PE64FILE::PrintBaseRelocationsInfo() {
printf(" BASE RELOCATIONS TABLE:\n");
printf(" -----------------------\n");
int szCounter = sizeof(___IMAGE_BASE_RELOCATION);
for (int i = 0; i < _basreloc_directory_count; i++) {
DWORD PAGERVA, BLOCKSIZE, BASE_RELOC_ADDR;
int ENTRIES;
BASE_RELOC_ADDR = resolve(PEFILE_BASERELOC_DIRECTORY.VirtualAddress, locate(PEFILE_BASERELOC_DIRECTORY.VirtualAddress));
PAGERVA = PEFILE_BASERELOC_TABLE[i].VirtualAddress;
BLOCKSIZE = PEFILE_BASERELOC_TABLE[i].SizeOfBlock;
ENTRIES = (BLOCKSIZE - sizeof(___IMAGE_BASE_RELOCATION)) / sizeof(WORD);
printf("\n Block 0x%X: \n", i);
printf(" Page RVA: 0x%X\n", PAGERVA);
printf(" Block size: 0x%X\n", BLOCKSIZE);
printf(" Number of entries: 0x%X\n", ENTRIES);
printf("\n Entries:\n");
for (int i = 0; i < ENTRIES; i++) {
BASE_RELOC_ENTRY entry;
int offset = (BASE_RELOC_ADDR + szCounter + (i * sizeof(WORD)));
fseek(Ppefile, offset, SEEK_SET);
fread(&entry, sizeof(WORD), 1, Ppefile);
printf("\n * Value: 0x%X\n", entry);
printf(" Relocation Type: 0x%X\n", entry.TYPE);
printf(" Offset: 0x%X\n", entry.OFFSET);
}
printf("\n ----------------------\n\n");
szCounter += BLOCKSIZE;
}
}
// MAIN
void PE64FILE::ParseFile() {
// PARSE DOS HEADER
ParseDOSHeader();
// PARSE RICH HEADER
ParseRichHeader();
//PARSE NT HEADERS
ParseNTHeaders();
// PARSE SECTION HEADERS
ParseSectionHeaders();
// PARSE IMPORT DIRECTORY
ParseImportDirectory();
// PARSE BASE RELOCATIONS
ParseBaseReloc();
}
void PE64FILE::PrintInfo() {
printf("\n\n");
PrintFileInfo();
printf("\n ----------------------------------\n\n");
PrintDOSHeaderInfo();
printf("\n ----------------------------------\n\n");
PrintRichHeaderInfo();
printf("\n ----------------------------------\n\n");
PrintNTHeadersInfo();
printf("\n ----------------------------------\n\n");
PrintSectionHeadersInfo();
printf("\n ----------------------------------\n\n");
PrintImportTableInfo();
printf("\n ----------------------------------\n\n");
PrintBaseRelocationsInfo();
printf("\n ----------------------------------\n\n");
return;
}
最终效果如下
image
代码放到:https://github.com/ybdt/evasion-hub/tree/master/Misc/PE-Parser
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:卡卡罗特取西经 ybdt ybdt《深入学习PE文件结构系列五自己实现一个PE解析器》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论