fix: 修复一个错误解析32与64dos头的问题。修复了未处理转发函数的问题

This commit is contained in:
381848900@qq.com 2024-12-18 22:45:42 +08:00
parent e68f3fd3db
commit ba627058f0
5 changed files with 68 additions and 40 deletions

View File

@ -1,6 +1,8 @@
// DOS的Magic值 // DOS的Magic值
#[allow(dead_code)]
pub const DOS_MAGIC: u16 = 0x5A4D; pub const DOS_MAGIC: u16 = 0x5A4D;
// DOS头部大小 // DOS头部大小
#[allow(dead_code)]
pub const DOS_HEADER_SIZE: usize = 0x40; pub const DOS_HEADER_SIZE: usize = 0x40;
// DOS头部中PE头部的偏移 // DOS头部中PE头部的偏移
pub const DOS_HEADER_PE_OFFSET: usize = 0x3C; pub const DOS_HEADER_PE_OFFSET: usize = 0x3C;
@ -12,4 +14,7 @@ pub const SECTION_ALIGNMENT_OFFSET: usize = 0x38;
pub const IMAGE_SIZE_OFFSET: usize = 0x50; pub const IMAGE_SIZE_OFFSET: usize = 0x50;
// 可选头Magic如果为32位的值 // 可选头Magic如果为32位的值
#[allow(dead_code)]
pub const OPTIONAL_MAGIC_32: u16 = 0x10B; pub const OPTIONAL_MAGIC_32: u16 = 0x10B;
// 可选头Magic如果为64位的值
pub const OPTIONAL_MAGIC_64: u16 = 0x20B;

View File

@ -16,8 +16,8 @@ pub enum PEParseError {
RvaToFoaError(u32), RvaToFoaError(u32),
#[error("RVA对应的是一个空节区数据!RVA: {0}")] #[error("RVA对应的是一个空节区数据!RVA: {0}")]
RvaToEmptySection(u32), RvaToEmptySection(u32),
#[error("错误的数据目录索")] #[error("错误的数据目录索: {0}")]
InvalidDataDirectoryIndex, InvalidDataDirectoryIndex(u16),
#[error("错误的导出函数序号: {0}")] #[error("错误的导出函数序号: {0}")]
ExportOrdinalNotFound(u16), ExportOrdinalNotFound(u16),
} }

View File

@ -477,8 +477,16 @@ pub enum ExportAddressTable {
// 转发函数字符串的RVA // 转发函数字符串的RVA
ForwarderStringRVA(u32), ForwarderStringRVA(u32),
} }
/// 从导出表中查找的函数符号,有可能是名字,有可能是序号
pub enum ProcName { pub enum ProcName {
Named(String), Named(String),
Ordinal(u16), Ordinal(u16),
} }
/// 导出函数
pub enum ExportFunEnum {
// 导出函数的RVA
ExportFunctionRVA(u32),
// 转发函数字符串
ForwarderString(String),
}

View File

