diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 4f0adf2..0501b83 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,17 +1,10 @@ use crate::{ app_error::AppError, - pe_parse::{header::ImageDosHeader, pe::PE}, - services::{ - self, - file::{ - get_nt_headers_data, ResponseDOSHeaderData, ResponseFileHeaderData, - ResponseNTHeaderData, - }, - GLOBAL_FILE_DATA, - }, + pe_parse::pe::PE, + services::{self, file::*, GLOBAL_FILE_DATA}, }; use serde::Serialize; -use tauri::{async_runtime::Mutex, AppHandle, Manager, State}; +use tauri::{AppHandle, Manager}; #[derive(Serialize)] pub struct PeNodeTreeData { @@ -96,6 +89,15 @@ pub fn command_open_file(file_path: &str) -> Result<(), AppError> { unsafe { services::GLOBAL_FILE_PATH = Some(file_path.to_string()); } + + // 判断文件是否是64位 + // TODO: GLOBAL_IS_64_BIT + let binding = GLOBAL_FILE_DATA.lock().unwrap(); + let file_data = binding.as_ref().unwrap(); + let is64bit = file_data.is_64_bit()?; + unsafe { + services::GLOBAL_IS_64_BIT = Some(is64bit); + } Ok(()) } @@ -125,3 +127,10 @@ pub fn command_get_pe_data_file_header() -> Result Result { + let result = services::file::get_optional_header_data()?; + Ok(result) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a96589d..729082e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -15,7 +15,8 @@ pub fn run() { commands::command_get_pe_data_dos_header, commands::command_get_pe_data_nt_header, commands::command_get_pe_data_file_header, - commands::set_complete + commands::command_get_pe_data_optional_header, + commands::set_complete, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/pe_parse/header.rs b/src-tauri/src/pe_parse/header.rs index 61f93d4..c81d117 100644 --- a/src-tauri/src/pe_parse/header.rs +++ b/src-tauri/src/pe_parse/header.rs @@ -34,6 +34,21 @@ pub struct ImageNTHeaders32 { pub optional_header: ImageOptionalHeader32, } +#[repr(C)] +#[derive(Debug, Clone, Copy, Serialize)] +pub struct ImageNTHeaders64 { + pub signature: u32, + pub file_header: ImageFileHeader, + pub optional_header: ImageOptionalHeader64, +} + +#[derive(Serialize, Clone, Copy)] +#[serde(untagged)] +pub enum ImageNTHeaders{ + NTHeaders32(ImageNTHeaders32), + NTHeaders64(ImageNTHeaders64), +} + #[repr(C)] #[derive(Debug, Clone, Copy, Serialize)] pub struct ImageFileHeader { @@ -45,21 +60,31 @@ pub struct ImageFileHeader { pub size_of_optional_header: u16, pub characteristics: FileCharacteristics, } -impl Serialize for FileCharacteristics{ +impl Serialize for FileCharacteristics { fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer { - // 直接返回bitflags的整数值 - serializer.serialize_u16(self.bits()) + S: serde::Serializer, + { + // 直接返回bitflags的整数值 + serializer.serialize_u16(self.bits()) } } - -impl Serialize for DLLCharacteristics{ +impl Serialize for DLLCharacteristics { fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer { - serializer.serialize_u16(self.bits()) + S: serde::Serializer, + { + serializer.serialize_u16(self.bits()) + } +} + +impl Serialize for SectionCharacteristics { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u32(self.bits()) } } @@ -102,6 +127,108 @@ bitflags! { 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)] @@ -112,9 +239,9 @@ pub struct ImageOptionalHeader32 { pub size_of_code: u32, pub size_of_initialized_data: u32, pub size_of_uninitialized_data: u32, - pub address_of_entry_point: RVA, - pub base_of_code: RVA, - pub base_of_data: RVA, + 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, @@ -137,3 +264,58 @@ pub struct ImageOptionalHeader32 { 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, +} +#[derive(Serialize, Clone, Copy)] +#[serde(untagged)] +pub enum ImageOptionalHeader { + OptionalHeader32(ImageOptionalHeader32), + OptionalHeader64(ImageOptionalHeader64), +} + +#[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, +} diff --git a/src-tauri/src/pe_parse/pe.rs b/src-tauri/src/pe_parse/pe.rs index d689710..ca522b7 100644 --- a/src-tauri/src/pe_parse/pe.rs +++ b/src-tauri/src/pe_parse/pe.rs @@ -1,5 +1,5 @@ use super::{error::PEParseError, header::*}; -use std::ops::{Deref, DerefMut}; +use std::{ops::{Deref, DerefMut}, option}; pub trait PE: Deref + DerefMut + Sized { /// Get a reference to a type at a given offset. @@ -22,6 +22,16 @@ pub trait PE: Deref + DerefMut + Sized { Ok(unsafe { &mut *ptr }) } + // 判断是64位还是32位 + fn is_64_bit(&self) -> Result { + // 先以32位加载可选头,通过可选头的Magic字段判断 + let optional_header: &ImageOptionalHeader32 = self.get_optional_header_32()?; + let is_64_bit = optional_header.magic == 0x20b; + Ok(is_64_bit) + } + + + /// Get the DOS header without verifying its contents. fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> { let result = self.get_ref::(0)?; @@ -33,12 +43,26 @@ pub trait PE: Deref + DerefMut + Sized { Ok(result) } - /// Get the NT headers without verifying its contents. - fn get_nt_headers(&self) -> Result<&ImageNTHeaders32, PEParseError> { + + + fn get_nt_headers32(&self) -> Result<&ImageNTHeaders32, PEParseError> { let nt_offset = self.get_nt_headers_offset()?; let result = self.get_ref::(nt_offset)?; Ok(result) } + fn get_nt_headers64(&self) -> Result<&ImageNTHeaders64, PEParseError> { + let nt_offset = self.get_nt_headers_offset()?; + let result = self.get_ref::(nt_offset)?; + Ok(result) + } + fn get_nt_headers(&self) -> Result { + let is_64_bit = self.is_64_bit()?; + let result = match is_64_bit { + true => ImageNTHeaders::NTHeaders64(*self.get_nt_headers64()?), + false => ImageNTHeaders::NTHeaders32(*self.get_nt_headers32()?), + }; + Ok(result) + } // 获取nt头的偏移 fn get_nt_headers_offset(&self) -> Result { @@ -76,5 +100,62 @@ pub trait PE: Deref + DerefMut + Sized { Ok(result) } + // 获取节区数量 + fn get_number_of_sections(&self) -> Result { + let file_header = self.get_file_header()?; + Ok(file_header.number_of_sections as usize) + } + // 获取可选头大小 + fn get_size_of_optional_header(&self) -> Result { + let file_header = self.get_file_header()?; + Ok(file_header.size_of_optional_header as usize) + } + + fn get_optional_header_32(&self) -> Result<&ImageOptionalHeader32, PEParseError> { + let file_header_offset = self.get_file_header_offset()?; + let optional_header_offset = file_header_offset + std::mem::size_of::(); + let result = self.get_ref::(optional_header_offset)?; + Ok(result) + } + + // 获取可选头 + fn get_optional_header_64(&self) -> Result<&ImageOptionalHeader64, PEParseError> { + let file_header_offset = self.get_file_header_offset()?; + let optional_header_offset = file_header_offset + std::mem::size_of::(); + let result = self.get_ref::(optional_header_offset)?; + Ok(result) + } + + fn get_optional_header(&self) -> Result { + let is_64_bit = self.is_64_bit()?; + let result = match is_64_bit { + true => ImageOptionalHeader::OptionalHeader64(*self.get_optional_header_64()?), + false => ImageOptionalHeader::OptionalHeader32(*self.get_optional_header_32()?), + }; + Ok(result) + } + + fn get_optional_header_offset(&self) -> Result { + let file_header_offset = self.get_file_header_offset()?; + let optional_header_offset = file_header_offset + std::mem::size_of::(); + Ok(optional_header_offset) + } + + // 获取所有节区头数据 + fn get_image_section_headers(&self) -> Result<&[ImageSectionHeader], PEParseError> { + // 1. 获取节区数量 + let number_of_sections = self.get_number_of_sections()?; + // 2. 找到节区头的偏移 + // 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算 + let optional_header_size = self.get_size_of_optional_header()?; + let file_header_offset = self.get_file_header_offset()?; + let section_header_offset = file_header_offset + std::mem::size_of::() + optional_header_size; + // 3. 获取节区头数据 + unsafe { + let ptr = self.as_ptr().wrapping_offset(section_header_offset as isize) as *const ImageSectionHeader; + let result = std::slice::from_raw_parts(ptr, number_of_sections); + Ok(result) + } + } } diff --git a/src-tauri/src/services/file.rs b/src-tauri/src/services/file.rs index 810e1b7..c00d2ef 100644 --- a/src-tauri/src/services/file.rs +++ b/src-tauri/src/services/file.rs @@ -1,9 +1,9 @@ use memmap2::*; use serde::Serialize; -use crate::{app_error::AppError, pe_parse::{header::{ImageDosHeader, ImageFileHeader, ImageNTHeaders32}, pe::PE}}; +use crate::{app_error::AppError, pe_parse::{header::{ImageDosHeader, ImageFileHeader, ImageNTHeaders, ImageNTHeaders32, ImageOptionalHeader}, pe::PE}}; -use super::GLOBAL_FILE_DATA; +use super::{GLOBAL_FILE_DATA, GLOBAL_IS_64_BIT}; // TODO: 打开文件,并将文件映射到内存 pub fn mmap_mut_file(file_path: &str) -> Result { @@ -25,20 +25,22 @@ pub struct ResponseDOSHeaderData { #[derive(Serialize)] pub struct ResponseNTHeaderData { - fields: ImageNTHeaders32, + fields: ImageNTHeaders, base_offset: usize, } -pub fn get_nt_headers_data() -> Result { - let binding = GLOBAL_FILE_DATA.lock().unwrap(); - let file_data = binding.as_ref().unwrap(); - let nt_header = file_data.get_nt_headers()?; - let nt_offset = file_data.get_nt_headers_offset()?; - let result = ResponseNTHeaderData { - fields: nt_header.clone(), - base_offset: nt_offset, - }; - Ok(result) +pub fn get_nt_headers_data<'a>() -> Result { + // pub static GLOBAL_FILE_DATA: Mutex> = Mutex::new(None); + let binding = GLOBAL_FILE_DATA.lock().unwrap(); + // `binding` does not live long enough borrowed value does not live long enough + let file_data = binding.as_ref().unwrap(); + let nt_header_enmu= file_data.get_nt_headers()?; + let nt_offset = file_data.get_nt_headers_offset()?; + let result = ResponseNTHeaderData { + fields: nt_header_enmu, + base_offset: nt_offset, + }; + Ok(result) } // 获取文件头数据 @@ -58,4 +60,23 @@ pub fn get_file_header_data() -> Result { base_offset: file_header_offset, }; Ok(result) +} +// 获取可选头数据 +#[derive(Serialize)] +pub struct ResponseOptionalHeaderData { + pub fields: ImageOptionalHeader, + pub base_offset: usize, +} + + +pub fn get_optional_header_data() -> Result { + let binding = GLOBAL_FILE_DATA.lock().unwrap(); + let file_data = binding.as_ref().unwrap(); + let optional_header = file_data.get_optional_header()?; + let optional_header_offset = file_data.get_optional_header_offset()?; + let result = ResponseOptionalHeaderData { + fields: optional_header.clone(), + base_offset: optional_header_offset, + }; + Ok(result) } \ No newline at end of file diff --git a/src-tauri/src/services/mod.rs b/src-tauri/src/services/mod.rs index 2d59074..0fb8b78 100644 --- a/src-tauri/src/services/mod.rs +++ b/src-tauri/src/services/mod.rs @@ -9,6 +9,8 @@ pub mod file; // 全局文件路径 pub static mut GLOBAL_FILE_PATH: Option = None; +// 文件是否是64位 +pub static mut GLOBAL_IS_64_BIT: Option = None; pub(crate) struct PeData(pub Vec); // 实现Deref diff --git a/src/components/OptionalHeader/OptionalHeader.tsx b/src/components/OptionalHeader/OptionalHeader.tsx new file mode 100644 index 0000000..d678252 --- /dev/null +++ b/src/components/OptionalHeader/OptionalHeader.tsx @@ -0,0 +1,278 @@ +import NodeTableComponent, { + DataTemplateInterface, +} from "../NodeTableComponent/NodeTableComponent"; + +export default function OptionalHeader() { + const dataTemplate: DataTemplateInterface = { + magic: { + name: "magic", + offset: 0, + size: 2, + value: null, + data_type: "hex", + description: "PE文件标志", + }, + major_linker_version: { + name: "major_linker_version", + offset: 2, + size: 1, + value: null, + data_type: "hex", + description: "链接器主版本号", + }, + minor_linker_version: { + name: "minor_linker_version", + offset: 3, + size: 1, + value: null, + data_type: "hex", + description: "链接器次版本号", + }, + size_of_code: { + name: "size_of_code", + offset: 4, + size: 4, + value: null, + data_type: "hex", + description: "代码段大小", + }, + size_of_initialized_data: { + name: "size_of_initialized_data", + offset: 8, + size: 4, + value: null, + data_type: "hex", + description: "初始化数据段大小", + }, + size_of_uninitialized_data: { + name: "size_of_uninitialized_data", + offset: 12, + size: 4, + value: null, + data_type: "hex", + description: "未初始化数据段大小", + }, + address_of_entry_point: { + name: "address_of_entry_point", + offset: 16, + size: 4, + value: null, + data_type: "hex", + description: "入口点地址", + }, + base_of_code: { + name: "base_of_code", + offset: 20, + size: 4, + value: null, + data_type: "hex", + description: "代码段基址", + }, + image_base: { + name: "image_base", + offset: 24, + size: 8, + value: null, + data_type: "hex", + description: "映像基址", + }, + section_alignment: { + name: "section_alignment", + offset: 32, + size: 4, + value: null, + data_type: "hex", + description: "节对齐", + }, + file_alignment: { + name: "file_alignment", + offset: 36, + size: 4, + value: null, + data_type: "hex", + description: "文件对齐", + }, + major_operating_system_version: { + name: "major_operating_system_version", + offset: 40, + size: 2, + value: null, + data_type: "hex", + description: "操作系统主版本号", + }, + minor_operating_system_version: { + name: "minor_operating_system_version", + offset: 42, + size: 2, + value: null, + data_type: "hex", + description: "操作系统次版本号", + }, + major_image_version: { + name: "major_image_version", + offset: 44, + size: 2, + value: null, + data_type: "hex", + description: "映像主版本号", + }, + minor_image_version: { + name: "minor_image_version", + offset: 46, + size: 2, + value: null, + data_type: "hex", + description: "映像次版本号", + }, + major_subsystem_version: { + name: "major_subsystem_version", + offset: 48, + size: 2, + value: null, + data_type: "hex", + description: "子系统主版本号", + }, + minor_subsystem_version: { + name: "minor_subsystem_version", + offset: 50, + size: 2, + value: null, + data_type: "hex", + description: "子系统次版本号", + }, + win32_version_value: { + name: "win32_version_value", + offset: 52, + size: 4, + value: null, + data_type: "hex", + description: "Win32版本值", + }, + size_of_image: { + name: "size_of_image", + offset: 56, + size: 4, + value: null, + data_type: "hex", + description: "映像大小", + }, + size_of_headers: { + name: "size_of_headers", + offset: 60, + size: 4, + value: null, + data_type: "hex", + description: "头部大小", + }, + checksum: { + name: "checksum", + offset: 64, + size: 4, + value: null, + data_type: "hex", + description: "校验和", + }, + subsystem: { + name: "subsystem", + offset: 68, + size: 2, + value: null, + data_type: "hex", + description: "子系统", + }, + dll_characteristics: { + name: "dll_characteristics", + offset: 70, + size: 2, + value: null, + data_type: "hex", + description: "DLL特性", + }, + size_of_stack_reserve: { + name: "size_of_stack_reserve", + offset: 72, + size: 8, + value: null, + data_type: "hex", + description: "堆栈保留大小", + }, + size_of_stack_commit: { + name: "size_of_stack_commit", + offset: 80, + size: 8, + value: null, + data_type: "hex", + description: "堆栈提交大小", + }, + size_of_heap_reserve: { + name: "size_of_heap_reserve", + offset: 88, + size: 8, + value: null, + data_type: "hex", + description: "堆保留大小", + }, + size_of_heap_commit: { + name: "size_of_heap_commit", + offset: 96, + size: 8, + value: null, + data_type: "hex", + description: "堆提交大小", + }, + loader_flags: { + name: "loader_flags", + offset: 104, + size: 4, + value: null, + data_type: "hex", + description: "加载器标志", + }, + number_of_rva_and_sizes: { + name: "number_of_rva_and_sizes", + offset: 108, + size: 4, + value: null, + data_type: "hex", + description: "RVA和大小数量", + }, + }; + const command = "command_get_pe_data_optional_header"; + const columns = [ + { + title: "字段名", + dataIndex: "name", + key: "name", + }, + { + title: "偏移", + dataIndex: "offset", + key: "offset", + hexSwitch: true, + }, + { + title: "大小", + dataIndex: "size", + key: "size", + }, + { + title: "值", + dataIndex: "value", + key: "value", + hexSwitch: true, + editable: true, + }, + { + title: "描述信息", + dataIndex: "description", + key: "description", + }, + ]; + return ( + + ); +} diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index 25d11b2..8610a43 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -9,6 +9,7 @@ import SiderTree from "../components/side_tree/SideTree"; import DosHeader from "../components/DosHeader/DosHeader"; import NtHeader from "../components/NTHeader/NTHeader"; import FileHeader from "../components/FileHeader/FileHeader"; +import OptionalHeader from "../components/OptionalHeader/OptionalHeader"; import NodeTableComponent, { DataTemplateInterface, } from "../components/NodeTableComponent/NodeTableComponent"; @@ -18,6 +19,7 @@ const SelectNodeMap = { dos_header: , nt_header: , file_header: , + optional_header: , }; export default function MainPage() {