feat: 封装头部扩容

This commit is contained in:
381848900@qq.com 2024-12-13 23:02:41 +08:00
parent eb98ae4fd8
commit 5b8715b591
9 changed files with 341 additions and 62 deletions

View File

@ -1,6 +1,9 @@
use thiserror; use thiserror;
use crate::pe_parse::error::PEParseError; use crate::pe_parse::error::{
MutablePEError,
PEParseError,
};
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum AppError { pub enum AppError {
@ -18,6 +21,9 @@ pub enum AppError {
#[error(transparent)] #[error(transparent)]
PeParseError(#[from] PEParseError), PeParseError(#[from] PEParseError),
#[error(transparent)]
MutablePeError(#[from] MutablePEError),
/// 初始化打开文件失败 /// 初始化打开文件失败
#[error("初始化打开文件失败!: {0}")] #[error("初始化打开文件失败!: {0}")]
InitOpenFileFailed(String), InitOpenFileFailed(String),

View File

@ -1,7 +1,8 @@
use std::io::Seek; use std::io::Seek;
use std::option; use std::mem::offset_of;
use crate::app_error::AppError; use crate::app_error::AppError;
use crate::pe_parse::header::ImageOptionalHeader;
use crate::{pe_parse::pe::ReadOnlyPE, services::file}; use crate::{pe_parse::pe::ReadOnlyPE, services::file};
use memmap2::{Mmap, MmapOptions}; use memmap2::{Mmap, MmapOptions};
@ -68,18 +69,12 @@ impl AppState {
section_size: usize, section_size: usize,
section_characteristics: u32, section_characteristics: u32,
) -> Result<(), AppError> { ) -> Result<(), AppError> {
// 1. section_name不能超过8个字符
if section_name.len() > 8 { if section_name.len() > 8 {
// section_name不能超过8个字符
return Err(AppError::SectionNameTooLong); return Err(AppError::SectionNameTooLong);
} }
// as_bytes 没有补0
let mut section_name_bytes = [0u8; 8]; let mut section_name_bytes = [0u8; 8];
// 循环拷贝section_name的数据 section_name_bytes[..section_name.len()].copy_from_slice(section_name.as_bytes());
for i in 0..section_name.len() {
if i < section_name.len() {
section_name_bytes[i] = section_name.as_bytes()[i];
}
}
// 判断是否可以添加节 // 判断是否可以添加节
// if(size_of_headers - 最后一个节表的偏移 - 40) >= 40则可以添加节表。 // if(size_of_headers - 最后一个节表的偏移 - 40) >= 40则可以添加节表。
@ -87,36 +82,22 @@ impl AppState {
let mmap = self.get_mmap_ref()?; let mmap = self.get_mmap_ref()?;
let origin_file_len = mmap.len(); let origin_file_len = mmap.len();
let optional_header = mmap.get_optional_header()?; 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 optional_header_offset = mmap.get_optional_header_offset()?;
let file_header = mmap.get_file_header()?; let file_header = mmap.get_file_header()?;
let size_of_headers = match optional_header { let file_header_offset = mmap.get_file_header_offset()?;
crate::pe_parse::header::ImageOptionalHeader::OptionalHeader32( let (size_of_headers, section_alignment) = match optional_header {
image_optional_header32, ImageOptionalHeader::OptionalHeader32(image_optional_header32) => {
) => image_optional_header32.size_of_headers, (image_optional_header32.size_of_headers, image_optional_header32.section_alignment)
crate::pe_parse::header::ImageOptionalHeader::OptionalHeader64( }
image_optional_header64, ImageOptionalHeader::OptionalHeader64(image_optional_header64) => {
) => image_optional_header64.size_of_headers, (image_optional_header64.size_of_headers, image_optional_header64.section_alignment)
}
}; };
let section_table_offset = mmap.get_section_headers_offset()?; let section_table_offset = mmap.get_section_headers_offset()?;
// 获取节表的数量 // 获取节表的数量
let number_of_sections = file_header.number_of_sections; 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; 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 { if size_of_headers - section_table_offset as u32 - (section_table_size as u32) < 40 {
// 需要看一下是否可以拓展文件大小
// 2. 计算size_of_headers对齐之后的大小 例如:0x400 -> 0x1000 // 2. 计算size_of_headers对齐之后的大小 例如:0x400 -> 0x1000
let aligned_size_of_headers = let aligned_size_of_headers =
(size_of_headers + section_alignment - 1) & !(section_alignment - 1); (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] 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()); .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()?; rw_mmap.flush()?;
// 3. 重新映射文件 // 3. 重新映射文件
self.mmap = Some(file::mmap_file(self.file_path.as_ref().unwrap())?); 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_offset = self.get_mmap_ref()?.len();
let new_section_header_offset = section_table_offset + section_table_size; let new_section_header_offset = section_table_offset + section_table_size;
{ {
@ -207,7 +193,8 @@ impl AppState {
.copy_from_slice(&section_name_bytes); .copy_from_slice(&section_name_bytes);
// virtual_size需要对齐 // 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 { if virtual_size == 0 {
virtual_size = section_alignment; virtual_size = section_alignment;
} }
@ -215,7 +202,6 @@ impl AppState {
rw_mmap[new_section_header_offset + 8..new_section_header_offset + 12] rw_mmap[new_section_header_offset + 8..new_section_header_offset + 12]
.copy_from_slice(&(virtual_size as u32).to_le_bytes()); .copy_from_slice(&(virtual_size as u32).to_le_bytes());
// 写入节的VA // 写入节的VA
let last_section_header_offset = let last_section_header_offset =
section_table_offset + 40 * (number_of_sections - 1) as usize; section_table_offset + 40 * (number_of_sections - 1) as usize;
@ -229,8 +215,8 @@ impl AppState {
.try_into() .try_into()
.unwrap(), .unwrap(),
); );
let last_section_alignment_size = (last_sction_size + section_alignment - 1) let last_section_alignment_size =
& !(section_alignment - 1); (last_sction_size + section_alignment - 1) & !(section_alignment - 1);
// 对齐后的VA, 对齐方式(last_section_va ) 和section_alignment进行对齐 // 对齐后的VA, 对齐方式(last_section_va ) 和section_alignment进行对齐
let aligned_va = ((last_section_va + last_section_alignment_size) + section_alignment - 1) 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] rw_mmap[file_header_offset + 2..file_header_offset + 4]
.copy_from_slice(&(number_of_sections + 1).to_le_bytes()); .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 { let origin_size_of_image = unsafe {
// 在0x38的位置 // 在0x38的位置
u32::from_le_bytes( u32::from_le_bytes(

View File

@ -1,10 +1,18 @@
use std::sync::Mutex; use std::{
io::{Seek, Write},
sync::Mutex,
};
use crate::{ use crate::{
app_error::AppError, app_error::AppError,
app_state::AppState, 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::Serialize;
use serde_json::{json, Value}; use serde_json::{json, Value};
use tauri::{AppHandle, Manager, State}; use tauri::{AppHandle, Manager, State};
@ -137,7 +145,9 @@ pub fn command_get_pe_data_nt_header(
// 命令,获取文件头数据 // 命令,获取文件头数据
#[tauri::command(async)] #[tauri::command(async)]
pub fn command_get_pe_data_file_header(app_state: State<'_, Mutex<AppState>>) -> Result<Value, AppError> { pub fn command_get_pe_data_file_header(
app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
let app_state = app_state.lock().unwrap(); let app_state = app_state.lock().unwrap();
let mmap = app_state.get_mmap_ref()?; let mmap = app_state.get_mmap_ref()?;
let file_header = mmap.get_file_header()?; let file_header = mmap.get_file_header()?;
@ -150,7 +160,9 @@ pub fn command_get_pe_data_file_header(app_state: State<'_, Mutex<AppState>>) ->
// 命令,获取可选头数据 // 命令,获取可选头数据
#[tauri::command(async)] #[tauri::command(async)]
pub fn command_get_pe_data_optional_header(app_state: State<'_, Mutex<AppState>>) -> Result<Value, AppError> { pub fn command_get_pe_data_optional_header(
app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
let app_state = app_state.lock().unwrap(); let app_state = app_state.lock().unwrap();
let mmap = app_state.get_mmap_ref()?; let mmap = app_state.get_mmap_ref()?;
let optional_header = mmap.get_optional_header()?; let optional_header = mmap.get_optional_header()?;
@ -165,7 +177,9 @@ pub fn command_get_pe_data_optional_header(app_state: State<'_, Mutex<AppState>>
// 命令,获取节区头数据 // 命令,获取节区头数据
#[tauri::command(async)] #[tauri::command(async)]
pub fn command_get_pe_data_section_headers(app_state: State<'_, Mutex<AppState>>) -> Result<Value, AppError> { pub fn command_get_pe_data_section_headers(
app_state: State<'_, Mutex<AppState>>,
) -> Result<Value, AppError> {
let app_state = app_state.lock().unwrap(); let app_state = app_state.lock().unwrap();
let mmap = app_state.get_mmap_ref()?; let mmap = app_state.get_mmap_ref()?;
let section_headers = mmap.get_section_headers()?; let section_headers = mmap.get_section_headers()?;
@ -189,7 +203,6 @@ pub fn command_write_data(
Ok(()) Ok(())
} }
// 命令,添加节 // 命令,添加节
#[tauri::command] #[tauri::command]
pub fn command_add_section( pub fn command_add_section(
@ -202,3 +215,44 @@ pub fn command_add_section(
app_state.add_section(&section_name, section_size, section_characteristics)?; app_state.add_section(&section_name, section_size, section_characteristics)?;
Ok(()) Ok(())
} }
// 测试一下expand_headers好使不好使
#[tauri::command]
pub fn command_expand_headers(
app_state: State<'_, Mutex<AppState>>,
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(())
}

View File

@ -26,6 +26,7 @@ pub fn run() {
commands::command_get_pe_data_section_headers, commands::command_get_pe_data_section_headers,
commands::command_write_data, commands::command_write_data,
commands::command_add_section, commands::command_add_section,
commands::command_expand_headers,
]) ])
.setup(|app| { .setup(|app| {
app.manage(Mutex::new(app_state::AppState::default())); app.manage(Mutex::new(app_state::AppState::default()));

View File

@ -13,3 +13,17 @@ pub enum PEParseError {
#[error("解析超出了文件范围")] #[error("解析超出了文件范围")]
OutOfBounds, 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),
}

View File

@ -42,6 +42,7 @@ pub struct ImageNTHeader64 {
pub optional_header: ImageOptionalHeader64, pub optional_header: ImageOptionalHeader64,
} }
#[repr(C)]
#[derive(Serialize, Clone, Copy)] #[derive(Serialize, Clone, Copy)]
#[serde(untagged)] #[serde(untagged)]
pub enum ImageNTHeader{ pub enum ImageNTHeader{
@ -49,6 +50,24 @@ pub enum ImageNTHeader{
NTHeader64(ImageNTHeader64), 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)] #[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)] #[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageFileHeader { pub struct ImageFileHeader {
@ -298,6 +317,7 @@ pub struct ImageOptionalHeader64 {
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(Serialize, Clone, Copy)] #[derive(Serialize, Clone, Copy)]
#[serde(untagged)] #[serde(untagged)]
pub enum ImageOptionalHeader { pub enum ImageOptionalHeader {
@ -305,6 +325,31 @@ pub enum ImageOptionalHeader {
OptionalHeader64(ImageOptionalHeader64), 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)] #[repr(C)]
#[derive(Debug, Clone, Copy, Serialize)] #[derive(Debug, Clone, Copy, Serialize)]
pub struct ImageSectionHeader { pub struct ImageSectionHeader {

View File

@ -1,7 +1,15 @@
use super::{error::PEParseError, header::*}; use memmap2::MmapMut;
use std::ops::Deref;
pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized { use super::{
error::{MutablePEError, PEParseError},
header::*,
};
use std::{
mem::{self, offset_of},
ops::{Deref, DerefMut, IndexMut},
};
pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized + AsRef<[u8]> {
/// Get a reference to a type at a given offset. /// Get a reference to a type at a given offset.
fn get_ref<T>(&self, offset: usize) -> Result<&T, PEParseError> { fn get_ref<T>(&self, offset: usize) -> Result<&T, PEParseError> {
let len = std::mem::size_of::<T>(); let len = std::mem::size_of::<T>();
@ -20,22 +28,49 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
Ok(is_64_bit) Ok(is_64_bit)
} }
/// 将size与节对齐值进行对齐返回对齐后的值
/// size: 需要对齐的值
fn align_size_with_section_alignment(&self, size: u32) -> Result<u32, PEParseError> {
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<u32, PEParseError> {
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. /// 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)?;
Ok(result) Ok(result)
} }
/// 作为32位的NT头解析
fn get_nt_header32(&self) -> Result<&ImageNTHeader32, PEParseError> { fn get_nt_header32(&self) -> Result<&ImageNTHeader32, PEParseError> {
let nt_offset = self.get_nt_headers_offset()?; let nt_offset = self.get_nt_headers_offset()?;
let result = self.get_ref::<ImageNTHeader32>(nt_offset)?; let result = self.get_ref::<ImageNTHeader32>(nt_offset)?;
Ok(result) Ok(result)
} }
/// 作为64位的NT头解析
fn get_nt_header64(&self) -> Result<&ImageNTHeader64, PEParseError> { fn get_nt_header64(&self) -> Result<&ImageNTHeader64, PEParseError> {
let nt_offset = self.get_nt_headers_offset()?; let nt_offset = self.get_nt_headers_offset()?;
let result = self.get_ref::<ImageNTHeader64>(nt_offset)?; let result = self.get_ref::<ImageNTHeader64>(nt_offset)?;
Ok(result) Ok(result)
} }
/// 动态的解析NT头 无论是32位还是64位
fn get_nt_header(&self) -> Result<ImageNTHeader, PEParseError> { fn get_nt_header(&self) -> Result<ImageNTHeader, PEParseError> {
let is_64_bit = self.is_64_bit()?; let is_64_bit = self.is_64_bit()?;
let result = match is_64_bit { let result = match is_64_bit {
@ -79,7 +114,7 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
let file_header = self.get_file_header()?; let file_header = self.get_file_header()?;
Ok(file_header.size_of_optional_header as usize) Ok(file_header.size_of_optional_header as usize)
} }
/// 作为32位的可选头解析
fn get_optional_header_32(&self) -> Result<&ImageOptionalHeader32, PEParseError> { fn get_optional_header_32(&self) -> Result<&ImageOptionalHeader32, PEParseError> {
let file_header_offset = self.get_file_header_offset()?; let file_header_offset = self.get_file_header_offset()?;
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>(); let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
@ -87,14 +122,14 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
Ok(result) Ok(result)
} }
// 获取可选头 // 作为64位的可选头解析
fn get_optional_header_64(&self) -> Result<&ImageOptionalHeader64, PEParseError> { fn get_optional_header_64(&self) -> Result<&ImageOptionalHeader64, PEParseError> {
let file_header_offset = self.get_file_header_offset()?; let file_header_offset = self.get_file_header_offset()?;
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>(); let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
let result = self.get_ref::<ImageOptionalHeader64>(optional_header_offset)?; let result = self.get_ref::<ImageOptionalHeader64>(optional_header_offset)?;
Ok(result) Ok(result)
} }
/// 动态的解析可选头 无论是32位还是64位
fn get_optional_header(&self) -> Result<ImageOptionalHeader, PEParseError> { fn get_optional_header(&self) -> Result<ImageOptionalHeader, PEParseError> {
let is_64_bit = self.is_64_bit()?; let is_64_bit = self.is_64_bit()?;
let result = match is_64_bit { let result = match is_64_bit {
@ -136,4 +171,136 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
Ok(result) Ok(result)
} }
} }
/// 获取头映射最大可扩容大小
fn get_header_max_expand_size(&self) -> Result<u32, PEParseError> {
// 最大可扩容大小 = 节对齐大小 - 最后一个节区头最后一个字节的偏移
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::<ImageSectionHeader>());
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<Target = [u8]> + AsMut<[u8]> {
/// 实现一个get_mut
fn get_mut<T>(&mut self, offset: usize) -> Result<&mut T, PEParseError> {
let len = std::mem::size_of::<T>();
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::<ImageNTHeader64>(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::<ImageNTHeader32>(nt_offset)?;
Ok(result)
}
/// 获取可变的NT头数据
fn get_nt_header_mut(&mut self) -> Result<ImageNTHeaderMut, PEParseError> {
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(())
}
} }

View File

@ -1,6 +1,13 @@
use memmap2::Mmap; use memmap2::{MmapMut, Mmap};
use crate::pe_parse::pe::ReadOnlyPE; use crate::pe_parse::pe::{
ReadOnlyPE,
MutablePE
};
pub mod file; pub mod file;
// 为文件映射实现PE结构 // 为文件映射实现PE结构
impl ReadOnlyPE for Mmap {} impl ReadOnlyPE for Mmap {}
impl ReadOnlyPE for MmapMut {}
// 为可变文件映射实现可操作PE结构
impl MutablePE for MmapMut {}

View File

@ -12,7 +12,7 @@ import {
Input, Input,
InputNumber, InputNumber,
Select, Select,
message, // message,
} from "antd"; } from "antd";
import { PlusOutlined, EditOutlined } from "@ant-design/icons"; import { PlusOutlined, EditOutlined } from "@ant-design/icons";
@ -387,6 +387,12 @@ export default function SectionHeaders() {
}); });
}; };
const handleRequestExtendLastSection = () => {
invoke("command_expand_headers", {
expandSize: 0xffff,
});
}
useEffect(() => { useEffect(() => {
requestData(); requestData();
}, []); }, []);
@ -406,9 +412,7 @@ export default function SectionHeaders() {
type="primary" type="primary"
icon={<EditOutlined />} icon={<EditOutlined />}
className={styles.optionItem} className={styles.optionItem}
onClick={() => { onClick={handleRequestExtendLastSection}
message.info("还没有实现!");
}}
> >
</Button> </Button>