@ -24,7 +24,7 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized + AsRef<[u8]> {
fn is_64_bit(&self) -> Result<bool, PEParseError> { fn is_64_bit(&self) -> Result<bool, PEParseError> {
// 先以32位加载可选头通过可选头的Magic字段判断 // 先以32位加载可选头通过可选头的Magic字段判断
let optional_header: &ImageOptionalHeader32 = self.get_optional_header_32()?; let optional_header: &ImageOptionalHeader32 = self.get_optional_header_32()?;
let is_64_bit = optional_header.magic == OPTIONAL_MAGIC_32; let is_64_bit = optional_header.magic == OPTIONAL_MAGIC_64;
Ok(is_64_bit) Ok(is_64_bit)
} }
@ -53,9 +53,9 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized + AsRef<[u8]> {
data_directory: ImageDirectoryEntry, data_directory: ImageDirectoryEntry,
) -> Result<&ImageDataDirectory, PEParseError> { ) -> Result<&ImageDataDirectory, PEParseError> {
let data_directories = self.get_data_directories()?; let data_directories = self.get_data_directories()?;
let data_directory = data_directories let data_directory = data_directories.get(data_directory as usize).ok_or(
.get(data_directory as usize) PEParseError::InvalidDataDirectoryIndex(data_directory as u16),
.ok_or(PEParseError::InvalidDataDirectoryIndex)?; )?;
Ok(data_directory) Ok(data_directory)
} }
@ -301,9 +301,13 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized + AsRef<[u8]> {
} }
/// 获取导出函数的RVA地址类似于GetProcAddress /// 获取导出函数的RVA地址类似于GetProcAddress
fn get_export_function_rva(&self, proc_name: ProcName) -> Result<Option<u32>, PEParseError> { fn get_export_function_rva(
&self,
proc_name: ProcName,
) -> Result<Option<ExportFunEnum>, PEParseError> {
let export_table_dir = self.get_data_directory(ImageDirectoryEntry::Export)?; let export_table_dir = self.get_data_directory(ImageDirectoryEntry::Export)?;
let export_table_rva = export_table_dir.virtual_address; let export_table_rva = export_table_dir.virtual_address;
let export_table_size = export_table_dir.size;
let export_table = self.parse_export_table(export_table_rva)?; let export_table = self.parse_export_table(export_table_rva)?;
let base = export_table.base; // 序号基数 let base = export_table.base; // 序号基数
let number_of_fun = export_table.number_of_functions; let number_of_fun = export_table.number_of_functions;
@ -311,50 +315,57 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized + AsRef<[u8]> {
// 名称指针表的FOA // 名称指针表的FOA
let names_table_foa = self.rva_to_foa(export_table.address_of_names)?; let names_table_foa = self.rva_to_foa(export_table.address_of_names)?;
let get_function_rva = |ordinal: u32| -> Result<u32, PEParseError> {
let functions_table_foa = self.rva_to_foa(export_table.address_of_functions)?;
let function_item_foa =
functions_table_foa + ordinal * std::mem::size_of::<u32>() as u32;
Ok(self.get_ref::<u32>(function_item_foa as usize)?.clone())
};
let check_forwarder = |rva: u32| -> Result<Option<ExportFunEnum>, PEParseError> {
if rva >= export_table_rva && rva < export_table_rva + export_table_size {
let forwarder_foa = self.rva_to_foa(rva)?;
let forwarder = unsafe {
std::ffi::CStr::from_ptr(
self.get_ref::<i8>(forwarder_foa as usize)? as *const i8
)
.to_str()
.unwrap()
};
return Ok(Some(ExportFunEnum::ForwarderString(forwarder.to_string())));
}
Ok(Some(ExportFunEnum::ExportFunctionRVA(rva)))
};
match proc_name { match proc_name {
ProcName::Named(proc_name_str) => { ProcName::Named(proc_name_str) => {
// 遍历名称表
for index in 0..number_of_names { for index in 0..number_of_names {
let name_item_foa = names_table_foa + index * std::mem::size_of::<u32>() as u32; 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_rva = self.get_ref::<u32>(name_item_foa as usize)?.clone();
let name_foa = self.rva_to_foa(name_rva)?; let name_foa = self.rva_to_foa(name_rva)?;
let name = unsafe { let name = unsafe {
std::ffi::CStr::from_ptr( std::ffi::CStr::from_ptr(self.get_ref::<i8>(name_foa as usize)? as *const i8)
self.get_ref::<i8>(name_foa as usize)? as *const i8
)
.to_str() .to_str()
.unwrap() .unwrap()
}; };
// 比较
if name == proc_name_str { if name == proc_name_str {
// 找到了这个函数 那么需要找到这个函数的序号
let ordinals_table_foa = let ordinals_table_foa =
self.rva_to_foa(export_table.address_of_name_ordinals)?; self.rva_to_foa(export_table.address_of_name_ordinals)?;
let ordinal_item_foa = let ordinal_item_foa =
ordinals_table_foa + index * std::mem::size_of::<u16>() as u32; ordinals_table_foa + index * std::mem::size_of::<u16>() as u32;
let ordinal = self.get_ref::<u16>(ordinal_item_foa as usize)?.clone(); let ordinal = self.get_ref::<u16>(ordinal_item_foa as usize)?.clone();
// 找到了序号 那么就可以找到函数地址 let rva = get_function_rva(ordinal as u32)?;
let functions_table_foa = return check_forwarder(rva);
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) => { ProcName::Ordinal(order) => {
// 通过序号查找
// 序号就在序号表的第order - base的下标位置
let find_ordinal = order as u32 - base; let find_ordinal = order as u32 - base;
if find_ordinal >= number_of_fun { if find_ordinal >= number_of_fun {
return Err(PEParseError::ExportOrdinalNotFound(order)); return Err(PEParseError::ExportOrdinalNotFound(order));
} }
let functions_table_foa = self.rva_to_foa(export_table.address_of_functions)?; let rva = get_function_rva(find_ordinal)?;
let function_item_foa = return check_forwarder(rva);
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) Ok(None)
@ -463,9 +474,9 @@ pub trait MutablePE: ReadOnlyPE + DerefMut<Target = [u8]> + AsMut<[u8]> {
data_directory: ImageDirectoryEntry, data_directory: ImageDirectoryEntry,
) -> Result<&mut ImageDataDirectory, PEParseError> { ) -> Result<&mut ImageDataDirectory, PEParseError> {
let data_directories = self.get_data_directories_mut()?; let data_directories = self.get_data_directories_mut()?;
let data_directory = data_directories let data_directory = data_directories.get_mut(data_directory as usize).ok_or(
.get_mut(data_directory as usize) PEParseError::InvalidDataDirectoryIndex(data_directory as u16),
.ok_or(PEParseError::InvalidDataDirectoryIndex)?; )?;
Ok(data_directory) Ok(data_directory)
} }

View File

@ -1,5 +1,4 @@
mod test { mod test {
use super::*;
use memmap2::Mmap; use memmap2::Mmap;
use pe_parse::header::ProcName; use pe_parse::header::ProcName;
#[test] #[test]
@ -61,8 +60,8 @@ mod test {
#[test] #[test]
fn test_find_export_function() { fn test_find_export_function() {
// let find_function_str = ProcName::Named("test_def_add".to_string()); let find_function_str = ProcName::Named("test_def_add".to_string());
let find_function_str = ProcName::Ordinal(2); // let find_function_str = ProcName::Ordinal("div");
// 1. 还是先映射 // 1. 还是先映射
use pe_parse::pe::ReadOnlyPE; use pe_parse::pe::ReadOnlyPE;
let file = std::fs::OpenOptions::new() let file = std::fs::OpenOptions::new()
@ -76,9 +75,14 @@ mod test {
println!("Can't find the function"); println!("Can't find the function");
return; return;
} }
Some(rva) => { Some(rva) => match rva {
println!("Find Function RVA: {:#x}", rva); pe_parse::header::ExportFunEnum::ExportFunctionRVA(rva) => {
} println!("Find the function at: {:#x}", rva);
}
pe_parse::header::ExportFunEnum::ForwarderString(forward_str) => {
println!("转发函数,转发到: {}", forward_str);
}
},
} }
} }
} }