PE 文件概述 PE(Portable Executable)是 Windows 系统中可执行文件的标准格式,包括:
EXE(可执行文件) DLL(动态链接库) SYS(系统驱动) OCX(ActiveX 控件) 文件结构 1
2
3
4
5
typedef struct _IMAGE_DOS_HEADER {
WORD e_magic ; // DOS签名 "MZ"
// ... 其他DOS头字段
LONG e_lfanew ; // PE头的偏移
} IMAGE_DOS_HEADER , * PIMAGE_DOS_HEADER ;
特点:
保持与 DOS 程序兼容 e_magic 必须为 “MZ” e_lfanew 指向 PE 头 1
2
3
4
5
typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature ; // PE签名 "PE\0\0"
IMAGE_FILE_HEADER FileHeader ; // 文件头
IMAGE_OPTIONAL_HEADER64 OptionalHeader ; // 可选头
} IMAGE_NT_HEADERS64 , * PIMAGE_NT_HEADERS64 ;
1
2
3
4
5
6
7
8
9
typedef struct _IMAGE_FILE_HEADER {
WORD Machine ; // 目标CPU类型
WORD NumberOfSections ; // 节数量
DWORD TimeDateStamp ; // 创建时间戳
DWORD PointerToSymbolTable ; // 符号表指针
DWORD NumberOfSymbols ; // 符号数量
WORD SizeOfOptionalHeader ; // 可选头大小
WORD Characteristics ; // 文件属性
} IMAGE_FILE_HEADER , * PIMAGE_FILE_HEADER ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct _IMAGE_OPTIONAL_HEADER64 {
WORD Magic ; // 魔数
BYTE MajorLinkerVersion ; // 链接器版本
BYTE MinorLinkerVersion ;
DWORD SizeOfCode ; // 代码大小
DWORD SizeOfInitializedData ; // 已初始化数据大小
DWORD SizeOfUninitializedData ; // 未初始化数据大小
DWORD AddressOfEntryPoint ; // 入口点RVA
DWORD BaseOfCode ; // 代码基址
ULONGLONG ImageBase ; // 默认加载基址
DWORD SectionAlignment ; // 节对齐
DWORD FileAlignment ; // 文件对齐
// ... 其他字段
IMAGE_DATA_DIRECTORY DataDirectory [ 16 ]; // 数据目录
} IMAGE_OPTIONAL_HEADER64 , * PIMAGE_OPTIONAL_HEADER64 ;
3. 节表(Section Table) 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name [ 8 ]; // 节名称
union {
DWORD PhysicalAddress ;
DWORD VirtualSize ; // 虚拟大小
} Misc ;
DWORD VirtualAddress ; // 虚拟地址(RVA)
DWORD SizeOfRawData ; // 原始大小
DWORD PointerToRawData ; // 文件偏移
DWORD PointerToRelocations ;
DWORD PointerToLinenumbers ;
WORD NumberOfRelocations ;
WORD NumberOfLinenumbers ;
DWORD Characteristics ; // 节属性
} IMAGE_SECTION_HEADER , * PIMAGE_SECTION_HEADER ;
常见节:
.text
:代码节.data
:数据节.rdata
:只读数据.idata
:导入表.edata
:导出表.reloc
:重定位信息重要数据目录 1. 导入表(Import Directory) 1
2
3
4
5
6
7
8
9
10
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics ;
DWORD OriginalFirstThunk ; // INT
};
DWORD TimeDateStamp ;
DWORD ForwarderChain ;
DWORD Name ; // DLL名称
DWORD FirstThunk ; // IAT
} IMAGE_IMPORT_DESCRIPTOR , * PIMAGE_IMPORT_DESCRIPTOR ;
导入函数信息:
1
2
3
4
5
6
7
8
typedef struct _IMAGE_THUNK_DATA64 {
union {
ULONGLONG ForwarderString ;
ULONGLONG Function ; // 函数地址
ULONGLONG Ordinal ; // 序号
ULONGLONG AddressOfData ; // 函数名称
} u1 ;
} IMAGE_THUNK_DATA64 , * PIMAGE_THUNK_DATA64 ;
2. 导出表(Export Directory) 1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics ;
DWORD TimeDateStamp ;
WORD MajorVersion ;
WORD MinorVersion ;
DWORD Name ; // DLL名称
DWORD Base ; // 序号基数
DWORD NumberOfFunctions ; // 函数数量
DWORD NumberOfNames ; // 名称数量
DWORD AddressOfFunctions ; // 函数地址表
DWORD AddressOfNames ; // 函数名称表
DWORD AddressOfNameOrdinals ; // 序号表
} IMAGE_EXPORT_DIRECTORY , * PIMAGE_EXPORT_DIRECTORY ;
3. 重定位表(Relocation Directory) 1
2
3
4
5
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress ; // 页面RVA
DWORD SizeOfBlock ; // 块大小
// WORD TypeOffset[1]; // 重定位项数组
} IMAGE_BASE_RELOCATION , * PIMAGE_BASE_RELOCATION ;
加载过程 映射文件
重定位处理
导入表处理
初始化
分析技巧 1. 文件分析 1
2
3
4
5
6
7
8
9
10
# 解析DOS头
dos_header = read_struct ( file , 0 , IMAGE_DOS_HEADER )
if dos_header . e_magic != 0x5A4D : # "MZ"
raise Exception ( "Invalid DOS signature" )
# 解析PE头
pe_offset = dos_header . e_lfanew
nt_headers = read_struct ( file , pe_offset , IMAGE_NT_HEADERS64 )
if nt_headers . Signature != 0x4550 : # "PE\0\0"
raise Exception ( "Invalid PE signature" )
2. 节分析 1
2
3
4
5
6
# 遍历节表
section_offset = pe_offset + sizeof ( IMAGE_NT_HEADERS64 )
for i in range ( nt_headers . FileHeader . NumberOfSections ):
section = read_struct ( file , section_offset , IMAGE_SECTION_HEADER )
# 分析节属性和内容
section_offset += sizeof ( IMAGE_SECTION_HEADER )
3. RVA转换 1
2
3
4
5
6
def rva_to_raw ( rva , sections ):
for section in sections :
if ( rva >= section . VirtualAddress and
rva < section . VirtualAddress + section . VirtualSize ):
return rva - section . VirtualAddress + section . PointerToRawData
return None
安全特性 1. ASLR 1
2
// 支持ASLR的DLL特征
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040
2. DEP 1
2
// 支持DEP的DLL特征
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100
3. 完整性检查 1
2
3
4
// 检查节校验和
DWORD calculate_checksum ( BYTE * data , DWORD size ) {
// 实现校验和算法
}
调试技巧 断点设置
内存保护
API监控
工具使用 PE查看器
CFF Explorer PE Bear Resource Hacker 调试器
分析工具
Process Monitor API Monitor Dependencies
Licensed under CC BY-NC-SA 4.0