1pub use self::{
2 dos::DosHeader,
3 nt::NtHeader,
4 tables::{ExportTable, ImportTable},
5};
6use byteorder::{LittleEndian, ReadBytesExt};
7use gaia_types::helpers::Architecture;
8use serde::{Deserialize, Serialize};
9use std::{
10 fmt::{Display, Formatter},
11 io::{Read, Seek},
12};
13
14pub mod coff;
15mod dos;
16mod nt;
17pub mod tables;
18
19pub use coff::*;
20use gaia_types::GaiaError;
21
22#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
27pub enum SubsystemType {
28 Console,
30 Windows,
32 Native,
34 Posix,
36 WindowsCe,
38 Efi,
40 EfiBootServiceDriver,
42 EfiRuntimeDriver,
44 EfiRom,
46 Xbox,
48 WindowsBootApplication,
50}
51
52impl Display for SubsystemType {
53 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
54 match self {
55 SubsystemType::Console => write!(f, "控制台应用程序"),
56 SubsystemType::Windows => write!(f, "Windows GUI 应用程序"),
57 SubsystemType::Native => write!(f, "原生驱动程序"),
58 SubsystemType::Posix => write!(f, "POSIX 子系统应用程序"),
59 SubsystemType::WindowsCe => write!(f, "Windows CE 子系统"),
60 SubsystemType::Efi => write!(f, "EFI 应用程序"),
61 SubsystemType::EfiBootServiceDriver => write!(f, "EFI 启动服务驱动程序"),
62 SubsystemType::EfiRuntimeDriver => write!(f, "EFI 运行时驱动程序"),
63 SubsystemType::EfiRom => write!(f, "EFI ROM 映像"),
64 SubsystemType::Xbox => write!(f, "Xbox 应用程序"),
65 SubsystemType::WindowsBootApplication => write!(f, "Windows 启动应用程序"),
66 }
67 }
68}
69
70impl From<u16> for SubsystemType {
71 fn from(value: u16) -> Self {
79 match value {
80 1 => SubsystemType::Native,
81 2 => SubsystemType::Windows,
82 3 => SubsystemType::Console,
83 7 => SubsystemType::Posix,
84 9 => SubsystemType::WindowsCe,
85 10 => SubsystemType::Efi,
86 11 => SubsystemType::EfiBootServiceDriver,
87 12 => SubsystemType::EfiRuntimeDriver,
88 13 => SubsystemType::EfiRom,
89 14 => SubsystemType::Xbox,
90 16 => SubsystemType::WindowsBootApplication,
91 _ => SubsystemType::Console, }
93 }
94}
95
96impl Default for DataDirectory {
97 fn default() -> Self {
98 Self { virtual_address: 0, size: 0 }
99 }
100}
101
102#[derive(Clone, Debug, Serialize, Deserialize)]
107pub struct OptionalHeader {
108 pub magic: u16,
110 pub major_linker_version: u8,
112 pub minor_linker_version: u8,
114 pub size_of_code: u32,
116 pub size_of_initialized_data: u32,
118 pub size_of_uninitialized_data: u32,
120 pub address_of_entry_point: u32,
122 pub base_of_code: u32,
124 pub base_of_data: Option<u32>, pub image_base: u64,
128 pub section_alignment: u32,
130 pub file_alignment: u32,
132 pub major_operating_system_version: u16,
134 pub minor_operating_system_version: u16,
136 pub major_image_version: u16,
138 pub minor_image_version: u16,
140 pub major_subsystem_version: u16,
142 pub minor_subsystem_version: u16,
144 pub win32_version_value: u32,
146 pub size_of_image: u32,
148 pub size_of_headers: u32,
150 pub checksum: u32,
152 pub subsystem: SubsystemType,
154 pub dll_characteristics: u16,
156 pub size_of_stack_reserve: u64,
158 pub size_of_stack_commit: u64,
160 pub size_of_heap_reserve: u64,
162 pub size_of_heap_commit: u64,
164 pub loader_flags: u32,
166 pub number_of_rva_and_sizes: u32,
168 pub data_directories: Vec<DataDirectory>,
170}
171
172impl OptionalHeader {
173 pub fn new(
175 entry_point: u32,
176 image_base: u64,
177 size_of_code: u32,
178 size_of_headers: u32,
179 size_of_image: u32,
180 subsystem: SubsystemType,
181 ) -> Self {
182 let mut data_directories = Vec::with_capacity(16);
183 for _ in 0..16 {
185 data_directories.push(DataDirectory::default());
186 }
187
188 Self {
189 magic: 0x020B, major_linker_version: 14,
191 minor_linker_version: 0,
192 size_of_code,
193 size_of_initialized_data: 0,
194 size_of_uninitialized_data: 0,
195 address_of_entry_point: entry_point,
196 base_of_code: 0x2000,
197 base_of_data: None, image_base,
199 section_alignment: 0x2000,
200 file_alignment: 0x200,
201 major_operating_system_version: 6,
202 minor_operating_system_version: 0,
203 major_image_version: 0,
204 minor_image_version: 0,
205 major_subsystem_version: 6,
206 minor_subsystem_version: 0,
207 win32_version_value: 0,
208 size_of_image,
209 size_of_headers,
210 checksum: 0,
211 subsystem,
212 dll_characteristics: 0x8500, size_of_stack_reserve: 0x100000,
216 size_of_stack_commit: 0x1000,
217 size_of_heap_reserve: 0x100000,
218 size_of_heap_commit: 0x1000,
219 loader_flags: 0,
220 number_of_rva_and_sizes: 16,
221 data_directories,
222 }
223 }
224
225 pub fn new_for_architecture(
227 architecture: &Architecture,
228 entry_point: u32,
229 image_base: u64,
230 size_of_code: u32,
231 size_of_headers: u32,
232 size_of_image: u32,
233 subsystem: SubsystemType,
234 ) -> Self {
235 let mut data_directories = Vec::with_capacity(16);
236 for _ in 0..16 {
238 data_directories.push(DataDirectory::default());
239 }
240
241 let (magic, base_of_data) = match architecture {
242 Architecture::X86 => (0x010B, Some(0x2000)), Architecture::X86_64 => (0x020B, None), _ => (0x010B, Some(0x2000)), };
246
247 Self {
248 magic,
249 major_linker_version: 14,
250 minor_linker_version: 0,
251 size_of_code,
252 size_of_initialized_data: 0,
253 size_of_uninitialized_data: 0,
254 address_of_entry_point: entry_point,
255 base_of_code: 0x1000,
256 base_of_data,
257 image_base,
258 section_alignment: 0x1000,
259 file_alignment: 0x200,
260 major_operating_system_version: 6,
261 minor_operating_system_version: 0,
262 major_image_version: 0,
263 minor_image_version: 0,
264 major_subsystem_version: 6,
265 minor_subsystem_version: 0,
266 win32_version_value: 0,
267 size_of_image,
268 size_of_headers,
269 checksum: 0,
270 subsystem,
271 dll_characteristics: 0x8160, size_of_stack_reserve: 0x100000,
273 size_of_stack_commit: 0x1000,
274 size_of_heap_reserve: 0x100000,
275 size_of_heap_commit: 0x1000,
276 loader_flags: 0,
277 number_of_rva_and_sizes: 16,
278 data_directories,
279 }
280 }
281}
282
283#[derive(Clone, Debug, Serialize, Deserialize)]
288pub struct PeHeader {
289 pub dos_header: DosHeader,
291 pub nt_header: NtHeader,
293 pub coff_header: CoffHeader,
295 pub optional_header: OptionalHeader,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
304pub struct PeSection {
305 pub name: String,
307 pub virtual_size: u32,
309 pub virtual_address: u32,
311 pub size_of_raw_data: u32,
313 pub pointer_to_raw_data: u32,
315 pub pointer_to_relocations: u32,
317 pub pointer_to_line_numbers: u32,
319 pub number_of_relocations: u16,
321 pub number_of_line_numbers: u16,
323 pub characteristics: u32,
325 #[serde(skip_serializing_if = "Vec::is_empty")]
327 pub data: Vec<u8>,
328}
329
330#[derive(Debug, Clone, Copy)]
335pub struct ReadConfig {
336 pub include_sections: bool,
338 pub validate_checksum: bool,
340 pub parse_imports: bool,
342 pub parse_exports: bool,
344}
345
346impl Default for ReadConfig {
347 fn default() -> Self {
352 Self { include_sections: true, validate_checksum: false, parse_imports: true, parse_exports: true }
353 }
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct PeProgram {
362 pub header: PeHeader,
364 pub sections: Vec<PeSection>,
366 pub imports: ImportTable,
368 pub exports: ExportTable,
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct PeInfo {
378 pub target_arch: Architecture,
380 pub subsystem: SubsystemType,
382 pub entry_point: u32,
384 pub image_base: u64,
386 pub section_count: u16,
388 pub file_size: u64,
390}
391
392#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
397pub struct DataDirectory {
398 pub virtual_address: u32,
400 pub size: u32,
402}
403
404impl DataDirectory {
405 pub fn read<R: Read>(mut reader: R) -> Result<Self, GaiaError> {
407 Ok(DataDirectory { virtual_address: reader.read_u32::<LittleEndian>()?, size: reader.read_u32::<LittleEndian>()? })
408 }
409}
410
411impl OptionalHeader {
412 pub fn read<R: Read>(mut reader: R) -> Result<Self, GaiaError> {
414 let magic = reader.read_u16::<LittleEndian>()?;
415 let is_pe32_plus = magic == 0x020B;
416
417 let major_linker_version = reader.read_u8()?;
418 let minor_linker_version = reader.read_u8()?;
419 let size_of_code = reader.read_u32::<LittleEndian>()?;
420 let size_of_initialized_data = reader.read_u32::<LittleEndian>()?;
421 let size_of_uninitialized_data = reader.read_u32::<LittleEndian>()?;
422 let address_of_entry_point = reader.read_u32::<LittleEndian>()?;
423 let base_of_code = reader.read_u32::<LittleEndian>()?;
424
425 let (base_of_data, image_base) = if is_pe32_plus {
426 (None, reader.read_u64::<LittleEndian>()?)
427 }
428 else {
429 (Some(reader.read_u32::<LittleEndian>()?), reader.read_u32::<LittleEndian>()? as u64)
430 };
431
432 let section_alignment = reader.read_u32::<LittleEndian>()?;
433 let file_alignment = reader.read_u32::<LittleEndian>()?;
434 let major_operating_system_version = reader.read_u16::<LittleEndian>()?;
435 let minor_operating_system_version = reader.read_u16::<LittleEndian>()?;
436 let major_image_version = reader.read_u16::<LittleEndian>()?;
437 let minor_image_version = reader.read_u16::<LittleEndian>()?;
438 let major_subsystem_version = reader.read_u16::<LittleEndian>()?;
439 let minor_subsystem_version = reader.read_u16::<LittleEndian>()?;
440 let win32_version_value = reader.read_u32::<LittleEndian>()?;
441 let size_of_image = reader.read_u32::<LittleEndian>()?;
442 let size_of_headers = reader.read_u32::<LittleEndian>()?;
443 let checksum = reader.read_u32::<LittleEndian>()?;
444 let subsystem = reader.read_u16::<LittleEndian>()?.into();
445 let dll_characteristics = reader.read_u16::<LittleEndian>()?;
446
447 let (size_of_stack_reserve, size_of_stack_commit, size_of_heap_reserve, size_of_heap_commit) = if is_pe32_plus {
448 (
449 reader.read_u64::<LittleEndian>()?,
450 reader.read_u64::<LittleEndian>()?,
451 reader.read_u64::<LittleEndian>()?,
452 reader.read_u64::<LittleEndian>()?,
453 )
454 }
455 else {
456 (
457 reader.read_u32::<LittleEndian>()? as u64,
458 reader.read_u32::<LittleEndian>()? as u64,
459 reader.read_u32::<LittleEndian>()? as u64,
460 reader.read_u32::<LittleEndian>()? as u64,
461 )
462 };
463
464 let loader_flags = reader.read_u32::<LittleEndian>()?;
465 let number_of_rva_and_sizes = reader.read_u32::<LittleEndian>()?;
466
467 let mut data_directories = Vec::new();
468 for _ in 0..number_of_rva_and_sizes {
469 data_directories.push(DataDirectory::read(&mut reader)?);
470 }
471
472 Ok(OptionalHeader {
473 magic,
474 major_linker_version,
475 minor_linker_version,
476 size_of_code,
477 size_of_initialized_data,
478 size_of_uninitialized_data,
479 address_of_entry_point,
480 base_of_code,
481 base_of_data,
482 image_base,
483 section_alignment,
484 file_alignment,
485 major_operating_system_version,
486 minor_operating_system_version,
487 major_image_version,
488 minor_image_version,
489 major_subsystem_version,
490 minor_subsystem_version,
491 win32_version_value,
492 size_of_image,
493 size_of_headers,
494 checksum,
495 subsystem,
496 dll_characteristics,
497 size_of_stack_reserve,
498 size_of_stack_commit,
499 size_of_heap_reserve,
500 size_of_heap_commit,
501 loader_flags,
502 number_of_rva_and_sizes,
503 data_directories,
504 })
505 }
506}