pe_parse/src/header.rs
2024-12-18 08:32:13 +08:00

453 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use super::types::*;
use bitflags::bitflags;
use serde::Serialize;
#[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageDosHeader {
pub e_magic: u16, // Magic number 固定值 0x5A4D
pub e_cblp: u16,
pub e_cp: u16,
pub e_crlc: u16,
pub e_cparhdr: u16,
pub e_minalloc: u16,
pub e_maxalloc: u16,
pub e_ss: u16,
pub e_sp: u16,
pub e_csum: u16,
pub e_ip: u16,
pub e_cs: u16,
pub e_lfarlc: u16,
pub e_ovno: u16,
pub e_res: [u16; 4],
pub e_oemid: u16,
pub e_oeminfo: u16,
pub e_res2: [u16; 10],
pub e_lfanew: Offset, // File address of new exe header nt头的偏移
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageNTHeader32 {
pub signature: u32,
pub file_header: ImageFileHeader,
pub optional_header: ImageOptionalHeader32,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageNTHeader64 {
pub signature: u32,
pub file_header: ImageFileHeader,
pub optional_header: ImageOptionalHeader64,
}
#[repr(C)]
#[derive(Serialize, Clone, Copy)]
#[serde(untagged)]
pub enum ImageNTHeader {
NTHeader32(ImageNTHeader32),
NTHeader64(ImageNTHeader64),
}
#[repr(C)]
#[derive(Serialize)]
#[serde(untagged)]
pub enum ImageNTHeaderMut<'a> {
NTHeader32(&'a mut ImageNTHeader32),
NTHeader64(&'a mut ImageNTHeader64),
}
impl<'a> ImageNTHeaderMut<'a> {
pub fn get_optional_header_mut(&mut self) -> ImageOptionalHeaderMut {
match self {
ImageNTHeaderMut::NTHeader32(header) => {
ImageOptionalHeaderMut::OptionalHeader32(&mut header.optional_header)
}
ImageNTHeaderMut::NTHeader64(header) => {
ImageOptionalHeaderMut::OptionalHeader64(&mut header.optional_header)
}
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageFileHeader {
pub machine: u16,
pub number_of_sections: u16,
pub time_date_stamp: u32,
pub pointer_to_symbol_table: Offset,
pub number_of_symbols: u32,
pub size_of_optional_header: u16,
pub characteristics: FileCharacteristics,
}
impl Serialize for FileCharacteristics {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
// 直接返回bitflags的整数值
serializer.serialize_u16(self.bits())
}
}
impl Serialize for DLLCharacteristics {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u16(self.bits())
}
}
impl Serialize for SectionCharacteristics {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u32(self.bits())
}
}
bitflags! {
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct FileCharacteristics: u16 {
const RELOCS_STRIPPED = 0x0001;
const EXECUTABLE_IMAGE = 0x0002;
const LINE_NUMS_STRIPPED = 0x0004;
const LOCAL_SYMS_STRIPPED = 0x0008;
const AGGRESSIVE_WS_TRIM = 0x0010;
const LARGE_ADDRESS_AWARE = 0x0020;
const BYTES_REVERSED_LO = 0x0080;
const MACHINE_32BIT = 0x0100;
const DEBUG_STRIPPED = 0x0200;
const REMOVABLE_RUN_FROM_SWAP = 0x0400;
const NET_RUN_FROM_SWAP = 0x0800;
const SYSTEM = 0x1000;
const DLL = 0x2000;
const UP_SYSTEM_ONLY = 0x4000;
const BYTES_REVERSED_HI = 0x8000;
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct DLLCharacteristics: u16 {
const RESERVED1 = 0x0001;
const RESERVED2 = 0x0002;
const RESERVED4 = 0x0004;
const RESERVED8 = 0x0008;
const HIGH_ENTROPY_VA = 0x0020;
const DYNAMIC_BASE = 0x0040;
const FORCE_INTEGRITY = 0x0080;
const NX_COMPAT = 0x0100;
const NO_ISOLATION = 0x0200;
const NO_SEH = 0x0400;
const NO_BIND = 0x0800;
const APPCONTAINER = 0x1000;
const WDM_DRIVER = 0x2000;
const GUARD_CF = 0x4000;
const TERMINAL_SERVER_AWARE = 0x8000;
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct SectionCharacteristics: u32 {
/// Reserved for future use.
const TYPE_REG = 0x00000000;
/// Reserved for future use.
const TYPE_DSECT = 0x00000001;
/// Reserved for future use.
const TYPE_NOLOAD = 0x00000002;
/// Reserved for future use.
const TYPE_GROUP = 0x00000004;
/// The section should not be padded to the next boundary.
/// This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES.
/// This is valid only for object files.
const TYPE_NO_PAD = 0x00000008;
/// Reserved for future use.
const TYPE_COPY = 0x00000010;
/// The section contains executable code.
const CNT_CODE = 0x00000020;
/// The section contains initialized data.
const CNT_INITIALIZED_DATA = 0x00000040;
/// The section contains uninitialized data.
const CNT_UNINITIALIZED_DATA = 0x00000080;
/// Reserved for future use.
const LNK_OTHER = 0x00000100;
/// The section contains comments or other information.
/// The .drectve section has this type. This is valid for object files only.
const LNK_INFO = 0x00000200;
/// Reserved for future use.
const TYPE_OVER = 0x00000400;
/// The section will not become part of the image.
/// This is valid only for object files.
const LNK_REMOVE = 0x00000800;
/// The section contains COMDAT data. This is valid only for object files.
const LNK_COMDAT = 0x00001000;
/// Unknown/Reserved.
const RESERVED = 0x00002000;
/// Unknown flag.
const MEM_PROTECTED = 0x00004000;
/// Unknown flag.
const NO_DEFER_SPEC_EXC = 0x00004000;
/// The section contains data referenced through the global pointer (GP).
const GPREL = 0x00008000;
/// Reserved for future use.
const MEM_FARDATA = 0x00008000;
/// Reserved for future use.
const MEM_SYSHEAP = 0x00010000;
/// Reserved for future use.
const MEM_PURGEABLE = 0x00020000;
/// Reserved for future use.
const MEM_16BIT = 0x00020000;
/// Reserved for future use.
const MEM_LOCKED = 0x00040000;
/// Reserved for future use.
const MEM_PRELOAD = 0x00080000;
/// Align data on a 1-byte boundary. Valid only for object files.
const ALIGN_1BYTES = 0x00100000;
/// Align data on a 2-byte boundary. Valid only for object files.
const ALIGN_2BYTES = 0x00200000;
/// Align data on a 4-byte boundary. Valid only for object files.
const ALIGN_4BYTES = 0x00300000;
/// Align data on an 8-byte boundary. Valid only for object files.
const ALIGN_8BYTES = 0x00400000;
/// Align data on a 16-byte boundary. Valid only for object files.
const ALIGN_16BYTES = 0x00500000;
/// Align data on a 32-byte boundary. Valid only for object files.
const ALIGN_32BYTES = 0x00600000;
/// Align data on a 64-byte boundary. Valid only for object files.
const ALIGN_64BYTES = 0x00700000;
/// Align data on a 128-byte boundary. Valid only for object files.
const ALIGN_128BYTES = 0x00800000;
/// Align data on a 256-byte boundary. Valid only for object files.
const ALIGN_256BYTES = 0x00900000;
/// Align data on a 512-byte boundary. Valid only for object files.
const ALIGN_512BYTES = 0x00A00000;
/// Align data on a 1024-byte boundary. Valid only for object files.
const ALIGN_1024BYTES = 0x00B00000;
/// Align data on a 2048-byte boundary. Valid only for object files.
const ALIGN_2048BYTES = 0x00C00000;
/// Align data on a 4096-byte boundary. Valid only for object files.
const ALIGN_4096BYTES = 0x00D00000;
/// Align data on an 8192-byte boundary. Valid only for object files.
const ALIGN_8192BYTES = 0x00E00000;
/// Mask for alignment.
const ALIGN_MASK = 0x00F00000;
/// The section contains extended relocations.
const LNK_NRELOC_OVFL = 0x01000000;
/// The section can be discarded as needed.
const MEM_DISCARDABLE = 0x02000000;
/// The section cannot be cached.
const MEM_NOT_CACHED = 0x04000000;
/// The section is not pageable.
const MEM_NOT_PAGED = 0x08000000;
/// The section can be shared in memory.
const MEM_SHARED = 0x10000000;
/// The section can be executed as code.
const MEM_EXECUTE = 0x20000000;
/// The section can be read.
const MEM_READ = 0x40000000;
/// The section can be written to.
const MEM_WRITE = 0x80000000;
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageOptionalHeader32 {
pub magic: u16,
pub major_linker_version: u8,
pub minor_linker_version: u8,
pub size_of_code: u32,
pub size_of_initialized_data: u32,
pub size_of_uninitialized_data: u32,
pub address_of_entry_point: u32,
pub base_of_code: u32,
pub base_of_data: u32,
pub image_base: u32,
pub section_alignment: u32,
pub file_alignment: u32,
pub major_operating_system_version: u16,
pub minor_operating_system_version: u16,
pub major_image_version: u16,
pub minor_image_version: u16,
pub major_subsystem_version: u16,
pub minor_subsystem_version: u16,
pub win32_version_value: u32,
pub size_of_image: u32,
pub size_of_headers: u32,
pub checksum: u32,
pub subsystem: u16,
pub dll_characteristics: DLLCharacteristics,
pub size_of_stack_reserve: u32,
pub size_of_stack_commit: u32,
pub size_of_heap_reserve: u32,
pub size_of_heap_commit: u32,
pub loader_flags: u32,
pub number_of_rva_and_sizes: u32,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Serialize)]
pub struct ImageOptionalHeader64 {
pub magic: u16,
pub major_linker_version: u8,
pub minor_linker_version: u8,
pub size_of_code: u32,
pub size_of_initialized_data: u32,
pub size_of_uninitialized_data: u32,
pub address_of_entry_point: u32,
pub base_of_code: u32,
pub image_base: u64,
pub section_alignment: u32,
pub file_alignment: u32,
pub major_operating_system_version: u16,
pub minor_operating_system_version: u16,
pub major_image_version: u16,
pub minor_image_version: u16,
pub major_subsystem_version: u16,
pub minor_subsystem_version: u16,
pub win32_version_value: u32,
pub size_of_image: u32,
pub size_of_headers: u32,
pub checksum: u32,
pub subsystem: u16,
pub dll_characteristics: DLLCharacteristics,
pub size_of_stack_reserve: u64,
pub size_of_stack_commit: u64,
pub size_of_heap_reserve: u64,
pub size_of_heap_commit: u64,
pub loader_flags: u32,
pub number_of_rva_and_sizes: u32,
}
#[repr(C)]
#[derive(Serialize, Clone, Copy)]
#[serde(untagged)]
pub enum ImageOptionalHeader {
OptionalHeader32(ImageOptionalHeader32),
OptionalHeader64(ImageOptionalHeader64),
}
#[repr(C)]
#[derive(Copy, Clone, Eq, PartialEq, Default, Debug)]
pub struct ImageDataDirectory {
pub virtual_address: u32,
pub size: u32,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ImageDirectoryEntry {
Export = 0,
Import = 1,
Resource = 2,
Exception = 3,
Security = 4,
BaseReloc = 5,
Debug = 6,
Architecture = 7,
GlobalPTR = 8,
TLS = 9,
LoadConfig = 10,
BoundImport = 11,
IAT = 12,
DelayImport = 13,
COMDescriptor = 14,
Reserved = 15,
}
#[repr(C)]
#[derive(Serialize)]
#[serde(untagged)]
pub enum ImageOptionalHeaderMut<'a> {
OptionalHeader32(&'a mut ImageOptionalHeader32),
OptionalHeader64(&'a mut ImageOptionalHeader64),
}
impl ImageOptionalHeader {
pub fn get_size_of_headers(&self) -> u32 {
match self {
ImageOptionalHeader::OptionalHeader32(header) => header.size_of_headers,
ImageOptionalHeader::OptionalHeader64(header) => header.size_of_headers,
}
}
pub fn get_size_of_image(&self) -> u32 {
match self {
ImageOptionalHeader::OptionalHeader32(header) => header.size_of_image,
ImageOptionalHeader::OptionalHeader64(header) => header.size_of_image,
}
}
pub fn get_size_of_optional_header(&self) -> u32 {
match self {
ImageOptionalHeader::OptionalHeader32(_) => {
size_of::<ImageOptionalHeader32>() as u32
}
ImageOptionalHeader::OptionalHeader64(_) => {
size_of::<ImageOptionalHeader64>() as u32
}
}
}
/// 获取数据目录数量
pub fn get_data_directory_count(&self) -> u32 {
// 如果数据目录数量大于16则返回16
match self {
ImageOptionalHeader::OptionalHeader32(header) => header.number_of_rva_and_sizes,
ImageOptionalHeader::OptionalHeader64(header) => header.number_of_rva_and_sizes,
}
.min(16)
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageSectionHeader {
pub name: [u8; 8],
pub virtual_size: u32,
pub virtual_address: u32,
pub size_of_raw_data: u32,
pub pointer_to_raw_data: u32,
pub pointer_to_relocations: u32,
pub pointer_to_linenumbers: u32,
pub number_of_relocations: u16,
pub number_of_linenumbers: u16,
pub characteristics: SectionCharacteristics,
}
#[repr(C)]
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
pub struct ImageImportDescriptor {
pub original_first_thunk: u32,
pub time_date_stamp: u32,
pub forwarder_chain: u32,
pub name: u32,
pub first_thunk: u32,
}
bitflags! {
/// 导入查找表 32位
/// [Import Lookup Table](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#import-lookup-table)
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImportLookupTable32: u32 {
/// 第31位为1表示导入函数通过序号导入
const IMPORT_BY_ORDINAL = 0x80000000;
/// 15-0 位表示导入函数的序号
const IMPORT_BY_ORDINAL_MASK = 0x0000FFFF;
/// 30-0 位表示导入函数的RVA
const IMPORT_BY_RVA_MASK = 0x7FFFFFFF;
}
/// 导入查找表 64位
/// [Import Lookup Table](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#import-lookup-table)
#[derive(Debug, Clone, Copy, Serialize)]
pub struct ImportLookupTable64: u64 {
/// 第63位为1表示导入函数通过序号导入
const IMPORT_BY_ORDINAL = 0x8000000000000000;
/// 15-0 位表示导入函数的序号
const IMPORT_BY_ORDINAL_MASK = 0x0000FFFF;
/// 30-0 位表示导入函数的RVA
const IMPORT_BY_RVA_MASK = 0x7FFFFFFFFFFFFFFF;
/// 62-31 must be zero.
const RESERVED = 0x7FFFFFFF00000000;
}
}