feat: 增加导出表解析的功能和测试用例

This commit is contained in:
2024-12-18 12:10:55 +08:00
parent f48803b3c5
commit 3e0a858318
7 changed files with 182 additions and 1 deletions

View File

@@ -18,6 +18,8 @@ pub enum PEParseError {
RvaToEmptySection(u32),
#[error("错误的数据目录索引")]
InvalidDataDirectoryIndex,
#[error("错误的导出函数序号: {0}")]
ExportOrdinalNotFound(u16),
}
/// PE操作的错误
#[derive(Error, Debug)]

View File

@@ -450,4 +450,36 @@ bitflags! {
const RESERVED = 0x7FFFFFFF00000000;
}
}
/// 导出目录表
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct ImageExportDirectoryTable {
pub characteristics: u32,
pub time_date_stamp: u32,
pub major_version: u16,
pub minor_version: u16,
pub name: u32,
pub base: u32,
pub number_of_functions: u32,
pub number_of_names: u32,
pub address_of_functions: u32,
pub address_of_names: u32,
pub address_of_name_ordinals: u32,
}
/// 导出地址表
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub enum ExportAddressTable {
// 导出函数的RVA
ExportFunctionRVA(u32),
// 转发函数字符串的RVA
ForwarderStringRVA(u32),
}
pub enum ProcName {
Named(String),
Ordinal(u16),
}

View File

@@ -291,6 +291,71 @@ pub trait ReadOnlyPE: Deref<Target = [u8]> + Sized + AsRef<[u8]> {
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<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(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(rva);
}
}
todo!()
}
}
/// 可修改的PE trait
pub trait MutablePE: ReadOnlyPE + DerefMut<Target = [u8]> + AsMut<[u8]> {