feat: 封装头部扩容
This commit is contained in:
parent
eb98ae4fd8
commit
5b8715b591
@ -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),
|
||||
|
@ -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(
|
||||
|
@ -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<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 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<AppState>>) ->
|
||||
|
||||
// 命令,获取可选头数据
|
||||
#[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 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<AppState>>
|
||||
|
||||
// 命令,获取节区头数据
|
||||
#[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 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(())
|
||||
}
|
||||
}
|
||||
|
||||
// 测试一下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(())
|
||||
}
|
||||
|
@ -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()));
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -1,7 +1,15 @@
|
||||
use super::{error::PEParseError, header::*};
|
||||
use std::ops::Deref;
|
||||
use memmap2::MmapMut;
|
||||
|
||||
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.
|
||||
fn get_ref<T>(&self, offset: usize) -> Result<&T, PEParseError> {
|
||||
let len = std::mem::size_of::<T>();
|
||||
@ -20,22 +28,49 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
|
||||
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.
|
||||
fn get_dos_header(&self) -> Result<&ImageDosHeader, PEParseError> {
|
||||
let result = self.get_ref::<ImageDosHeader>(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::<ImageNTHeader32>(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::<ImageNTHeader64>(nt_offset)?;
|
||||
Ok(result)
|
||||
}
|
||||
/// 动态的解析NT头 无论是32位还是64位
|
||||
fn get_nt_header(&self) -> Result<ImageNTHeader, PEParseError> {
|
||||
let is_64_bit = self.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()?;
|
||||
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::<ImageFileHeader>();
|
||||
@ -87,14 +122,14 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + 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::<ImageFileHeader>();
|
||||
let result = self.get_ref::<ImageOptionalHeader64>(optional_header_offset)?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// 动态的解析可选头 无论是32位还是64位
|
||||
fn get_optional_header(&self) -> Result<ImageOptionalHeader, PEParseError> {
|
||||
let is_64_bit = self.is_64_bit()?;
|
||||
let result = match is_64_bit {
|
||||
@ -136,4 +171,136 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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={<EditOutlined />}
|
||||
className={styles.optionItem}
|
||||
onClick={() => {
|
||||
message.info("还没有实现!");
|
||||
}}
|
||||
onClick={handleRequestExtendLastSection}
|
||||
>
|
||||
扩展最后一节大小
|
||||
</Button>
|
||||
|
Loading…
Reference in New Issue
Block a user