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