feat: 封装头部扩容
This commit is contained in:
parent
eb98ae4fd8
commit
5b8715b591
@ -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),
|
||||||
|
@ -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(§ion_name_bytes);
|
.copy_from_slice(§ion_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(
|
||||||
|
@ -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(
|
||||||
@ -201,4 +214,45 @@ pub fn command_add_section(
|
|||||||
let mut app_state = app_state.lock().unwrap();
|
let mut app_state = app_state.lock().unwrap();
|
||||||
app_state.add_section(§ion_name, section_size, section_characteristics)?;
|
app_state.add_section(§ion_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(())
|
||||||
|
}
|
||||||
|
@ -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()));
|
||||||
|
@ -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),
|
||||||
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {}
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user