feat: 增加导出表解析的功能和测试用例
This commit is contained in:
@@ -18,6 +18,8 @@ pub enum PEParseError {
|
||||
RvaToEmptySection(u32),
|
||||
#[error("错误的数据目录索引")]
|
||||
InvalidDataDirectoryIndex,
|
||||
#[error("错误的导出函数序号: {0}")]
|
||||
ExportOrdinalNotFound(u16),
|
||||
}
|
||||
/// PE操作的错误
|
||||
#[derive(Error, Debug)]
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
65
src/pe.rs
65
src/pe.rs
@@ -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]> {
|
||||
|
||||
Reference in New Issue
Block a user