diff --git a/src-tauri/src/app_error.rs b/src-tauri/src/app_error.rs index fed4fb8..8c5eeea 100644 --- a/src-tauri/src/app_error.rs +++ b/src-tauri/src/app_error.rs @@ -1,6 +1,9 @@ use thiserror; -use crate::pe_parse::error::PEParseError; +use crate::pe_parse::error::{ + MutablePEError, + PEParseError, +}; #[derive(Debug, thiserror::Error)] pub enum AppError { @@ -18,6 +21,9 @@ pub enum AppError { #[error(transparent)] PeParseError(#[from] PEParseError), + #[error(transparent)] + MutablePeError(#[from] MutablePEError), + /// 初始化打开文件失败 #[error("初始化打开文件失败!: {0}")] InitOpenFileFailed(String), diff --git a/src-tauri/src/app_state.rs b/src-tauri/src/app_state.rs index 5674812..acb4737 100644 --- a/src-tauri/src/app_state.rs +++ b/src-tauri/src/app_state.rs @@ -1,7 +1,8 @@ use std::io::Seek; -use std::option; +use std::mem::offset_of; use crate::app_error::AppError; +use crate::pe_parse::header::ImageOptionalHeader; use crate::{pe_parse::pe::ReadOnlyPE, services::file}; use memmap2::{Mmap, MmapOptions}; @@ -68,18 +69,12 @@ impl AppState { section_size: usize, section_characteristics: u32, ) -> Result<(), AppError> { - // 1. section_name不能超过8个字符 if section_name.len() > 8 { + // section_name不能超过8个字符 return Err(AppError::SectionNameTooLong); } - // as_bytes 没有补0 let mut section_name_bytes = [0u8; 8]; - // 循环拷贝section_name的数据 - for i in 0..section_name.len() { - if i < section_name.len() { - section_name_bytes[i] = section_name.as_bytes()[i]; - } - } + section_name_bytes[..section_name.len()].copy_from_slice(section_name.as_bytes()); // 判断是否可以添加节 // if(size_of_headers - 最后一个节表的偏移 - 40) >= 40,则可以添加节表。 @@ -87,36 +82,22 @@ impl AppState { let mmap = self.get_mmap_ref()?; let origin_file_len = mmap.len(); let optional_header = mmap.get_optional_header()?; - let file_header_offset = mmap.get_file_header_offset()?; let optional_header_offset = mmap.get_optional_header_offset()?; let file_header = mmap.get_file_header()?; - let size_of_headers = match optional_header { - crate::pe_parse::header::ImageOptionalHeader::OptionalHeader32( - image_optional_header32, - ) => image_optional_header32.size_of_headers, - crate::pe_parse::header::ImageOptionalHeader::OptionalHeader64( - image_optional_header64, - ) => image_optional_header64.size_of_headers, + let file_header_offset = mmap.get_file_header_offset()?; + let (size_of_headers, section_alignment) = match optional_header { + ImageOptionalHeader::OptionalHeader32(image_optional_header32) => { + (image_optional_header32.size_of_headers, image_optional_header32.section_alignment) + } + ImageOptionalHeader::OptionalHeader64(image_optional_header64) => { + (image_optional_header64.size_of_headers, image_optional_header64.section_alignment) + } }; let section_table_offset = mmap.get_section_headers_offset()?; // 获取节表的数量 let number_of_sections = file_header.number_of_sections; - // 1. 获取偏移 - let section_alignment = match optional_header { - crate::pe_parse::header::ImageOptionalHeader::OptionalHeader32( - image_optional_header32, - ) => image_optional_header32.section_alignment, - crate::pe_parse::header::ImageOptionalHeader::OptionalHeader64( - image_optional_header64, - ) => image_optional_header64.section_alignment, - }; - - // 3. 判断是否可以添加节表 let section_table_size = 40 * number_of_sections as usize; - if size_of_headers - section_table_offset as u32 - (section_table_size as u32) < 40 { - // 需要看一下是否可以拓展文件大小 - // 2. 计算size_of_headers对齐之后的大小 例如:0x400 -> 0x1000 let aligned_size_of_headers = (size_of_headers + section_alignment - 1) & !(section_alignment - 1); @@ -180,12 +161,17 @@ impl AppState { rw_mmap[optional_header_offset + 0x38..optional_header_offset + 0x3C] .copy_from_slice(&(origin_size_of_image + add_image_size as u32).to_le_bytes()); + // 修改SizeOfHeaders,修改后的长度是:size_of_headers + expand_size例如:0x400 -> 0x1000 + let new_size_of_headers = size_of_headers + expand_size; + rw_mmap[optional_header_offset + 0x3C..optional_header_offset + 0x40] + .copy_from_slice(&new_size_of_headers.to_le_bytes()); + rw_mmap.flush()?; // 3. 重新映射文件 self.mmap = Some(file::mmap_file(self.file_path.as_ref().unwrap())?); } - // 4. 添加节表 - // 新的节区文件偏移是文件末尾 + + // 可以添加节表 let new_section_offset = self.get_mmap_ref()?.len(); let new_section_header_offset = section_table_offset + section_table_size; { @@ -207,7 +193,8 @@ impl AppState { .copy_from_slice(§ion_name_bytes); // virtual_size需要对齐 - let mut virtual_size = ((section_size as u32) + section_alignment - 1) & !(section_alignment - 1); + let mut virtual_size = + ((section_size as u32) + section_alignment - 1) & !(section_alignment - 1); if virtual_size == 0 { virtual_size = section_alignment; } @@ -215,7 +202,6 @@ impl AppState { rw_mmap[new_section_header_offset + 8..new_section_header_offset + 12] .copy_from_slice(&(virtual_size as u32).to_le_bytes()); - // 写入节的VA let last_section_header_offset = section_table_offset + 40 * (number_of_sections - 1) as usize; @@ -229,8 +215,8 @@ impl AppState { .try_into() .unwrap(), ); - let last_section_alignment_size = (last_sction_size + section_alignment - 1) - & !(section_alignment - 1); + let last_section_alignment_size = + (last_sction_size + section_alignment - 1) & !(section_alignment - 1); // 对齐后的VA, 对齐方式(last_section_va ) 和section_alignment进行对齐 let aligned_va = ((last_section_va + last_section_alignment_size) + section_alignment - 1) @@ -255,11 +241,6 @@ impl AppState { rw_mmap[file_header_offset + 2..file_header_offset + 4] .copy_from_slice(&(number_of_sections + 1).to_le_bytes()); - // 修改size_of_headers的大小 - let new_size_of_headers = size_of_headers + 40; - rw_mmap[optional_header_offset + 0x3C..optional_header_offset + 0x40] - .copy_from_slice(&new_size_of_headers.to_le_bytes()); - let origin_size_of_image = unsafe { // 在0x38的位置 u32::from_le_bytes( diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 94ea936..c80a719 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1,10 +1,18 @@ -use std::sync::Mutex; +use std::{ + io::{Seek, Write}, + sync::Mutex, +}; use crate::{ app_error::AppError, app_state::AppState, - pe_parse::pe::ReadOnlyPE, + pe_parse::{ + error::MutablePEError, + pe::{MutablePE, ReadOnlyPE}, + }, + services::file::mmap_file_rw, }; +use memmap2::MmapOptions; use serde::Serialize; use serde_json::{json, Value}; use tauri::{AppHandle, Manager, State}; @@ -137,7 +145,9 @@ pub fn command_get_pe_data_nt_header( // 命令,获取文件头数据 #[tauri::command(async)] -pub fn command_get_pe_data_file_header(app_state: State<'_, Mutex>) -> Result { +pub fn command_get_pe_data_file_header( + app_state: State<'_, Mutex>, +) -> Result { let app_state = app_state.lock().unwrap(); let mmap = app_state.get_mmap_ref()?; let file_header = mmap.get_file_header()?; @@ -150,7 +160,9 @@ pub fn command_get_pe_data_file_header(app_state: State<'_, Mutex>) -> // 命令,获取可选头数据 #[tauri::command(async)] -pub fn command_get_pe_data_optional_header(app_state: State<'_, Mutex>) -> Result { +pub fn command_get_pe_data_optional_header( + app_state: State<'_, Mutex>, +) -> Result { let app_state = app_state.lock().unwrap(); let mmap = app_state.get_mmap_ref()?; let optional_header = mmap.get_optional_header()?; @@ -165,7 +177,9 @@ pub fn command_get_pe_data_optional_header(app_state: State<'_, Mutex> // 命令,获取节区头数据 #[tauri::command(async)] -pub fn command_get_pe_data_section_headers(app_state: State<'_, Mutex>) -> Result { +pub fn command_get_pe_data_section_headers( + app_state: State<'_, Mutex>, +) -> Result { let app_state = app_state.lock().unwrap(); let mmap = app_state.get_mmap_ref()?; let section_headers = mmap.get_section_headers()?; @@ -189,7 +203,6 @@ pub fn command_write_data( Ok(()) } - // 命令,添加节 #[tauri::command] pub fn command_add_section( @@ -201,4 +214,45 @@ pub fn command_add_section( let mut app_state = app_state.lock().unwrap(); app_state.add_section(§ion_name, section_size, section_characteristics)?; Ok(()) -} \ No newline at end of file +} + +// 测试一下expand_headers好使不好使 +#[tauri::command] +pub fn command_expand_headers( + app_state: State<'_, Mutex>, + expand_size: u32, +) -> Result<(), AppError> { + let app_state = app_state.lock().unwrap(); + // app_state.expand_headers(expand_size)?; + let mmap = app_state.get_mmap_ref()?; + // 获取文件对齐后的大小 + let file_alignment = mmap.align_size_with_file_alignment(expand_size)?; + // 获取最大可以拓展的大小 + let max_expand_size = mmap.get_header_max_expand_size()?; + if expand_size > max_expand_size { + return Err(AppError::MutablePeError( + MutablePEError::CannotExpandHeader(expand_size, max_expand_size), + )); + } + + let file_path = app_state.file_path.as_ref().unwrap(); + let mut file = std::fs::OpenOptions::new() + .read(true) + .write(true) + .open(file_path)?; + // 文件指针移动到文件末尾 + file.seek(std::io::SeekFrom::End(0))?; + // 拓展文件大小 + file.set_len(file.metadata()?.len() + file_alignment as u64)?; + file.seek(std::io::SeekFrom::Start(0))?; + file.flush()?; + // 映射 + let mut mut_mmap = unsafe { + MmapOptions::new() + .map_mut(&file) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))? + }; + mut_mmap.expand_headers(expand_size)?; + + Ok(()) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 626dba9..f4966e7 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -26,6 +26,7 @@ pub fn run() { commands::command_get_pe_data_section_headers, commands::command_write_data, commands::command_add_section, + commands::command_expand_headers, ]) .setup(|app| { app.manage(Mutex::new(app_state::AppState::default())); diff --git a/src-tauri/src/pe_parse/error.rs b/src-tauri/src/pe_parse/error.rs index 5dfe263..1cf148a 100644 --- a/src-tauri/src/pe_parse/error.rs +++ b/src-tauri/src/pe_parse/error.rs @@ -13,3 +13,17 @@ pub enum PEParseError { #[error("解析超出了文件范围")] OutOfBounds, } +/// PE操作的错误 +#[derive(Error, Debug)] +pub enum MutablePEError { + // 兼容PE解析错误 + #[error(transparent)] + PEParseError(#[from] PEParseError), + // 头部映射无法扩容,超出最大可扩容范围 + #[error("头部映射无法扩容, 需要扩容大小:{0:#X},超过了最大可扩容范围:{1:#X}")] + CannotExpandHeader(u32, u32), + + // 文件大小不足,无法扩容 + #[error("文件大小不足,无法扩容! 需要的大小:{0:#X}, 当前的文件大小:{1:#X}")] + CannotExpandFileSize(u32, u32), +} diff --git a/src-tauri/src/pe_parse/header.rs b/src-tauri/src/pe_parse/header.rs index a4a9522..4155e74 100644 --- a/src-tauri/src/pe_parse/header.rs +++ b/src-tauri/src/pe_parse/header.rs @@ -42,6 +42,7 @@ pub struct ImageNTHeader64 { pub optional_header: ImageOptionalHeader64, } +#[repr(C)] #[derive(Serialize, Clone, Copy)] #[serde(untagged)] pub enum ImageNTHeader{ @@ -49,6 +50,24 @@ pub enum ImageNTHeader{ NTHeader64(ImageNTHeader64), } +#[repr(C)] +#[derive(Serialize)] +#[serde(untagged)] +pub enum ImageNTHeaderMut<'a>{ + NTHeader32(&'a mut ImageNTHeader32), + NTHeader64(&'a mut ImageNTHeader64), +} + +impl <'a> ImageNTHeaderMut<'a>{ + pub fn get_optional_header_mut(&mut self) -> ImageOptionalHeaderMut{ + match self{ + ImageNTHeaderMut::NTHeader32(header) => ImageOptionalHeaderMut::OptionalHeader32(&mut header.optional_header), + ImageNTHeaderMut::NTHeader64(header) => ImageOptionalHeaderMut::OptionalHeader64(&mut header.optional_header), + } + } +} + + #[repr(C)] #[derive(Debug, Clone, Copy, Serialize)] pub struct ImageFileHeader { @@ -298,6 +317,7 @@ pub struct ImageOptionalHeader64 { pub loader_flags: u32, pub number_of_rva_and_sizes: u32, } +#[repr(C)] #[derive(Serialize, Clone, Copy)] #[serde(untagged)] pub enum ImageOptionalHeader { @@ -305,6 +325,31 @@ pub enum ImageOptionalHeader { OptionalHeader64(ImageOptionalHeader64), } +#[repr(C)] +#[derive(Serialize)] +#[serde(untagged)] +pub enum ImageOptionalHeaderMut<'a> { + OptionalHeader32(&'a mut ImageOptionalHeader32), + OptionalHeader64(&'a mut ImageOptionalHeader64), +} + +impl ImageOptionalHeader { + pub fn get_size_of_headers(&self) -> u32 { + match self { + ImageOptionalHeader::OptionalHeader32(header) => header.size_of_headers, + ImageOptionalHeader::OptionalHeader64(header) => header.size_of_headers, + } + } + + pub fn get_size_of_image(&self) -> u32 { + match self { + ImageOptionalHeader::OptionalHeader32(header) => header.size_of_image, + ImageOptionalHeader::OptionalHeader64(header) => header.size_of_image, + } + } +} + + #[repr(C)] #[derive(Debug, Clone, Copy, Serialize)] pub struct ImageSectionHeader { diff --git a/src-tauri/src/pe_parse/pe.rs b/src-tauri/src/pe_parse/pe.rs index db40d25..5c20224 100644 --- a/src-tauri/src/pe_parse/pe.rs +++ b/src-tauri/src/pe_parse/pe.rs @@ -1,7 +1,15 @@ -use super::{error::PEParseError, header::*}; -use std::ops::Deref; +use memmap2::MmapMut; -pub trait ReadOnlyPE: Deref + Sized { +use super::{ + error::{MutablePEError, PEParseError}, + header::*, +}; +use std::{ + mem::{self, offset_of}, + ops::{Deref, DerefMut, IndexMut}, +}; + +pub trait ReadOnlyPE: Deref + Sized + AsRef<[u8]> { /// Get a reference to a type at a given offset. fn get_ref(&self, offset: usize) -> Result<&T, PEParseError> { let len = std::mem::size_of::(); @@ -20,22 +28,49 @@ pub trait ReadOnlyPE: Deref + Sized { Ok(is_64_bit) } + /// 将size与节对齐值进行对齐,返回对齐后的值 + /// size: 需要对齐的值 + fn align_size_with_section_alignment(&self, size: u32) -> Result { + let nt_header = self.get_nt_header()?; + let section_alignment = match nt_header { + ImageNTHeader::NTHeader32(nt_header) => nt_header.optional_header.section_alignment, + ImageNTHeader::NTHeader64(nt_header) => nt_header.optional_header.section_alignment, + }; + let aligned_size = (size + section_alignment - 1) & !(section_alignment - 1); + Ok(aligned_size) + } + + /// 将size与文件对齐值进行对齐,返回对齐后的值 + /// size: 需要对齐的值 + fn align_size_with_file_alignment(&self, size: u32) -> Result { + let nt_header = self.get_nt_header()?; + let file_alignment = match nt_header { + ImageNTHeader::NTHeader32(nt_header) => nt_header.optional_header.file_alignment, + ImageNTHeader::NTHeader64(nt_header) => nt_header.optional_header.file_alignment, + }; + let aligned_size = (size + file_alignment - 1) & !(file_alignment - 1); + Ok(aligned_size) + } + /// Get the DOS header without verifying its contents. fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> { let result = self.get_ref::(0)?; Ok(result) } + /// 作为32位的NT头解析 fn get_nt_header32(&self) -> Result<&ImageNTHeader32, PEParseError> { let nt_offset = self.get_nt_headers_offset()?; let result = self.get_ref::(nt_offset)?; Ok(result) } + /// 作为64位的NT头解析 fn get_nt_header64(&self) -> Result<&ImageNTHeader64, PEParseError> { let nt_offset = self.get_nt_headers_offset()?; let result = self.get_ref::(nt_offset)?; Ok(result) } + /// 动态的解析NT头 无论是32位还是64位 fn get_nt_header(&self) -> Result { let is_64_bit = self.is_64_bit()?; let result = match is_64_bit { @@ -79,7 +114,7 @@ pub trait ReadOnlyPE: Deref + Sized { let file_header = self.get_file_header()?; Ok(file_header.size_of_optional_header as usize) } - + /// 作为32位的可选头解析 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::(); @@ -87,14 +122,14 @@ pub trait ReadOnlyPE: Deref + Sized { Ok(result) } - // 获取可选头 + // 作为64位的可选头解析 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) } - + /// 动态的解析可选头 无论是32位还是64位 fn get_optional_header(&self) -> Result { let is_64_bit = self.is_64_bit()?; let result = match is_64_bit { @@ -136,4 +171,136 @@ pub trait ReadOnlyPE: Deref + Sized { Ok(result) } } + + /// 获取头映射最大可扩容大小 + fn get_header_max_expand_size(&self) -> Result { + // 最大可扩容大小 = 节对齐大小 - 最后一个节区头最后一个字节的偏移 + let nt_header: ImageNTHeader = self.get_nt_header()?; + let (section_alignment, file_alignment) = match nt_header { + ImageNTHeader::NTHeader32(nt_header) => (nt_header.optional_header.section_alignment, nt_header.optional_header.file_alignment), + ImageNTHeader::NTHeader64(nt_header) => (nt_header.optional_header.section_alignment, nt_header.optional_header.file_alignment), + }; + let section_header_offset = self.get_section_headers_offset()?; + let section_headers = self.get_number_of_sections()? as u32; + let last_section_header_offset = section_header_offset + + (section_headers as usize * std::mem::size_of::()); + let mut max_size_of_headers = section_alignment - last_section_header_offset as u32; + // max_size_of_headers 向下对齐 + max_size_of_headers &= !(file_alignment - 1); + + Ok(max_size_of_headers) + } + + +} +/// 可修改的PE trait +pub trait MutablePE: ReadOnlyPE + DerefMut + AsMut<[u8]> { + /// 实现一个get_mut + fn get_mut(&mut self, offset: usize) -> Result<&mut T, PEParseError> { + let len = std::mem::size_of::(); + if offset + len > self.len() { + return Err(PEParseError::OutOfBounds); + } + let ptr = self.as_mut_ptr().wrapping_offset(offset as isize) as *mut T; + Ok(unsafe { &mut *ptr }) + } + + /// 获取可变的节区头数据 + fn get_section_headers_mut(&mut self) -> Result<&mut [ImageSectionHeader], PEParseError> { + // 1. 获取节区数量 + let number_of_sections = self.get_number_of_sections()?; + // 2. 获取节区头偏移 + let section_header_offset = self.get_section_headers_offset()?; + // 3. 获取节区头数据 + unsafe { + let ptr = self + .as_mut_ptr() + .wrapping_offset(section_header_offset as isize) + as *mut ImageSectionHeader; + let result = std::slice::from_raw_parts_mut(ptr, number_of_sections); + Ok(result) + } + } + /// 获取可变的NT头数据64位 + fn get_nt_header64_mut(&mut self) -> Result<&mut ImageNTHeader64, PEParseError> { + let nt_offset = self.get_nt_headers_offset()?; + let result = self.get_mut::(nt_offset)?; + Ok(result) + } + + /// 获取可变的NT头数据32位 + fn get_nt_header32_mut(&mut self) -> Result<&mut ImageNTHeader32, PEParseError> { + let nt_offset = self.get_nt_headers_offset()?; + let result = self.get_mut::(nt_offset)?; + Ok(result) + } + + /// 获取可变的NT头数据 + fn get_nt_header_mut(&mut self) -> Result { + let is_64_bit = self.is_64_bit()?; + let result = match is_64_bit { + true => ImageNTHeaderMut::NTHeader64(self.get_nt_header64_mut()?), + false => ImageNTHeaderMut::NTHeader32(self.get_nt_header32_mut()?), + }; + Ok(result) + } + + /// 扩大头映射大小,调用者必须要保证当挪动所有节区数据时,不会超出文件范围 + /// 也就是,调用者必须要在扩大头映射大小之前,先扩大文件大小 + /// add_size: 需要扩大的大小,不需要进行对齐,会自动对齐 + fn expand_headers(&mut self, add_size: u32) -> Result<(), MutablePEError> { + // aligned_size: 需要增加的大小,对齐后的值 + let aligned_file_size = self.align_size_with_file_alignment(add_size)?; + let max_expand_size = self.get_header_max_expand_size()?; + let optional_header = self.get_optional_header()?; + let origin_size_for_headers = optional_header.get_size_of_headers(); + // 如果扩大后超过了最大可扩容大小,就不允许扩容 + if aligned_file_size > max_expand_size { + return Err(MutablePEError::CannotExpandHeader( + aligned_file_size, + origin_size_for_headers, + )); + } + // 检查一下把,万一调用者没有扩大文件大小 + let sections = self.get_section_headers()?; + let self_len = self.len(); + let last_section = sections.last().unwrap(); + let last_section_end = last_section.pointer_to_raw_data + last_section.size_of_raw_data; + if last_section_end as usize + aligned_file_size as usize > self_len { + return Err(MutablePEError::CannotExpandFileSize( + last_section_end as u32 + aligned_file_size, + self_len as u32, + )); + } + let mut nt_header = self.get_nt_header_mut()?; + let op = nt_header.get_optional_header_mut(); + + // 更新可选头的SizeOfHeaders和SizeOfImage + match op { + ImageOptionalHeaderMut::OptionalHeader32(op) => { + op.size_of_headers += aligned_file_size; + } + ImageOptionalHeaderMut::OptionalHeader64(op) => { + op.size_of_headers += aligned_file_size; + } + } + + let mut_section = self.get_section_headers_mut()?; + + let start_offset = mut_section.first().unwrap().pointer_to_raw_data; + let end_offset = last_section_end; + // 更新节区头的PointerToRawData + for section in mut_section.iter_mut() { + section.pointer_to_raw_data += aligned_file_size; + } + { + let self_data = self.as_mut(); + // 把[start_offset, end_offset)的数据往后挪动aligned_file_size + self_data.copy_within( + start_offset as usize..end_offset as usize, + (start_offset + aligned_file_size) as usize, + ); + } + Ok(()) + } } diff --git a/src-tauri/src/services/mod.rs b/src-tauri/src/services/mod.rs index 735c4a2..026a865 100644 --- a/src-tauri/src/services/mod.rs +++ b/src-tauri/src/services/mod.rs @@ -1,6 +1,13 @@ -use memmap2::Mmap; -use crate::pe_parse::pe::ReadOnlyPE; +use memmap2::{MmapMut, Mmap}; +use crate::pe_parse::pe::{ + ReadOnlyPE, + MutablePE +}; pub mod file; // 为文件映射实现PE结构 impl ReadOnlyPE for Mmap {} + +impl ReadOnlyPE for MmapMut {} +// 为可变文件映射实现可操作PE结构 +impl MutablePE for MmapMut {} diff --git a/src/components/SectionHeaders/SectionHeaders.tsx b/src/components/SectionHeaders/SectionHeaders.tsx index bc42714..ebe5717 100644 --- a/src/components/SectionHeaders/SectionHeaders.tsx +++ b/src/components/SectionHeaders/SectionHeaders.tsx @@ -12,7 +12,7 @@ import { Input, InputNumber, Select, - message, + // message, } from "antd"; import { PlusOutlined, EditOutlined } from "@ant-design/icons"; @@ -387,6 +387,12 @@ export default function SectionHeaders() { }); }; + const handleRequestExtendLastSection = () => { + invoke("command_expand_headers", { + expandSize: 0xffff, + }); + } + useEffect(() => { requestData(); }, []); @@ -406,9 +412,7 @@ export default function SectionHeaders() { type="primary" icon={} className={styles.optionItem} - onClick={() => { - message.info("还没有实现!"); - }} + onClick={handleRequestExtendLastSection} > 扩展最后一节大小