feat: 可选头部已经解析
This commit is contained in:
parent
7cf5a9c531
commit
45148ead6e
@ -1,17 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
pe_parse::{header::ImageDosHeader, pe::PE},
|
pe_parse::pe::PE,
|
||||||
services::{
|
services::{self, file::*, GLOBAL_FILE_DATA},
|
||||||
self,
|
|
||||||
file::{
|
|
||||||
get_nt_headers_data, ResponseDOSHeaderData, ResponseFileHeaderData,
|
|
||||||
ResponseNTHeaderData,
|
|
||||||
},
|
|
||||||
GLOBAL_FILE_DATA,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tauri::{async_runtime::Mutex, AppHandle, Manager, State};
|
use tauri::{AppHandle, Manager};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct PeNodeTreeData {
|
pub struct PeNodeTreeData {
|
||||||
@ -96,6 +89,15 @@ pub fn command_open_file(file_path: &str) -> Result<(), AppError> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
services::GLOBAL_FILE_PATH = Some(file_path.to_string());
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,3 +127,10 @@ pub fn command_get_pe_data_file_header() -> Result<ResponseFileHeaderData, AppEr
|
|||||||
let result = services::file::get_file_header_data()?;
|
let result = services::file::get_file_header_data()?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 命令,获取可选头数据
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn command_get_pe_data_optional_header() -> Result<ResponseOptionalHeaderData, AppError> {
|
||||||
|
let result = services::file::get_optional_header_data()?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
@ -15,7 +15,8 @@ pub fn run() {
|
|||||||
commands::command_get_pe_data_dos_header,
|
commands::command_get_pe_data_dos_header,
|
||||||
commands::command_get_pe_data_nt_header,
|
commands::command_get_pe_data_nt_header,
|
||||||
commands::command_get_pe_data_file_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!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -34,6 +34,21 @@ pub struct ImageNTHeaders32 {
|
|||||||
pub optional_header: ImageOptionalHeader32,
|
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)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, Serialize)]
|
#[derive(Debug, Clone, Copy, Serialize)]
|
||||||
pub struct ImageFileHeader {
|
pub struct ImageFileHeader {
|
||||||
@ -48,21 +63,31 @@ pub struct ImageFileHeader {
|
|||||||
impl Serialize for FileCharacteristics {
|
impl Serialize for FileCharacteristics {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer {
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
// 直接返回bitflags的整数值
|
// 直接返回bitflags的整数值
|
||||||
serializer.serialize_u16(self.bits())
|
serializer.serialize_u16(self.bits())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Serialize for DLLCharacteristics {
|
impl Serialize for DLLCharacteristics {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
S: serde::Serializer {
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
serializer.serialize_u16(self.bits())
|
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! {
|
bitflags! {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@ -102,6 +127,108 @@ bitflags! {
|
|||||||
const GUARD_CF = 0x4000;
|
const GUARD_CF = 0x4000;
|
||||||
const TERMINAL_SERVER_AWARE = 0x8000;
|
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)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, Serialize)]
|
#[derive(Debug, Clone, Copy, Serialize)]
|
||||||
@ -112,9 +239,9 @@ pub struct ImageOptionalHeader32 {
|
|||||||
pub size_of_code: u32,
|
pub size_of_code: u32,
|
||||||
pub size_of_initialized_data: u32,
|
pub size_of_initialized_data: u32,
|
||||||
pub size_of_uninitialized_data: u32,
|
pub size_of_uninitialized_data: u32,
|
||||||
pub address_of_entry_point: RVA,
|
pub address_of_entry_point: u32,
|
||||||
pub base_of_code: RVA,
|
pub base_of_code: u32,
|
||||||
pub base_of_data: RVA,
|
pub base_of_data: u32,
|
||||||
pub image_base: u32,
|
pub image_base: u32,
|
||||||
pub section_alignment: u32,
|
pub section_alignment: u32,
|
||||||
pub file_alignment: u32,
|
pub file_alignment: u32,
|
||||||
@ -137,3 +264,58 @@ pub struct ImageOptionalHeader32 {
|
|||||||
pub loader_flags: u32,
|
pub loader_flags: u32,
|
||||||
pub number_of_rva_and_sizes: 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,
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use super::{error::PEParseError, header::*};
|
use super::{error::PEParseError, header::*};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::{ops::{Deref, DerefMut}, option};
|
||||||
|
|
||||||
pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
||||||
/// Get a reference to a type at a given offset.
|
/// Get a reference to a type at a given offset.
|
||||||
@ -22,6 +22,16 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
Ok(unsafe { &mut *ptr })
|
Ok(unsafe { &mut *ptr })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断是64位还是32位
|
||||||
|
fn is_64_bit(&self) -> Result<bool, PEParseError> {
|
||||||
|
// 先以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.
|
/// Get the DOS header without verifying its contents.
|
||||||
fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> {
|
fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> {
|
||||||
let result = self.get_ref::<ImageDosHeader>(0)?;
|
let result = self.get_ref::<ImageDosHeader>(0)?;
|
||||||
@ -33,12 +43,26 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
Ok(result)
|
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 nt_offset = self.get_nt_headers_offset()?;
|
||||||
let result = self.get_ref::<ImageNTHeaders32>(nt_offset)?;
|
let result = self.get_ref::<ImageNTHeaders32>(nt_offset)?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
fn get_nt_headers64(&self) -> Result<&ImageNTHeaders64, PEParseError> {
|
||||||
|
let nt_offset = self.get_nt_headers_offset()?;
|
||||||
|
let result = self.get_ref::<ImageNTHeaders64>(nt_offset)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
fn get_nt_headers(&self) -> Result<ImageNTHeaders, PEParseError> {
|
||||||
|
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头的偏移
|
// 获取nt头的偏移
|
||||||
fn get_nt_headers_offset(&self) -> Result<usize, PEParseError> {
|
fn get_nt_headers_offset(&self) -> Result<usize, PEParseError> {
|
||||||
@ -76,5 +100,62 @@ pub trait PE: Deref<Target = [u8]> + DerefMut<Target = [u8]> + Sized {
|
|||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取节区数量
|
||||||
|
fn get_number_of_sections(&self) -> Result<usize, PEParseError> {
|
||||||
|
let file_header = self.get_file_header()?;
|
||||||
|
Ok(file_header.number_of_sections as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取可选头大小
|
||||||
|
fn get_size_of_optional_header(&self) -> Result<usize, PEParseError> {
|
||||||
|
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::<ImageFileHeader>();
|
||||||
|
let result = self.get_ref::<ImageOptionalHeader32>(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::<ImageFileHeader>();
|
||||||
|
let result = self.get_ref::<ImageOptionalHeader64>(optional_header_offset)?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_optional_header(&self) -> Result<ImageOptionalHeader, PEParseError> {
|
||||||
|
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<usize, PEParseError> {
|
||||||
|
let file_header_offset = self.get_file_header_offset()?;
|
||||||
|
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
|
||||||
|
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::<ImageFileHeader>() + 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use memmap2::*;
|
use memmap2::*;
|
||||||
use serde::Serialize;
|
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: 打开文件,并将文件映射到内存
|
// TODO: 打开文件,并将文件映射到内存
|
||||||
pub fn mmap_mut_file(file_path: &str) -> Result<Mmap, std::io::Error> {
|
pub fn mmap_mut_file(file_path: &str) -> Result<Mmap, std::io::Error> {
|
||||||
@ -25,17 +25,19 @@ pub struct ResponseDOSHeaderData {
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct ResponseNTHeaderData {
|
pub struct ResponseNTHeaderData {
|
||||||
fields: ImageNTHeaders32,
|
fields: ImageNTHeaders,
|
||||||
base_offset: usize,
|
base_offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_nt_headers_data() -> Result<ResponseNTHeaderData, AppError> {
|
pub fn get_nt_headers_data<'a>() -> Result<ResponseNTHeaderData, AppError> {
|
||||||
|
// pub static GLOBAL_FILE_DATA: Mutex<Option<PeData>> = Mutex::new(None);
|
||||||
let binding = GLOBAL_FILE_DATA.lock().unwrap();
|
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 file_data = binding.as_ref().unwrap();
|
||||||
let nt_header = file_data.get_nt_headers()?;
|
let nt_header_enmu= file_data.get_nt_headers()?;
|
||||||
let nt_offset = file_data.get_nt_headers_offset()?;
|
let nt_offset = file_data.get_nt_headers_offset()?;
|
||||||
let result = ResponseNTHeaderData {
|
let result = ResponseNTHeaderData {
|
||||||
fields: nt_header.clone(),
|
fields: nt_header_enmu,
|
||||||
base_offset: nt_offset,
|
base_offset: nt_offset,
|
||||||
};
|
};
|
||||||
Ok(result)
|
Ok(result)
|
||||||
@ -59,3 +61,22 @@ pub fn get_file_header_data() -> Result<ResponseFileHeaderData, AppError> {
|
|||||||
};
|
};
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
// 获取可选头数据
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct ResponseOptionalHeaderData {
|
||||||
|
pub fields: ImageOptionalHeader,
|
||||||
|
pub base_offset: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn get_optional_header_data() -> Result<ResponseOptionalHeaderData, AppError> {
|
||||||
|
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)
|
||||||
|
}
|
@ -9,6 +9,8 @@ pub mod file;
|
|||||||
|
|
||||||
// 全局文件路径
|
// 全局文件路径
|
||||||
pub static mut GLOBAL_FILE_PATH: Option<String> = None;
|
pub static mut GLOBAL_FILE_PATH: Option<String> = None;
|
||||||
|
// 文件是否是64位
|
||||||
|
pub static mut GLOBAL_IS_64_BIT: Option<bool> = None;
|
||||||
|
|
||||||
pub(crate) struct PeData(pub Vec<u8>);
|
pub(crate) struct PeData(pub Vec<u8>);
|
||||||
// 实现Deref
|
// 实现Deref
|
||||||
|
278
src/components/OptionalHeader/OptionalHeader.tsx
Normal file
278
src/components/OptionalHeader/OptionalHeader.tsx
Normal file
@ -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 (
|
||||||
|
<NodeTableComponent
|
||||||
|
dataTemplate={dataTemplate}
|
||||||
|
command={command}
|
||||||
|
columns={columns as any}
|
||||||
|
></NodeTableComponent>
|
||||||
|
);
|
||||||
|
}
|
@ -9,6 +9,7 @@ import SiderTree from "../components/side_tree/SideTree";
|
|||||||
import DosHeader from "../components/DosHeader/DosHeader";
|
import DosHeader from "../components/DosHeader/DosHeader";
|
||||||
import NtHeader from "../components/NTHeader/NTHeader";
|
import NtHeader from "../components/NTHeader/NTHeader";
|
||||||
import FileHeader from "../components/FileHeader/FileHeader";
|
import FileHeader from "../components/FileHeader/FileHeader";
|
||||||
|
import OptionalHeader from "../components/OptionalHeader/OptionalHeader";
|
||||||
import NodeTableComponent, {
|
import NodeTableComponent, {
|
||||||
DataTemplateInterface,
|
DataTemplateInterface,
|
||||||
} from "../components/NodeTableComponent/NodeTableComponent";
|
} from "../components/NodeTableComponent/NodeTableComponent";
|
||||||
@ -18,6 +19,7 @@ const SelectNodeMap = {
|
|||||||
dos_header: <DosHeader />,
|
dos_header: <DosHeader />,
|
||||||
nt_header: <NtHeader />,
|
nt_header: <NtHeader />,
|
||||||
file_header: <FileHeader />,
|
file_header: <FileHeader />,
|
||||||
|
optional_header: <OptionalHeader />,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MainPage() {
|
export default function MainPage() {
|
||||||
|
Loading…
Reference in New Issue
Block a user