630 lines
28 KiB
Rust
630 lines
28 KiB
Rust
use super::{
|
||
error::{MutablePEError, PEParseError},
|
||
header::*,
|
||
};
|
||
use crate::align_to;
|
||
use crate::constants::*;
|
||
use std::{
|
||
mem::{self},
|
||
ops::{Deref, DerefMut},
|
||
};
|
||
|
||
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>();
|
||
if offset + len > self.len() {
|
||
return Err(PEParseError::OutOfBounds);
|
||
}
|
||
let ptr = self.as_ptr().wrapping_offset(offset as isize) as *const T;
|
||
Ok(unsafe { &*ptr })
|
||
}
|
||
|
||
// 判断是64位还是32位
|
||
fn is_64_bit(&self) -> Result<bool, PEParseError> {
|
||
// 先以32位加载可选头,通过可选头的Magic字段判断
|
||
let optional_header: &ImageOptionalHeader32 = self.get_optional_header_32()?;
|
||
let is_64_bit = optional_header.magic == OPTIONAL_MAGIC_32;
|
||
Ok(is_64_bit)
|
||
}
|
||
|
||
/// 获取数据目录
|
||
fn get_data_directories(&self) -> Result<&[ImageDataDirectory], PEParseError> {
|
||
// 1. 获取数据目录偏移
|
||
|
||
let data_directories_offset = self.get_data_directories_offset()?;
|
||
// 2. 解析数据目录
|
||
let data_directories = unsafe {
|
||
let ptr = self
|
||
.as_ptr()
|
||
.wrapping_offset(data_directories_offset as isize)
|
||
as *const ImageDataDirectory;
|
||
let data_directories_count = self.get_optional_header()?.get_data_directory_count();
|
||
let result = std::slice::from_raw_parts(ptr, data_directories_count as usize);
|
||
result
|
||
};
|
||
Ok(data_directories)
|
||
}
|
||
|
||
/// 通过枚举获取某项数据目录的成员
|
||
/// data_directory: 数据目录枚举
|
||
fn get_data_directory(
|
||
&self,
|
||
data_directory: ImageDirectoryEntry,
|
||
) -> Result<&ImageDataDirectory, PEParseError> {
|
||
let data_directories = self.get_data_directories()?;
|
||
let data_directory = data_directories
|
||
.get(data_directory as usize)
|
||
.ok_or(PEParseError::InvalidDataDirectoryIndex)?;
|
||
Ok(data_directory)
|
||
}
|
||
|
||
/// 获取数据目录的偏移
|
||
fn get_data_directories_offset(&self) -> Result<u32, PEParseError> {
|
||
// 1. 获取可选头和可选头的偏移
|
||
let optional_header: ImageOptionalHeader = self.get_optional_header()?;
|
||
let optional_header_offset = self.get_optional_header_offset()? as u32;
|
||
// 2. 数据目录的偏移=可选头的偏移+可选头的大小
|
||
let data_directories_offset =
|
||
optional_header_offset + optional_header.get_size_of_optional_header();
|
||
Ok(data_directories_offset)
|
||
}
|
||
|
||
/// 将RVA转换为FOA
|
||
/// rva: 需要转换的RVA
|
||
fn rva_to_foa(&self, rva: u32) -> Result<u32, PEParseError> {
|
||
let sections = self.get_section_headers()?;
|
||
for section in sections.iter() {
|
||
let section_start = section.virtual_address;
|
||
let section_end =
|
||
section_start + self.align_size_with_file_alignment(section.size_of_raw_data)?;
|
||
if rva >= section_start && rva < section_end {
|
||
if section.size_of_raw_data == 0 {
|
||
// 如果节区的SizeOfRawData是0,那么这个节区是没有数据的 映射到这个节区的RVA一定是无效的
|
||
return Err(PEParseError::RvaToEmptySection(rva));
|
||
}
|
||
let foa = rva - section_start + section.pointer_to_raw_data;
|
||
return Ok(foa);
|
||
}
|
||
}
|
||
Err(PEParseError::RvaToFoaError(rva))
|
||
}
|
||
|
||
/// 将FOA转换为RVA
|
||
/// foa: 需要转换的FOA
|
||
fn foa_to_rva(&self, foa: u32) -> Result<u32, PEParseError> {
|
||
let sections = self.get_section_headers()?;
|
||
for section in sections.iter() {
|
||
// 如果section的PointerToRawData是0,那么这个节区是没有数据的,直接跳过
|
||
if section.pointer_to_raw_data == 0 {
|
||
continue;
|
||
}
|
||
let section_start = section.pointer_to_raw_data;
|
||
let section_end = section_start + section.size_of_raw_data;
|
||
if foa >= section_start && foa < section_end {
|
||
let rva = foa - section_start + section.virtual_address;
|
||
return Ok(rva);
|
||
}
|
||
}
|
||
Err(PEParseError::RvaToFoaError(foa))
|
||
}
|
||
|
||
/// 将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,
|
||
};
|
||
Ok(align_to!(size, section_alignment))
|
||
}
|
||
|
||
/// 将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,
|
||
};
|
||
Ok(align_to!(size, file_alignment))
|
||
}
|
||
|
||
/// 获取DOS头
|
||
/// 此方法不会验证DOS头的合法性,它仅从0偏移处获取DOS头
|
||
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 {
|
||
true => ImageNTHeader::NTHeader64(*self.get_nt_header64()?),
|
||
false => ImageNTHeader::NTHeader32(*self.get_nt_header32()?),
|
||
};
|
||
Ok(result)
|
||
}
|
||
|
||
/// 获取nt头的偏移
|
||
fn get_nt_headers_offset(&self) -> Result<usize, PEParseError> {
|
||
let dos_header = self.get_dos_header()?;
|
||
let nt_offset = dos_header.e_lfanew as usize;
|
||
Ok(nt_offset)
|
||
}
|
||
|
||
/// 获取文件头的偏移
|
||
fn get_file_header_offset(&self) -> Result<usize, PEParseError> {
|
||
// 1. 获取nt头偏移
|
||
let nt_offset = self.get_nt_headers_offset()?;
|
||
// 2. 计算文件头偏移
|
||
let file_header_offset = nt_offset + std::mem::size_of::<u32>();
|
||
Ok(file_header_offset)
|
||
}
|
||
|
||
/// 获取文件头数据
|
||
fn get_file_header(&self) -> Result<&ImageFileHeader, PEParseError> {
|
||
let file_header_offset = self.get_file_header_offset()?;
|
||
let result = self.get_ref::<ImageFileHeader>(file_header_offset)?;
|
||
Ok(result)
|
||
}
|
||
|
||
/// 获取节区数量
|
||
fn get_number_of_sections(&self) -> Result<usize, PEParseError> {
|
||
let file_header = self.get_file_header()?;
|
||
Ok(file_header.number_of_sections as usize)
|
||
}
|
||
|
||
/// 获取可选头大小
|
||
fn get_size_of_optional_header(&self) -> Result<usize, PEParseError> {
|
||
let file_header = self.get_file_header()?;
|
||
Ok(file_header.size_of_optional_header as usize)
|
||
}
|
||
/// 作为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>();
|
||
let result = self.get_ref::<ImageOptionalHeader32>(optional_header_offset)?;
|
||
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 {
|
||
true => ImageOptionalHeader::OptionalHeader64(*self.get_optional_header_64()?),
|
||
false => ImageOptionalHeader::OptionalHeader32(*self.get_optional_header_32()?),
|
||
};
|
||
Ok(result)
|
||
}
|
||
/// 获取可选头的偏移
|
||
fn get_optional_header_offset(&self) -> Result<usize, PEParseError> {
|
||
let file_header_offset = self.get_file_header_offset()?;
|
||
let optional_header_offset = file_header_offset + std::mem::size_of::<ImageFileHeader>();
|
||
Ok(optional_header_offset)
|
||
}
|
||
|
||
/// 获取节区头的偏移
|
||
/// 算法:节区头偏移 = 可选头偏移 + 可选头大小
|
||
fn get_section_headers_offset(&self) -> Result<usize, PEParseError> {
|
||
// 节区头偏移在可选头之后,可选头大小是可变的,所以需要计算
|
||
let optional_header_size = self.get_size_of_optional_header()?;
|
||
let optional_header_offset = self.get_optional_header_offset()?;
|
||
let section_header_offset = optional_header_offset + optional_header_size;
|
||
Ok(section_header_offset)
|
||
}
|
||
|
||
/// 获取所有节区头数据
|
||
fn get_section_headers(&self) -> Result<&[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_ptr()
|
||
.wrapping_offset(section_header_offset as isize)
|
||
as *const ImageSectionHeader;
|
||
let result = std::slice::from_raw_parts(ptr, number_of_sections);
|
||
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)
|
||
}
|
||
|
||
/// 获取头部空余空间大小
|
||
/// 头部空余空间大小 = 可选头的SizeOfHeaders - 最后一个节区头最后一个字节的偏移
|
||
fn get_header_empty_space_size(&self) -> Result<u32, PEParseError> {
|
||
let nt_header: ImageNTHeader = self.get_nt_header()?;
|
||
let size_of_headers = match nt_header {
|
||
ImageNTHeader::NTHeader32(nt_header) => nt_header.optional_header.size_of_headers,
|
||
ImageNTHeader::NTHeader64(nt_header) => nt_header.optional_header.size_of_headers,
|
||
};
|
||
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 empty_space_size = size_of_headers - last_section_header_offset as u32;
|
||
Ok(empty_space_size)
|
||
}
|
||
|
||
/// 以传入的RVA为开始偏移,从中解析导出表
|
||
fn parse_export_table(&self, rva: u32) -> Result<&ImageExportDirectoryTable, PEParseError> {
|
||
let foa = self.rva_to_foa(rva)?;
|
||
let export_table = self.get_ref::<ImageExportDirectoryTable>(foa as usize)?;
|
||
Ok(export_table)
|
||
}
|
||
|
||
/// 获取导出函数的RVA地址,类似于GetProcAddress
|
||
fn get_export_function_rva(&self, proc_name: ProcName) -> Result<Option<u32>, PEParseError> {
|
||
let export_table_dir = self.get_data_directory(ImageDirectoryEntry::Export)?;
|
||
let export_table_rva = export_table_dir.virtual_address;
|
||
let export_table = self.parse_export_table(export_table_rva)?;
|
||
let base = export_table.base; // 序号基数
|
||
let number_of_fun = export_table.number_of_functions;
|
||
let number_of_names = export_table.number_of_names;
|
||
// 名称指针表的FOA
|
||
let names_table_foa = self.rva_to_foa(export_table.address_of_names)?;
|
||
|
||
match proc_name {
|
||
ProcName::Named(proc_name_str) => {
|
||
// 遍历名称表
|
||
for index in 0..number_of_names {
|
||
let name_item_foa = names_table_foa + index * std::mem::size_of::<u32>() as u32;
|
||
let name_rva = self.get_ref::<u32>(name_item_foa as usize)?.clone();
|
||
let name_foa = self.rva_to_foa(name_rva)?;
|
||
let name = unsafe {
|
||
std::ffi::CStr::from_ptr(
|
||
self.get_ref::<i8>(name_foa as usize)? as *const i8
|
||
)
|
||
.to_str()
|
||
.unwrap()
|
||
};
|
||
// 比较
|
||
if name == proc_name_str {
|
||
// 找到了这个函数 那么需要找到这个函数的序号
|
||
let ordinals_table_foa =
|
||
self.rva_to_foa(export_table.address_of_name_ordinals)?;
|
||
let ordinal_item_foa =
|
||
ordinals_table_foa + index * std::mem::size_of::<u16>() as u32;
|
||
let ordinal = self.get_ref::<u16>(ordinal_item_foa as usize)?.clone();
|
||
// 找到了序号 那么就可以找到函数地址
|
||
let functions_table_foa =
|
||
self.rva_to_foa(export_table.address_of_functions)?;
|
||
let function_item_foa = functions_table_foa
|
||
+ ordinal as u32 * std::mem::size_of::<u32>() as u32;
|
||
let rva = self.get_ref::<u32>(function_item_foa as usize)?.clone();
|
||
return Ok(Some(rva));
|
||
}
|
||
}
|
||
}
|
||
ProcName::Ordinal(order) => {
|
||
// 通过序号查找
|
||
// 序号就在序号表的第order - base的下标位置
|
||
let find_ordinal = order as u32 - base;
|
||
if find_ordinal >= number_of_fun {
|
||
return Err(PEParseError::ExportOrdinalNotFound(order));
|
||
}
|
||
let functions_table_foa = self.rva_to_foa(export_table.address_of_functions)?;
|
||
let function_item_foa =
|
||
functions_table_foa + find_ordinal * std::mem::size_of::<u32>() as u32;
|
||
let rva = self.get_ref::<u32>(function_item_foa as usize)?.clone();
|
||
return Ok(Some(rva));
|
||
}
|
||
}
|
||
Ok(None)
|
||
}
|
||
|
||
/// 以传入的RVA为开始偏移,从中解析导入表
|
||
fn parse_import_tables(&self, rva: u32) -> Result<&[ImageImportDescriptor], PEParseError> {
|
||
let foa = self.rva_to_foa(rva)?;
|
||
let mut current_foa = foa;
|
||
let mut numbers = 0;
|
||
loop {
|
||
let import_table = self.get_ref::<ImageImportDescriptor>(current_foa as usize)?;
|
||
if import_table.original_first_thunk == 0 {
|
||
break;
|
||
}
|
||
numbers += 1;
|
||
current_foa += std::mem::size_of::<ImageImportDescriptor>() as u32;
|
||
}
|
||
let result_tables = unsafe {
|
||
let ptr = self.as_ptr().wrapping_offset(foa as isize) as *const ImageImportDescriptor;
|
||
let result = std::slice::from_raw_parts(ptr, numbers);
|
||
result
|
||
};
|
||
Ok(result_tables)
|
||
}
|
||
}
|
||
/// 可修改的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_file_header_mut(&mut self) -> Result<&mut ImageFileHeader, PEParseError> {
|
||
let file_header_offset = self.get_file_header_offset()?;
|
||
let result = self.get_mut::<ImageFileHeader>(file_header_offset)?;
|
||
Ok(result)
|
||
}
|
||
/// 获取可变的节区头数据
|
||
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)
|
||
}
|
||
|
||
/// 获取可变的数据目录引用
|
||
fn get_data_directories_mut(&mut self) -> Result<&mut [ImageDataDirectory], PEParseError> {
|
||
// 1. 获取数据目录偏移
|
||
let data_directories_offset = self.get_data_directories_offset()?;
|
||
// 2. 解析数据目录
|
||
let data_directories = unsafe {
|
||
let ptr = self
|
||
.as_mut_ptr()
|
||
.wrapping_offset(data_directories_offset as isize)
|
||
as *mut ImageDataDirectory;
|
||
let data_directories_count = self.get_optional_header()?.get_data_directory_count();
|
||
let result = std::slice::from_raw_parts_mut(ptr, data_directories_count as usize);
|
||
result
|
||
};
|
||
Ok(data_directories)
|
||
}
|
||
|
||
/// 通过枚举获取某项数据目录的可变引用
|
||
/// data_directory: 数据目录枚举
|
||
fn get_data_directory_mut(
|
||
&mut self,
|
||
data_directory: ImageDirectoryEntry,
|
||
) -> Result<&mut ImageDataDirectory, PEParseError> {
|
||
let data_directories = self.get_data_directories_mut()?;
|
||
let data_directory = data_directories
|
||
.get_mut(data_directory as usize)
|
||
.ok_or(PEParseError::InvalidDataDirectoryIndex)?;
|
||
Ok(data_directory)
|
||
}
|
||
|
||
/// 扩大头映射大小,调用者必须要保证当挪动所有节区数据时,不会超出文件范围
|
||
/// 也就是,调用者必须要在扩大头映射大小之前,先扩大文件大小
|
||
/// 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();
|
||
// 需要反向遍历,找到最后一个size_of_raw_data不为0的节区
|
||
// 然后计算这个节区的PointerToRawData+(SizeOfRawData对齐到FileAlignment的值)
|
||
let mut last_section_end = 0;
|
||
for section in sections.iter().rev() {
|
||
if section.size_of_raw_data != 0 {
|
||
last_section_end = section.pointer_to_raw_data
|
||
+ self.align_size_with_file_alignment(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,
|
||
));
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
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,
|
||
);
|
||
// 把[start_offset, start_offset+aligned_file_size)的数据填充为0
|
||
self_data[start_offset as usize..(start_offset + aligned_file_size) as usize].fill(0);
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
/// 添加一个节区
|
||
/// section_name: 节区名
|
||
/// section_size: 节区大小
|
||
/// section_characteristics: 节区特征
|
||
fn add_section(
|
||
&mut self,
|
||
section_name: &[u8; 8],
|
||
section_size: u32,
|
||
section_characteristics: SectionCharacteristics,
|
||
) -> Result<(), MutablePEError> {
|
||
// 1. 判断是否有空余空间
|
||
let empty_space_size = self.get_header_empty_space_size()?;
|
||
const SIZE_OF_SECTION_HEADER: u32 = mem::size_of::<ImageSectionHeader>() as u32;
|
||
// section_size与文件对齐后的大小
|
||
let file_alignment = self.align_size_with_file_alignment(section_size)?;
|
||
|
||
if empty_space_size < SIZE_OF_SECTION_HEADER {
|
||
// 判断是否能够扩容
|
||
let max_expand_size = self.get_header_max_expand_size()?;
|
||
if max_expand_size < file_alignment {
|
||
return Err(MutablePEError::CannotExpandHeader(
|
||
file_alignment,
|
||
max_expand_size,
|
||
));
|
||
}
|
||
self.expand_headers(file_alignment)?;
|
||
}
|
||
// 增加节区头
|
||
let sections_offset = self.get_section_headers_offset()?;
|
||
let number_of_sections = self.get_number_of_sections()?;
|
||
let new_section_offset =
|
||
sections_offset + (number_of_sections * SIZE_OF_SECTION_HEADER as usize) as usize;
|
||
let new_section = unsafe {
|
||
let ptr = self
|
||
.as_mut_ptr()
|
||
.wrapping_offset(new_section_offset as isize)
|
||
as *mut ImageSectionHeader;
|
||
&mut *ptr
|
||
};
|
||
new_section.name = *section_name;
|
||
// 新节区的virtual_size是section_size对齐到section_alignment的值
|
||
let mut section_alignment = self.align_size_with_section_alignment(section_size)?;
|
||
if section_size == 0 {
|
||
section_alignment = self.align_size_with_section_alignment(1)?;
|
||
}
|
||
new_section.virtual_size = section_alignment;
|
||
// 如果section_size是0,那么virtual_size必须得是最小的section_alignment
|
||
// 新节区的virtual_address是上一个节区的virtual_address+(pointer_to_raw_data 对齐到 section_alignment的值)
|
||
let last_section = self.get_section_headers()?.last().unwrap();
|
||
let mut last_section_size_of_raw_data_aligned =
|
||
self.align_size_with_section_alignment(last_section.size_of_raw_data)?;
|
||
if last_section_size_of_raw_data_aligned == 0 {
|
||
last_section_size_of_raw_data_aligned = self.align_size_with_section_alignment(1)?;
|
||
}
|
||
new_section.virtual_address =
|
||
last_section.virtual_address + last_section_size_of_raw_data_aligned;
|
||
new_section.size_of_raw_data = file_alignment;
|
||
// 如果上一个节区的size_of_raw_data是0,那么上一个节区的pointer_to_raw_data是可以乱写的
|
||
// 正确的做法应该是,找到上一个size_of_raw_data不为0的节区,然后计算
|
||
let sections = self.get_section_headers()?;
|
||
// 反向遍历
|
||
for section in sections.iter().rev() {
|
||
if section.size_of_raw_data != 0 {
|
||
new_section.pointer_to_raw_data = section.pointer_to_raw_data
|
||
+ self.align_size_with_file_alignment(section.size_of_raw_data)?;
|
||
break;
|
||
}
|
||
}
|
||
new_section.characteristics = section_characteristics;
|
||
// 其他字段最好填充为0
|
||
new_section.number_of_linenumbers = 0;
|
||
new_section.number_of_relocations = 0;
|
||
new_section.pointer_to_linenumbers = 0;
|
||
new_section.pointer_to_relocations = 0;
|
||
// 更新文件头的NumberOfSections
|
||
let file_header = self.get_file_header_mut()?;
|
||
file_header.number_of_sections += 1;
|
||
|
||
// 更新可选头的SizeOfImage
|
||
let mut nt_header = self.get_nt_header_mut()?;
|
||
let op = nt_header.get_optional_header_mut();
|
||
match op {
|
||
ImageOptionalHeaderMut::OptionalHeader32(op) => {
|
||
op.size_of_image += section_alignment;
|
||
}
|
||
ImageOptionalHeaderMut::OptionalHeader64(op) => {
|
||
op.size_of_image += section_alignment;
|
||
}
|
||
}
|
||
Ok(())
|
||
}
|
||
}
|