pe_assembler/types/dos/
mod.rs

1use byteorder::{LittleEndian, ReadBytesExt};
2use gaia_types::GaiaError;
3use serde::{Deserialize, Serialize};
4use std::io::Read;
5
6/// DOS 头结构
7///
8/// 包含 DOS 可执行文件的基本信息,是 PE 文件的第一个结构。
9/// 虽然现代 Windows 程序不运行在 DOS 模式下,但 PE 格式仍保留这个结构用于兼容性。
10#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
11pub struct DosHeader {
12    /// DOS 签名,通常为 0x5A4D("MZ")
13    pub e_magic: u16,
14    /// 文件最后页的字节数
15    pub e_cblp: u16,
16    /// 文件的总页数
17    pub e_cp: u16,
18    /// 重定位项的数量
19    pub e_crlc: u16,
20    /// 段落中头部的大小
21    pub e_cparhdr: u16,
22    /// 所需的最小段落数
23    pub e_min_allocate: u16,
24    /// 所需的最大段落数
25    pub e_max_allocate: u16,
26    /// 初始的 SS 寄存器值
27    pub e_ss: u16,
28    /// 初始的 SP 寄存器值
29    pub e_sp: u16,
30    /// 校验和
31    pub e_check_sum: u16,
32    /// 初始的 IP 寄存器值
33    pub e_ip: u16,
34    /// 初始的 CS 寄存器值
35    pub e_cs: u16,
36    /// 重定位表的文件偏移
37    pub e_lfarlc: u16,
38    /// 覆盖号
39    pub e_ovno: u16,
40    /// 保留字段,通常为 0
41    pub e_res: [u16; 4],
42    /// OEM 标识符
43    pub e_oem_id: u16,
44    /// OEM 信息
45    pub e_oem_info: u16,
46    /// 保留字段,通常为 0
47    pub e_res2: [u16; 10],
48    /// PE 头的文件偏移,指向真正的 PE 结构
49    pub e_lfanew: u32,
50}
51
52impl Default for DosHeader {
53    fn default() -> Self {
54        Self {
55            e_magic: 0x5A4D, // "MZ"
56            e_cblp: 0x90,
57            e_cp: 0x03,
58            e_crlc: 0x00,
59            e_cparhdr: 0x04,
60            e_min_allocate: 0x00,
61            e_max_allocate: 0xFFFF,
62            e_ss: 0x00,
63            e_sp: 0xB8,
64            e_check_sum: 0x00,
65            e_ip: 0x00,
66            e_cs: 0x00,
67            e_lfarlc: 0x40,
68            e_ovno: 0x00,
69            e_res: [0; 4],
70            e_oem_id: 0x00,
71            e_oem_info: 0x00,
72            e_res2: [0; 10],
73            e_lfanew: 0x80, // PE header offset
74        }
75    }
76}
77
78impl DosHeader {
79    /// 从二进制读取器中读取 DOS 头
80    ///
81    /// # Arguments
82    /// * `lexer` - 二进制读取器
83    ///
84    /// # Returns
85    /// 返回 DOS 头结构或错误
86    pub fn read<R: Read>(mut reader: R) -> Result<Self, GaiaError> {
87        let e_magic = reader.read_u16::<LittleEndian>()?;
88        let e_cblp = reader.read_u16::<LittleEndian>()?;
89        let e_cp = reader.read_u16::<LittleEndian>()?;
90        let e_crlc = reader.read_u16::<LittleEndian>()?;
91        let e_cparhdr = reader.read_u16::<LittleEndian>()?;
92        let e_min_allocate = reader.read_u16::<LittleEndian>()?;
93        let e_max_allocate = reader.read_u16::<LittleEndian>()?;
94        let e_ss = reader.read_u16::<LittleEndian>()?;
95        let e_sp = reader.read_u16::<LittleEndian>()?;
96        let e_check_sum = reader.read_u16::<LittleEndian>()?;
97        let e_ip = reader.read_u16::<LittleEndian>()?;
98        let e_cs = reader.read_u16::<LittleEndian>()?;
99        let e_lfarlc = reader.read_u16::<LittleEndian>()?;
100        let e_ovno = reader.read_u16::<LittleEndian>()?;
101
102        let mut e_res = [0u16; 4];
103        for i in 0..4 {
104            e_res[i] = reader.read_u16::<LittleEndian>()?;
105        }
106
107        let e_oem_id = reader.read_u16::<LittleEndian>()?;
108        let e_oem_info = reader.read_u16::<LittleEndian>()?;
109
110        let mut e_res2 = [0u16; 10];
111        for i in 0..10 {
112            e_res2[i] = reader.read_u16::<LittleEndian>()?;
113        }
114
115        let e_lfanew = reader.read_u32::<LittleEndian>()?;
116
117        Ok(DosHeader {
118            e_magic,
119            e_cblp,
120            e_cp,
121            e_crlc,
122            e_cparhdr,
123            e_min_allocate,
124            e_max_allocate,
125            e_ss,
126            e_sp,
127            e_check_sum,
128            e_ip,
129            e_cs,
130            e_lfarlc,
131            e_ovno,
132            e_res,
133            e_oem_id,
134            e_oem_info,
135            e_res2,
136            e_lfanew,
137        })
138    }
139}
140
141impl DosHeader {
142    /// 创建一个标准的 DOS 头,指定 PE 头的偏移
143    pub fn new(header_offset: u32) -> Self {
144        Self { e_lfanew: header_offset, ..Default::default() }
145    }
146}